diff --git a/.gitignore b/.gitignore
index 0d31019..59248e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
.sass-cache/
+vendor/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..2b0a6d6
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,33 @@
+language: php
+
+git:
+ depth: 1
+
+cache:
+ directories:
+ - $HOME/.composer/cache
+
+sudo: false
+
+env:
+ global:
+ - COMPOSER_ALLOW_XDEBUG=0
+ - SYMFONY_DEPRECATIONS_HELPER=weak
+
+matrix:
+ include:
+ - php: 5.6
+ - php: 7.0
+ - php: 7.0
+ env: COMPOSER_FLAGS='--prefer-lowest --prefer-stable'
+ - php: 7.1
+ fast_finish: true
+
+before_install:
+ - composer selfupdate
+
+before_script:
+ - travis_wait composer update $COMPOSER_FLAGS --no-interaction
+
+script:
+ - php vendor/bin/phpunit
diff --git a/composer.json b/composer.json
index 587dc3b..de98bbf 100644
--- a/composer.json
+++ b/composer.json
@@ -18,11 +18,18 @@
"source":"https://github.com/madeyourday/contao-rocksolid-slider"
},
"require":{
- "php":">=5.5",
+ "php":">=5.6",
"contao/core-bundle":"^4.3"
},
"require-dev": {
- "contao/manager-plugin": "^2.0"
+ "contao/news-bundle":"^4.3",
+ "contao/calendar-bundle": "^4.3",
+ "contao/manager-plugin": "^2.0",
+ "phpunit/phpunit": "^5.7 | ^6.1"
+ },
+ "suggest": {
+ "contao/news-bundle": "To create sliders from news entries (requires license key).",
+ "contao/calendar-bundle": "To create sliders from calendar events (requires license key)."
},
"conflict": {
"contao/core": "*",
@@ -33,6 +40,11 @@
"MadeYourDay\\RockSolidSlider\\": "src/"
}
},
+ "autoload-dev":{
+ "psr-4": {
+ "MadeYourDay\\RockSolidSlider\\Test\\": "tests/"
+ }
+ },
"extra": {
"contao-manager-plugin": "MadeYourDay\\RockSolidSlider\\ContaoManagerPlugin"
},
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..528677b
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+ ./tests
+ ./tests/Fixtures
+
+
+
+
+
+ src
+
+ ./src/Resources
+
+
+
+
diff --git a/src/DependencyInjection/Compiler/AddProvidersPass.php b/src/DependencyInjection/Compiler/AddProvidersPass.php
new file mode 100644
index 0000000..8f9ca0f
--- /dev/null
+++ b/src/DependencyInjection/Compiler/AddProvidersPass.php
@@ -0,0 +1,52 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Adds the providers to the registry.
+ *
+ * @author Christian Schiffler
+ */
+class AddProvidersPass implements CompilerPassInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $definition = $container->getDefinition('madeyourday.rocksolid_slider.slideproviders');
+ $arguments = $definition->getArguments();
+
+ // Collect provider services.
+ $arguments[0] = array_merge(count($arguments) > 0 ? $arguments[0] : [], $this->getProviders($container));
+
+ $definition->setArguments($arguments);
+ }
+
+ /**
+ * Returns the available provider implementations.
+ *
+ * @return Reference[]
+ */
+ private function getProviders(ContainerBuilder $container)
+ {
+ $services = $container->findTaggedServiceIds('madeyourday.rocksolid_slider.slideprovider');
+ $result = [];
+ foreach (array_keys($services) as $service) {
+ $result[] = new Reference($service);
+ }
+
+ return $result;
+ }
+}
diff --git a/src/DependencyInjection/RockSolidSliderExtension.php b/src/DependencyInjection/RockSolidSliderExtension.php
new file mode 100644
index 0000000..4e5d4ba
--- /dev/null
+++ b/src/DependencyInjection/RockSolidSliderExtension.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\DependencyInjection;
+
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\Extension;
+use Symfony\Component\DependencyInjection\Loader;
+
+/**
+ * This is the class that loads and manages the bundle configuration
+ */
+class RockSolidSliderExtension extends Extension
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function load(array $configs, ContainerBuilder $container)
+ {
+ $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
+ $loader->load('services.yml');
+ }
+}
diff --git a/src/Helper/FileHelper.php b/src/Helper/FileHelper.php
new file mode 100644
index 0000000..e6e5ba7
--- /dev/null
+++ b/src/Helper/FileHelper.php
@@ -0,0 +1,239 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Helper;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\File;
+use Contao\FilesModel;
+use Contao\Frontend;
+use Contao\Model\Collection;
+use Contao\StringUtil;
+use Contao\Validator;
+
+/**
+ * This class is a helper service for processing files.
+ *
+ * @author Christian Schiffler
+ */
+class FileHelper
+{
+ /**
+ * @var Adapter|FilesModel
+ */
+ private $filesModelAdapter;
+
+ /**
+ * @var Adapter|Frontend
+ */
+ private $frontendAdapter;
+
+ /**
+ * Create a new instance.
+ *
+ * @param Adapter|FilesModel $filesModelAdapter
+ * @param Adapter|Frontend $frontendAdapter
+ */
+ public function __construct(Adapter $filesModelAdapter, Adapter $frontendAdapter)
+ {
+ $this->filesModelAdapter = $filesModelAdapter;
+ $this->frontendAdapter = $frontendAdapter;
+ }
+
+ /**
+ * Find multiple files by their UUIDs.
+ *
+ * @param array $uuids An array of UUIDs.
+ * @param array $options An optional options array.
+ *
+ * @return Collection|FilesModel[]|FilesModel|null A collection of models or null if there are no files.
+ */
+ public function findMultipleFilesByUuids($uuids, array $options = [])
+ {
+ return $this->filesModelAdapter->findMultipleByUuids($uuids, $options);
+ }
+
+ /**
+ * Find multiple files by their UUIDs.
+ *
+ * @param string[]|Collection|FilesModel[] $uuids An array of UUIDs to be used as pid.
+ * @param array $options An optional options array.
+ *
+ * @return Collection|FilesModel[]|FilesModel|null A collection of models or null if there are no files.
+ */
+ public function findMultipleFilesByUuidRecursive($uuids, array $options = [])
+ {
+ $result = [];
+ $dirs = [];
+ if (!$uuids instanceof Collection) {
+ $uuids = $this->findMultipleFilesByUuids($uuids, $options);
+ }
+
+ foreach ($uuids as $file) {
+ if ($file->type === 'file') {
+ $result[] = $file;
+ continue;
+ }
+
+ $dirs[] = $file->uuid;
+ }
+ if (empty($dirs)) {
+ return $result;
+ }
+
+ return array_merge($result, $this->findMultipleFilesByPidRecursive($dirs, $options));
+ }
+
+ /**
+ * Find multiple files by their UUID-pid.
+ *
+ * @param string[]|Collection|FilesModel[] $pids An array of UUIDs to be used as pid.
+ * @param array $options An optional options array.
+ *
+ * @return Collection|FilesModel[]|FilesModel|null A collection of models or null if there are no files.
+ */
+ public function findMultipleFilesByPidRecursive($pids, array $options = [])
+ {
+ $result = [];
+ $dirs = [];
+ if (!$pids instanceof Collection) {
+ $pids = $this->filesModelAdapter->findBy([
+ $this->filesModelAdapter->getTable() . '.pid IN (' .
+ implode(',', array_fill(0, count($pids), 'UNHEX(?)')) . ')'
+ ], array_map(function ($id) {
+ return Validator::isStringUuid($id) ? bin2hex(StringUtil::uuidToBin($id)) : bin2hex($id);
+ }, $pids), $options);
+ }
+
+ foreach ($pids as $file) {
+ if ($file->type === 'file') {
+ $result[] = $file;
+ continue;
+ }
+
+ $dirs[] = $file->uuid;
+ }
+
+ if (empty($dirs)) {
+ return $result;
+ }
+
+ return array_merge($result, $this->findMultipleFilesByPidRecursive($dirs, $options));
+ }
+
+ /**
+ * Gateway to frontend adapter.
+ *
+ * @param array $data The image data as array.
+ *
+ * @return \stdClass
+ */
+ public function prepareImageForTemplate($data)
+ {
+ $image = new \stdClass;
+ $this->frontendAdapter->addImageToTemplate($image, $data);
+
+ return $image;
+ }
+
+ /**
+ * Try to prepare the file with the passed uuid.
+ *
+ * @param string|FilesModel $uuidOrModel The uuid of the file.
+ * @param array $attributes The attributes to pass to Frontend::addImageToTemplate().
+ * @param bool $addMeta If true, the Meta information attributes will also get added
+ * 'alt' => meta['title']
+ * 'imageUrl' => meta['link'],
+ * 'caption' => meta['caption']
+ *
+ * @return null|array
+ */
+ public function tryPrepareImage($uuidOrModel, $attributes, $addMeta = false)
+ {
+ if (null === ($file = $this->ensureFileModel($uuidOrModel))) {
+ return null;
+ }
+ $fileObject = $this->getFileInstance($file->path);
+ // FIXME: Why check for isGdImage here? if isImage == true it is always also isGdImage == true?
+ if (!$fileObject->isGdImage && !$fileObject->isImage) {
+ return null;
+ }
+
+ if ($addMeta) {
+ // FIXME: this is only needed because of the language, we need it via another way!
+ global $objPage;
+ $meta = $this->frontendAdapter->getMetaData($file->meta, $objPage->language);
+ $attributes['alt'] = $meta['title'];
+ $attributes['imageUrl'] = $meta['link'];
+ $attributes['caption'] = $meta['caption'];
+ }
+
+ return array_merge([
+ 'id' => $file->id,
+ 'uuid' => isset($file->uuid) ? $file->uuid : null,
+ 'name' => $fileObject->basename,
+ 'singleSRC' => $file->path,
+ ], $attributes);
+ }
+
+ /**
+ * Try to prepare the file with the passed uuid.
+ *
+ * @param string|FilesModel $uuidOrModel The uuid of the file.
+ * @param array $attributes The attributes to pass to Frontend::addImageToTemplate().
+ * @param bool $addMeta If true, the Meta information attributes will also get added
+ * 'alt' => meta['title']
+ * 'imageUrl' => meta['link'],
+ * 'caption' => meta['caption']
+ *
+ * @return null|\stdClass
+ */
+ public function tryPrepareImageForTemplate($uuidOrModel, $attributes, $addMeta = false)
+ {
+ if (null === ($imageData = $this->tryPrepareImage($uuidOrModel, $attributes, $addMeta))) {
+ return null;
+ }
+
+ return $this->prepareImageForTemplate($imageData);
+ }
+
+ /**
+ * Instantiate a file instance and return it.
+ *
+ * The purpose of this function is to be able to mock it in tests and to replace it when needed.
+ *
+ * @param string $path The path below TL_ROOT.
+ *
+ * @return File
+ */
+ public function getFileInstance($path)
+ {
+ return new File($path);
+ }
+
+ /**
+ * Convert an uuid to a FilesModel instance if not one already.
+ *
+ * @param string|FilesModel $uuidOrModel
+ *
+ * @return FilesModel|null
+ */
+ private function ensureFileModel($uuidOrModel)
+ {
+ if ($uuidOrModel instanceof FilesModel) {
+ return $uuidOrModel;
+ }
+
+ if (!trim($uuidOrModel)) {
+ return null;
+ }
+
+ return $this->filesModelAdapter->findByUuid($uuidOrModel);
+ }
+}
diff --git a/src/Module/Slider.php b/src/Module/Slider.php
index 385e72f..a70e131 100644
--- a/src/Module/Slider.php
+++ b/src/Module/Slider.php
@@ -8,14 +8,22 @@
namespace MadeYourDay\RockSolidSlider\Module;
-use MadeYourDay\RockSolidSlider\Model\SlideModel;
+use Contao\System;
+use MadeYourDay\RockSolidSlider\Helper\FileHelper;
use MadeYourDay\RockSolidSlider\Model\SliderModel;
-use MadeYourDay\RockSolidSlider\Model\ContentModel;
+use MadeYourDay\RockSolidSlider\SliderContent;
/**
* Slider Frontend Module
*
* @author Martin Auswöger
+ *
+ * @property string rsts_content_type The slider content type.
+ * @property string rsts_thumbs_imgSize
+ * @property string rsts_navType
+ * @property string rsts_template
+ * @property string rsts_import_settings
+ * @property string rsts_import_settings_from
*/
class Slider extends \Module
{
@@ -24,6 +32,16 @@ class Slider extends \Module
*/
protected $strTemplate = 'rsts_default';
+ /**
+ * @var SliderContent
+ */
+ private $content;
+
+ /**
+ * @var string
+ */
+ private $root;
+
/**
* @return string
*/
@@ -48,52 +66,19 @@ public function generate()
return $template->parse();
}
- if ($this->rsts_content_type === 'rsts_news') {
- $newsModule = new SliderNews($this->objModel, $this->strColumn);
- $this->newsArticles = $newsModule->getNewsArticles();
- if (!count($this->newsArticles)) {
- // Return if there are no news articles
+ $registry = System::getContainer()->get('madeyourday.rocksolid_slider.slideproviders');
+ /** @var \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry $registry */
+ if ($registry->hasProvider($this->rsts_content_type)) {
+ $this->content = new SliderContent();
+ $registry
+ ->getProvider($this->rsts_content_type)
+ ->process(array_merge(['slider-column' => $this->strColumn], $this->objModel->row()), $this->content);
+ if (!$this->content->hasSlides() && !$this->content->hasFiles()) {
return '';
}
}
- else if ($this->rsts_content_type === 'rsts_events') {
- $eventsModule = new SliderEvents($this->objModel, $this->strColumn);
- $this->eventItems = $eventsModule->getEventItems();
- if (!count($this->eventItems)) {
- // Return if there are no events
- return '';
- }
- }
- else if ($this->rsts_content_type === 'rsts_settings') {
- return '';
- }
- else if ($this->rsts_content_type === 'rsts_images' || !$this->rsts_id) {
-
- $this->multiSRC = deserialize($this->multiSRC);
- if (!is_array($this->multiSRC) || !count($this->multiSRC)) {
- // Return if there are no images
- return '';
- }
-
- }
- else {
-
- $this->slider = SliderModel::findByPk($this->rsts_id);
-
- // Return if there is no slider
- if (! $this->slider || $this->slider->id !== $this->rsts_id) {
- return '';
- }
-
- if ($this->slider->type === 'image') {
- $this->multiSRC = deserialize($this->slider->multiSRC);
- $this->orderSRC = $this->slider->orderSRC;
- }
-
- }
-
- $this->files = \FilesModel::findMultipleByUuids($this->multiSRC);
+ $this->root = dirname(System::getContainer()->getParameter('kernel.root_dir'));
if (
$this->rsts_import_settings
&& $this->rsts_import_settings_from
@@ -123,125 +108,13 @@ public function generate()
*/
protected function compile()
{
- global $objPage;
-
- $images = array();
-
- if ($this->files) {
-
- $files = $this->files;
- $filesExpaned = array();
-
- // Get all images
- while ($files->next()) {
- if ($files->type === 'file') {
- $filesExpaned[] = $files->current();
- }
- else {
- $subFiles = \FilesModel::findByPid($files->uuid);
- while ($subFiles && $subFiles->next()) {
- if ($subFiles->type === 'file'){
- $filesExpaned[] = $subFiles->current();
- }
- }
- }
- }
-
- foreach ($filesExpaned as $files) {
-
- // Continue if the files has been processed or does not exist
- if (isset($images[$files->path]) || ! file_exists(TL_ROOT . '/' . $files->path)) {
- continue;
- }
-
- $file = new \File($files->path, true);
-
- if (!$file->isGdImage && !$file->isImage) {
- continue;
- }
-
- $arrMeta = $this->getMetaData($files->meta, $objPage->language);
-
- // Add the image
- $images[$files->path] = array
- (
- 'id' => $files->id,
- 'uuid' => isset($files->uuid) ? $files->uuid : null,
- 'name' => $file->basename,
- 'singleSRC' => $files->path,
- 'alt' => $arrMeta['title'],
- 'imageUrl' => $arrMeta['link'],
- 'caption' => $arrMeta['caption'],
- );
-
- }
-
- if ($this->orderSRC) {
- // Turn the order string into an array and remove all values
- $order = deserialize($this->orderSRC);
- if (!$order || !is_array($order)) {
- $order = array();
- }
- $order = array_flip($order);
- $order = array_map(function(){}, $order);
-
- // Move the matching elements to their position in $order
- foreach ($images as $k => $v) {
- if (array_key_exists($v['uuid'], $order)) {
- $order[$v['uuid']] = $v;
- unset($images[$k]);
- }
- }
-
- $order = array_merge($order, array_values($images));
-
- // Remove empty (unreplaced) entries
- $images = array_filter($order);
- unset($order);
- }
-
- $images = array_values($images);
-
- foreach ($images as $key => $image) {
- $newImage = new \stdClass();
- $image['size'] = isset($this->imgSize) ? $this->imgSize : $this->size;
- $this->addImageToTemplate($newImage, $image);
- if ($this->rsts_navType === 'thumbs') {
- $newImage->thumb = new \stdClass;
- $image['size'] = $this->rsts_thumbs_imgSize;
- $this->addImageToTemplate($newImage->thumb, $image);
- }
- $images[$key] = $newImage;
- }
-
- }
-
// use custom skin if specified
if (trim($this->arrData['rsts_customSkin'])) {
$this->arrData['rsts_skin'] = trim($this->arrData['rsts_customSkin']);
}
- $this->Template->images = $images;
- $slides = array();
- if (isset($this->newsArticles)) {
- foreach ($this->newsArticles as $newsArticle) {
- $slides[] = array(
- 'text' => $newsArticle,
- );
- }
- }
- else if (isset($this->eventItems)) {
- foreach ($this->eventItems as $eventItem) {
- $slides[] = array(
- 'text' => $eventItem,
- );
- }
- }
- else if (isset($this->slider->id) && $this->slider->type === 'content') {
- $slides = $this->parseSlides(SlideModel::findPublishedByPid($this->slider->id));
- }
-
- $this->Template->slides = $slides;
+ $this->Template->images = $this->prepareFiles($this->content->getFiles(), $this->content->getFilesOrder());
+ $this->Template->slides = $this->content->getSlides();
$options = array();
@@ -385,186 +258,79 @@ protected function compile()
$GLOBALS['TL_JAVASCRIPT'][] = $assetsDir . '/js/rocksolid-slider.min.js|static';
$GLOBALS['TL_CSS'][] = $assetsDir . '/css/rocksolid-slider.min.css||static';
$skinPath = $assetsDir . '/css/' . (empty($this->arrData['rsts_skin']) ? 'default' : $this->arrData['rsts_skin']) . '-skin.min.css';
- if (file_exists(TL_ROOT . '/' . $skinPath)) {
+ if (file_exists($this->root . '/' . $skinPath)) {
$GLOBALS['TL_CSS'][] = $skinPath . '||static';
}
}
/**
- * Parse slides
+ * Prepare the images.
+ *
+ * @param array $files The file list.
+ * @param array $order The order list.
*
- * @param \Model\Collection $objSlides slides retrieved from the database
- * @return array parsed slides
+ * @return array
*/
- protected function parseSlides($objSlides)
+ private function prepareFiles($files, $order)
{
- global $objPage;
-
- $slides = array();
- $pids = array();
- $idIndexes = array();
-
- if (! $objSlides) {
- return $slides;
+ if (empty($files)) {
+ return [];
}
+ /** @var FileHelper $helper */
+ $helper = System::getContainer()->get('madeyourday.rocksolid_slider.file_helper');
+ $images = [];
+ foreach ($helper->findMultipleFilesByUuidRecursive($files) as $files) {
- while ($objSlides->next()) {
-
- $slide = $objSlides->row();
- $slide['text'] = '';
- if ($slide['type'] === 'content') {
- $pids[] = $slide['id'];
- $idIndexes[(int)$slide['id']] = count($slides);
+ // Continue if the files has been processed or does not exist
+ if (isset($images[$files->path]) || !file_exists($this->root . '/' . $files->path)) {
+ continue;
}
- if (
- in_array($slide['type'], array('image', 'video')) &&
- trim($slide['singleSRC']) &&
- ($file = \FilesModel::findByUuid($slide['singleSRC'])) &&
- ($fileObject = new \File($file->path, true)) &&
- ($fileObject->isGdImage || $fileObject->isImage)
- ) {
- $meta = $this->getMetaData($file->meta, $objPage->language);
- $slide['image'] = new \stdClass;
- $this->addImageToTemplate($slide['image'], array(
- 'id' => $file->id,
- 'name' => $fileObject->basename,
- 'singleSRC' => $file->path,
- 'alt' => $meta['title'],
- 'imageUrl' => $meta['link'],
- 'caption' => $meta['caption'],
- 'size' => isset($this->imgSize) ? $this->imgSize : $this->size,
- ));
+ if (null !== ($imageData = $helper->tryPrepareImage($files, [], true))) {
+ // Add the image
+ $images[$files->path] = $imageData;
}
+ }
- if ($slide['type'] === 'video' && $slide['videoURL'] && empty($slide['image'])) {
- $slide['image'] = new \stdClass;
- if (preg_match(
- '(^
- https?:// # http or https
- (?:
- www\\.youtube\\.com/(?:watch\\?v=|v/|embed/) # Different URL formats
- | youtu\\.be/ # Short YouTube domain
- )
- ([0-9a-z_\\-]{11}) # YouTube ID
- (?:$|&|/) # End or separator
- )ix',
- html_entity_decode($slide['videoURL']), $matches)
- ) {
- $video = $matches[1];
- $slide['image']->src = '//img.youtube.com/vi/' . $video . '/0.jpg';
+ if ($order) {
+ // Turn the order string into an array and remove all values
+ if (!$order || !is_array($order)) {
+ $order = array();
+ }
+ $order = array_flip($order);
+ $order = array_map(
+ function () {
+ },
+ $order
+ );
+
+ // Move the matching elements to their position in $order
+ foreach ($images as $k => $v) {
+ if (array_key_exists($v['uuid'], $order)) {
+ $order[$v['uuid']] = $v;
+ unset($images[$k]);
}
- else {
- // Grey dummy image
- $slide['image']->src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAJCAMAAAAM9FwAAAAAA1BMVEXGxsbd/8BlAAAAFUlEQVR42s3BAQEAAACAkP6vdiO6AgCZAAG/wrlvAAAAAElFTkSuQmCC';
- }
- $slide['image']->imgSize = '';
- $slide['image']->alt = '';
- $slide['image']->picture = array(
- 'img' => array('src' => $slide['image']->src, 'srcset' => $slide['image']->src),
- 'sources' => array(),
- );
- }
-
- if ($slide['type'] !== 'video' && $slide['videoURL']) {
- $slide['videoURL'] = '';
}
- if ($slide['type'] === 'video' && $slide['videos']) {
- $videoFiles = deserialize($slide['videos'], true);
- $videoFiles = \FilesModel::findMultipleByUuids($videoFiles);
- $videos = array();
- foreach ($videoFiles as $file) {
- $videos[] = $file;
- }
- $slide['videos'] = $videos;
- }
- else {
- $slide['videos'] = null;
- }
+ $order = array_merge($order, array_values($images));
- if (
- trim($slide['backgroundImage']) &&
- ($file = \FilesModel::findByUuid($slide['backgroundImage'])) &&
- ($fileObject = new \File($file->path, true)) &&
- ($fileObject->isGdImage || $fileObject->isImage)
- ) {
- $meta = $this->getMetaData($file->meta, $objPage->language);
- $slide['backgroundImage'] = new \stdClass;
- $this->addImageToTemplate($slide['backgroundImage'], array(
- 'id' => $file->id,
- 'name' => $fileObject->basename,
- 'singleSRC' => $file->path,
- 'alt' => $meta['title'],
- 'imageUrl' => $meta['link'],
- 'caption' => $meta['caption'],
- 'size' => $slide['backgroundImageSize'],
- ));
- }
- else {
- $slide['backgroundImage'] = null;
- }
+ // Remove empty (unreplaced) entries
+ $images = array_filter($order);
+ unset($order);
+ }
- if ($slide['backgroundVideos']) {
- $videoFiles = deserialize($slide['backgroundVideos'], true);
- $videoFiles = \FilesModel::findMultipleByUuids($videoFiles);
- $videos = array();
- foreach ($videoFiles as $file) {
- $videos[] = $file;
- }
- $slide['backgroundVideos'] = $videos;
- }
+ $images = array_values($images);
+ foreach ($images as $key => $image) {
+ $image['size'] = isset($this->imgSize) ? $this->imgSize : $this->size;
+ $newImage = $helper->prepareImageForTemplate($image);
if ($this->rsts_navType === 'thumbs') {
- $slide['thumb'] = new \stdClass;
- if (
- trim($slide['thumbImage']) &&
- ($file = \FilesModel::findByUuid($slide['thumbImage'])) &&
- ($fileObject = new \File($file->path, true)) &&
- ($fileObject->isGdImage || $fileObject->isImage)
- ) {
- $this->addImageToTemplate($slide['thumb'], array(
- 'id' => $file->id,
- 'name' => $fileObject->basename,
- 'singleSRC' => $file->path,
- 'size' => $this->rsts_thumbs_imgSize,
- ));
- }
- elseif (
- in_array($slide['type'], array('image', 'video')) &&
- trim($slide['singleSRC']) &&
- ($file = \FilesModel::findByUuid($slide['singleSRC'])) &&
- ($fileObject = new \File($file->path, true)) &&
- ($fileObject->isGdImage || $fileObject->isImage)
- ) {
- $this->addImageToTemplate($slide['thumb'], array(
- 'id' => $file->id,
- 'name' => $fileObject->basename,
- 'singleSRC' => $file->path,
- 'size' => $this->rsts_thumbs_imgSize,
- ));
- }
- elseif (!empty($slide['image']->src)) {
- $slide['thumb'] = clone $slide['image'];
- }
- elseif (!empty($slide['backgroundImage']->src)) {
- $slide['thumb'] = clone $slide['backgroundImage'];
- }
- }
-
- $slides[] = $slide;
-
- }
-
- if (count($pids)) {
- $slideContents = ContentModel::findPublishedByPidsAndTable($pids, SlideModel::getTable());
- if ($slideContents) {
- while ($slideContents->next()) {
- $slides[$idIndexes[(int)$slideContents->pid]]['text'] .= $this->getContentElement($slideContents->current());
- }
+ $image['size'] = $this->rsts_thumbs_imgSize;
+ $newImage->thumb = $helper->prepareImageForTemplate($image);
}
+ $images[$key] = $newImage;
}
- return $slides;
+ return $images;
}
}
diff --git a/src/Module/SliderEvents.php b/src/Module/SliderEvents.php
index a32d6de..22f6d65 100644
--- a/src/Module/SliderEvents.php
+++ b/src/Module/SliderEvents.php
@@ -8,15 +8,15 @@
namespace MadeYourDay\RockSolidSlider\Module;
+@trigger_error('Class MadeYourDay\RockSolidSlider\Module\SliderEvents is deprecated and will get removed.', E_USER_DEPRECATED);
+
/**
* Slider Events Module
*
* @author Martin Auswöger
*/
-class SliderEvents extends \ModuleEventlist
+class SliderEvents extends \MadeYourDay\RockSolidSlider\SlideProvider\Bridge\ContaoEvents
{
- const TEMPLATE_SEPARATOR = '';
-
/**
* Get an array of events (HTML output) generated by Contao\ModuleEventlist
*
@@ -24,45 +24,11 @@ class SliderEvents extends \ModuleEventlist
*/
public function getEventItems()
{
- $this->cal_calendar = $this->sortOutProtected(deserialize($this->cal_calendar, true));
-
- // Return if there are no calendars
- if (!is_array($this->cal_calendar) || empty($this->cal_calendar))
- {
- return array();
+ $slides = parent::getSlides();
+ $articles = [];
+ foreach ($slides as $slide) {
+ $articles[] = $slide['text'];
}
-
- // Dummy template object to retrive data from the compile method
- $this->Template = new \stdClass;
- $this->perPage = 0;
-
- $parseTemplateHook = array(
- 'MadeYourDay\\RockSolidSlider\\Slider',
- 'parseEventsTemplateHook'
- );
- // Add the TEMPLATE_SEPARATOR to be able to split the output into single events
- $GLOBALS['TL_HOOKS']['parseFrontendTemplate'][] = $parseTemplateHook;
-
- $this->compile();
-
- // Remove the hook
- foreach ($GLOBALS['TL_HOOKS']['parseFrontendTemplate'] as $key => $hook) {
- if ($hook[0] === $parseTemplateHook[0] && $hook[1] === $parseTemplateHook[1]) {
- unset($GLOBALS['TL_HOOKS']['parseFrontendTemplate'][$key]);
- }
- }
-
- // Split the output into single event items
- $eventItems = explode(static::TEMPLATE_SEPARATOR, $this->Template->events);
-
- if (count($eventItems) < 2) {
- // No events found
- return array();
- }
-
- // Remove output before the first event
- array_shift($eventItems);
-
- return $eventItems;
+ return $articles;
}
}
diff --git a/src/Module/SliderNews.php b/src/Module/SliderNews.php
index f8d55a7..f93ddf2 100644
--- a/src/Module/SliderNews.php
+++ b/src/Module/SliderNews.php
@@ -8,12 +8,14 @@
namespace MadeYourDay\RockSolidSlider\Module;
+@trigger_error('Class MadeYourDay\RockSolidSlider\Module\SliderNews is deprecated and will get removed.', E_USER_DEPRECATED);
+
/**
* Slider News Module
*
* @author Martin Auswöger
*/
-class SliderNews extends \ModuleNewsList
+class SliderNews extends \MadeYourDay\RockSolidSlider\SlideProvider\Bridge\ContaoNews
{
/**
* Get an array of news articles (HTML output) generated by Contao\ModuleNewsList
@@ -22,23 +24,11 @@ class SliderNews extends \ModuleNewsList
*/
public function getNewsArticles()
{
- $this->news_archives = $this->sortOutProtected(deserialize($this->news_archives));
-
- // Return if there are no archives
- if (!is_array($this->news_archives) || !count($this->news_archives)) {
- return array();
+ $slides = parent::getSlides();
+ $articles = [];
+ foreach ($slides as $slide) {
+ $articles[] = $slide['text'];
}
-
- // Dummy template object to retrive data from the compile method
- $this->Template = new \stdClass;
- $this->perPage = 0;
-
- $this->compile();
-
- if (!is_array($this->Template->articles) || !count($this->Template->articles)) {
- return array();
- }
-
- return $this->Template->articles;
+ return $articles;
}
}
diff --git a/src/Resources/config/model_adapter.yml b/src/Resources/config/model_adapter.yml
new file mode 100644
index 0000000..a241f00
--- /dev/null
+++ b/src/Resources/config/model_adapter.yml
@@ -0,0 +1,21 @@
+services:
+
+ madeyourday.rocksolid_slider.model_adapter.files_model:
+ class: Contao\CoreBundle\Framework\Adapter
+ arguments: ['Contao\FilesModel']
+ public: false
+
+ madeyourday.rocksolid_slider.model_adapter.module:
+ class: Contao\CoreBundle\Framework\Adapter
+ arguments: ['Contao\ModuleModel']
+ public: false
+
+ madeyourday.rocksolid_slider.model_adapter.slide_model:
+ class: Contao\CoreBundle\Framework\Adapter
+ arguments: ['MadeYourDay\RockSolidSlider\Model\SlideModel']
+ public: false
+
+ madeyourday.rocksolid_slider.model_adapter.slider_model:
+ class: Contao\CoreBundle\Framework\Adapter
+ arguments: ['MadeYourDay\RockSolidSlider\Model\SliderModel']
+ public: false
diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml
new file mode 100644
index 0000000..7f61a43
--- /dev/null
+++ b/src/Resources/config/services.yml
@@ -0,0 +1,40 @@
+imports:
+ - { resource: model_adapter.yml }
+services:
+ madeyourday.rocksolid_slider.file_helper:
+ class: MadeYourDay\RockSolidSlider\Helper\FileHelper
+ arguments:
+ - "@madeyourday.rocksolid_slider.model_adapter.files_model"
+ - "@madeyourday.rocksolid_slider.slideprovider.frontend_adapter"
+
+ madeyourday.rocksolid_slider.slideproviders:
+ class: MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry
+ arguments: []
+
+ madeyourday.rocksolid_slider.slideprovider.frontend_adapter:
+ class: Contao\CoreBundle\Framework\Adapter
+ arguments: ['Contao\Frontend']
+
+ madeyourday.rocksolid_slider.slideprovider.default:
+ class: MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider
+ arguments:
+ - "@madeyourday.rocksolid_slider.file_helper"
+ - "@madeyourday.rocksolid_slider.model_adapter.slider_model"
+ - "@madeyourday.rocksolid_slider.model_adapter.slide_model"
+ - "@madeyourday.rocksolid_slider.slideprovider.frontend_adapter"
+ tags:
+ - { name: madeyourday.rocksolid_slider.slideprovider }
+
+ madeyourday.rocksolid_slider.slideprovider.events:
+ class: MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider
+ arguments:
+ - "@madeyourday.rocksolid_slider.model_adapter.module"
+ tags:
+ - { name: madeyourday.rocksolid_slider.slideprovider }
+
+ madeyourday.rocksolid_slider.slideprovider.news:
+ class: MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider
+ arguments:
+ - "@madeyourday.rocksolid_slider.model_adapter.module"
+ tags:
+ - { name: madeyourday.rocksolid_slider.slideprovider }
diff --git a/src/RockSolidSliderBundle.php b/src/RockSolidSliderBundle.php
index 64018ef..842dbd2 100644
--- a/src/RockSolidSliderBundle.php
+++ b/src/RockSolidSliderBundle.php
@@ -1,4 +1,5 @@
*
@@ -8,13 +9,25 @@
namespace MadeYourDay\RockSolidSlider;
+use MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Configures the RockSolid Slider bundle.
*
* @author Martin Auswöger
+ * @author Christian Schiffler
*/
class RockSolidSliderBundle extends Bundle
{
+ /**
+ * {@inheritDoc}
+ */
+ public function build(ContainerBuilder $container)
+ {
+ parent::build($container);
+
+ $container->addCompilerPass(new AddProvidersPass());
+ }
}
diff --git a/src/SlideProvider/Bridge/ContaoEvents.php b/src/SlideProvider/Bridge/ContaoEvents.php
new file mode 100644
index 0000000..45f2be0
--- /dev/null
+++ b/src/SlideProvider/Bridge/ContaoEvents.php
@@ -0,0 +1,78 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider\Bridge;
+
+/**
+ * Slider Events Module
+ *
+ * @author Christian Schiffler
+ * @author Martin Auswöger
+ */
+class ContaoEvents extends \ModuleEventlist
+{
+ const TEMPLATE_SEPARATOR = '';
+
+ /**
+ * Get an array of news articles (HTML output) generated by Contao\ModuleNewsList
+ *
+ * @return array
+ *
+ * @codeCoverageIgnore - This is simply not testable. :-/
+ */
+ public function getSlides()
+ {
+ $this->cal_calendar = $this->sortOutProtected(deserialize($this->cal_calendar, true));
+
+ // Return if there are no calendars
+ if (!is_array($this->cal_calendar) || empty($this->cal_calendar)) {
+ return array();
+ }
+
+ // Dummy template object to retrive data from the compile method
+ $this->Template = new \stdClass;
+ $this->perPage = 0;
+
+ $parseTemplateHook = array(
+ 'MadeYourDay\\RockSolidSlider\\Slider',
+ 'parseEventsTemplateHook'
+ );
+ // Add the TEMPLATE_SEPARATOR to be able to split the output into single events
+ $GLOBALS['TL_HOOKS']['parseFrontendTemplate'][] = $parseTemplateHook;
+
+ $this->compile();
+
+ // Remove the hook
+ foreach (array_reverse($GLOBALS['TL_HOOKS']['parseFrontendTemplate']) as $key => $hook) {
+ if ($hook[0] === $parseTemplateHook[0] && $hook[1] === $parseTemplateHook[1]) {
+ unset($GLOBALS['TL_HOOKS']['parseFrontendTemplate'][$key]);
+ break;
+ }
+ }
+
+ // Split the output into single event items
+ $eventItems = explode(static::TEMPLATE_SEPARATOR, $this->Template->events);
+
+ if (count($eventItems) < 2) {
+ // No events found
+ return array();
+ }
+
+ // Remove output before the first event
+ array_shift($eventItems);
+
+
+ $slides = [];
+ foreach ($eventItems as $newsArticle) {
+ $slides[] = ['text' => $newsArticle];
+ }
+
+ return $slides;
+ }
+}
diff --git a/src/SlideProvider/Bridge/ContaoNews.php b/src/SlideProvider/Bridge/ContaoNews.php
new file mode 100644
index 0000000..f483ce5
--- /dev/null
+++ b/src/SlideProvider/Bridge/ContaoNews.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider\Bridge;
+
+/**
+ * Renders slides from news archives.
+ *
+ * @author Christian Schiffler
+ * @author Martin Auswöger
+ *
+ * @codeCoverageIgnore - This is simply not testable. :-/
+ */
+class ContaoNews extends \ModuleNewsList
+{
+ /**
+ * Get an array of news articles (HTML output) generated by Contao\ModuleNewsList
+ *
+ * @return array
+ */
+ public function getSlides()
+ {
+ $this->news_archives = $this->sortOutProtected(deserialize($this->news_archives));
+
+ // Return if there are no archives
+ if (!is_array($this->news_archives) || !count($this->news_archives)) {
+ return [];
+ }
+
+ // Dummy template object to receive data from the compile method
+ $this->Template = new \stdClass;
+ $this->perPage = 0;
+
+ $this->compile();
+
+ if (!is_array($this->Template->articles) || !count($this->Template->articles)) {
+ return [];
+ }
+
+ $slides = [];
+ foreach ($this->Template->articles as $newsArticle) {
+ $slides[] = ['text' => $newsArticle];
+ }
+
+ return $slides;
+ }
+}
diff --git a/src/SlideProvider/DefaultSlideProvider.php b/src/SlideProvider/DefaultSlideProvider.php
new file mode 100644
index 0000000..f4aee32
--- /dev/null
+++ b/src/SlideProvider/DefaultSlideProvider.php
@@ -0,0 +1,245 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\Frontend;
+use Contao\StringUtil;
+use MadeYourDay\RockSolidSlider\Helper\FileHelper;
+use MadeYourDay\RockSolidSlider\Model\ContentModel;
+use MadeYourDay\RockSolidSlider\Model\SlideModel;
+use MadeYourDay\RockSolidSlider\Model\SliderModel;
+use MadeYourDay\RockSolidSlider\SliderContent;
+
+/**
+ * Provides slides from the embedded slide table.
+ *
+ * @author Christian Schiffler
+ */
+class DefaultSlideProvider implements SlideProviderInterface
+{
+ /**
+ * @var Adapter|SliderModel
+ */
+ private $sliderModelAdapter;
+
+ /**
+ * @var Adapter|SlideModel
+ */
+ private $slideModelAdapter;
+
+ /**
+ * @var Adapter|Frontend
+ */
+ private $frontendAdapter;
+
+ /**
+ * @var FileHelper
+ */
+ private $fileHelper;
+
+ /**
+ * Create a new instance.
+ *
+ * @param FileHelper $fileHelper
+ * @param Adapter $sliderModelAdapter
+ * @param Adapter $slideModelAdapter
+ * @param Adapter $frontendAdapter
+ */
+ public function __construct(
+ FileHelper $fileHelper,
+ Adapter $sliderModelAdapter,
+ Adapter $slideModelAdapter,
+ Adapter $frontendAdapter
+ ) {
+ $this->fileHelper = $fileHelper;
+ $this->sliderModelAdapter = $sliderModelAdapter;
+ $this->slideModelAdapter = $slideModelAdapter;
+ $this->frontendAdapter = $frontendAdapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return 'rsts_default';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function process(array $config, SliderContent $content)
+ {
+ $slider = $this->sliderModelAdapter->findByPk($config['rsts_id']);
+
+ // Return if there is no slider
+ if (!$slider || $slider->id !== $config['rsts_id']) {
+ return;
+ }
+
+ if ($slider->type === 'image') {
+ $content->addFiles(
+ StringUtil::deserialize($slider->multiSRC),
+ StringUtil::deserialize($slider->orderSRC) ?: []
+ );
+
+ return;
+ }
+
+ if ($slider->type === 'content') {
+ $content->addSlides($this->parseSlides($this->slideModelAdapter->findPublishedByPid($slider->id), $config));
+ }
+ }
+
+ /**
+ * Parse slides
+ *
+ * @param \Model\Collection $objSlides slides retrieved from the database
+ * @param array $config The configuration to process (refer to provider implementation for contents).
+ *
+ * @return array parsed slides
+ */
+ private function parseSlides($objSlides, $config)
+ {
+ $slides = array();
+ $pids = array();
+ $idIndexes = array();
+
+ if (! $objSlides) {
+ return $slides;
+ }
+
+ while ($objSlides->next()) {
+
+ $slide = $objSlides->row();
+ $slide['text'] = '';
+ if ($slide['type'] === 'content') {
+ $pids[] = $slide['id'];
+ $idIndexes[(int)$slide['id']] = count($slides);
+ }
+
+ if (in_array($slide['type'], ['image', 'video'])) {
+ $slide['image'] = $this->fileHelper->tryPrepareImage(
+ $slide['singleSRC'],
+ ['size' => isset($config['imgSize']) ? $config['imgSize'] : $config['size']],
+ true
+ );
+ }
+
+ if ($slide['type'] === 'video' && $slide['videoURL'] && empty($slide['image'])) {
+ $slide['image'] = new \stdClass;
+ if (preg_match(
+ '(^
+ https?:// # http or https
+ (?:
+ www\\.youtube\\.com/(?:watch\\?v=|v/|embed/) # Different URL formats
+ | youtu\\.be/ # Short YouTube domain
+ )
+ ([0-9a-z_\\-]{11}) # YouTube ID
+ (?:$|&|/) # End or separator
+ )ix',
+ html_entity_decode($slide['videoURL']), $matches)
+ ) {
+ $video = $matches[1];
+ $slide['image']->src = '//img.youtube.com/vi/' . $video . '/0.jpg';
+ }
+ else {
+ // Grey dummy image
+ $slide['image']->src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAJCAMAAAAM9FwAAAAAA1BMVEXGxsbd/8BlAAAAFUlEQVR42s3BAQEAAACAkP6vdiO6AgCZAAG/wrlvAAAAAElFTkSuQmCC';
+ }
+ $slide['image']->imgSize = '';
+ $slide['image']->alt = '';
+ $slide['image']->picture = [
+ 'img' => ['src' => $slide['image']->src, 'srcset' => $slide['image']->src],
+ 'sources' => [],
+ ];
+ }
+
+ if ($slide['type'] !== 'video' && $slide['videoURL']) {
+ $slide['videoURL'] = '';
+ }
+
+ if ($slide['type'] === 'video' && $slide['videos']) {
+ $videoFiles = deserialize($slide['videos'], true);
+ $videoFiles = $this->fileHelper->findMultipleFilesByUuids($videoFiles);
+ $videos = [];
+ foreach ($videoFiles as $file) {
+ $videos[] = $file;
+ }
+ $slide['videos'] = $videos;
+ }
+ else {
+ $slide['videos'] = null;
+ }
+
+ $slide['backgroundImage'] = $this->fileHelper->tryPrepareImage(
+ $slide['backgroundImage'],
+ ['size' => $slide['backgroundImageSize']],
+ true
+ );
+
+ if ($slide['backgroundVideos']) {
+ $videoFiles = deserialize($slide['backgroundVideos'], true);
+ $videoFiles = $this->fileHelper->findMultipleFilesByUuids($videoFiles);
+ $videos = array();
+ foreach ($videoFiles as $file) {
+ $videos[] = $file;
+ }
+ $slide['backgroundVideos'] = $videos;
+ }
+
+ if ($config['rsts_navType'] === 'thumbs') {
+ $slide['thumb'] = $this->generateThumb($slide, $config);
+ }
+
+ $slides[] = $slide;
+
+ }
+
+ if (count($pids)) {
+ $slideContents = ContentModel::findPublishedByPidsAndTable($pids, SlideModel::getTable());
+ if ($slideContents) {
+ while ($slideContents->next()) {
+ $slides[$idIndexes[(int)$slideContents->pid]]['text'] .=
+ $this->frontendAdapter->getContentElement($slideContents->current());
+ }
+ }
+ }
+
+ return $slides;
+ }
+
+ /**
+ * Generate the thumbnail for a slide.
+ *
+ * @param array $slide The slide.
+ * @param array $config The configuration.
+ *
+ * @return \stdClass
+ */
+ private function generateThumb($slide, $config)
+ {
+ if ($thumb = $this->fileHelper->tryPrepareImageForTemplate($slide['thumbImage'], ['size' => $config['rsts_thumbs_imgSize']])) {
+ return $thumb;
+ }
+ if (in_array($slide['type'], ['image', 'video']) &&
+ ($thumb = $this->fileHelper->tryPrepareImageForTemplate($slide['singleSRC'], ['size' => $config['rsts_thumbs_imgSize']]))) {
+ return $thumb;
+ }
+ if (!empty($slide['image']->src)) {
+ return clone $slide['image'];
+ }
+ if (!empty($slide['backgroundImage']->src)) {
+ return clone $slide['backgroundImage'];
+ }
+ return $thumb;
+ }
+}
diff --git a/src/SlideProvider/EventsSlideProvider.php b/src/SlideProvider/EventsSlideProvider.php
new file mode 100644
index 0000000..0f11d07
--- /dev/null
+++ b/src/SlideProvider/EventsSlideProvider.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use MadeYourDay\RockSolidSlider\SlideProvider\Bridge\ContaoEvents;
+use MadeYourDay\RockSolidSlider\SliderContent;
+
+/**
+ * Provides slides from events archives.
+ *
+ * @author Christian Schiffler
+ */
+class EventsSlideProvider implements SlideProviderInterface
+{
+ /**
+ * @var Adapter|\Contao\ModuleModel
+ */
+ private $modelAdapter;
+
+ /**
+ * Create a new instance.
+ *
+ * @param Adapter $modelAdapter
+ */
+ public function __construct(Adapter $modelAdapter)
+ {
+ $this->modelAdapter = $modelAdapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return 'rsts_events';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function process(array $config, SliderContent $content)
+ {
+ $bridge = $this->getBridge($this->modelAdapter->findByPk($config['id']), $config['slider-column']);
+
+ $content->addSlides($bridge->getSlides());
+ }
+
+ /**
+ * Initialize the bridge.
+ *
+ * @param \Contao\ModuleModel $module
+ * @param string $column
+ *
+ * @return ContaoEvents
+ */
+ protected function getBridge($module, $column)
+ {
+ return new ContaoEvents($module, $column);
+ }
+}
diff --git a/src/SlideProvider/ImageSlideProvider.php b/src/SlideProvider/ImageSlideProvider.php
new file mode 100644
index 0000000..f3208ae
--- /dev/null
+++ b/src/SlideProvider/ImageSlideProvider.php
@@ -0,0 +1,37 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider;
+
+use Contao\StringUtil;
+use MadeYourDay\RockSolidSlider\SliderContent;
+
+/**
+ * Provides files.
+ *
+ * @author Christian Schiffler
+ */
+class ImageSlideProvider implements SlideProviderInterface
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return 'rsts_images';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function process(array $config, SliderContent $content)
+ {
+ $content->addFiles(StringUtil::deserialize($config['multiSRC']));
+ }
+}
diff --git a/src/SlideProvider/NewsSlideProvider.php b/src/SlideProvider/NewsSlideProvider.php
new file mode 100644
index 0000000..75e4a02
--- /dev/null
+++ b/src/SlideProvider/NewsSlideProvider.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use MadeYourDay\RockSolidSlider\SlideProvider\Bridge\ContaoNews;
+use MadeYourDay\RockSolidSlider\SliderContent;
+
+/**
+ * Provides slides from news archives.
+ *
+ * @author Christian Schiffler
+ */
+class NewsSlideProvider implements SlideProviderInterface
+{
+ /**
+ * @var Adapter|\Contao\ModuleModel
+ */
+ private $modelAdapter;
+
+ /**
+ * Create a new instance.
+ *
+ * @param Adapter $modelAdapter
+ */
+ public function __construct(Adapter $modelAdapter)
+ {
+ $this->modelAdapter = $modelAdapter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getName()
+ {
+ return 'rsts_news';
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function process(array $config, SliderContent $content)
+ {
+ $bridge = $this->getBridge($this->modelAdapter->findByPk($config['id']), $config['slider-column']);
+
+ $content->addSlides($bridge->getSlides());
+ }
+
+ /**
+ * Initialize the bridge.
+ *
+ * @param \Contao\ModuleModel $module
+ * @param string $column
+ *
+ * @return ContaoNews
+ */
+ protected function getBridge($module, $column)
+ {
+ return new ContaoNews($module, $column);
+ }
+}
diff --git a/src/SlideProvider/SlideProviderInterface.php b/src/SlideProvider/SlideProviderInterface.php
new file mode 100644
index 0000000..f929633
--- /dev/null
+++ b/src/SlideProvider/SlideProviderInterface.php
@@ -0,0 +1,37 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider;
+
+use MadeYourDay\RockSolidSlider\SliderContent;
+
+/**
+ * Describes a generic slide provider.
+ *
+ * @author Christian Schiffler
+ */
+interface SlideProviderInterface
+{
+ /**
+ * Retrieve the name of the provider.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Process the passed configuration.
+ *
+ * @param array $config The configuration to process (refer to provider implementation for contents).
+ * @param SliderContent $content The content to populate.
+ *
+ * @return void
+ */
+ public function process(array $config, SliderContent $content);
+}
diff --git a/src/SlideProvider/SlideProviderRegistry.php b/src/SlideProvider/SlideProviderRegistry.php
new file mode 100644
index 0000000..ab1d6df
--- /dev/null
+++ b/src/SlideProvider/SlideProviderRegistry.php
@@ -0,0 +1,77 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\SlideProvider;
+
+/**
+ * The registry for slide providers.
+ *
+ * @author Christian Schiffler
+ */
+class SlideProviderRegistry
+{
+ /**
+ * Registered providers by type as key and instance as value.
+ *
+ * @var SlideProviderInterface[]
+ */
+ private $providers = [];
+
+ /**
+ * Create a new instance.
+ *
+ * @param SlideProviderInterface[] $providers
+ */
+ public function __construct(array $providers = [])
+ {
+ foreach ($providers as $provider) {
+ $this->addProvider($provider);
+ }
+ }
+
+ /**
+ * Add a provider.
+ *
+ * @param SlideProviderInterface $provider The provider to add.
+ *
+ * @return void
+ */
+ public function addProvider(SlideProviderInterface $provider)
+ {
+ $this->providers[(string) $provider->getName()] = $provider;
+ }
+
+ /**
+ * Retrieve the provider by name.
+ *
+ * @param string $name The provider to retrieve.
+ *
+ * @return bool
+ */
+ public function hasProvider($name)
+ {
+ return isset($this->providers[(string) $name]);
+ }
+
+ /**
+ * Retrieve the provider by name.
+ *
+ * @param string $name The provider to retrieve.
+ *
+ * @return SlideProviderInterface
+ */
+ public function getProvider($name)
+ {
+ if (!$this->hasProvider($name)) {
+ throw new \InvalidArgumentException('No provider with the name ' . $name);
+ }
+
+ return $this->providers[(string) $name];
+ }
+}
diff --git a/src/SliderContent.php b/src/SliderContent.php
new file mode 100644
index 0000000..ec7c208
--- /dev/null
+++ b/src/SliderContent.php
@@ -0,0 +1,124 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider;
+
+/**
+ * This class holds the slider contents.
+ *
+ * @author Christian Schiffler
+ */
+class SliderContent
+{
+ /**
+ * The parsed slides.
+ *
+ * @var array
+ */
+ private $slides = [];
+
+ /**
+ * The uuids of the files to add.
+ *
+ * @var string[]
+ */
+ private $files = [];
+
+ /**
+ * The file order.
+ *
+ * @var string[]
+ */
+ private $filesOrder = [];
+
+ /**
+ * Add slides.
+ *
+ * Each slide must at least contain the key 'text'.
+ *
+ * @param array $slides The slides to add.
+ *
+ * @return void
+ */
+ public function addSlides($slides)
+ {
+ foreach ($slides as $slide) {
+ if (!isset($slide['text'])) {
+ throw new \InvalidArgumentException('Slide does not contain key "text".');
+ }
+ $this->slides[] = $slide;
+ }
+ }
+
+ /**
+ * Check if slides are contained.
+ *
+ * @return bool
+ */
+ public function hasSlides()
+ {
+ return (bool) $this->slides;
+ }
+
+ /**
+ * Retrieve the slides.
+ *
+ * @return array
+ */
+ public function getSlides()
+ {
+ return $this->slides;
+ }
+
+ /**
+ * Add files to the content.
+ *
+ * @param string[] $files The uuids.
+ * @param string[] $filesOrder The uuids for sort order.
+ *
+ * @return void
+ */
+ public function addFiles(array $files, array $filesOrder = [])
+ {
+ $this->files = array_merge($this->files, array_values($files));
+ if (!empty($this->filesOrder) || empty($filesOrder)) {
+ $this->filesOrder = array_merge($this->filesOrder, array_values($filesOrder ?: $files));
+ }
+ }
+
+ /**
+ * Check if files are contained.
+ *
+ * @return bool
+ */
+ public function hasFiles()
+ {
+ return (bool) $this->files;
+ }
+
+ /**
+ * Retrieve the files.
+ *
+ * @return array
+ */
+ public function getFiles()
+ {
+ return $this->files;
+ }
+
+ /**
+ * Retrieve the files.
+ *
+ * @return array
+ */
+ public function getFilesOrder()
+ {
+ return $this->filesOrder;
+ }
+}
diff --git a/tests/DependencyInjection/Compiler/AddProvidersPassTest.php b/tests/DependencyInjection/Compiler/AddProvidersPassTest.php
new file mode 100644
index 0000000..4c809ba
--- /dev/null
+++ b/tests/DependencyInjection/Compiler/AddProvidersPassTest.php
@@ -0,0 +1,114 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\DependencyInjection\Compiler;
+
+use MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Tests the AddProvidersPass class.
+ *
+ * @author Christian Schiffler
+ */
+class AddProvidersPassTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @coversNothing
+ */
+ public function testInstantiation()
+ {
+ $pass = new AddProvidersPass();
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass', $pass);
+ }
+
+ /**
+ * Test the processing.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass::process()
+ * @covers \MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass::getProviders()
+ */
+ public function testProcess()
+ {
+ $container = new ContainerBuilder();
+
+ $mock1 = new Reference('foo');
+
+ $container->setDefinition(
+ 'madeyourday.rocksolid_slider.slideproviders',
+ $registry = new Definition('', [[$mock1]])
+ );
+
+ $tagged1 = new Definition('Tagged1');
+ $tagged1->addTag('madeyourday.rocksolid_slider.slideprovider');
+ $tagged2 = new Definition('Tagged1');
+ $tagged2->addTag('madeyourday.rocksolid_slider.slideprovider');
+
+ $container->setDefinition('tagged1', $tagged1);
+ $container->setDefinition('tagged2', $tagged2);
+
+ $pass = new AddProvidersPass();
+
+ $pass->process($container);
+
+ $ids = [];
+ foreach ($registry->getArguments()[0] as $argument) {
+ $this->assertInstanceOf(Reference::class, $argument);
+ $ids[] = (string) $argument;
+ }
+
+ $this->assertEquals(['foo', 'tagged1', 'tagged2'], $ids);
+ }
+
+ /**
+ * Test the processing when no arguments have been provided so far.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass::process()
+ * @covers \MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass::getProviders()
+ */
+ public function testProcessWithoutArguments()
+ {
+ $container = new ContainerBuilder();
+
+ $container->setDefinition(
+ 'madeyourday.rocksolid_slider.slideproviders',
+ $registry = new Definition('')
+ );
+
+ $tagged1 = new Definition('Tagged1');
+ $tagged1->addTag('madeyourday.rocksolid_slider.slideprovider');
+ $tagged2 = new Definition('Tagged1');
+ $tagged2->addTag('madeyourday.rocksolid_slider.slideprovider');
+
+ $container->setDefinition('tagged1', $tagged1);
+ $container->setDefinition('tagged2', $tagged2);
+
+ $pass = new AddProvidersPass();
+
+ $pass->process($container);
+
+ $ids = [];
+ foreach ($registry->getArguments()[0] as $argument) {
+ $this->assertInstanceOf(Reference::class, $argument);
+ $ids[] = (string) $argument;
+ }
+
+ $this->assertEquals(['tagged1', 'tagged2'], $ids);
+ }
+}
diff --git a/tests/DependencyInjection/RockSolidSliderExtensionTest.php b/tests/DependencyInjection/RockSolidSliderExtensionTest.php
new file mode 100644
index 0000000..98545db
--- /dev/null
+++ b/tests/DependencyInjection/RockSolidSliderExtensionTest.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\DependencyInjection;
+
+use MadeYourDay\RockSolidSlider\DependencyInjection\RockSolidSliderExtension;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Tests the RockSolidSliderExtension class.
+ *
+ * @author Christian Schiffler
+ */
+class RockSolidSliderExtensionTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @coversNothing
+ */
+ public function testInstantiation()
+ {
+ $extension = new RockSolidSliderExtension();
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\DependencyInjection\RockSolidSliderExtension', $extension);
+ }
+
+ /**
+ * Tests adding the bundle services to the container.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\DependencyInjection\RockSolidSliderExtension::load()
+ */
+ public function testLoad()
+ {
+ $container = new ContainerBuilder();
+
+ $extension = new RockSolidSliderExtension();
+ $extension->load([], $container);
+
+ $this->assertSame(
+ realpath(__DIR__ . '/../../src/Resources/config/services.yml'),
+ (string) $container->getResources()[0]
+ );
+ $this->assertTrue($container->has('madeyourday.rocksolid_slider.slideproviders'));
+ }
+}
diff --git a/tests/Helper/FileHelperTest.php b/tests/Helper/FileHelperTest.php
new file mode 100644
index 0000000..e744544
--- /dev/null
+++ b/tests/Helper/FileHelperTest.php
@@ -0,0 +1,535 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\Helper;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\FilesModel;
+use MadeYourDay\RockSolidSlider\Helper\FileHelper;
+use PHPUnit\Framework\TestCase;
+use PHPUnit_Framework_MockObject_MockObject;
+
+/**
+ * Tests the FileHelper class.
+ *
+ * @author Christian Schiffler
+ */
+class FileHelperTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ */
+ public function testInstantiation()
+ {
+ $helper = new FileHelper(
+ $this->mockAdapter(),
+ $this->mockAdapter()
+ );
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\Helper\FileHelper', $helper);
+ }
+
+ /**
+ * Test the findMultipleFilesByUuids method.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByUuids()
+ */
+ public function testFindMultipleFilesByUuids()
+ {
+ $filesModelAdapter = $this->mockAdapter(['findMultipleByUuids']);
+ $frontendAdapter = $this->mockAdapter();
+
+ $collection = $this
+ ->getMockBuilder('\Contao\Model\Collection')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $filesModelAdapter
+ ->expects($this->once())
+ ->method('findMultipleByUuids')
+ ->with(['uuid1', 'uuid2'], ['option1' => 'value1', 'option2' => 'value2'])
+ ->willReturn($collection);
+
+ $helper = new FileHelper($filesModelAdapter, $frontendAdapter);
+
+ $this->assertSame(
+ $collection,
+ $helper->findMultipleFilesByUuids(
+ ['uuid1', 'uuid2'],
+ ['option1' => 'value1', 'option2' => 'value2']
+ )
+ );
+ }
+
+ /**
+ * Test the findMultipleFilesByUuidRecursive method.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByUuids()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByUuidRecursive()
+ *
+ * @return void
+ */
+ public function testFindMultipleFilesByUuidRecursive()
+ {
+ $filesModelAdapter = $this->mockAdapter(['findMultipleByUuids', 'getTable', 'findBy']);
+ $frontendAdapter = $this->mockAdapter();
+
+ $filesModelAdapter->method('getTable')->willReturn('tl_files');
+
+ $initial = ['uuid1', 'uuid2'];
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['findMultipleFilesByUuids', 'findMultipleFilesByPidRecursive'])
+ ->getMock();
+ $helper->expects($this->once())
+ ->method('findMultipleFilesByUuids')
+ ->with($initial)
+ ->willReturn([
+ $file1 = $this->mockFileModel(['uuid' => 'uuid1', 'pid' => null, 'type' => 'file']),
+ $this->mockFileModel(['uuid' => 'uuid2', 'pid' => null, 'type' => 'folder']),
+ ]);
+ $helper->expects($this->once())
+ ->method('findMultipleFilesByPidRecursive')
+ ->with(['uuid2'])
+ ->willReturn([
+ $file3 = $this->mockFileModel(['uuid' => 'uuid3', 'pid' => 'uuid2', 'type' => 'file']),
+ $file4 = $this->mockFileModel(['uuid' => 'uuid4', 'pid' => 'uuid2', 'type' => 'file']),
+ ]);
+
+ /** @var FileHelper $helper */
+ $this->assertEquals([$file1, $file3, $file4], $helper->findMultipleFilesByUuidRecursive($initial));
+ }
+
+ /**
+ * Test the findMultipleFilesByUuidRecursive method.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByUuids()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByUuidRecursive()
+ *
+ * @return void
+ */
+ public function testFindMultipleFilesByUuidRecursive2()
+ {
+ $filesModelAdapter = $this->mockAdapter(['findMultipleByUuids', 'getTable', 'findBy']);
+ $frontendAdapter = $this->mockAdapter();
+
+ $filesModelAdapter->method('getTable')->willReturn('tl_files');
+
+ $initial = ['uuid1', 'uuid2'];
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['findMultipleFilesByUuids', 'findMultipleFilesByPidRecursive'])
+ ->getMock();
+ $helper->expects($this->once())
+ ->method('findMultipleFilesByUuids')
+ ->with($initial)
+ ->willReturn([
+ $file1 = $this->mockFileModel(['uuid' => 'uuid1', 'pid' => null, 'type' => 'file']),
+ $file2 = $this->mockFileModel(['uuid' => 'uuid2', 'pid' => null, 'type' => 'file']),
+ ]);
+ $helper->expects($this->never())
+ ->method('findMultipleFilesByPidRecursive');
+
+ /** @var FileHelper $helper */
+ $this->assertEquals([$file1, $file2], $helper->findMultipleFilesByUuidRecursive($initial));
+ }
+
+ /**
+ * Test the findMultipleFilesByPidRecursive method.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByUuids()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::findMultipleFilesByPidRecursive()
+ *
+ * @return void
+ */
+ public function testFindMultipleFilesByPidRecursive()
+ {
+ $filesModelAdapter = $this->mockAdapter(['getTable', 'findBy']);
+ $frontendAdapter = $this->mockAdapter();
+
+ $file3 = $this->mockFileModel(['uuid' => 'uuid3', 'pid' => 'uuid1', 'type' => 'folder']);
+ $file4 = $this->mockFileModel(['uuid' => 'uuid4', 'pid' => 'uuid1', 'type' => 'file']);
+ $file5 = $this->mockFileModel(['uuid' => 'uuid4', 'pid' => 'uuid1', 'type' => 'file']);
+
+ $filesModelAdapter->method('getTable')->willReturn('tl_files');
+
+ $initial = ['uuid1', 'uuid2'];
+
+ $filesModelAdapter->method('findBy')
+ ->withConsecutive(
+ [
+ ['tl_files.pid IN (UNHEX(?),UNHEX(?))'],
+ [bin2hex('uuid1'), bin2hex('uuid2')],
+ []
+ ],
+ [
+ ['tl_files.pid IN (UNHEX(?))'],
+ [bin2hex('uuid3')],
+ []
+ ]
+ )
+ ->willReturnOnConsecutiveCalls(
+ [$file3, $file4],
+ [$file5]
+ );
+
+ $helper = new FileHelper($filesModelAdapter, $frontendAdapter);
+
+ /** @var FileHelper $helper */
+ $this->assertEquals([$file4, $file5], $helper->findMultipleFilesByPidRecursive($initial));
+ }
+
+ /**
+ * Test the prepareImageForTemplate method.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::prepareImageForTemplate()
+ */
+ public function testPrepareImageForTemplate()
+ {
+ $filesModelAdapter = $this->mockAdapter();
+ $frontendAdapter = $this->mockAdapter(['addImageToTemplate']);
+ $frontendAdapter
+ ->expects($this->once())
+ ->method('addImageToTemplate')
+ ->with(new \stdClass, ['option1' => 'value1', 'option2' => 'value2']);
+
+ $helper = new FileHelper($filesModelAdapter, $frontendAdapter);
+
+ $helper->prepareImageForTemplate(['option1' => 'value1', 'option2' => 'value2']);
+ }
+
+ /**
+ * Test the tryPrepareImage method.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::prepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImage()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::ensureFileModel()
+ */
+ public function testTryPrepareImageForTemplate()
+ {
+ $GLOBALS['objPage'] = (object) ['language' => 'en_EN'];
+
+ $filesModelAdapter = $this->mockAdapter(['findByUuid']);
+ $frontendAdapter = $this->mockAdapter(['getMetaData', 'addImageToTemplate']);
+
+ $fileModelMock = (object) [
+ 'id' => 1,
+ 'uuid' => 'the-uuid',
+ 'path' => 'some/path/file.ext',
+ 'meta' => ['file-meta-data']
+ ];
+ $fileMock = (object) [
+ 'uuid' => 'the-uuid',
+ 'path' => 'some/path/file.ext',
+ 'basename' => 'file.ext',
+ 'isGdImage' => true,
+ 'isImage' => true,
+ ];
+
+ $filesModelAdapter
+ ->expects($this->once())
+ ->method('findByUuid')
+ ->with('the-uuid')
+ ->willReturn($fileModelMock);
+
+ $frontendAdapter
+ ->expects($this->once())
+ ->method('getMetaData')
+ ->with(['file-meta-data'], 'en_EN')
+ ->willReturn([
+ 'title' => 'Title',
+ 'link' => 'https://example.org',
+ 'caption' => 'File caption!'
+ ]);
+ $frontendAdapter
+ ->expects($this->once())
+ ->method('addImageToTemplate')
+ ->with(
+ new \stdClass,
+ [
+ 'id' => 1,
+ 'uuid' => 'the-uuid',
+ 'name' => 'file.ext',
+ 'singleSRC' => 'some/path/file.ext',
+ 'additional' => 'attribute',
+ 'alt' => 'Title',
+ 'imageUrl' => 'https://example.org',
+ 'caption' => 'File caption!'
+ ]
+ )
+ ->willReturnCallback(function ($image) { $image->result = 'Success!';});
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['getFileInstance'])
+ ->getMock();
+ $helper
+ ->expects($this->once())
+ ->method('getFileInstance')
+ ->with($fileModelMock->path)
+ ->willReturn($fileMock);
+
+ /** @var FileHelper $helper */
+ $this->assertSame(
+ 'Success!',
+ $helper->tryPrepareImageForTemplate('the-uuid', ['additional' => 'attribute'], true)->result
+ );
+ }
+
+ /**
+ * Test the tryPrepareImage method.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImage()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::ensureFileModel()
+ */
+ public function testTryPrepareImageForTemplateWithoutUuid()
+ {
+
+ $filesModelAdapter = $this->mockAdapter(['findByUuid']);
+ $frontendAdapter = $this->mockAdapter(['getMetaData', 'addImageToTemplate']);
+
+ $filesModelAdapter
+ ->expects($this->never())
+ ->method('findByUuid');
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('getMetaData');
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('addImageToTemplate');
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['getFileInstance'])
+ ->getMock();
+ $helper
+ ->expects($this->never())
+ ->method('getFileInstance');
+
+ /** @var FileHelper $helper */
+ $this->assertNull($helper->tryPrepareImageForTemplate('', []));
+ }
+
+ /**
+ * Test the tryPrepareImage method.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::prepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImage()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::ensureFileModel()
+ */
+ public function testTryPrepareImageForTemplateWithUnknownUuid()
+ {
+
+ $filesModelAdapter = $this->mockAdapter(['findByUuid']);
+ $frontendAdapter = $this->mockAdapter(['getMetaData', 'addImageToTemplate']);
+
+ $filesModelAdapter
+ ->expects($this->once())
+ ->method('findByUuid')
+ ->with('unknown-uuid')
+ ->willReturn(null);
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('getMetaData');
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('addImageToTemplate');
+
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['getFileInstance'])
+ ->getMock();
+ $helper
+ ->expects($this->never())
+ ->method('getFileInstance');
+
+ /** @var FileHelper $helper */
+ $this->assertNull($helper->tryPrepareImageForTemplate('unknown-uuid', []));
+ }
+
+ /**
+ * Test the tryPrepareImage method.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::prepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImage()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImageForTemplate()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::ensureFileModel()
+ */
+ public function testTryPrepareImageForTemplateWithNonImageUuid()
+ {
+ $filesModelAdapter = $this->mockAdapter(['findByUuid']);
+ $frontendAdapter = $this->mockAdapter(['getMetaData', 'addImageToTemplate']);
+
+ $fileModelMock = (object) [
+ 'id' => 1,
+ 'uuid' => 'the-uuid',
+ 'path' => 'some/path/file.ext',
+ 'meta' => ['file-meta-data']
+ ];
+ $fileMock = (object) [
+ 'uuid' => 'the-uuid',
+ 'path' => 'some/path/file.ext',
+ 'basename' => 'file.ext',
+ 'isGdImage' => false,
+ 'isImage' => false,
+ ];
+
+ $filesModelAdapter
+ ->expects($this->once())
+ ->method('findByUuid')
+ ->with('the-uuid')
+ ->willReturn($fileModelMock);
+
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('getMetaData');
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('addImageToTemplate');
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['getFileInstance'])
+ ->getMock();
+ $helper
+ ->expects($this->once())
+ ->method('getFileInstance')
+ ->with('some/path/file.ext')
+ ->willReturn($fileMock);
+
+ /** @var FileHelper $helper */
+ $this->assertNull($helper->tryPrepareImageForTemplate('the-uuid', []));
+ }
+
+ /**
+ * Test the ensureFileModel method does try to look up a passed files model again.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::tryPrepareImage()
+ * @covers \MadeYourDay\RockSolidSlider\Helper\FileHelper::ensureFileModel()
+ */
+ public function testEnsureFileModelDoesNotConvertModel()
+ {
+ $filesModelAdapter = $this->mockAdapter(['findByUuid']);
+ $frontendAdapter = $this->mockAdapter(['getMetaData', 'addImageToTemplate']);
+ $fileModelMock = $this->mockFileModel(['path' => 'some/path/file.ext']);
+
+ $fileMock = (object) [
+ 'isGdImage' => false,
+ 'isImage' => false,
+ ];
+
+ $filesModelAdapter
+ ->expects($this->never())
+ ->method('findByUuid');
+
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('getMetaData');
+ $frontendAdapter
+ ->expects($this->never())
+ ->method('addImageToTemplate');
+
+ $helper = $this
+ ->getMockBuilder(FileHelper::class)
+ ->setConstructorArgs([$filesModelAdapter, $frontendAdapter])
+ ->setMethods(['getFileInstance'])
+ ->getMock();
+ $helper
+ ->expects($this->once())
+ ->method('getFileInstance')
+ ->with('some/path/file.ext')
+ ->willReturn($fileMock);
+
+ /** @var FileHelper $helper */
+ $this->assertNull($helper->tryPrepareImage($fileModelMock, []));
+ }
+
+
+ /**
+ * Mock an adapter
+ *
+ * @param string[] $methods The methods to mock.
+ *
+ * @return Adapter|PHPUnit_Framework_MockObject_MockObject
+ */
+ private function mockAdapter($methods = [])
+ {
+ return $this
+ ->getMockBuilder('Contao\CoreBundle\Framework\Adapter')
+ ->setMethods($methods)
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ /**
+ * Mock a file model.
+ *
+ * @param array $data The data to return.
+ *
+ * @return FilesModel
+ */
+ private function mockFileModel($data)
+ {
+ if (!class_exists('Model')) {
+ class_alias('Contao\Model', 'Model');
+ }
+
+ $fileModelMock = $this
+ ->getMockBuilder(FilesModel::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['__get'])
+ ->getMock();
+ $fileModelMock
+ ->method('__get')
+ ->willReturnCallback(function ($key) use ($data) {
+ if (isset($data[$key])) {
+ return $data[$key];
+ }
+ return null;
+ });
+
+ return $fileModelMock;
+ }
+}
diff --git a/tests/RockSolidSliderBundleTest.php b/tests/RockSolidSliderBundleTest.php
new file mode 100644
index 0000000..7b53db6
--- /dev/null
+++ b/tests/RockSolidSliderBundleTest.php
@@ -0,0 +1,76 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test;
+
+use MadeYourDay\RockSolidSlider\RockSolidSliderBundle;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Tests the RockSolidSliderBundle class.
+ *
+ * @author Christian Schiffler
+ */
+class RockSolidSliderBundleTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @coversNothing
+ */
+ public function testInstantiation()
+ {
+ $bundle = new RockSolidSliderBundle();
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\RockSolidSliderBundle', $bundle);
+ }
+
+ /**
+ * Tests the getContainerExtension() method.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\RockSolidSliderBundle::getContainerExtension()
+ */
+ public function testGetContainerExtension()
+ {
+ $bundle = new RockSolidSliderBundle();
+
+ $this->assertInstanceOf(
+ 'MadeYourDay\RockSolidSlider\DependencyInjection\RockSolidSliderExtension',
+ $bundle->getContainerExtension()
+ );
+ }
+
+ /**
+ * Tests the build() method.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\RockSolidSliderBundle::build()
+ */
+ public function testBuild()
+ {
+ $container = new ContainerBuilder();
+
+ $bundle = new RockSolidSliderBundle();
+ $bundle->build($container);
+
+ $classes = [];
+
+ foreach ($container->getCompilerPassConfig()->getBeforeOptimizationPasses() as $pass) {
+ $reflection = new \ReflectionClass($pass);
+ $classes[] = $reflection->getName();
+ }
+
+ $this->assertEquals(
+ [
+ 'MadeYourDay\RockSolidSlider\DependencyInjection\Compiler\AddProvidersPass',
+ ],
+ $classes
+ );
+ }
+}
diff --git a/tests/SlideProvider/DefaultSlideProviderTest.php b/tests/SlideProvider/DefaultSlideProviderTest.php
new file mode 100644
index 0000000..ba70180
--- /dev/null
+++ b/tests/SlideProvider/DefaultSlideProviderTest.php
@@ -0,0 +1,147 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use MadeYourDay\RockSolidSlider\Helper\FileHelper;
+use MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider;
+use MadeYourDay\RockSolidSlider\SliderContent;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the DefaultSlideProvider class.
+ *
+ * @author Christian Schiffler
+ */
+class DefaultSlideProviderTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider::getName()
+ */
+ public function testInstantiation()
+ {
+ $filesHelper = $this->getMockBuilder(FileHelper::class)->disableOriginalConstructor()->getMock();
+ $sliderModelAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+ $slideModelAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+ $frontendAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+
+ $provider = new DefaultSlideProvider(
+ $filesHelper,
+ $sliderModelAdapter,
+ $slideModelAdapter,
+ $frontendAdapter
+ );
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider', $provider);
+ $this->assertSame('rsts_default', $provider->getName());
+ }
+
+ /**
+ * Test adding providers.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider::process()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::addFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::getFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasSlides()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::getSlides()
+ */
+ public function testProcessWithoutSlider()
+ {
+ $filesHelper = $this->getMockBuilder(FileHelper::class)->disableOriginalConstructor()->getMock();
+ $sliderModelAdapter = $this->getMockBuilder(Adapter::class)->setMethods(['findByPk'])->disableOriginalConstructor()->getMock();
+ $slideModelAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+ $frontendAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+
+ $sliderModelAdapter
+ ->expects($this->once())
+ ->method('findByPk')
+ ->willReturn(null);
+
+ $provider = new DefaultSlideProvider(
+ $filesHelper,
+ $sliderModelAdapter,
+ $slideModelAdapter,
+ $frontendAdapter
+ );
+ $content = new SliderContent();
+
+ $provider->process(['rsts_id' => 42], $content);
+
+ $this->assertFalse($content->hasSlides());
+ $this->assertFalse($content->hasFiles());
+ $this->assertSame([], $content->getSlides());
+ $this->assertSame([], $content->getFiles());
+ }
+
+ /**
+ * Test adding providers.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\DefaultSlideProvider::process()
+ */
+ public function testProcessWithImageSlides()
+ {
+ $filesHelper = $this->getMockBuilder(FileHelper::class)->disableOriginalConstructor()->getMock();
+ $sliderModelAdapter = $this->getMockBuilder(Adapter::class)->setMethods(['findByPk'])->disableOriginalConstructor()->getMock();
+ $slideModelAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+ $frontendAdapter = $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock();
+
+ $sliderModelAdapter
+ ->expects($this->once())
+ ->method('findByPk')
+ ->willReturn((object) [
+ 'id' => 42,
+ 'type' => 'image',
+ 'multiSRC' => serialize(['uuid1', 'uuid2']),
+ 'orderSRC' => serialize(['uuid1', 'uuid2', 'uuid3', 'uuid4']),
+ ]);
+
+ $provider = new DefaultSlideProvider(
+ $filesHelper,
+ $sliderModelAdapter,
+ $slideModelAdapter,
+ $frontendAdapter
+ );
+
+ new SliderContent();
+
+ $content = $this->getMockBuilder(SliderContent::class)->setMethods(
+ [
+ 'addFiles',
+ 'getFiles',
+ 'hasFiles',
+ 'hasSlides',
+ 'getSlides',
+ 'getFilesOrder',
+ ]
+ )->getMock();
+ $content->expects($this->once())->method('addFiles')->with(
+ ['uuid1', 'uuid2'],
+ ['uuid1', 'uuid2', 'uuid3', 'uuid4']
+ );
+ $content->expects($this->never())->method('hasFiles');
+ $content->expects($this->never())->method('getFiles');
+ $content->expects($this->never())->method('getFilesOrder');
+ $content->expects($this->never())->method('hasSlides');
+ $content->expects($this->never())->method('getSlides');
+ $content->expects($this->never())->method('getFiles');
+
+ $provider->process(['rsts_id' => 42], $content);
+ }
+}
diff --git a/tests/SlideProvider/EventsSlideProviderTest.php b/tests/SlideProvider/EventsSlideProviderTest.php
new file mode 100644
index 0000000..7c5fa03
--- /dev/null
+++ b/tests/SlideProvider/EventsSlideProviderTest.php
@@ -0,0 +1,95 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\ModuleModel;
+use MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider;
+use MadeYourDay\RockSolidSlider\SliderContent;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the EventsSlideProvider class.
+ *
+ * @author Christian Schiffler
+ */
+class EventsSlideProviderTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider::getName()
+ */
+ public function testInstantiation()
+ {
+ $provider = new EventsSlideProvider(
+ $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock()
+ );
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider', $provider);
+ $this->assertSame('rsts_events', $provider->getName());
+ }
+
+ /**
+ * Test adding providers.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\EventsSlideProvider::process()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::addSlides()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::getSlides()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasSlides()
+ */
+ public function testProcess()
+ {
+ $bridge= $this
+ ->getMockBuilder(\stdClass::class)
+ ->setMethods(['getSlides'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $bridge->expects($this->once())->method('getSlides')->willReturn([['text' => 'content']]);
+
+ $model = $this->getMockBuilder(ModuleModel::class)->disableOriginalConstructor()->getMock();
+
+ $adapter = $this
+ ->getMockBuilder(Adapter::class)
+ ->setMethods(['findByPk'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $adapter
+ ->expects($this->once())
+ ->method('findByPk')
+ ->with(42)
+ ->willReturn($model);
+
+ $provider = $this
+ ->getMockBuilder(EventsSlideProvider::class)
+ ->setMethods(['getBridge'])
+ ->setConstructorArgs([$adapter])
+ ->getMock();
+ $provider
+ ->expects($this->once())
+ ->method('getBridge')
+ ->with($model, 'main')
+ ->willReturn($bridge);
+
+ $content = new SliderContent();
+
+ /** @@var EventsSlideProvider $provider */
+ $provider->process(['id' => 42, 'slider-column' => 'main'], $content);
+
+ $this->assertTrue($content->hasSlides());
+ $this->assertFalse($content->hasFiles());
+ $this->assertSame([['text' => 'content']], $content->getSlides());
+ }
+}
diff --git a/tests/SlideProvider/ImageSlideProviderTest.php b/tests/SlideProvider/ImageSlideProviderTest.php
new file mode 100644
index 0000000..e6c9cbc
--- /dev/null
+++ b/tests/SlideProvider/ImageSlideProviderTest.php
@@ -0,0 +1,62 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\ModuleModel;
+use MadeYourDay\RockSolidSlider\SlideProvider\ImageSlideProvider;
+use MadeYourDay\RockSolidSlider\SliderContent;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the ImageSlideProvider class.
+ *
+ * @author Christian Schiffler
+ */
+class ImageSlideProviderTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\ImageSlideProvider::getName()
+ */
+ public function testInstantiation()
+ {
+ $provider = new ImageSlideProvider(
+ $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock()
+ );
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\SlideProvider\ImageSlideProvider', $provider);
+ $this->assertSame('rsts_images', $provider->getName());
+ }
+
+ /**
+ * Test adding providers.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\ImageSlideProvider::process()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::addFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::getFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasSlides()
+ */
+ public function testProcess()
+ {
+ $provider = new ImageSlideProvider();
+ $content = new SliderContent();
+
+ $provider->process(['multiSRC' => serialize(['uuid1', 'uuid2'])], $content);
+
+ $this->assertFalse($content->hasSlides());
+ $this->assertTrue($content->hasFiles());
+ $this->assertSame(['uuid1', 'uuid2'], $content->getFiles());
+ }
+}
diff --git a/tests/SlideProvider/NewsSlideProviderTest.php b/tests/SlideProvider/NewsSlideProviderTest.php
new file mode 100644
index 0000000..25e1014
--- /dev/null
+++ b/tests/SlideProvider/NewsSlideProviderTest.php
@@ -0,0 +1,95 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\SlideProvider;
+
+use Contao\CoreBundle\Framework\Adapter;
+use Contao\ModuleModel;
+use MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider;
+use MadeYourDay\RockSolidSlider\SliderContent;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the NewsSlideProvider class.
+ *
+ * @author Christian Schiffler
+ */
+class NewsSlideProviderTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider::getName()
+ */
+ public function testInstantiation()
+ {
+ $provider = new NewsSlideProvider(
+ $this->getMockBuilder(Adapter::class)->disableOriginalConstructor()->getMock()
+ );
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider', $provider);
+ $this->assertSame('rsts_news', $provider->getName());
+ }
+
+ /**
+ * Test adding providers.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\NewsSlideProvider::process()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::addSlides()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::getSlides()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @uses \MadeYourDay\RockSolidSlider\SliderContent::hasSlides()
+ */
+ public function testProcess()
+ {
+ $bridge= $this
+ ->getMockBuilder(\stdClass::class)
+ ->setMethods(['getSlides'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $bridge->expects($this->once())->method('getSlides')->willReturn([['text' => 'content']]);
+
+ $model = $this->getMockBuilder(ModuleModel::class)->disableOriginalConstructor()->getMock();
+
+ $adapter = $this
+ ->getMockBuilder(Adapter::class)
+ ->setMethods(['findByPk'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $adapter
+ ->expects($this->once())
+ ->method('findByPk')
+ ->with(42)
+ ->willReturn($model);
+
+ $provider = $this
+ ->getMockBuilder(NewsSlideProvider::class)
+ ->setMethods(['getBridge'])
+ ->setConstructorArgs([$adapter])
+ ->getMock();
+ $provider
+ ->expects($this->once())
+ ->method('getBridge')
+ ->with($model, 'main')
+ ->willReturn($bridge);
+
+ $content = new SliderContent();
+
+ /** @@var NewsSlideProvider $provider */
+ $provider->process(['id' => 42, 'slider-column' => 'main'], $content);
+
+ $this->assertTrue($content->hasSlides());
+ $this->assertFalse($content->hasFiles());
+ $this->assertSame([['text' => 'content']], $content->getSlides());
+ }
+}
diff --git a/tests/SlideProvider/SlideProviderRegistryTest.php b/tests/SlideProvider/SlideProviderRegistryTest.php
new file mode 100644
index 0000000..8865148
--- /dev/null
+++ b/tests/SlideProvider/SlideProviderRegistryTest.php
@@ -0,0 +1,105 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test\SlideProvider;
+
+use InvalidArgumentException;
+use MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderInterface;
+use MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the SlideProviderRegistry class.
+ *
+ * @author Christian Schiffler
+ */
+class SlideProviderRegistryTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::__construct()
+ */
+ public function testInstantiation()
+ {
+ $registry = new SlideProviderRegistry();
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry', $registry);
+ }
+
+ /**
+ * Test adding providers.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::addProvider()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::getProvider()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::hasProvider()
+ */
+ public function testAddProvider()
+ {
+ $registry = new SlideProviderRegistry();
+
+ $this->assertFalse($registry->hasProvider('test-provider'));
+
+ $mock = $this->getMockForAbstractClass(SlideProviderInterface::class);
+ $mock->method('getName')->willReturn('test-provider');
+
+ $registry->addProvider($mock);
+
+ $this->assertTrue($registry->hasProvider('test-provider'));
+ $this->assertSame($mock, $registry->getProvider('test-provider'));
+ }
+
+ /**
+ * Test that the instance get's populated with constructor arguments.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::addProvider()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::getProvider()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::hasProvider()
+ */
+ public function testInitWithProviders()
+ {
+ $mock1 = $this->getMockForAbstractClass(SlideProviderInterface::class);
+ $mock1->method('getName')->willReturn('test-provider1');
+ $mock2 = $this->getMockForAbstractClass(SlideProviderInterface::class);
+ $mock2->method('getName')->willReturn('test-provider2');
+
+ $registry = new SlideProviderRegistry([$mock1, $mock2]);
+
+ $this->assertTrue($registry->hasProvider('test-provider1'));
+ $this->assertSame($mock1, $registry->getProvider('test-provider1'));
+ $this->assertTrue($registry->hasProvider('test-provider2'));
+ $this->assertSame($mock2, $registry->getProvider('test-provider2'));
+ }
+
+
+ /**
+ * Test that the instance get's populated with constructor arguments.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::__construct()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::getProvider()
+ * @covers \MadeYourDay\RockSolidSlider\SlideProvider\SlideProviderRegistry::hasProvider()
+ */
+ public function testRetrieveUnknownProvider()
+ {
+ $registry = new SlideProviderRegistry();
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('No provider with the name slide-type');
+
+ $registry->getProvider('slide-type');
+ }
+}
diff --git a/tests/SliderContentTest.php b/tests/SliderContentTest.php
new file mode 100644
index 0000000..bb63ecc
--- /dev/null
+++ b/tests/SliderContentTest.php
@@ -0,0 +1,166 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace MadeYourDay\RockSolidSlider\Test;
+
+use MadeYourDay\RockSolidSlider\SliderContent;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests the SliderContent class.
+ *
+ * @author Christian Schiffler
+ */
+class SliderContentTest extends TestCase
+{
+ /**
+ * Tests the object instantiation.
+ *
+ * @coversNothing
+ */
+ public function testInstantiation()
+ {
+ $content = new SliderContent();
+
+ $this->assertInstanceOf('MadeYourDay\RockSolidSlider\SliderContent', $content);
+ }
+
+ /**
+ * Test that empty slides are really empty.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::hasSlides()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::getSlides()
+ */
+ public function testEmptySlides()
+ {
+ $content = new SliderContent();
+
+ $this->assertFalse($content->hasSlides());
+ $this->assertEquals([], $content->getSlides());
+ }
+
+ /**
+ * Test that slides can get added and are returned correctly.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::addSlides()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::hasSlides()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::getSlides()
+ */
+ public function testAddSlides()
+ {
+ $content = new SliderContent();
+ $content->addSlides([
+ ['text' => 'slide 1'],
+ ['text' => 'slide 2'],
+ ['text' => 'slide 3'],
+ ]);
+ $content->addSlides([
+ 'some_key' => ['text' => 'slide 4'],
+ ['text' => 'slide 5'],
+ ['text' => 'slide 6'],
+ ]);
+
+ $this->assertTrue($content->hasSlides());
+ $this->assertEquals(
+ [
+ ['text' => 'slide 1'],
+ ['text' => 'slide 2'],
+ ['text' => 'slide 3'],
+ ['text' => 'slide 4'],
+ ['text' => 'slide 5'],
+ ['text' => 'slide 6'],
+ ],
+ $content->getSlides()
+ );
+ }
+
+ /**
+ * Test that invalid slides can not get added.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::addSlides()
+ */
+ public function testAddInvalidSlide()
+ {
+ $content = new SliderContent();
+ $this->expectException('\InvalidArgumentException');
+ $this->expectExceptionMessage('Slide does not contain key "text".');
+ $content->addSlides([['invalid' => 'slide']]);
+ }
+
+ /**
+ * Test that empty files are really empty.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::getFiles()
+ */
+ public function testEmptyFiles()
+ {
+ $content = new SliderContent();
+
+ $this->assertFalse($content->hasFiles());
+ $this->assertEquals([], $content->getFiles());
+ }
+
+ /**
+ * Test that files can get added and are returned correctly.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::addFiles()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::getFiles()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::getFilesOrder()
+ */
+ public function testAddFiles()
+ {
+ $content = new SliderContent();
+ $content->addFiles(['file 1', 'file 2', 'file 3']);
+ $content->addFiles(['file 4', 'file 5', 'file 6']);
+
+ $this->assertTrue($content->hasFiles());
+ $this->assertEquals(
+ ['file 1', 'file 2', 'file 3', 'file 4', 'file 5', 'file 6'],
+ $content->getFiles()
+ );
+ $this->assertEquals(
+ ['file 1', 'file 2', 'file 3', 'file 4', 'file 5', 'file 6'],
+ $content->getFilesOrder()
+ );
+ }
+
+ /**
+ * Test that files preserve order.
+ *
+ * @return void
+ *
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::addFiles()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::hasFiles()
+ * @covers \MadeYourDay\RockSolidSlider\SliderContent::getFilesOrder()
+ */
+ public function testAddPreservesOrder()
+ {
+ $content = new SliderContent();
+ $content->addFiles(['file 1', 'file 2', 'file 3']);
+ $content->addFiles(['file 4', 'file 5', 'file 6'], ['file 6', 'file 4', 'file 5']);
+
+ $this->assertEquals(
+ ['file 1', 'file 2', 'file 3', 'file 6', 'file 4', 'file 5'],
+ $content->getFilesOrder()
+ );
+ }
+
+}