Merge branch 'update-talks'
This commit is contained in:
commit
b108d9b855
|
@ -59,7 +59,6 @@ events:
|
||||||
|
|
||||||
nomad_php:
|
nomad_php:
|
||||||
name: Nomad PHP
|
name: Nomad PHP
|
||||||
location: Online
|
|
||||||
url: https://nomadphp.com
|
url: https://nomadphp.com
|
||||||
|
|
||||||
nwdug:
|
nwdug:
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
{% set talks = getAllTalks([page], site.events) %}
|
{% if page.events %}
|
||||||
{% if talks is not empty %}
|
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<h2 class="mb-2">Events</h2>
|
<h2 class="mb-2">Presented at</h2>
|
||||||
|
|
||||||
{% include "talks/table" with {
|
<ul class="markup">
|
||||||
talks: talks|reverse,
|
{% for event in page.events %}
|
||||||
talk_page: true
|
<li>
|
||||||
} %}
|
{% set eventData = site.events[event.event] %}
|
||||||
|
{% if eventData.url %}
|
||||||
|
<a href="{{ eventData.url }}">{{ eventData.name }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ eventData.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% if eventData.location %}
|
||||||
|
in {{ eventData.location }}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
17
source/_partials/talks/talk.html.twig
Normal file
17
source/_partials/talks/talk.html.twig
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<article>
|
||||||
|
<h3 class="text-lg text-black mb-1">{{ talk.title }}</h3>
|
||||||
|
|
||||||
|
<div class="text-sm text-grey-darkest">
|
||||||
|
<p>{{ talk.description }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if talk.url %}
|
||||||
|
<footer class="mt-1">
|
||||||
|
<a href="{{ talk.url }}" class="text-sm text-grey-dark hover:text-grey-darkest focus:text-grey-darkest no-underline hover:underline">
|
||||||
|
Find out more
|
||||||
|
<span class="visuallyhidden">about {{ talk.title }}</span>
|
||||||
|
→
|
||||||
|
</a>
|
||||||
|
</footer>
|
||||||
|
{% endif %}
|
||||||
|
</article>
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Building Static Websites with Sculpin
|
title: Building Static Websites with Sculpin
|
||||||
|
description: A lightning talk on how to use Sculpin to generate static HTML websites.
|
||||||
type: Lightning talk
|
type: Lightning talk
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 6c9c4be1a1344f1291ff13a391674a66
|
id: 6c9c4be1a1344f1291ff13a391674a66
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Configuring all the Things (in Drupal 8)"
|
title: "Configuring all the Things (in Drupal 8)"
|
||||||
|
description: A short notice talk on configuration management in Drupal 8, and things I’ve learned working on my current Drupal 8 project.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 6de3fe8947a34727b79eb9d9dcc66bf2
|
id: 6de3fe8947a34727b79eb9d9dcc66bf2
|
||||||
ratio: "1.37081659973226"
|
ratio: "1.37081659973226"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Dancing for Drupal
|
title: Dancing for Drupal
|
||||||
|
description: A talk on Drupal, presented alongside others representing Umbraco, Sitecore and Episerver.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: ffa9b6dea6dc4a8eb207b9982ed6e1bd
|
id: ffa9b6dea6dc4a8eb207b9982ed6e1bd
|
||||||
ratio: '1.33333333333333'
|
ratio: '1.33333333333333'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: 'Deploying Drupal with Fabric'
|
title: 'Deploying Drupal with Fabric'
|
||||||
type: Talk
|
description: How to use Fabric, a Python command line based library, to deploy your Drupal applications.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 40d1eca4bd484afc86295924fff5dd41
|
id: 40d1eca4bd484afc86295924fff5dd41
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Deploying PHP applications with Ansible, Ansible Vault and Ansistrano
|
title: Deploying PHP applications with Ansible, Ansible Vault and Ansistrano
|
||||||
|
description: How to use Ansible and Ansistrano to perform robust, secure deployments of your PHP applications.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: c11fe635ed8f4741b35bf3ebe53e8323
|
id: c11fe635ed8f4741b35bf3ebe53e8323
|
||||||
ratio: "1.77777777777778"
|
ratio: "1.77777777777778"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Deploying PHP Applications with Fabric
|
title: Deploying PHP Applications with Fabric
|
||||||
|
description: How to use Fabric, a Python command line based library, to deploy your PHP applications.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: c147618ce07546ca92f92983c52d6a41
|
id: c147618ce07546ca92f92983c52d6a41
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Getting Started with Drupal 8 Module Development
|
title: Getting Started with Drupal 8 Module Development
|
||||||
|
description: How to build your first module for Drupal 8.
|
||||||
tags: [conference, php, drupal, drupalcamp, drupal-8]
|
tags: [conference, php, drupal, drupalcamp, drupal-8]
|
||||||
tweets: yes
|
tweets: yes
|
||||||
code: https://github.com/opdavies/dclondon16-d8-module
|
code: https://github.com/opdavies/dclondon16-d8-module
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Having Fun with Drupal 8, PHP libraries and the Drupal.org API
|
title: Having Fun with Drupal 8, PHP libraries and the Drupal.org API
|
||||||
|
description: A crash course in developing PHP packages and Drupal 8 modules, based on the Drupal.org API.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 6e42ae9620bb4e91b3955f8c30d66934
|
id: 6e42ae9620bb4e91b3955f8c30d66934
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Drupal 8: Rejoining the Herd
|
title: Drupal 8: Rejoining the Herd
|
||||||
|
description: A talk highlighting some of the recent technical and non-technical changes in Drupal 8.
|
||||||
tags: [conference, php, drupal, drupal-8]
|
tags: [conference, php, drupal, drupal-8]
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 440fd6592f474741bc606c96bc32c104
|
id: 440fd6592f474741bc606c96bc32c104
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Drupal 8
|
title: Drupal 8
|
||||||
|
description: A lightning talk presented to the PHPSW user group, highlighting some of the relevant changes in Drupal 8.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
url: https://speakerdeck.com/opdavies/drupal-8
|
url: https://speakerdeck.com/opdavies/drupal-8
|
||||||
id: 46ba4ba577d94a32b7abdade610ceb69
|
id: 46ba4ba577d94a32b7abdade610ceb69
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Drupal VM Generator
|
title: Drupal VM Generator
|
||||||
|
description: Announcing the Drupal VM Generator CLI tool.
|
||||||
type: Lightning talk
|
type: Lightning talk
|
||||||
code: https://github.com/opdavies/drupal-vm-generator
|
code: https://github.com/opdavies/drupal-vm-generator
|
||||||
tags: [drupal-vm, drupal-vm-generator, meetup, symfony]
|
tags: [drupal-vm, drupal-vm-generator, meetup, symfony]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Drupal VM, Meet Symfony Console
|
title: Drupal VM, Meet Symfony Console
|
||||||
|
description: How to develop command line applications using Symfony Console, using the Drupal VM CLI as an example.
|
||||||
tags: [conference, php, drupal-vm, symfony]
|
tags: [conference, php, drupal-vm, symfony]
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 56c79770f73f4e47a542a30243437c49
|
id: 56c79770f73f4e47a542a30243437c49
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Drupal.org in 2015: What's Coming Next
|
title: Drupal.org in 2015: What's Coming Next
|
||||||
|
description: A retrospective of the Drupal Association’s work in 2014 and a look forward to what we’ll be working on in 2015.
|
||||||
tags: [conference, drupalcamp, drupalcamp-london, drupal-association]
|
tags: [conference, drupalcamp, drupalcamp-london, drupal-association]
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 0cf8d7b647c94ae289e9db2b46a9e8f2
|
id: 0cf8d7b647c94ae289e9db2b46a9e8f2
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: drush make drupalbristol
|
title: drush make drupalbristol
|
||||||
|
description: How to Drush Make to build your Drupal websites.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 42605700f102013198de5a5f6f23ab67
|
id: 42605700f102013198de5a5f6f23ab67
|
||||||
ratio: '1.29456384323641'
|
ratio: '1.29456384323641'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Getting (Your Data) Into Drupal 8
|
title: Getting (Your Data) Into Drupal 8
|
||||||
|
description: An overview of Drupal’s Migrate functionality, and a look at how to write your own migrations.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 63e5dfce996e46699e304d50e896477b
|
id: 63e5dfce996e46699e304d50e896477b
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Never Commit to Master - An Introduction to Git Flow
|
title: Never Commit to Master - An Introduction to Git Flow
|
||||||
|
description: An introduction to and demonstation of the Git Flow braching model.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 201559e0f103013198dd5a5f6f23ab67
|
id: 201559e0f103013198dd5a5f6f23ab67
|
||||||
ratio: '1.29456384323641'
|
ratio: '1.29456384323641'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Goodbye Drush Make. Hello Composer!
|
title: Goodbye Drush Make. Hello Composer!
|
||||||
|
description: How to use Composer to manage your Drupal applications.
|
||||||
tags: ['meetup', 'drupal', 'composer']
|
tags: ['meetup', 'drupal', 'composer']
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 1c1e0e129ab34816bd4c4edb5f6642c2
|
id: 1c1e0e129ab34816bd4c4edb5f6642c2
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: It All Started With A Patch
|
title: It All Started With A Patch
|
||||||
|
description: A lightning talk on how and why to get involved with open source.
|
||||||
type: Lightning talk
|
type: Lightning talk
|
||||||
tags: [meetup, phpsw, open-source]
|
tags: [meetup, phpsw, open-source]
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Modern Drupal Development with Composer
|
title: Modern Drupal Development with Composer
|
||||||
|
description: A lightning talk on how to use Composer to manage your Drupal projects.
|
||||||
type: Lightning talk
|
type: Lightning talk
|
||||||
tags: ['meetups', 'phpsw', 'drupal', 'composer']
|
tags: ['meetups', 'phpsw', 'drupal', 'composer']
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: So, what is this Drupal thing?
|
title: So, what is this Drupal thing?
|
||||||
|
description: My first talk, where I talk about Drupal, what it is and what it can do.
|
||||||
vimeo:
|
vimeo:
|
||||||
id: 49827006
|
id: 49827006
|
||||||
tags: [meetup, drupal, unified-diff]
|
tags: [meetup, drupal, unified-diff]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Taking Flight with Tailwind CSS
|
title: Taking Flight with Tailwind CSS
|
||||||
|
description: An introduction to the utility-first approach to writing CSS with a focus on the Tailwind CSS framework.
|
||||||
type: Lightning talk
|
type: Lightning talk
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 10ca51f23560443d83b898a92929b4b3
|
id: 10ca51f23560443d83b898a92929b4b3
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: TDD - Test Driven Drupal
|
title: TDD - Test Driven Drupal
|
||||||
|
description: How to write automated tests for Drupal, and how to create a new Drupal module using test driven development.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 088cb18033064f5cb18d1079795294a1
|
id: 088cb18033064f5cb18d1079795294a1
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Test Drive Twig with Sculpin
|
title: Test Drive Twig with Sculpin
|
||||||
|
description: With Drupal 8 just around the corner, see how you can develop your Twig skills with Sculpin - a static site generator based on Symfony components and Twig.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 54589d2e50a3476a9a75aed809e9edf1
|
id: 54589d2e50a3476a9a75aed809e9edf1
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Things you should know about PHP
|
title: Things you should know about PHP
|
||||||
|
description: An introduction to PHP, presented to the Swansea Software Development Community (SSDC) meetup.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: fe360f1030f34bdb9eb14cdab907bb3c
|
id: fe360f1030f34bdb9eb14cdab907bb3c
|
||||||
ratio: '1.37081659973226'
|
ratio: '1.37081659973226'
|
||||||
|
@ -14,4 +15,4 @@ events:
|
||||||
- event: ssdc
|
- event: ssdc
|
||||||
date: 2019-01-28
|
date: 2019-01-28
|
||||||
---
|
---
|
||||||
An introduction to PHP, presented to the Swansea Software Development Community (SSDC).
|
An introduction to PHP, presented to the Swansea Software Development Community (SSDC) meetup.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
title: Using Laravel Collections... Outside Laravel
|
title: Using Laravel Collections... Outside Laravel
|
||||||
|
description: How to include and use Laravel’s Illuminate Collections in your non-Laravel PHP projects.
|
||||||
speakerdeck:
|
speakerdeck:
|
||||||
id: 76f1718a75a74940b0b028aac8b9f78b
|
id: 76f1718a75a74940b0b028aac8b9f78b
|
||||||
ratio: '1.77777777777778'
|
ratio: '1.77777777777778'
|
||||||
|
|
|
@ -6,21 +6,26 @@ meta:
|
||||||
use: [talks]
|
use: [talks]
|
||||||
talks:
|
talks:
|
||||||
- title: 'Drupal and the LDAP module'
|
- title: 'Drupal and the LDAP module'
|
||||||
|
description: A review and demonstration of some of the recent single sign-on work that I did using Drupal’s LDAP module.
|
||||||
events:
|
events:
|
||||||
- event: swdug
|
- event: swdug
|
||||||
date: 2013-07-10
|
date: 2013-07-10
|
||||||
|
|
||||||
- title: 'About the Drupal Association'
|
- title: 'About the Drupal Association'
|
||||||
|
description: An impromptu talk about what the Drupal Association is, and what work I’ve been doing since I joined the Association staff.
|
||||||
events:
|
events:
|
||||||
- event: swdug
|
- event: swdug
|
||||||
date: 2014-08-19
|
date: 2014-08-19
|
||||||
|
|
||||||
- title: 'Automated testing with Drupal 8 and PHPUnit'
|
- title: 'Automated testing with Drupal 8 and PHPUnit'
|
||||||
|
description: A workshop that I gave to teach others about automated testing in Drupal 8.
|
||||||
type: Workshop
|
type: Workshop
|
||||||
events:
|
events:
|
||||||
- event: drupal_bristol
|
- event: drupal_bristol
|
||||||
date: 2018-06-27
|
date: 2018-06-27
|
||||||
|
|
||||||
- title: 'Episode #175 - Automated Testing'
|
- title: 'Episode #175 - Automated Testing'
|
||||||
|
description: I joined the Talking Drupal team to discuss automated testing.
|
||||||
type: Podcast
|
type: Podcast
|
||||||
url: http://talkingdrupal.com/175
|
url: http://talkingdrupal.com/175
|
||||||
events:
|
events:
|
||||||
|
@ -28,29 +33,27 @@ talks:
|
||||||
date: 2018-09-05
|
date: 2018-09-05
|
||||||
---
|
---
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="mb-8">
|
<div class="spaced-y-10">
|
||||||
<p>I regularly speak at conferences and user groups about a range of subjects including PHP, Drupal, automated testing, Git and systems administration.</p>
|
<div>
|
||||||
</div>
|
<h2 class="font-extrabold mb-4">Upcoming Talks</h2>
|
||||||
|
|
||||||
<div class="mb-8">
|
<div class="spaced-y-10">
|
||||||
<h2 class="mb-2">Upcoming Talks</h2>
|
{% for talk in getUpcomingTalks(page.talks|merge(data.talks)) %}
|
||||||
|
{% include 'talks/talk' %}
|
||||||
|
{% else %}
|
||||||
|
<p>sdf</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% set upcoming_talks = getUpcomingTalks(data.talks|merge(page.talks), site.events) %}
|
<div>
|
||||||
{% if not upcoming_talks.empty %}
|
<h2 class="font-extrabold mb-4">Previous Talks</h2>
|
||||||
{% include "talks/table" with {
|
|
||||||
talks: upcoming_talks,
|
|
||||||
upcoming: true,
|
|
||||||
} %}
|
|
||||||
{% else %}
|
|
||||||
<p>Nothing scheduled at the moment.</p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div class="spaced-y-10">
|
||||||
<h2 class="mb-2">Previous Talks</h2>
|
{% for talk in getPastTalks(page.talks|merge(data.talks))|reverse %}
|
||||||
|
{% include 'talks/talk' %}
|
||||||
{% include "talks/table" with {
|
{% endfor %}
|
||||||
talks: getPastTalks(data.talks|merge(page.talks), site.events)
|
</div>
|
||||||
} %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -34,77 +34,46 @@ class TalksExtension extends Twig_Extension
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all upcoming and previous talks.
|
* Get all upcoming and previous talks.
|
||||||
*
|
*
|
||||||
* @param ProxySourceCollection|array $talks All talk nodes.
|
* @param ProxySourceCollection|array $talks All talk nodes.
|
||||||
* @param array $eventData Shared event data.
|
*
|
||||||
*
|
* @return Collection A sorted collection of talks.
|
||||||
* @return Collection A sorted collection of talks.
|
*/
|
||||||
*/
|
public function getAll($talks): Collection
|
||||||
public function getAll($talks, array $eventData = [])
|
|
||||||
{
|
{
|
||||||
return $this->format($talks, $eventData)->sortBy('event.date');
|
return collect($talks)->sortBy(function ($talk) {
|
||||||
|
return $this->getLastDate($talk);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all upcoming talks.
|
* Get all upcoming talks.
|
||||||
*
|
*
|
||||||
* @param ProxySourceCollection|array $talks All talk nodes.
|
* @param ProxySourceCollection|array $talks All talk nodes.
|
||||||
* @param array $eventData Shared event data.
|
|
||||||
*
|
*
|
||||||
* @return Collection A sorted collection of talks.
|
* @return Collection A sorted collection of talks.
|
||||||
*/
|
*/
|
||||||
public function getUpcoming($talks, array $eventData = [])
|
public function getUpcoming($talks): Collection
|
||||||
{
|
{
|
||||||
return $this->format($talks, $eventData)
|
return $this->getAll($talks)->filter(function ($talk) {
|
||||||
->filter(function ($talk) {
|
return $this->getLastDate($talk) >= $this->today;
|
||||||
return $talk['event']['date'] >= $this->today;
|
})->values();
|
||||||
})
|
|
||||||
->sortBy('event.date');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all past talks.
|
* Get all past talks.
|
||||||
*
|
*
|
||||||
* @param ProxySourceCollection|array $talks All talk nodes.
|
* @param ProxySourceCollection|array $talks All talk nodes.
|
||||||
* @param array $eventData Shared event data.
|
|
||||||
*
|
*
|
||||||
* @return Collection A sorted collection of talks.
|
* @return Collection A sorted collection of talks.
|
||||||
*/
|
*/
|
||||||
public function getPast($talks, array $eventData = [])
|
public function getPast($talks): Collection
|
||||||
{
|
{
|
||||||
return $this->format($talks, $eventData)
|
return $this->getAll($talks)->filter(function ($talk) {
|
||||||
->filter(function ($talk) {
|
return $this->getLastDate($talk) < $this->today;
|
||||||
return $talk['event']['date'] < $this->today;
|
})->values();
|
||||||
})
|
|
||||||
->sortByDesc('event.date');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the talk data into the required format.
|
|
||||||
*
|
|
||||||
* @param ProxySourceCollection|array $talks All talk nodes.
|
|
||||||
* @param array $eventData Shared event data.
|
|
||||||
*
|
|
||||||
* @return Collection The combined event and talk data.
|
|
||||||
*/
|
|
||||||
public function format($talks, array $eventData)
|
|
||||||
{
|
|
||||||
$eventData = collect($eventData);
|
|
||||||
|
|
||||||
return collect($talks)->flatMap(function ($talk) use ($eventData) {
|
|
||||||
// Build an associative array with the talk, as well as the
|
|
||||||
// specified event data (e.g. date and time) as well as the shared
|
|
||||||
// event data (e.g. event name and website).
|
|
||||||
return collect($talk['events'])
|
|
||||||
->map(function ($event) use ($talk, $eventData) {
|
|
||||||
$event = collect($event);
|
|
||||||
$event = $event->merge($eventData->get($event->get('event')))->all();
|
|
||||||
|
|
||||||
return compact('event', 'talk');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,4 +83,9 @@ class TalksExtension extends Twig_Extension
|
||||||
{
|
{
|
||||||
return 'talks';
|
return 'talks';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getLastDate($talk): string
|
||||||
|
{
|
||||||
|
return (string) collect($talk['events'])->pluck('date')->sort()->last();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,177 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\FormatTalksBundle\TwigExtension;
|
|
||||||
|
|
||||||
use DateTime;
|
|
||||||
use TalksBundle\TwigExtension\TalksExtension;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class FormatTalksTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var TalksExtension
|
|
||||||
*/
|
|
||||||
private $extension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function setUp()
|
|
||||||
{
|
|
||||||
$this->extension = new TalksExtension();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function format_events()
|
|
||||||
{
|
|
||||||
$event_data = [
|
|
||||||
'event-a' => [
|
|
||||||
'name' => 'Event A',
|
|
||||||
'location' => 'Somewhere',
|
|
||||||
'website' => 'http://event-a.com',
|
|
||||||
],
|
|
||||||
'event-b' => [
|
|
||||||
'name' => 'Event B',
|
|
||||||
'location' => 'Somewhere else',
|
|
||||||
'website' => 'http://event-b.com',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$talks = [
|
|
||||||
[
|
|
||||||
'title' => 'Talk A',
|
|
||||||
'events' => [
|
|
||||||
['event' => 'event-a', 'date' => strtotime('2018-01-01'), 'time' => '09:00'],
|
|
||||||
['event' => 'event-b', 'date' => strtotime('2018-01-30'), 'time' => '12:00'],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'title' => 'Talk B',
|
|
||||||
'events' => [
|
|
||||||
['event' => 'event-b', 'date' => strtotime('2018-01-31'), 'time' => '17:00'],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$results = $this->extension->format($talks, $event_data);
|
|
||||||
|
|
||||||
$this->assertCount(3, $results);
|
|
||||||
|
|
||||||
tap($results->first(), function ($result) {
|
|
||||||
$this->assertArrayHasKey('event', $result);
|
|
||||||
$this->assertArrayHasKey('talk', $result);
|
|
||||||
|
|
||||||
$this->assertEquals([
|
|
||||||
'date' => '1514764800',
|
|
||||||
'event' => 'event-a',
|
|
||||||
'location' => 'Somewhere',
|
|
||||||
'name' => 'Event A',
|
|
||||||
'time' => '09:00',
|
|
||||||
'website' => 'http://event-a.com',
|
|
||||||
], $result['event']);
|
|
||||||
|
|
||||||
$this->assertEquals('Talk A', $result['talk']['title']);
|
|
||||||
});
|
|
||||||
|
|
||||||
tap($results->get(1), function ($result) {
|
|
||||||
$this->assertArrayHasKey('event', $result);
|
|
||||||
$this->assertArrayHasKey('talk', $result);
|
|
||||||
|
|
||||||
$this->assertEquals([
|
|
||||||
'date' => 1517270400,
|
|
||||||
'event' => 'event-b',
|
|
||||||
'location' => 'Somewhere else',
|
|
||||||
'name' => 'Event B',
|
|
||||||
'time' => '12:00',
|
|
||||||
'website' => 'http://event-b.com',
|
|
||||||
], $result['event']);
|
|
||||||
|
|
||||||
$this->assertEquals('Talk A', $result['talk']['title']);
|
|
||||||
});
|
|
||||||
|
|
||||||
tap($results[2], function ($result) {
|
|
||||||
$this->assertEquals('Talk B', $result['talk']['title']);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function get_all_events()
|
|
||||||
{
|
|
||||||
$eventA = ['date' => (new DateTime('+1 week'))->getTimestamp()];
|
|
||||||
$eventB = ['date' => (new DateTime('-2 weeks'))->getTimestamp()];
|
|
||||||
$eventC = ['date' => (new DateTime('today'))->getTimestamp()];
|
|
||||||
|
|
||||||
$talks = [
|
|
||||||
['events' => [$eventA, $eventB]],
|
|
||||||
['events' => [$eventC]],
|
|
||||||
];
|
|
||||||
|
|
||||||
$results = $this->extension->getAll($talks);
|
|
||||||
|
|
||||||
$this->assertCount(3, $results);
|
|
||||||
|
|
||||||
// Earliest events should be returned first.
|
|
||||||
$this->assertEquals(
|
|
||||||
[$eventB['date'], $eventC['date'], $eventA['date']],
|
|
||||||
$this->extractDates($results)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function get_upcoming_events()
|
|
||||||
{
|
|
||||||
$eventA = ['date' => (new DateTime('+1 week'))->getTimestamp()];
|
|
||||||
$eventB = ['date' => (new DateTime('-2 weeks'))->getTimestamp()];
|
|
||||||
$eventC = ['date' => (new DateTime('today'))->getTimestamp()];
|
|
||||||
$eventD = ['date' => (new DateTime('+1 day'))->getTimestamp()];
|
|
||||||
$eventE = ['date' => (new DateTime('+2 weeks'))->getTimestamp()];
|
|
||||||
|
|
||||||
$talks = [
|
|
||||||
['events' => [$eventA, $eventC]],
|
|
||||||
['events' => [$eventB, $eventE]],
|
|
||||||
];
|
|
||||||
|
|
||||||
$results = $this->extension->getUpcoming($talks);
|
|
||||||
|
|
||||||
$this->assertCount(3, $results);
|
|
||||||
|
|
||||||
// Earliest events should be returned first.
|
|
||||||
$this->assertEquals(
|
|
||||||
[$eventC['date'], $eventA['date'], $eventE['date']],
|
|
||||||
$this->extractDates($results)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @test */
|
|
||||||
public function get_past_events()
|
|
||||||
{
|
|
||||||
$eventA = ['date' => (new DateTime('+1 week'))->getTimestamp()];
|
|
||||||
$eventB = ['date' => (new DateTime('-2 weeks'))->getTimestamp()];
|
|
||||||
$eventC = ['date' => (new DateTime('today'))->getTimestamp()];
|
|
||||||
$eventD = ['date' => (new DateTime('+1 day'))->getTimestamp()];
|
|
||||||
$eventE = ['date' => (new DateTime('-2 days'))->getTimestamp()];
|
|
||||||
$eventF = ['date' => (new DateTime('-2 months'))->getTimestamp()];
|
|
||||||
|
|
||||||
$talks = [
|
|
||||||
['events' => [$eventD]],
|
|
||||||
['events' => [$eventA, $eventB, $eventC]],
|
|
||||||
['events' => [$eventF]],
|
|
||||||
];
|
|
||||||
|
|
||||||
$results = $this->extension->getPast($talks);
|
|
||||||
|
|
||||||
$this->assertCount(2, $results);
|
|
||||||
|
|
||||||
// Latest events should be returned first.
|
|
||||||
$this->assertEquals(
|
|
||||||
[$eventB['date'], $eventF['date']],
|
|
||||||
$this->extractDates($results)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function extractDates(Collection $results)
|
|
||||||
{
|
|
||||||
return $results->pluck('event.date')->all();
|
|
||||||
}
|
|
||||||
}
|
|
144
tests/TalksBundle/TwigExtension/TalksExtensionTest.php
Normal file
144
tests/TalksBundle/TwigExtension/TalksExtensionTest.php
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\FormatTalksBundle\TwigExtension;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use TalksBundle\TwigExtension\TalksExtension;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class TalksExtensionTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TalksExtension
|
||||||
|
*/
|
||||||
|
private $extension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->extension = new TalksExtension();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function talks_given_multiple_times_are_only_returned_once()
|
||||||
|
{
|
||||||
|
$talkA = [
|
||||||
|
'title' => 'Talk A',
|
||||||
|
'events' => [
|
||||||
|
['event' => 'event_a', 'date' => (new DateTime('-1 days'))->getTimestamp()],
|
||||||
|
['event' => 'event_b', 'date' => (new DateTime('+1 days'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$talkB = [
|
||||||
|
'title' => 'Talk B',
|
||||||
|
'events' => [
|
||||||
|
['event' => 'event_a', 'date' => (new DateTime('-3 days'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertCount(2, $this->extension->getAll([$talkA, $talkB]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function talks_are_ordered_by_the_most_recent_event_date()
|
||||||
|
{
|
||||||
|
$talkA = [
|
||||||
|
'title' => 'Talk A',
|
||||||
|
'events' => [
|
||||||
|
['event' => 'event_a', 'date' => (new DateTime('-5 days'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$talkB = [
|
||||||
|
'title' => 'Talk B',
|
||||||
|
'events' => [
|
||||||
|
['event' => 'event_a', 'date' => (new DateTime('-20 days'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$talkC = [
|
||||||
|
'title' => 'Talk C',
|
||||||
|
'events' => [
|
||||||
|
['event' => 'event_a', 'date' => (new DateTime('-3 days'))->getTimestamp()],
|
||||||
|
['event' => 'event_b', 'date' => (new DateTime('-10 days'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$unorderedTalks = [$talkC, $talkA, $talkB];
|
||||||
|
$orderedTalks = $this->extension->getAll($unorderedTalks);
|
||||||
|
|
||||||
|
$this->assertEquals([$talkC, $talkA, $talkB], $orderedTalks->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function only_past_talks_can_be_retrieved()
|
||||||
|
{
|
||||||
|
$pastTalk = [
|
||||||
|
'title' => 'Past talk',
|
||||||
|
'events' => [
|
||||||
|
['date' => (new DateTime('-1 day'))->getTimestamp()],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$futureTalk = [
|
||||||
|
'title' => 'Future talk',
|
||||||
|
'events' => [
|
||||||
|
['date' => (new DateTime('+1 day'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $this->extension->getPast([$pastTalk, $futureTalk]);
|
||||||
|
|
||||||
|
$this->assertCount(1, $result);
|
||||||
|
$this->assertSame($pastTalk, $result->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function only_current_and_future_talks_can_be_retrieved()
|
||||||
|
{
|
||||||
|
$pastTalk = [
|
||||||
|
'title' => 'Past talk',
|
||||||
|
'events' => [
|
||||||
|
['date' => (new DateTime('-1 day'))->getTimestamp()],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$todayTalk = [
|
||||||
|
'title' => 'A talk that it happening today',
|
||||||
|
'events' => [
|
||||||
|
['date' => (new DateTime('now'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$futureTalk = [
|
||||||
|
'title' => 'Future talk',
|
||||||
|
'events' => [
|
||||||
|
['date' => (new DateTime('+1 day'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $this->extension->getUpcoming([$pastTalk, $todayTalk, $futureTalk]);
|
||||||
|
|
||||||
|
$this->assertCount(2, $result);
|
||||||
|
$this->assertSame([$todayTalk, $futureTalk], $result->toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function if_a_talk_is_both_upcoming_and_past_then_it_is_only_shown_as_upcoming()
|
||||||
|
{
|
||||||
|
$talk = [
|
||||||
|
'title' => 'An upcoming talk that has been given before',
|
||||||
|
'events' => [
|
||||||
|
['date' => (new DateTime('-1 week'))->getTimestamp()],
|
||||||
|
['date' => (new DateTime('+1 week'))->getTimestamp()],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertCount(1, $this->extension->getUpcoming([$talk]));
|
||||||
|
$this->assertEmpty($this->extension->getPast([$talk]));
|
||||||
|
}
|
||||||
|
}
|
|
@ -6550,10 +6550,9 @@ tailwindcss-skip-link@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/tailwindcss-skip-link/-/tailwindcss-skip-link-1.0.1.tgz#b965624ed0b007ddd33f0326f2719d9a88b857c7"
|
resolved "https://registry.yarnpkg.com/tailwindcss-skip-link/-/tailwindcss-skip-link-1.0.1.tgz#b965624ed0b007ddd33f0326f2719d9a88b857c7"
|
||||||
integrity sha512-Hxivkqu7UEluZY+ZPv+aQv4dreqTfYRgniEtux4qb9yJPjyR4dXiHMIWk7LgNqsyCPKpoRL8FJq55uIQN4ms+w==
|
integrity sha512-Hxivkqu7UEluZY+ZPv+aQv4dreqTfYRgniEtux4qb9yJPjyR4dXiHMIWk7LgNqsyCPKpoRL8FJq55uIQN4ms+w==
|
||||||
|
|
||||||
tailwindcss-spaced-items@^0.1.0:
|
"tailwindcss-spaced-items@https://github.com/n1kk/tailwindcss-spaced-items#master":
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/tailwindcss-spaced-items/-/tailwindcss-spaced-items-0.1.0.tgz#e7f381e5c780a034bcdbc38a6a2cfb31f828a020"
|
resolved "https://github.com/n1kk/tailwindcss-spaced-items#00aeaa1b37b6a6c2614b1f656bd9120b3839a089"
|
||||||
integrity sha512-YiT1h89fp13r6I+EBM8wS1RWfsTwzHSi4BAnHoTXXQK1GQ53DUCPeFNmiksYSdx2aQLMdp/DTPvErqBVfTALiQ==
|
|
||||||
|
|
||||||
tailwindcss-visuallyhidden@^1.0.1:
|
tailwindcss-visuallyhidden@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
|
|
Loading…
Reference in a new issue