Initial standalone configurable views pane module
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
29
README.md
Normal file
29
README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Configurable Views Pane
|
||||
|
||||
Standalone Drupal module that provides one block plugin for Page Manager / Panels variants:
|
||||
|
||||
- Plugin ID: `booking_configurable_views_pane`
|
||||
- Form fields: `view_id`, `display_id`, `arguments`
|
||||
|
||||
It lets editors set view target and contextual arguments per block instance, similar to legacy Drupal 7 pane behavior.
|
||||
|
||||
## Install
|
||||
|
||||
1. Place this module at:
|
||||
`web/modules/custom/configurable_views_pane`
|
||||
2. Enable module:
|
||||
`drush en configurable_views_pane -y`
|
||||
3. Rebuild cache:
|
||||
`drush cr`
|
||||
|
||||
## Use in Page Manager
|
||||
|
||||
Add block **Configurable Views Pane** and set:
|
||||
|
||||
- **View ID**: e.g. `audio_resource_embedded_player`
|
||||
- **Display ID**: e.g. `default` or `block_1`
|
||||
- **Contextual arguments**: e.g. `1770` (comma/pipe/newline separated)
|
||||
|
||||
## Notes
|
||||
|
||||
- This module intentionally keeps plugin id `booking_configurable_views_pane` for compatibility with any existing block config already using that id.
|
||||
9
composer.json
Normal file
9
composer.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "custom/configurable_views_pane",
|
||||
"description": "Drupal module providing configurable views pane block for Page Manager.",
|
||||
"type": "drupal-module",
|
||||
"license": "proprietary",
|
||||
"require": {
|
||||
"drupal/core": "^10 || ^11"
|
||||
}
|
||||
}
|
||||
7
configurable_views_pane.info.yml
Normal file
7
configurable_views_pane.info.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
name: Configurable Views Pane
|
||||
type: module
|
||||
description: 'Reusable block plugin that lets editors configure view_id/display/arguments per Page Manager block instance.'
|
||||
package: Custom
|
||||
core_version_requirement: ^10 || ^11
|
||||
dependencies:
|
||||
- drupal:views
|
||||
213
src/Plugin/Block/ConfigurableViewsPaneBlock.php
Normal file
213
src/Plugin/Block/ConfigurableViewsPaneBlock.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\configurable_views_pane\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\views\Views;
|
||||
|
||||
/**
|
||||
* Configurable Views block for Page Manager / Panels variants.
|
||||
*
|
||||
* @Block(
|
||||
* id = "booking_configurable_views_pane",
|
||||
* admin_label = @Translation("Configurable Views Pane"),
|
||||
* category = @Translation("Custom")
|
||||
* )
|
||||
*/
|
||||
final class ConfigurableViewsPaneBlock extends BlockBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration(): array {
|
||||
return [
|
||||
'view_id' => '',
|
||||
'display_id' => '',
|
||||
'arguments' => '',
|
||||
] + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function blockAccess(AccountInterface $account): AccessResult {
|
||||
$view_id = $this->normalizedViewId((string) ($this->configuration['view_id'] ?? ''));
|
||||
$display_id = trim((string) ($this->configuration['display_id'] ?? ''));
|
||||
if ($view_id === '' || $display_id === '') {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
$view = Views::getView($view_id);
|
||||
if (!$view || !$this->displayExists($view_id, $display_id)) {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
$result = AccessResult::allowedIf($view->access($display_id, $account));
|
||||
if ($view->storage) {
|
||||
$result = $result->addCacheableDependency($view->storage);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build(): array {
|
||||
$view_id = $this->normalizedViewId((string) ($this->configuration['view_id'] ?? ''));
|
||||
$display_id = trim((string) ($this->configuration['display_id'] ?? ''));
|
||||
if ($view_id === '' || $display_id === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$view = Views::getView($view_id);
|
||||
if (!$view || !$this->displayExists($view_id, $display_id)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$args = $this->parseArguments((string) ($this->configuration['arguments'] ?? ''));
|
||||
$build = $view->buildRenderable($display_id, $args, FALSE);
|
||||
if (!is_array($build)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$build['#attributes']['class'][] = 'configurable-views-pane-block';
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockForm($form, FormStateInterface $form_state): array {
|
||||
$form = parent::blockForm($form, $form_state);
|
||||
|
||||
$form['view_id'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('View ID'),
|
||||
'#default_value' => (string) ($this->configuration['view_id'] ?? ''),
|
||||
'#required' => TRUE,
|
||||
'#description' => $this->t('Machine name of the view. Example: audio_resource_embedded_player'),
|
||||
];
|
||||
$form['display_id'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Display ID'),
|
||||
'#default_value' => (string) ($this->configuration['display_id'] ?? ''),
|
||||
'#required' => TRUE,
|
||||
'#description' => $this->t('Display machine name. Example: block_1, page_1, block_nid_1770'),
|
||||
];
|
||||
$form['arguments'] = [
|
||||
'#type' => 'textarea',
|
||||
'#title' => $this->t('Contextual arguments'),
|
||||
'#default_value' => (string) ($this->configuration['arguments'] ?? ''),
|
||||
'#rows' => 2,
|
||||
'#description' => $this->t('Optional contextual arguments. Separate multiple values with comma, pipe, or newline. Example: 1770'),
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockValidate($form, FormStateInterface $form_state): void {
|
||||
parent::blockValidate($form, $form_state);
|
||||
|
||||
$view_id = $this->normalizedViewId((string) $form_state->getValue('view_id'));
|
||||
$display_id = trim((string) $form_state->getValue('display_id'));
|
||||
|
||||
if ($view_id === '') {
|
||||
$form_state->setErrorByName('view_id', $this->t('View ID is required.'));
|
||||
return;
|
||||
}
|
||||
if ($display_id === '') {
|
||||
$form_state->setErrorByName('display_id', $this->t('Display ID is required.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$view = Views::getView($view_id);
|
||||
if (!$view) {
|
||||
$form_state->setErrorByName('view_id', $this->t('View %view was not found.', ['%view' => $view_id]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->displayExists($view_id, $display_id)) {
|
||||
$displays = implode(', ', $this->displayIds($view_id));
|
||||
$form_state->setErrorByName(
|
||||
'display_id',
|
||||
$this->t('Display %display does not exist on view %view. Available displays: %available', [
|
||||
'%display' => $display_id,
|
||||
'%view' => $view_id,
|
||||
'%available' => $displays !== '' ? $displays : '<none>',
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function blockSubmit($form, FormStateInterface $form_state): void {
|
||||
parent::blockSubmit($form, $form_state);
|
||||
$this->configuration['view_id'] = $this->normalizedViewId((string) $form_state->getValue('view_id'));
|
||||
$this->configuration['display_id'] = trim((string) $form_state->getValue('display_id'));
|
||||
$this->configuration['arguments'] = trim((string) $form_state->getValue('arguments'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a display exists on a view.
|
||||
*/
|
||||
private function displayExists(string $view_id, string $display_id): bool {
|
||||
return in_array($display_id, $this->displayIds($view_id), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns known display IDs for a view.
|
||||
*
|
||||
* @return string[]
|
||||
* Display IDs.
|
||||
*/
|
||||
private function displayIds(string $view_id): array {
|
||||
$view = Views::getView($view_id);
|
||||
if (!$view || !$view->storage) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$definitions = (array) ($view->storage->get('display') ?? []);
|
||||
return array_values(array_filter(array_map(static function ($id) {
|
||||
return is_scalar($id) ? trim((string) $id) : '';
|
||||
}, array_keys($definitions)), static function ($id) {
|
||||
return $id !== '';
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses arguments from a config string.
|
||||
*
|
||||
* @return string[]
|
||||
* Clean argument list.
|
||||
*/
|
||||
private function parseArguments(string $raw): array {
|
||||
$raw = trim($raw);
|
||||
if ($raw === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$parts = preg_split('/[\r\n,\|]+/', $raw) ?: [];
|
||||
return array_values(array_filter(array_map(static function ($item) {
|
||||
return trim((string) $item);
|
||||
}, $parts), static function ($item) {
|
||||
return $item !== '';
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes view machine names.
|
||||
*/
|
||||
private function normalizedViewId(string $value): string {
|
||||
$value = strtolower(trim($value));
|
||||
return preg_replace('/[^a-z0-9_]+/', '_', $value) ?: '';
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user