lory-8.x-1.x-dev/src/LoryManager.php
src/LoryManager.php
<?php
namespace Drupal\lory;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\blazy\Blazy;
use Drupal\blazy\BlazyManagerBase;
use Drupal\lory\Entity\Lory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Implements LoryManagerInterface.
*/
class LoryManager extends BlazyManagerBase implements LoryManagerInterface {
use StringTranslationTrait;
/**
* The lory skin manager service.
*
* @var \Drupal\lory\LoryAssetManagerInterface
*/
protected $assetManager;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->setAssetManager($container->get('lory.asset_manager'));
return $instance;
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks() {
return ['preRenderLory'];
}
/**
* Returns lory asset manager service.
*/
public function assetManager() {
return $this->assetManager;
}
/**
* Sets lory skin manager service.
*/
public function setAssetManager(LoryAssetManagerInterface $asset_manager) {
$this->assetManager = $asset_manager;
return $this;
}
/**
* {@inheritdoc}
*/
public function attach($attach = []) {
$load = parent::attach($attach);
$this->assetManager->attach($load, $attach);
$this->moduleHandler->alter('lory_attach', $load, $attach);
return $load;
}
/**
* {@inheritdoc}
*/
public function lory(array $build = []) {
$element['#theme'] = 'lory';
foreach (LoryDefault::themeProperties() as $key) {
$element["#$key"] = isset($build[$key]) ? $build[$key] : [];
}
$element['#attached'] = $this->attach($build['settings']);
$this->getModuleHandler()->alter('lory', $element, $build);
return empty($build['items']) ? [] : $element;
}
/**
* {@inheritdoc}
*/
public function build(array $build = []) {
foreach (LoryDefault::themeProperties() as $key) {
$build[$key] = isset($build[$key]) ? $build[$key] : [];
}
$lory = [
'#theme' => 'lory_wrapper',
'#items' => [],
'#build' => $build,
'#pre_render' => [[$this, 'preRenderLory']],
'items' => [],
];
$this->moduleHandler->alter('lory_build', $lory, $build['settings']);
return empty($build['items']) ? [] : $lory;
}
/**
* Checks for features.
*/
private function checkFeatures(array &$settings, $optionset) {
foreach ($this->assetManager->getAssets()['features'] as $key => $properties) {
$name = isset($properties['name']) ? $properties['name'] : $key;
if (in_array($key, ['lazy', 'responsive'])) {
$settings[$name] = !empty($settings[$key]);
}
else {
$settings[$name] = $optionset->getOption($name);
}
}
}
/**
* Prepare settings for the known module features, not necessarily users'.
*/
protected function prepareSettings(array &$element, array &$build) {
$settings = &$build['settings'];
$settings += LoryDefault::htmlSettings();
$id = $settings['id'] = Blazy::getHtmlId('lory', $settings['id']);
$skins = $this->assetManager->getAssets()['skins'];
// Additional settings.
$build['optionset'] = $build['optionset'] ?: Lory::loadWithFallback($settings['optionset']);
$settings['count'] = count($build['items']);
$settings['navset'] = (!empty($settings['navset']) && isset($build['items'][1])) ? $settings['navset'] : FALSE;
$settings['navpos'] = ($settings['navset'] && !empty($settings['navpos'])) ? $settings['navpos'] : FALSE;
foreach (['autoWidth', 'infinite', 'vertical', 'width'] as $key) {
$settings[$key] = $build['optionset']->getOption($key);
}
if ($settings['navset']) {
$navset = $build['navset'] = Lory::loadWithFallback($settings['navset']);
$settings['asNavFor'] = '#' . $id . '-nav';
$settings['vertical_tn'] = $navset->getOption('vertical');
}
if (!empty($settings['infinite'])) {
Lory::parseResponsive($settings);
}
Lory::getLayout($settings);
// Pass custom skin options into optionset, only for Main display, not nav.
if (!empty($settings['skin']) && $skin = $skins[$settings['skin']]) {
$skin_options = isset($skin['options']) ? $skin['options'] : [];
if (!empty($skin_options)) {
$build['optionset']->setOptions($skin_options);
}
}
// Supports Blazy multi-breakpoint or lightbox images if provided.
// Cases: Blazy within Views gallery, or references without direct image.
if (!empty($settings['check_blazy']) && !empty($settings['first_image'])) {
$this->isBlazy($settings, $settings['first_image']);
}
}
/**
* Returns lory navigation.
*/
protected function buildNavigation(array &$build, array $thumbs) {
$settings = $build['settings'];
$nav = [];
foreach (['items', 'settings'] as $key) {
$nav[$key] = isset($thumbs[$key]) ? $thumbs[$key] : [];
}
$nav_settings = &$nav['settings'];
foreach (['infinite', 'vertical', 'width'] as $key) {
$nav_settings[$key] = $build['navset']->getOption($key);
}
Lory::getLayout($nav_settings);
if (!empty($nav_settings['infinite'])) {
Lory::parseResponsive($nav_settings);
}
else {
unset($nav_settings['infinite']);
}
$this->checkFeatures($nav_settings, $build['navset']);
$nav_settings['optionset'] = $nav_settings['navset'] = $settings['navset'];
$nav_settings['display'] = 'nav';
$nav_settings['id'] = $settings['id'] . '-nav';
$nav_settings['asNavFor'] = "#" . $settings['id'];
$nav_settings['skin'] = empty($settings['navskin']) ? '' : $settings['navskin'];
$nav['optionset'] = $build['navset'];
unset($build['navset']);
return $this->lory($nav);
}
/**
* One theme_lory() to serve multiple displays: main, overlay, thumbnail.
*/
public function preRenderLory($element) {
$build = $element['#build'];
unset($element['#build']);
// Prepare settings and assets.
$this->prepareSettings($element, $build);
$settings = $build['settings'];
$this->checkFeatures($settings, $build['optionset']);
$thumbs = isset($build['thumb']) ? $build['thumb'] : [];
unset($build['thumb']);
// Build the main Lory.
$lory[0] = $this->lory($build);
// Build the thumbnail Lory.
if ($settings['navset'] && $thumbs) {
$lory[1] = $this->buildNavigation($build, $thumbs);
}
// Reverse lories if thumbnail position is provided to get CSS float works.
if ($settings['navpos']) {
$lory = array_reverse($lory);
}
// Collect the lory instances.
$element['#items'] = $lory;
$element['#settings'] = $settings;
$element['#cache'] = $this->getCacheMetadata($build);
return $element;
}
}
