io-8.x-1.x-dev/modules/io_browser/src/Plugin/views/style/IoBrowserViews.php
modules/io_browser/src/Plugin/views/style/IoBrowserViews.php
<?php
namespace Drupal\io_browser\Plugin\views\style;
use Drupal\Core\Form\FormStateInterface;
use Drupal\blazy\Views\BlazyStyleBase;
use Drupal\io_browser\IoBrowserDefault;
use Drupal\views\Render\ViewsRenderPipelineMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* IO Browser style plugin.
*/
class IoBrowserViews extends BlazyStyleBase {
/**
* {@inheritdoc}
*/
protected static $namespace = 'io';
/**
* {@inheritdoc}
*/
protected static $itemId = 'ib';
/**
* {@inheritdoc}
*/
protected static $itemPrefix = 'ib';
/**
* {@inheritdoc}
*/
protected static $captionId = 'caption';
/**
* {@inheritdoc}
*/
protected $usesRowPlugin = TRUE;
/**
* {@inheritdoc}
*/
protected $usesGrouping = FALSE;
/**
* The io manager service.
*
* @var \Drupal\io\IoManagerInterface
*/
protected $ioManager;
/**
* The blazy formatter service manager.
*
* @var \Drupal\blazy\BlazyFormatterInterface
*/
protected $manager;
/**
* The fields treated as previews.
*
* @var array
*
* @todo recheck other fields, normally images.
*/
protected $previews = [
'blazy_media',
'blazy_file',
'field_image',
];
/**
* {@inheritdoc}
*/
public static function create(
ContainerInterface $container,
array $configuration,
$plugin_id,
$plugin_definition,
) {
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->manager = $instance->manager ?? $container->get('blazy.formatter');
$instance->ioManager = $container->get('io.manager');
return $instance;
}
/**
* Returns the admin.
*/
public function admin() {
return $this->manager->service('blazy.admin.formatter');
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = [];
foreach (IoBrowserDefault::viewsSettings() as $key => $value) {
$options[$key] = ['default' => $value];
}
return $options + parent::defineOptions();
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$definition = [
'plugin_id' => $this->getPluginId(),
'caches' => FALSE,
'namespace' => 'io',
'grid_form' => TRUE,
'grid_required' => TRUE,
'grid_simple' => TRUE,
'no_image_style' => TRUE,
'settings' => $this->options,
'style' => TRUE,
'opening_class' => 'form--io',
'_views' => TRUE,
];
// @todo Adds field handlers to reduce configuration if time permits.
$this->admin()->buildSettingsForm($form, $definition);
$title = '<p class="form__header form__title">';
$title .= $this->t('Use filter IO Browser to have a view switcher. <small>Add one under <strong>Filter criteria</strong> section.</small>');
$title .= '</p>';
$form['opening']['#markup'] = '<div class="form--slick form--style form--views form--half b-tooltip">' . $title;
if (isset($form['style']['#description'])) {
$form['style']['#description'] .= ' ' . $this->t('Ignored if IO Browser view filter has only list (table-like) enabled.');
}
}
/**
* {@inheritdoc}
*/
public function render() {
$view = $this->view;
$settings = $this->buildSettings();
$blazies = $settings['blazies'];
$elements = [];
foreach ($this->renderGrouping($view->result, $settings['grouping']) as $rows) {
$contents = [];
foreach ($this->buildElements($settings, $rows) as $item) {
$contents[] = $item;
}
// Supports Blazy multi-breakpoint images if using Blazy formatter.
if ($data = $this->getFirstImage($rows[0] ?? NULL)) {
$blazies->set('first.data', $data);
}
$build = ['items' => $contents, '#settings' => $settings];
// Attach media assets if a File with potential videos, or Media entity.
if (in_array($view->getBaseEntityType()->id(), ['file', 'media'])) {
$build['#attached']['library'][] = 'io_browser/media';
}
$elements = $this->manager->build($build);
unset($build);
}
return $elements;
}
/**
* Provides generator contents.
*/
protected function buildElements(array $settings, $rows): \Generator {
$view = $this->view;
$keys = array_keys($view->field);
$keys = array_combine($keys, $keys);
$previews = $this->previews;
$previews = array_combine($previews, $previews);
$id = static::$itemId;
foreach ($rows as $index => $row) {
$sets = $settings;
$view->row_index = $index;
$item = $caption = $preview = [];
$sets['delta'] = $index;
$blazy = $sets['blazies']->reset($sets);
$blazy->set('delta', $index);
// Exclude non-preview fields so that theme_views_view_fields() kicks in
// and only render expected preview fields.
// $excludes = array_diff_assoc($keys, $previews);.
foreach ($previews as $name) {
$exclude = FALSE;
if ($field = $view->field[$name] ?? NULL) {
// Blazy views fields: File and Media.
if ($output = $field->render($row)) {
if (!($output instanceof ViewsRenderPipelineMarkup)) {
$preview[] = $output;
$exclude = TRUE;
}
}
// Core plain image.
if ($output = $this->getFieldRenderable($row, $index, $name)) {
if ($rendered = $output['rendered'] ?? []) {
// $theme = $rendered['#theme'] ?? NULL;
// If ($theme == 'image_formatter') {.
// @todo add buttons.
// }
$preview[] = $rendered;
$exclude = TRUE;
}
}
// Exclude previews now so they are not re-rendered below.
$field->options['exclude'] = $exclude;
}
}
$item['preview']['#theme'] = 'container';
$item['preview']['#attributes']['class'][] = $id . '__preview';
$item['preview']['#children'] = $preview;
// The rest of fields are grouped under caption for easy organization.
$caption[] = $view->rowPlugin->render($view->result[$index]);
$item['caption']['#theme'] = 'container';
$item['caption']['#attributes']['class'][] = $id . '__caption';
$item['caption']['#children'] = $caption;
$box = [
'#settings' => $sets,
$id => $item,
];
yield $box;
}
unset($view->row_index);
}
/**
* {@inheritdoc}
*/
protected function buildSettings() {
$settings = parent::buildSettings();
$blazies = $settings['blazies'];
// Prepare needed settings to work with.
$blazies->set('is.browser', TRUE)
->set('is.grid', TRUE)
// @todo remove post blazy:2.18.
->set('item.id', static::$itemId)
->set('namespace', static::$namespace);
return $settings;
}
}
