Skip to content
This repository has been archived by the owner on May 11, 2020. It is now read-only.

Talk videos #72

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app/config/website_generator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ services:
tags:
- {name: "TwigExtension"}

app.websiteGenerator.twigExtension.youTubeEmbedUrl:
class: \Phpsw\Website\WebsiteGenerator\TemplateRenderer\TwigExtension\YouTubeEmbedUrlExtension
autowire: true
tags:
- {name: "TwigExtension"}

app.websiteGenerator.twigExtension.slidesEmbed:
class: \Phpsw\Website\WebsiteGenerator\TemplateRenderer\TwigExtension\SlidesEmbedExtension
autowire: true
tags:
- {name: "TwigExtension"}


# Register content type generators
app.websiteGenerator.contentTypeGenerator.events:
Expand Down
5 changes: 5 additions & 0 deletions app/resources/views/partials/talk/joindin.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if talk.joindinUrl %}
<div class="text-right">
<a href="{{ talk.joindinUrl }}" class="button bg-orange hover:bg-orange-dark">Leave feedback on Joind.in</a>
</div>
{% endif %}
30 changes: 30 additions & 0 deletions app/resources/views/partials/talk/resources.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% if talk.videoUrl or talk.slidesUrl %}
<div class="-mx-4 md:flex">
{% if talk.videoUrl %}
<div class="px-4 pb-6 md:w-2/3 md:pb-0">
<div class="mb-6">
<div class="w-full relative" style="padding-bottom:56.25%">
<iframe id="ytplayer" type="text/html" class="absolute w-full h-full"
src="{{ youTubeEmbedUrl(talk) }}?autoplay=0&origin=https://phpsw.uk&rel=0&showinfo=0"
frameborder="0" scrolling="no" allowfullscreen="" mozallowfullscreen="" webkitallowfullscreen=""></iframe>
<a href="{{ talk.videoUrl }}" class="block mb-1">
<svg class="fill-current w-4 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.26 13a2 2 0 0 1 .01-2.01A3 3 0 0 0 9 5H5a3 3 0 0 0 0 6h.08a6.06 6.06 0 0 0 0 2H5A5 5 0 0 1 5 3h4a5 5 0 0 1 .26 10zm1.48-6a2 2 0 0 1-.01 2.01A3 3 0 0 0 11 15h4a3 3 0 0 0 0-6h-.08a6.06 6.06 0 0 0 0-2H15a5 5 0 0 1 0 10h-4a5 5 0 0 1-.26-10z"></path></svg>
View on YouTube
</a>
</div>
</div>
</div>
{% if talk.slidesUrl %}
<div class="px-4 md:w-1/3">
{{ embedSlides(talk) }}
{{ slidesLink(talk) }}
</div>
{% endif %}
{% elseif talk.slidesUrl %}
<div class="px-4 pb-6 md:w-2/3 md:pb-0">
{{ embedSlides(talk) }}
{{ slidesLink(talk) }}
</div>
{% endif %}
</div>
{% endif %}
11 changes: 11 additions & 0 deletions app/resources/views/talk.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
<div class="-mx-4 md:flex">
<div class="px-4 pb-6 md:w-2/3 md:pb-0">
{% include 'partials/talk/title.html.twig' %}
</div>

<div class="px-4 md:w-1/3">
{% include 'partials/talk/joindin.html.twig' %}
</div>
</div>

{% include 'partials/talk/resources.html.twig' %}

<div class="-mx-4 md:flex">
<div class="px-4 pb-6 md:w-2/3 md:pb-0">
{% include 'partials/talk/abstract.html.twig' %}
{% include 'partials/talk/speakers.html.twig' %}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Phpsw\Website\WebsiteGenerator\TemplateRenderer\TwigExtension;

use Phpsw\Website\Entity\Talk;
use Twig_Extension;
use Twig_SimpleFunction;

class SlidesEmbedExtension extends Twig_Extension
{
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new Twig_SimpleFunction('embedSlides', [$this, 'getSlidesEmbed'], ['is_safe' => ['html']]),
new Twig_SimpleFunction('slidesLink', [$this, 'getSlidesLink'], ['is_safe' => ['html']]),
];
}

/**
* Returns the string to embed the slides.
*
* How we embed them will differ depending on the source
*
* @param Talk $talk
*
* @return string
*/
public function getSlidesEmbed(Talk $talk): string
{
$iFrameUrl = '';
$embedString = '';

if ('.pdf' == substr($talk->getSlidesUrl(), -4)) {
// PDFs can be embedded via an iFrame
$iFrameUrl = "https://mozilla.github.io/pdf.js/web/viewer.html?file={$talk->getSlidesUrl()}#zoom=page-fit";
} elseif (strpos($talk->getSlidesUrl(), 'slideshare')) {
// We use embedly to embed slideshare
$embedString = '<blockquote class="embedly-card"><h4><a href="'.$talk->getSlidesUrl().'">'.$talk->getTitle().'</a></h4></blockquote><script async src="//cdn.embedly.com/widgets/platform.js" charset="UTF-8"></script>';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want markup like this within PHP code? Or should it be split into different Twig partials or something else? Just seems a little weird.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I've only done 3 so far, but we could end up with about 7 or so different embed/sharing approaches which all subtly different html to render.
I wasn't completely convinced about putting the logic to determine which one we should use within the templates, but I'm open for suggestions.

} else {
$iFrameUrl = $talk->getSlidesUrl();
}

// If we have an iFrame URL, the embeddable should be an iFrame
if ($iFrameUrl) {
$embedString = "<iframe class=\"w-full\" style=\"height:300px\" src=\"$iFrameUrl\" frameborder=\"0\" allowfullscreen mozallowfullscreen webkitallowfullscreen></iframe>";
}

return $embedString;
}

public function getSlidesLink(Talk $talk): string
{
if ('.pdf' == substr($talk->getSlidesUrl(), -4)) {
return '<a href="'.$talk->getSlidesUrl().'" class="block mb-1" target="_blank">
<svg class="fill-current w-4 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M4,18 L4,2 L12,2 L12,6 L16,6 L16,18 L4,18 Z M2,19 L2,0 L3,0 L12,0 L14,0 L18,4 L18,6 L18,20 L17,20 L2,20 L2,19 Z" id="Combined-Shape"></path></svg>
View PDF
</a>';
} else {
return '<a href="'.$talk->getSlidesUrl().'" class="block mb-1" target="_blank">
<svg class="fill-current w-4 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.26 13a2 2 0 0 1 .01-2.01A3 3 0 0 0 9 5H5a3 3 0 0 0 0 6h.08a6.06 6.06 0 0 0 0 2H5A5 5 0 0 1 5 3h4a5 5 0 0 1 .26 10zm1.48-6a2 2 0 0 1-.01 2.01A3 3 0 0 0 11 15h4a3 3 0 0 0 0-6h-.08a6.06 6.06 0 0 0 0-2H15a5 5 0 0 1 0 10h-4a5 5 0 0 1-.26-10z"></path></svg>
View Slides
</a>';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Phpsw\Website\WebsiteGenerator\TemplateRenderer\TwigExtension;

use Phpsw\Website\Entity\Talk;
use Twig_Extension;
use Twig_SimpleFunction;

class YouTubeEmbedUrlExtension extends Twig_Extension
{
/**
* {@inheritdoc}
*/
public function getFunctions()
{
return [
new Twig_SimpleFunction('youTubeEmbedUrl', [$this, 'getYouTubeEmbedUrl']),
];
}

/**
* Returns the URL which can be used for a YouTube iFrame embed.
*
* @param Talk $talk
*
* @return string
*/
public function getYouTubeEmbedUrl(Talk $talk): string
{
preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^\?&\"'>]+)/", $talk->getVideoUrl(), $matches);

return 'https://www.youtube.com/embed/'.$matches[1];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

declare(strict_types=1);

namespace Phpsw\Website\Tests\WebsiteGenerator\TemplateRenderer\TwigExtension;

use Phpsw\Website\Entity\Talk;
use Phpsw\Website\WebsiteGenerator\TemplateRenderer\TwigExtension\SlidesEmbedExtension;
use PHPUnit\Framework\TestCase;

class SlidesEmbedExtensionTest extends TestCase
{
/**
* When the slides url is a link to a website, we should get an iFrame back.
*/
public function testGetSlidesEmbedStandardLink()
{
$talk = new Talk();
$talk->setSlidesUrl('https://talks.philsturgeon.uk/instances/phpsw-jan18/http-caching-to-save-the-polar-bears/html/#/');

$slidesEmbedExtension = new SlidesEmbedExtension();
$actual = $slidesEmbedExtension->getSlidesEmbed($talk);
$this->assertEquals(
'<iframe class="w-full" style="height:300px" src="https://talks.philsturgeon.uk/instances/phpsw-jan18/http-caching-to-save-the-polar-bears/html/#/" frameborder="0" allowfullscreen mozallowfullscreen webkitallowfullscreen></iframe>',
$actual
);
}

/**
* When the slides url is a PDF, we should get an iFrame back.
* The iFrame should link to the mozilla tooling which helps show the PDF.
*/
public function testGetSlidesEmbedPdf()
{
$talk = new Talk();
$talk->setSlidesUrl('https://slides.phpsw.uk/2018/01/command-emission-promise.pdf');

$slidesEmbedExtension = new SlidesEmbedExtension();
$actual = $slidesEmbedExtension->getSlidesEmbed($talk);
$this->assertEquals(
'<iframe class="w-full" style="height:300px" src="https://mozilla.github.io/pdf.js/web/viewer.html?file=https://slides.phpsw.uk/2018/01/command-emission-promise.pdf#zoom=page-fit" frameborder="0" allowfullscreen mozallowfullscreen webkitallowfullscreen></iframe>',
$actual
);
}

/**
* When the slides url is slideshare, we get an embedly embed back.
*/
public function testGetSlidesEmbedSlideshare()
{
$talk = new Talk();
$talk->setSlidesUrl('https://www.slideshare.net/asgrim1/crafting-quality-php-applications-an-overview-phpsw-march-2018');
$talk->setTitle('Crafting Quality PHP Applications: an overview');

$slidesEmbedExtension = new SlidesEmbedExtension();
$actual = $slidesEmbedExtension->getSlidesEmbed($talk);
$this->assertEquals(
'<blockquote class="embedly-card"><h4><a href="https://www.slideshare.net/asgrim1/crafting-quality-php-applications-an-overview-phpsw-march-2018">Crafting Quality PHP Applications: an overview</a></h4></blockquote><script async src="//cdn.embedly.com/widgets/platform.js" charset="UTF-8"></script>',
$actual
);
}

/**
* When the slides url is a link to a website, we should get a standard link back.
*/
public function testGetSlidesLinkStandardLink()
{
$talk = new Talk();
$talk->setSlidesUrl('https://talks.philsturgeon.uk/instances/phpsw-jan18/http-caching-to-save-the-polar-bears/html/#/');

$slidesEmbedExtension = new SlidesEmbedExtension();
$actual = $slidesEmbedExtension->getSlidesLink($talk);
$this->assertEquals(
'<a href="https://talks.philsturgeon.uk/instances/phpsw-jan18/http-caching-to-save-the-polar-bears/html/#/" class="block mb-1" target="_blank">
<svg class="fill-current w-4 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.26 13a2 2 0 0 1 .01-2.01A3 3 0 0 0 9 5H5a3 3 0 0 0 0 6h.08a6.06 6.06 0 0 0 0 2H5A5 5 0 0 1 5 3h4a5 5 0 0 1 .26 10zm1.48-6a2 2 0 0 1-.01 2.01A3 3 0 0 0 11 15h4a3 3 0 0 0 0-6h-.08a6.06 6.06 0 0 0 0-2H15a5 5 0 0 1 0 10h-4a5 5 0 0 1-.26-10z"></path></svg>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to include the markup within the texts? I've usually tried to avoid this and focus on the data properties and methods, just so that the tests don't break if a class is changed in a template.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is, the main thing we're doing with this extension is generating the relevant markup to embed the slides for a given service.

We could split each slides service up into it's own class and sort of handle it that way, which might make things a bit neater

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we keep it this way for now, and then look at refactoring it into different services post-launch?

View Slides
</a>',
$actual
);
}

/**
* When the slides url is a slideshare link, we should get a standard link back.
*/
public function testGetSlidesLinkSlideshare()
{
$talk = new Talk();
$talk->setSlidesUrl('https://www.slideshare.net/asgrim1/crafting-quality-php-applications-an-overview-phpsw-march-2018');

$slidesEmbedExtension = new SlidesEmbedExtension();
$actual = $slidesEmbedExtension->getSlidesLink($talk);
$this->assertEquals(
'<a href="https://www.slideshare.net/asgrim1/crafting-quality-php-applications-an-overview-phpsw-march-2018" class="block mb-1" target="_blank">
<svg class="fill-current w-4 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.26 13a2 2 0 0 1 .01-2.01A3 3 0 0 0 9 5H5a3 3 0 0 0 0 6h.08a6.06 6.06 0 0 0 0 2H5A5 5 0 0 1 5 3h4a5 5 0 0 1 .26 10zm1.48-6a2 2 0 0 1-.01 2.01A3 3 0 0 0 11 15h4a3 3 0 0 0 0-6h-.08a6.06 6.06 0 0 0 0-2H15a5 5 0 0 1 0 10h-4a5 5 0 0 1-.26-10z"></path></svg>
View Slides
</a>',
$actual
);
}

/**
* When the slides url is a PDF, we should get a PDF link back.
*/
public function testGetSlidesLinkPdf()
{
$talk = new Talk();
$talk->setSlidesUrl('https://slides.phpsw.uk/2018/01/command-emission-promise.pdf');

$slidesEmbedExtension = new SlidesEmbedExtension();
$actual = $slidesEmbedExtension->getSlidesLink($talk);
$this->assertEquals(
'<a href="https://slides.phpsw.uk/2018/01/command-emission-promise.pdf" class="block mb-1" target="_blank">
<svg class="fill-current w-4 mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M4,18 L4,2 L12,2 L12,6 L16,6 L16,18 L4,18 Z M2,19 L2,0 L3,0 L12,0 L14,0 L18,4 L18,6 L18,20 L17,20 L2,20 L2,19 Z" id="Combined-Shape"></path></svg>
View PDF
</a>',
$actual
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Phpsw\Website\Tests\WebsiteGenerator\TemplateRenderer\TwigExtension;

use Phpsw\Website\Entity\Talk;
use Phpsw\Website\WebsiteGenerator\TemplateRenderer\TwigExtension\YouTubeEmbedUrlExtension;
use PHPUnit\Framework\TestCase;

class YouTubeEmbedUrlExtensionTest extends TestCase
{
public function testGetYouTubeEmbedUrl()
{
$talk = new Talk();
$talk->setVideoUrl('https://www.youtube.com/watch?v=nMeDxw4wUXI');

$youTubeEmberUrlExtension = new YouTubeEmbedUrlExtension();
$actual = $youTubeEmberUrlExtension->getYouTubeEmbedUrl($talk);

$this->assertEquals('https://www.youtube.com/embed/nMeDxw4wUXI', $actual);
}

/**
* Checks that query strings which could also exist in the YouTube URL are removed.
*/
public function testGetYouTubeEmbedUrlWithQueryString()
{
$talk = new Talk();
$talk->setVideoUrl('https://www.youtube.com/watch?time_continue=635&v=nMeDxw4wUXI');

$youTubeEmberUrlExtension = new YouTubeEmbedUrlExtension();
$actual = $youTubeEmberUrlExtension->getYouTubeEmbedUrl($talk);

$this->assertEquals('https://www.youtube.com/embed/nMeDxw4wUXI', $actual);
}
}
5 changes: 4 additions & 1 deletion data/talks/2018/01/command-and-emission-control.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"event": "2018-01-new-year-new-topics",
"speakers": [
"barney-hanlon"
]
],
"video-url": "https://www.youtube.com/watch?v=nMeDxw4wUXI",
"slides-url": "https://slides.phpsw.uk/2018/01/command-emission-promise.pdf",
"joindin-url": "https://joind.in/talk/6aefb"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@
"speakers": [
"phil-sturgeon"
],
"video-url": "https://www.youtube.com/watch?v=OwoVFGnpqpM",
"slides-url": "https://talks.philsturgeon.uk/instances/phpsw-jan18/http-caching-to-save-the-polar-bears/html/#/",
"showcase": true
}
2 changes: 1 addition & 1 deletion data/talks/2018/03/crafting-quality-php-applications.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"james-titcumb"
],
"joindin-url": "96cee",
"slides-url": "",
"slides-url": "https://www.slideshare.net/asgrim1/crafting-quality-php-applications-an-overview-phpsw-march-2018",
"video-url": "",
"showcase": true
}
4 changes: 4 additions & 0 deletions tailwind.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ let colors = {
'red-dark': '#cc1f1a',
'red': '#e3342f',
'red-light': '#d9534f',

'orange': '#f0ad4e',
'orange-dark': '#ee8401',

}

module.exports = {
Expand Down