wip
This commit is contained in:
parent
66667bcb5b
commit
4fa5cd767d
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use FormatTalksBundle\SculpinFormatTalksBundle;
|
||||||
use Opdavies\Sculpin\Bundle\ContentGeneratorBundle\SculpinContentGeneratorBundle;
|
use Opdavies\Sculpin\Bundle\ContentGeneratorBundle\SculpinContentGeneratorBundle;
|
||||||
use Opdavies\Sculpin\Bundle\GistEmbedBundle\SculpinGistEmbedBundle;
|
use Opdavies\Sculpin\Bundle\GistEmbedBundle\SculpinGistEmbedBundle;
|
||||||
use Opdavies\Sculpin\Bundle\TwigMarkdownBundle\SculpinTwigMarkdownBundle;
|
use Opdavies\Sculpin\Bundle\TwigMarkdownBundle\SculpinTwigMarkdownBundle;
|
||||||
|
@ -16,6 +17,8 @@ class SculpinKernel extends AbstractKernel
|
||||||
SculpinContentGeneratorBundle::class,
|
SculpinContentGeneratorBundle::class,
|
||||||
SculpinGistEmbedBundle::class,
|
SculpinGistEmbedBundle::class,
|
||||||
SculpinTwigMarkdownBundle::class,
|
SculpinTwigMarkdownBundle::class,
|
||||||
|
|
||||||
|
SculpinFormatTalksBundle::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
sculpin:
|
|
||||||
ignore: ['**/.DS*', '**/*.swp']
|
|
||||||
|
|
||||||
sculpin_content_types:
|
sculpin_content_types:
|
||||||
posts:
|
posts:
|
||||||
permalink: blog/:slug_title/
|
permalink: blog/:year/:month/:day/:slug_title/
|
||||||
taxonomies: [tags]
|
taxonomies: [tags]
|
||||||
talks:
|
talks:
|
||||||
permalink: talks/:basename/
|
permalink: talks/:basename/
|
||||||
|
|
|
@ -6,17 +6,22 @@ fuzzy_date_format: F Y
|
||||||
apple_touch_icon_sizes: [ 57, 114, 72, 144, 60, 120, 76, 152 ]
|
apple_touch_icon_sizes: [ 57, 114, 72, 144, 60, 120, 76, 152 ]
|
||||||
favicon_sizes: [ 160, 96, 32, 16 ]
|
favicon_sizes: [ 160, 96, 32, 16 ]
|
||||||
|
|
||||||
|
nav_links:
|
||||||
|
- { title: About, href: '/', pattern: '/\.' }
|
||||||
|
- { title: Experience, href: '/experience' }
|
||||||
|
- { title: Talks, href: '/talks' }
|
||||||
|
- { title: Blog, href: '/blog' }
|
||||||
|
- { title: Contact, href: '/contact' }
|
||||||
|
|
||||||
ansible_galaxy:
|
ansible_galaxy:
|
||||||
url: https://galaxy.ansible.com/opdavies
|
url: https://galaxy.ansible.com/opdavies
|
||||||
|
|
||||||
author: Oliver Davies
|
|
||||||
|
|
||||||
availability:
|
availability:
|
||||||
part: no
|
part: no
|
||||||
full: no
|
full: no
|
||||||
|
|
||||||
avatar:
|
avatar:
|
||||||
url: /build/static/images/me-precedent.jpg
|
url: /assets/images/me-precedent.jpg
|
||||||
|
|
||||||
drupalorg:
|
drupalorg:
|
||||||
name: opdavies
|
name: opdavies
|
||||||
|
@ -27,7 +32,7 @@ drupalorg:
|
||||||
email: oliver+website@oliverdavies.uk
|
email: oliver+website@oliverdavies.uk
|
||||||
|
|
||||||
favicon:
|
favicon:
|
||||||
url: /build/static/images/me-phpnw.png
|
url: /assets/images/me-phpnw.png
|
||||||
|
|
||||||
github:
|
github:
|
||||||
name: opdavies
|
name: opdavies
|
||||||
|
@ -105,7 +110,6 @@ companies:
|
||||||
name: Microserve
|
name: Microserve
|
||||||
logo: microserve.png
|
logo: microserve.png
|
||||||
url: https://microserve.io
|
url: https://microserve.io
|
||||||
github: https://github.com/microserve-io
|
|
||||||
|
|
||||||
nomensa:
|
nomensa:
|
||||||
name: Nomensa
|
name: Nomensa
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
imports:
|
imports:
|
||||||
- sculpin_site.yml
|
- sculpin_site.yml
|
||||||
url: https://www.oliverdavi.es
|
url: https://www.oliverdavies.uk
|
||||||
images_url: //www.oliverdavi.es
|
images_url: //www.oliverdavies.uk
|
||||||
short_url: oliverdavi.es
|
short_url: oliverdavies.uk
|
||||||
google_analytics_tracking_id: UA-11967257-1
|
google_analytics_tracking_id: UA-11967257-1
|
||||||
|
|
|
@ -20,5 +20,23 @@
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"FormatTalksBundle\\": "src/FormatTalksBundle"
|
||||||
|
},
|
||||||
|
"files": ["src/helpers.php"]
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Tests\\": "tests"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"merge-plugin": {
|
||||||
|
"include": [
|
||||||
|
"src/*/composer.json"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
98
composer.lock
generated
98
composer.lock
generated
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"_readme": [
|
"_readme": [
|
||||||
"This file locks the dependencies of your project to a known state",
|
"This file locks the dependencies of your project to a known state",
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "64706bd116a4c0a0f4483034b6e965fd",
|
"content-hash": "077bd67921b19ca9f0e2dbb0b3389f85",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/ca-bundle",
|
"name": "composer/ca-bundle",
|
||||||
|
@ -2419,6 +2419,53 @@
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2017-06-01T20:52:29+00:00"
|
"time": "2017-06-01T20:52:29+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "tightenco/collect",
|
||||||
|
"version": "v5.4.33",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/tightenco/collect.git",
|
||||||
|
"reference": "73aa38b20d932f5e8f8ccf721e4c27f4304783d6"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/tightenco/collect/zipball/73aa38b20d932f5e8f8ccf721e4c27f4304783d6",
|
||||||
|
"reference": "73aa38b20d932f5e8f8ccf721e4c27f4304783d6",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.6.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^0.9.7",
|
||||||
|
"phpunit/phpunit": "^5.7"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/Illuminate/Support/helpers.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Illuminate\\": "src/Illuminate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Taylor Otwell",
|
||||||
|
"email": "taylorotwell@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Collect - Illuminate Collections as a separate package.",
|
||||||
|
"keywords": [
|
||||||
|
"collection",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"time": "2017-08-14T20:47:19+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tsphethean/sculpin-related-posts-bundle",
|
"name": "tsphethean/sculpin-related-posts-bundle",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
@ -4083,53 +4130,6 @@
|
||||||
"homepage": "https://github.com/sebastianbergmann/version",
|
"homepage": "https://github.com/sebastianbergmann/version",
|
||||||
"time": "2016-10-03T07:35:21+00:00"
|
"time": "2016-10-03T07:35:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "tightenco/collect",
|
|
||||||
"version": "v5.4.33",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/tightenco/collect.git",
|
|
||||||
"reference": "73aa38b20d932f5e8f8ccf721e4c27f4304783d6"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/tightenco/collect/zipball/73aa38b20d932f5e8f8ccf721e4c27f4304783d6",
|
|
||||||
"reference": "73aa38b20d932f5e8f8ccf721e4c27f4304783d6",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.6.4"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"mockery/mockery": "^0.9.7",
|
|
||||||
"phpunit/phpunit": "^5.7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/Illuminate/Support/helpers.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"Illuminate\\": "src/Illuminate"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Taylor Otwell",
|
|
||||||
"email": "taylorotwell@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Collect - Illuminate Collections as a separate package.",
|
|
||||||
"keywords": [
|
|
||||||
"collection",
|
|
||||||
"laravel"
|
|
||||||
],
|
|
||||||
"time": "2017-08-14T20:47:19+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
|
|
59
source/_includes/talks-table-row.html.twig
Normal file
59
source/_includes/talks-table-row.html.twig
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ row.event.date|date(row.event.fuzzy_date ? 'F Y' : 'j F Y') }}
|
||||||
|
|
||||||
|
{% if row.event.time is defined %}
|
||||||
|
<div class="text-xs text-grey-dark">
|
||||||
|
{{ row.event.time }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{% if not talk_page %}
|
||||||
|
<td>
|
||||||
|
{% if row.talk.url is not empty %}
|
||||||
|
<a href="{{ row.talk.url }}">
|
||||||
|
{{ row.talk.title }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{{ row.talk.title }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="text-xs text-grey-dark">
|
||||||
|
{% if row.talk.type %}
|
||||||
|
{{ row.talk.type }}
|
||||||
|
{% else %}
|
||||||
|
{{ row.event.type|default('Talk') }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{% if row.event.website is not empty %}
|
||||||
|
<a href="{{ row.event.website }}">
|
||||||
|
{{ row.event.name }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{{ row.event.name }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if row.event.location is defined %}
|
||||||
|
<div class="text-xs text-grey-dark">
|
||||||
|
{{ row.event.location }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{% if not upcoming %}
|
||||||
|
<td>
|
||||||
|
{% if row.event.feedback and row.event.date <= today %}
|
||||||
|
<a href="{{ row.event.feedback }}"
|
||||||
|
class="button"
|
||||||
|
title="Read or leave feedback for this talk">
|
||||||
|
<i class="fa fa-comment-o"></i> joind.in
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
26
source/_includes/talks-table.html.twig
Normal file
26
source/_includes/talks-table.html.twig
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-1/4">Date</th>
|
||||||
|
|
||||||
|
{% if not talk_page %}
|
||||||
|
<th class="w-1/3">Talk</th>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<th>Event</th>
|
||||||
|
|
||||||
|
{% if not upcoming %}
|
||||||
|
<th>Feedback</th>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for row in talks %}
|
||||||
|
{% include "talks-table-row" with {
|
||||||
|
today: 'today'|date('Y-m-d')
|
||||||
|
} %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
23
source/_talks/building-static-websites-sculpin.md
Normal file
23
source/_talks/building-static-websites-sculpin.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
title: Building Static Websites with Sculpin
|
||||||
|
type: Lightning talk
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/building-static-websites-with-sculpin
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="6c9c4be1a1344f1291ff13a391674a66" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
code: https://github.com/opdavies/sculpin-demo
|
||||||
|
tags: [meetups, phpsw, sculpin]
|
||||||
|
tweets: yes
|
||||||
|
video:
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/aN53arCKZAU" frameborder="0" allowfullscreen></iframe>
|
||||||
|
url: https://www.youtube.com/watch?v=aN53arCKZAU
|
||||||
|
events:
|
||||||
|
- { event: phpsw, date: '2015-10-14', feedback: https://joind.in/talk/view/15486 }
|
||||||
|
---
|
||||||
|
[Sculpin][0] is a static site generator written in PHP. It converts Markdown files, Twig templates and standard HTML into a static HTML site that can be easily deployed.
|
||||||
|
|
||||||
|
This talk will cover a little of the background to Sculpin and what it is, and then will move into some demonstrations of how to build a Sculpin site and what it can do!
|
||||||
|
|
||||||
|
You can [view the full slides][1], including the embedded videos.
|
||||||
|
|
||||||
|
[0]: http://sculpin.io
|
||||||
|
[1]: https://opdavies.github.io/slides-phpsw-sculpin
|
25
source/_talks/dancing-for-drupal.md
Normal file
25
source/_talks/dancing-for-drupal.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
title: Dancing for Drupal
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/umbristol-dancing-for-drupal
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="ffa9b6dea6dc4a8eb207b9982ed6e1bd" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
tags: [meetup, umbristol, drupal]
|
||||||
|
tweets: yes
|
||||||
|
events:
|
||||||
|
- { event: umbristol, date: '2015-08-25' }
|
||||||
|
---
|
||||||
|
As part of their [CMS Dance-Off][1], I was selected to speak about Drupal alongside other speakers representing Umbraco, Sitecore and Episerver.
|
||||||
|
|
||||||
|
The points to cover were:
|
||||||
|
|
||||||
|
* How does your CMS store configuration data, 'structure' and content?
|
||||||
|
* How do you manage source-control, versioning and deployment?
|
||||||
|
* How do you manage multiple simultaneous editors and/or developers?
|
||||||
|
* How do you manage upgrades?
|
||||||
|
* What are the 3 best things about your CMS?
|
||||||
|
* What are the 3 worst things about your CMS?
|
||||||
|
* What does the future of your CMS look like?
|
||||||
|
|
||||||
|
In each point, tried to cover the differences between Drupal core and developing a project using Drupal, as well as between Drupal 7 and Drupal 8, as things like source control and versioning would be approached differently.
|
||||||
|
|
||||||
|
[1]: http://www.meetup.com/umBristol/events/223807592
|
27
source/_talks/deploying-drupal-fabric.md
Normal file
27
source/_talks/deploying-drupal-fabric.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
title: 'Deploying Drupal with Fabric'
|
||||||
|
type: Talk
|
||||||
|
slides:
|
||||||
|
url: 'https://speakerdeck.com/opdavies/deploying-drupal-and-anything-else-with-fabric'
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="40d1eca4bd484afc86295924fff5dd41" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
video:
|
||||||
|
embed: ~
|
||||||
|
url: ~
|
||||||
|
tags: [meetup, conference, php, fabric, drupal]
|
||||||
|
meta:
|
||||||
|
og:
|
||||||
|
title: Deploying Drupal with Fabric
|
||||||
|
description: "You've built your Drupal site, now learn how to deploy it with Fabric."
|
||||||
|
type: website
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-dublin-17, date: '2017-10-20', time: '15:00 - 15:40' }
|
||||||
|
- { event: drupal-somerset, date: '2017-10-26' }
|
||||||
|
- { event: drupalcamp-london-18, date: '2018-03-03', time: '14:00 - 14:45' }
|
||||||
|
---
|
||||||
|
You’ve built your website, and now you just need to deploy it. There are various ways that this could be done - from (S)FTP, to SCP and rsync, to running commands like “git pull” and “composer install” directly on the server (not recommended).
|
||||||
|
|
||||||
|
My favourite deployment tool of late is [Fabric][1] - a Python based command line tool for running commands locally as well as on remote servers. It’s language and framework agnostic, and unopinionated so you define the steps and workflow that you need - from a basic few-step deployment to a full Capistrano style zero-downtime deployment.
|
||||||
|
|
||||||
|
This talk will cover some introduction to Fabric and how to write your own fabfiles, to then covering some examples and demos of different use case deployments for your Drupal project.
|
||||||
|
|
||||||
|
[1]: http://www.fabfile.org
|
31
source/_talks/deploying-php-fabric.md
Normal file
31
source/_talks/deploying-php-fabric.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
title: Deploying PHP Applications with Fabric
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/deploying-php-applications-with-fabric
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="c147618ce07546ca92f92983c52d6a41" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
# video:
|
||||||
|
# embed: '<iframe width="560" height="315" src="https://www.youtube.com/embed/kM0MDUJE8ys" frameborder="0" allowfullscreen></iframe>'
|
||||||
|
# url: https://www.youtube.com/watch?v=kM0MDUJE8ys
|
||||||
|
tags: [meetup, conference, php, fabric]
|
||||||
|
meta:
|
||||||
|
og:
|
||||||
|
title: Deploying PHP Applcations with Fabric
|
||||||
|
description: "You've built your PHP application, now learn how to deploy it with Fabric."
|
||||||
|
type: website
|
||||||
|
image:
|
||||||
|
url: /assets/images/talks/deploying-php-fabric.png
|
||||||
|
width: 2560
|
||||||
|
height: 1440
|
||||||
|
type: image/png
|
||||||
|
events:
|
||||||
|
- { event: nomad-php, date: '2017-04-20', time: '19:00 (CET)', type: 'Lightning talk' }
|
||||||
|
- { event: phpsw, date: '2017-09-13', feedback: https://joind.in/talk/a5ff3 }
|
||||||
|
- { event: phpnw17, date: '2017-10-01', time: '09:00 - 09:45', feedback: https://joind.in/talk/4e35d }
|
||||||
|
---
|
||||||
|
You’ve built your application, and now you just need to deploy it. There are various ways that this could be done – from (S)FTP, to SCP and rsync, to running commands like “git pull” and “composer install” directly on the server (not recommended).
|
||||||
|
|
||||||
|
My favourite deployment tool of late is [Fabric][1] – a Python based command line tool for running commands locally as well as on remote servers. It’s language and framework agnostic, and unopinionated so you define the steps and workflow that you need – from a basic few-step deployment to a full Capistrano style zero-downtime deployment.
|
||||||
|
|
||||||
|
This talk will cover some introduction to Fabric and how to write your own fabfiles, and then look at some examples of different use case deployments for your PHP project.
|
||||||
|
|
||||||
|
[1]: http://www.fabfile.org
|
36
source/_talks/drupal-8-module-development.md
Normal file
36
source/_talks/drupal-8-module-development.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
title: Getting Started with Drupal 8 Module Development
|
||||||
|
tags: [conference, php, drupal, drupalcamp, drupal-8]
|
||||||
|
tweets: yes
|
||||||
|
code: https://github.com/opdavies/dclondon16-d8-module
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/getting-started-with-drupal-8-module-development
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="0041804e52664d12a8e31cd118264813" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=qO_Wh5WE3VA
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/qO_Wh5WE3VA" frameborder="0" allowfullscreen></iframe>
|
||||||
|
meta:
|
||||||
|
og:
|
||||||
|
title: Getting Started with Drupal 8 Module Development
|
||||||
|
image:
|
||||||
|
url: /assets/images/talks/dclondon16.png
|
||||||
|
type: 'image/png'
|
||||||
|
height: 540
|
||||||
|
width: 960
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-london-16, date: '2016-03-05' }
|
||||||
|
---
|
||||||
|
New to object-orientated PHP, Symfony or YAML, and want to get started building modules in Drupal 8? This is the session for you!
|
||||||
|
|
||||||
|
In this session, we’ll cover:
|
||||||
|
|
||||||
|
* Where Drupal 8 modules are located, and how they are structured.
|
||||||
|
* How to build a simple module, including our own permissions and routes.
|
||||||
|
* How to add your own controller and service classes.
|
||||||
|
* What is the service/dependency injection container, and how do we use it?
|
||||||
|
* How we can use tools such as PhpStorm and Drupal Console to speed up the process.
|
||||||
|
|
||||||
|
What we won’t be covering:
|
||||||
|
|
||||||
|
* Automated testing in PHPUnit or Simpletest.
|
||||||
|
* Adding third party libraries and external dependencies via Composer.
|
14
source/_talks/drupal-8-rejoining-the-herd.md
Normal file
14
source/_talks/drupal-8-rejoining-the-herd.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
title: Drupal 8: Rejoining the Herd
|
||||||
|
tags: [conference, php, drupal, drupal-8]
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/drupal-rejoining-the-herd
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="440fd6592f474741bc606c96bc32c104" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
events:
|
||||||
|
- { event: phpsc16, date: '2016-06-11', feedback: https://joind.in/talk/41d0f }
|
||||||
|
---
|
||||||
|
[Drupal 8][0] was (finally) released on November 19th 2015, after almost 4 years of work and code commits by over 3,200 different contributors. Whilst it’s pretty much the same as the Drupal that we know and, hopefully, love, a lot has changed behind the scenes and under the hood!
|
||||||
|
|
||||||
|
In this talk, I'll highlight some of the new features and improvements in Drupal 8, and discuss some of the benefits to Drupal site builders, themers, and module developers. I'll also talk about some of the non-technical changes and the cultural shift from "not invented here" to "proudly found elsewhere", and how we are rejoining the PHP herd.
|
||||||
|
|
||||||
|
[0]: https://www.drupal.org/8
|
16
source/_talks/drupal-8.md
Normal file
16
source/_talks/drupal-8.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
title: Drupal 8
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/drupal-8
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="46ba4ba577d94a32b7abdade610ceb69" data-ratio="1.29456384323641" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=36zCxPrOOzM
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/36zCxPrOOzM" frameborder="0" allowfullscreen></iframe>
|
||||||
|
tags: [meetup, phpsw, drupal, drupal-8]
|
||||||
|
tweets: yes
|
||||||
|
events:
|
||||||
|
- { event: phpsw, date: '2015-04-08' }
|
||||||
|
---
|
||||||
|
This was a ten minute lightning talk, designed to highlight the major changes coming in Drupal 8.
|
||||||
|
|
||||||
|
I categorised the technical changes into groups for site builders, developers and themers, and also highlighted the cultural shift from "not invented here" to "proudly found elsewhere" and the benefits that brings.
|
18
source/_talks/drupal-vm-generator.md
Normal file
18
source/_talks/drupal-vm-generator.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
title: Drupal VM Generator
|
||||||
|
type: Lightning talk
|
||||||
|
code: https://github.com/opdavies/drupal-vm-generator
|
||||||
|
tags: [drupal-vm, drupal-vm-generator, meetup, symfony]
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/bristol-dug-drupal-vm-generator
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="a27ee1d2bfed4a209dc395fa455acb41" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
video:
|
||||||
|
url: https://youtu.be/U1pbKAAO2Wo?t=3696
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/U1pbKAAO2Wo?start=3696" frameborder="0" allowfullscreen></iframe>
|
||||||
|
events:
|
||||||
|
- { event: nwdug, date: '2016-03-08' }
|
||||||
|
- { event: drupal-bristol, date: '2016-04-02' }
|
||||||
|
---
|
||||||
|
An short talk about the [Drupal VM Generator][1] project.
|
||||||
|
|
||||||
|
[1]: https://github.com/opdavies/drupal-vm-generator
|
19
source/_talks/drupal-vm-meet-symfony-console.md
Normal file
19
source/_talks/drupal-vm-meet-symfony-console.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
title: Drupal VM, Meet Symfony Console
|
||||||
|
tags: [conference, php, drupal-vm, symfony]
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/drupal-vm-meet-symfony-console
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="56c79770f73f4e47a542a30243437c49" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
image: drupal-vm-meet-symfony-console.png
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-bristol-16, date: '2016-07-23' }
|
||||||
|
---
|
||||||
|
_TL;DR - Come and learn about Symfony Console, with examples from a real-world project._
|
||||||
|
|
||||||
|
The [Drupal VM Generator][2] is a CLI application, built on [Symfony Console][0], that generates configuration files for [Drupal VM][1] based on personal settings and user interaction.
|
||||||
|
|
||||||
|
After an introduction to Drupal VM itself and the Drupal VM Generator, we’ll jump into the code and see how Symfony Console applications are structured, how to write new commands, and how to integrate additional libraries like Guzzle, Twig and other Symfony components - whilst referencing code from the Drupal VM Generator project.
|
||||||
|
|
||||||
|
[0]: http://symfony.com/doc/current/components/console/introduction.html
|
||||||
|
[1]: https://www.drupalvm.com
|
||||||
|
[2]: https://www.drupalvmgenerator.com
|
10
source/_talks/drupalorg-2015.md
Normal file
10
source/_talks/drupalorg-2015.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
title: Drupal.org in 2015: What's Coming Next
|
||||||
|
tags: [conference, drupalcamp, drupalcamp-london, drupal-association]
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/drupal-dot-org-in-15
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="0cf8d7b647c94ae289e9db2b46a9e8f2" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-brighton-15, date: '2015-01-18' }
|
||||||
|
- { event: drupalcamp-london-15, date: '2015-02-28' }
|
||||||
|
---
|
9
source/_talks/drush-make-drupalbristol.md
Normal file
9
source/_talks/drush-make-drupalbristol.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: drush make drupalbristol
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/drush-make-drupalbristol
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="42605700f102013198de5a5f6f23ab67" data-ratio="1.29456384323641" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
tags: [meetup, drupal, drupal-bristol, drush, drush-make]
|
||||||
|
events:
|
||||||
|
- { event: drupal-bristol, date: '2014-08-19' }
|
||||||
|
---
|
29
source/_talks/getting-your-data-into-drupal-8.md
Normal file
29
source/_talks/getting-your-data-into-drupal-8.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
title: Getting (Your Data) Into Drupal 8
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/getting-your-data-into-drupal-8-drupal-bristol
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="63e5dfce996e46699e304d50e896477b" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=jtmARTuYhp8
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/jtmARTuYhp8" frameborder="0" allowfullscreen></iframe>
|
||||||
|
tags: [drupalcamp, migration, drupal-8]
|
||||||
|
meta:
|
||||||
|
og:
|
||||||
|
title: Getting (Your Data) into Drupal 8
|
||||||
|
description: "How I migrated the Drupal Bristol website onto Drupal 8."
|
||||||
|
type: website
|
||||||
|
image:
|
||||||
|
url: /assets/images/talks/getting-your-data-into-drupal-8.png
|
||||||
|
width: 2560
|
||||||
|
height: 1440
|
||||||
|
type: image/png
|
||||||
|
use: [talks]
|
||||||
|
events:
|
||||||
|
- { event: drupal-bristol, date: '2017-01-18' }
|
||||||
|
- { event: drupalcamp-london-17, date: '2017-03-04', time: '12:05 - 12:50' }
|
||||||
|
---
|
||||||
|
If you’ve moved a site from Drupal 6 to 7, the chances are that you’ve either used the upgrade path to update your old site in-place, or you built a new site from scratch and used the Migrate module from contrib to migrate your data from the old database.
|
||||||
|
|
||||||
|
In Drupal 8, things have changed as there’s no upgrade path from Drupal 7 and the Migrate module has been moved into core, though there are still migration related modules available in contrib.
|
||||||
|
|
||||||
|
This talk will look at the core Migrate module and how it implements Drupal 8 features such as YAML and the plugin and configuration systems, and how to write your own migrations to get your data into Drupal 8.
|
13
source/_talks/git-flow.md
Normal file
13
source/_talks/git-flow.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
title: Never Commit to Master - An Introduction to Git Flow
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/never-commit-to-master-an-introduction-to-git-flow
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="201559e0f103013198dd5a5f6f23ab67" data-ratio="1.29456384323641" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=T-miCpHxfds
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/T-miCpHxfds" frameborder="0" allowfullscreen></iframe>
|
||||||
|
tags: [conference, drupalcamp, drupalcamp-london, git, git-flow]
|
||||||
|
tweets: yes
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-london-14, date: '2014-03-01' }
|
||||||
|
---
|
17
source/_talks/goodbye-drush-make-hello-composer.md
Normal file
17
source/_talks/goodbye-drush-make-hello-composer.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
title: Goodbye Drush Make. Hello Composer!
|
||||||
|
tags: ['meetup', 'drupal', 'composer']
|
||||||
|
slides:
|
||||||
|
url: http://bit.ly/slides-goodbye-drush-make-hello-composer2
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="1c1e0e129ab34816bd4c4edb5f6642c2" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
events:
|
||||||
|
- { event: drupal-bristol, date: '2016-11-17' }
|
||||||
|
- { event: phpuk18, date: '2018-02-16', time: '14:40 - 15:40' }
|
||||||
|
---
|
||||||
|
One of the main outcomes of Drupal 8 was “getting off the island” with third-party code included in core and adopting modern best practices from the wider PHP ecosystem - including [Composer][1], PHP’s dependency manager.
|
||||||
|
|
||||||
|
Included to manage core’s dependencies, it has also gained traction in the contrib space with the creation of the Drupal Composer project, and the Drupal Packagist and now native endpoints on Drupal.org exposing contrib project metadata.
|
||||||
|
|
||||||
|
In this session, I'll show how to fully manage a Drupal 7 or Drupal 8 website including contributed modules and themes and external libraries with Composer.
|
||||||
|
|
||||||
|
[1]: https://getcomposer.org
|
14
source/_talks/it-all-started-with-a-patch.md
Normal file
14
source/_talks/it-all-started-with-a-patch.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
title: It All Started With A Patch
|
||||||
|
type: Lightning talk
|
||||||
|
tags: [meetup, phpsw, open-source]
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/it-all-started-with-a-patch-phpsw
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="5862bdecb7a24cfaa5fc844696fafa0c" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=5FYMRR61sdo
|
||||||
|
embed: '<iframe width="560" height="315" src="https://www.youtube.com/embed/5FYMRR61sdo" frameborder="0" allowfullscreen></iframe>'
|
||||||
|
events:
|
||||||
|
- { event: phpsw, date: '2017-02-08' }
|
||||||
|
---
|
||||||
|
A crash course of why and how to get involved with open source.
|
18
source/_talks/modern-drupal-development-with-composer.md
Normal file
18
source/_talks/modern-drupal-development-with-composer.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
title: Modern Drupal Development with Composer
|
||||||
|
type: Lightning talk
|
||||||
|
tags: ['meetups', 'phpsw', 'drupal', 'composer']
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/modern-drupal-development-with-composer
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="7a1358502526425a9cfd288f85fb32f3" data-ratio="1.37081659973226" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=Yi_FPI3xHwc
|
||||||
|
embed: '<iframe width="560" height="315" src="https://www.youtube.com/embed/Yi_FPI3xHwc" frameborder="0" allowfullscreen></iframe>'
|
||||||
|
events:
|
||||||
|
- { event: phpsw, date: '2016-11-09' }
|
||||||
|
---
|
||||||
|
Building a Drupal application? You no longer need to download archives to add new modules or update core, or deal with Drupal specific tools to manage your codebase.
|
||||||
|
|
||||||
|
With Drupal "getting off the island" there has been an increase in the adoption of common PHP tools within the Drupal ecosystem.
|
||||||
|
|
||||||
|
In this lightning talk, I’ll show how to build a Drupal application using Composer for dependency management.
|
9
source/_talks/so-what-is-this-drupal-thing.md
Normal file
9
source/_talks/so-what-is-this-drupal-thing.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
title: So, what is this Drupal thing?
|
||||||
|
video:
|
||||||
|
url: https://vimeo.com/49827006
|
||||||
|
embed: <iframe src="https://player.vimeo.com/video/49827006" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||||
|
tags: [meetup, drupal, unified-diff]
|
||||||
|
events:
|
||||||
|
- { event: unifieddiff, date: '2012-09-05' }
|
||||||
|
---
|
30
source/_talks/taking-flight-with-tailwind-css.md
Normal file
30
source/_talks/taking-flight-with-tailwind-css.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
title: Taking Flight with Tailwind CSS
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/taking-flight-with-tailwind-css
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="10ca51f23560443d83b898a92929b4b3" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
tags: [css, tailwind, meetup]
|
||||||
|
type: Lightning talk
|
||||||
|
events:
|
||||||
|
- { event: drupal-bristol, date: '2018-01-17' }
|
||||||
|
meta:
|
||||||
|
og:
|
||||||
|
title: Taking Flight with Tailwind CSS
|
||||||
|
description: An introduction to utility CSS and Tailwind.
|
||||||
|
type: website
|
||||||
|
image:
|
||||||
|
url: '/assets/images/talks/taking-flight-tailwind.png'
|
||||||
|
width: 2560
|
||||||
|
height: 1440
|
||||||
|
type: 'image/png'
|
||||||
|
---
|
||||||
|
An introduction to utility class and component based styling, and how to soar with [Tailwind CSS][1].
|
||||||
|
|
||||||
|
Things we’ll cover:
|
||||||
|
|
||||||
|
- Advantages and disadvantages to utility based styling and Tailwind.
|
||||||
|
- How to install Tailwind and add it to your build process.
|
||||||
|
- How to customise Tailwind.
|
||||||
|
- How to promote repeating classes into re-usable components.
|
||||||
|
|
||||||
|
[1]: https://tailwindcss.com
|
30
source/_talks/tdd-test-driven-drupal.md
Normal file
30
source/_talks/tdd-test-driven-drupal.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
title: TDD - Test Driven Drupal
|
||||||
|
slides:
|
||||||
|
url: 'https://speakerdeck.com/opdavies/tdd-test-driven-drupal'
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="088cb18033064f5cb18d1079795294a1" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
video:
|
||||||
|
url: https://www.youtube.com/watch?v=fdbxXOi2HP4
|
||||||
|
embed: <iframe width="560" height="315" src="https://www.youtube.com/embed/fdbxXOi2HP4" frameborder="0" allowfullscreen></iframe>
|
||||||
|
tags: [drupalcamp, simpletest, phpunit, testing]
|
||||||
|
meta:
|
||||||
|
og:
|
||||||
|
title: TDD - Test Driven Drupal
|
||||||
|
description: "How to write tests and follow TDD for Drupal applications."
|
||||||
|
type: website
|
||||||
|
image:
|
||||||
|
url: /assets/images/talks/test-driven-drupal-development.png
|
||||||
|
width: 2560
|
||||||
|
height: 1440
|
||||||
|
type: image/png
|
||||||
|
use: [talks]
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-london-17, date: '2017-03-04', time: '16:15 - 17:00' }
|
||||||
|
- { event: drupalcamp-dublin-17, date: '2017-10-21', time: '12:00 - 12:40' }
|
||||||
|
- { event: drupal-bristol, date: '2017-11-22' }
|
||||||
|
---
|
||||||
|
Testing is important. Why? It allows developers to add new features and edit and refactor existing code without the worry of adding regressions, reduces the reliance on manual testing to discover bugs, and by taking a test driven approach, your implementation code is leaner as you only write what is needed for your tests to pass.
|
||||||
|
|
||||||
|
Drupal 7 includes the SimpleTest module for unit and functional testing, whilst Drupal 8 also includes and supports PHPUnit - the defacto PHP testing framework, used by other PHP projects including Symfony and Laravel - making it easier for people to test their code. And with testing being one of the Drupal core gates with tests needing to be included with every new feature or bug fix, and core’s 100% pass rate policy, testing has become an essential skill when contributing to core, or when working on your own projects.
|
||||||
|
|
||||||
|
In this talk, we’ll cover the methodology and terminology involved with automated testing, and then take a test driven approach to creating a new Drupal module.
|
19
source/_talks/test-drive-twig-with-sculpin.md
Normal file
19
source/_talks/test-drive-twig-with-sculpin.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
title: Test Drive Twig with Sculpin
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/test-drive-twig-with-sculpin
|
||||||
|
embed: <script async class="speakerdeck-embed" data-id="54589d2e50a3476a9a75aed809e9edf1" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
|
||||||
|
code: https://github.com/opdavies/sculpin-demo
|
||||||
|
tags: [conference, drupalcamp, drupalcamp-north, sculpin, twig]
|
||||||
|
tweets: yes
|
||||||
|
events:
|
||||||
|
- { event: drupalcamp-north-15, date: '2015-07-25' }
|
||||||
|
---
|
||||||
|
[Sculpin][1] is a static site generator written in PHP, and based on [Symfony components][2]. It uses [YAML][3] and [Twig][4], which makes it very appealing to Drupal people wanting to learn these in preparation for Drupal 8.
|
||||||
|
|
||||||
|
This session covered how to install Sculpin itself, as well as how to use it to build a static site from Markdown, HTML and Twig templates. We also covered Sculpin concepts such as content types, themes and partials, and Twig layouts, blocks and inheritance, as well as some tips and tricks that I've found whilst developing with Sculpin.
|
||||||
|
|
||||||
|
[1]: https://sculpin.io
|
||||||
|
[2]: http://symfony.com/doc/current/components/index.html
|
||||||
|
[3]: http://yaml.org
|
||||||
|
[4]: http://twig.sensiolabs.org
|
14
source/_talks/using-laravel-collections-outside-laravel.md
Normal file
14
source/_talks/using-laravel-collections-outside-laravel.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
title: Using Laravel Collections... Outside Laravel
|
||||||
|
slides:
|
||||||
|
url: https://speakerdeck.com/opdavies/using-laravel-collections-dot-dot-dot-outside-laravel
|
||||||
|
embed: '<script async class="speakerdeck-embed" data-id="76f1718a75a74940b0b028aac8b9f78b" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>'
|
||||||
|
video:
|
||||||
|
url: https://youtu.be/1l0kO-iaN_o
|
||||||
|
embed: '<iframe width="560" height="315" src="https://www.youtube.com/embed/1l0kO-iaN_o" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>'
|
||||||
|
tags: [nomad-php, lightning-talk, laravel, collections]
|
||||||
|
type: Lightning talk
|
||||||
|
events:
|
||||||
|
- { event: nomad-php, date: '2017-12-21', 'time': 19:00 CET }
|
||||||
|
---
|
||||||
|
Laravel Collections are a powerful object-orientated way of interacting with PHP arrays, but did you know that they can be used outside of Laravel, in any PHP project? This short talk shows how we can use Composer to include Laravel Collections within a non-Laravel project and put them to use within your own code.
|
40
source/talks-archive.html.twig
Normal file
40
source/talks-archive.html.twig
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
layout: page
|
||||||
|
title: Talk Archive
|
||||||
|
permalink: talks/archive
|
||||||
|
use: [talks]
|
||||||
|
talks:
|
||||||
|
- title: 'Drupal and the LDAP module'
|
||||||
|
events:
|
||||||
|
- { date: '2013-07-10', event: swdug }
|
||||||
|
- title: 'About the Drupal Association'
|
||||||
|
events:
|
||||||
|
- { date: '2014-08-19', event: swdug }
|
||||||
|
---
|
||||||
|
{% block breadcrumb %}
|
||||||
|
<div class="breadcrumb border-b border-grey-lighter mb-6 -mt-6 bg-grey-lightest">
|
||||||
|
<div class="container mx-auto px-4">
|
||||||
|
<ul class="flex pl-0 mb-0">
|
||||||
|
<li class="list-reset flex items-center">
|
||||||
|
<a class="inline py-2" href="{{ site.url }}/">Home</a>
|
||||||
|
{% include "svg/chevron-right" with { class: 'text-grey-light mx-1', style: "height: 20px" } %}
|
||||||
|
</li>
|
||||||
|
<li class="list-reset flex items-center">
|
||||||
|
<a class="inline py-2" href="{{ site.url }}/talks">Talks</a>
|
||||||
|
{% include "svg/chevron-right" with { class: 'text-grey-light mx-1', style: "height: 20px" } %}
|
||||||
|
</li>
|
||||||
|
<li class="list-reset flex truncate">
|
||||||
|
<span class="inline py-2 truncate">Archive</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<p>Here are a list of my previous conference and user group talks:</p>
|
||||||
|
|
||||||
|
{% include "talks-table" with { talks: getPastTalks(data.talks, site.events) } %}
|
||||||
|
|
||||||
|
<p>Upcoming talks can be found on the <a href="{{ site.url }}/talks">talks page</a>.</p>
|
||||||
|
{% endblock %}
|
|
@ -6,21 +6,20 @@ meta:
|
||||||
use: [talks]
|
use: [talks]
|
||||||
---
|
---
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% for talk in data.talks %}
|
<p>I regularly speak at conferences and user groups about a range of subjects including Drupal, Sculpin and Git. If you would like to me to speak at your group or conference, please <a href="{{ site.url }}/contact">get in touch</a>.</p>
|
||||||
<div class="sm:flex sm:flex-row-reverse sm:-mx-2 mb-12 sm:mb-12">
|
|
||||||
<div class="sm:flex-1 sm:mx-2">
|
|
||||||
<h2>
|
|
||||||
<a href="{{ talk.url }}">
|
|
||||||
{{ talk.title }}
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div>
|
<h2>Upcoming Talks</h2>
|
||||||
{{ talk.summary|markdown }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% include 'talk/image.html.twig' %}
|
{% set upcoming_talks = getUpcomingTalks(data.talks, site.events) %}
|
||||||
</div>
|
{% if upcoming_talks %}
|
||||||
{% endfor %}
|
{% include "talks-table" with { talks: upcoming_talks, upcoming: true } %}
|
||||||
|
{% else %}
|
||||||
|
<p>Nothing scheduled at the moment.</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h2>Last 5 Talks</h2>
|
||||||
|
|
||||||
|
{% include "talks-table" with { talks: getPastTalks(data.talks, site.events)|slice(0,5) } %}
|
||||||
|
|
||||||
|
<p>All previous talks can be found in the <a href="{{ site.url }}/talks/archive">talks archive</a>.</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FormatTalksBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
||||||
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
|
||||||
|
class SculpinFormatTalksExtension extends Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
|
||||||
|
$loader->load('services.yml');
|
||||||
|
}
|
||||||
|
}
|
5
src/FormatTalksBundle/Resources/config/services.yml
Normal file
5
src/FormatTalksBundle/Resources/config/services.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
services:
|
||||||
|
twig.format_talks:
|
||||||
|
class: 'FormatTalksBundle\TwigExtension\FormatTalksExtension'
|
||||||
|
tags:
|
||||||
|
- { name: twig.extension }
|
9
src/FormatTalksBundle/SculpinFormatTalksBundle.php
Normal file
9
src/FormatTalksBundle/SculpinFormatTalksBundle.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FormatTalksBundle;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
|
||||||
|
class SculpinFormatTalksBundle extends Bundle
|
||||||
|
{
|
||||||
|
}
|
114
src/FormatTalksBundle/TwigExtension/FormatTalksExtension.php
Normal file
114
src/FormatTalksBundle/TwigExtension/FormatTalksExtension.php
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FormatTalksBundle\TwigExtension;
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Sculpin\Contrib\ProxySourceCollection\ProxySourceCollection;
|
||||||
|
use Twig_Extension;
|
||||||
|
use Twig_SimpleFunction;
|
||||||
|
|
||||||
|
class FormatTalksExtension extends Twig_Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string The current date.
|
||||||
|
*/
|
||||||
|
private $today;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->today = (new \DateTime())->format('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFunctions()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new Twig_SimpleFunction('getAllTalks', [$this, 'getAll']),
|
||||||
|
new Twig_SimpleFunction('getUpcomingTalks', [$this, 'getUpcoming']),
|
||||||
|
new Twig_SimpleFunction('getPastTalks', [$this, 'getPast']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all upcoming and previous talks.
|
||||||
|
*
|
||||||
|
* @param ProxySourceCollection|array $talks All talk nodes.
|
||||||
|
* @param array $eventData Shared event data.
|
||||||
|
*
|
||||||
|
* @return Collection A sorted collection of talks.
|
||||||
|
*/
|
||||||
|
public function getAll($talks, array $eventData = [])
|
||||||
|
{
|
||||||
|
return $this->format($talks, $eventData)->sortBy('event.date');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all upcoming talks.
|
||||||
|
*
|
||||||
|
* @param ProxySourceCollection|array $talks All talk nodes.
|
||||||
|
* @param array $eventData Shared event data.
|
||||||
|
*
|
||||||
|
* @return Collection A sorted collection of talks.
|
||||||
|
*/
|
||||||
|
public function getUpcoming($talks, array $eventData = [])
|
||||||
|
{
|
||||||
|
return $this->format($talks, $eventData)
|
||||||
|
->filter(function ($talk) {
|
||||||
|
return $talk['event']['date'] >= $this->today;
|
||||||
|
})
|
||||||
|
->sortBy('event.date');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all past talks.
|
||||||
|
*
|
||||||
|
* @param ProxySourceCollection|array $talks All talk nodes.
|
||||||
|
* @param array $eventData Shared event data.
|
||||||
|
*
|
||||||
|
* @return Collection A sorted collection of talks.
|
||||||
|
*/
|
||||||
|
public function getPast($talks, array $eventData = [])
|
||||||
|
{
|
||||||
|
return $this->format($talks, $eventData)
|
||||||
|
->filter(function ($talk) {
|
||||||
|
return $talk['event']['date'] < $this->today;
|
||||||
|
})
|
||||||
|
->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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'format_talks';
|
||||||
|
}
|
||||||
|
}
|
5
src/FormatTalksBundle/composer.json
Normal file
5
src/FormatTalksBundle/composer.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"tightenco/collect": "^5.4"
|
||||||
|
}
|
||||||
|
}
|
8
src/helpers.php
Normal file
8
src/helpers.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function tap($value, $callback)
|
||||||
|
{
|
||||||
|
$callback($value);
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
192
tests/FormatTalksBundle/TwigExtension/FormatTalksTest.php
Normal file
192
tests/FormatTalksBundle/TwigExtension/FormatTalksTest.php
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\FormatTalksBundle\TwigExtension;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use FormatTalksBundle\TwigExtension\FormatTalksExtension;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class FormatTalksTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var FormatTalksExtension
|
||||||
|
*/
|
||||||
|
private $extension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->extension = new FormatTalksExtension();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers FormatTalksExtension::format()
|
||||||
|
*/
|
||||||
|
public function testFormat()
|
||||||
|
{
|
||||||
|
$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' => '2018-01-01', 'time' => '09:00'],
|
||||||
|
['event' => 'event-b', 'date' => '2018-01-30', 'time' => '12:00'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => 'Talk B',
|
||||||
|
'events' => [
|
||||||
|
['event' => 'event-b', 'date' => '2018-01-31', 'time' => '17:00'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$results = $this->extension->format($talks, $event_data)->all();
|
||||||
|
|
||||||
|
$this->assertCount(3, $results);
|
||||||
|
|
||||||
|
tap($results[0], function ($result) {
|
||||||
|
$this->assertArrayHasKey('event', $result);
|
||||||
|
$this->assertArrayHasKey('talk', $result);
|
||||||
|
|
||||||
|
$this->assertEquals([
|
||||||
|
'date' => '2018-01-01',
|
||||||
|
'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[1], function ($result) {
|
||||||
|
$this->assertArrayHasKey('event', $result);
|
||||||
|
$this->assertArrayHasKey('talk', $result);
|
||||||
|
|
||||||
|
$this->assertEquals([
|
||||||
|
'date' => '2018-01-30',
|
||||||
|
'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']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers FormatTalksExtension::getAll()
|
||||||
|
*/
|
||||||
|
public function testGetAll()
|
||||||
|
{
|
||||||
|
$eventA = ['date' => (new DateTime('+1 week'))->format('Y-m-d')];
|
||||||
|
$eventB = ['date' => (new DateTime('-2 weeks'))->format('Y-m-d')];
|
||||||
|
$eventC = ['date' => (new DateTime('today'))->format('Y-m-d')];
|
||||||
|
|
||||||
|
$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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers FormatTalksExtension::getUpcoming()
|
||||||
|
*/
|
||||||
|
public function testGetUpcoming()
|
||||||
|
{
|
||||||
|
$eventA = ['date' => (new DateTime('+1 week'))->format('Y-m-d')];
|
||||||
|
$eventB = ['date' => (new DateTime('-2 weeks'))->format('Y-m-d')];
|
||||||
|
$eventC = ['date' => (new DateTime('today'))->format('Y-m-d')];
|
||||||
|
$eventD = ['date' => (new DateTime('+1 day'))->format('Y-m-d')];
|
||||||
|
$eventE = ['date' => (new DateTime('+2 weeks'))->format('Y-m-d')];
|
||||||
|
|
||||||
|
$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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers FormatTalksExtension::getPast()
|
||||||
|
*/
|
||||||
|
public function testGetPast()
|
||||||
|
{
|
||||||
|
$eventA = ['date' => (new DateTime('+1 week'))->format('Y-m-d')];
|
||||||
|
$eventB = ['date' => (new DateTime('-2 weeks'))->format('Y-m-d')];
|
||||||
|
$eventC = ['date' => (new DateTime('today'))->format('Y-m-d')];
|
||||||
|
$eventD = ['date' => (new DateTime('+1 day'))->format('Y-m-d')];
|
||||||
|
$eventE = ['date' => (new DateTime('-2 days'))->format('Y-m-d')];
|
||||||
|
$eventF = ['date' => (new DateTime('-2 months'))->format('Y-m-d')];
|
||||||
|
|
||||||
|
$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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the returned dates from the results.
|
||||||
|
*
|
||||||
|
* @param Collection $results The results returned from the filter.
|
||||||
|
*
|
||||||
|
* @return array An array of dates.
|
||||||
|
*/
|
||||||
|
private function extractDates(Collection $results)
|
||||||
|
{
|
||||||
|
return $results->pluck('event.date')->all();
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue