Initial Drupal 11 with DDEV setup

This commit is contained in:
gluebox
2025-10-08 11:39:17 -04:00
commit 89ef74b305
25344 changed files with 2599172 additions and 0 deletions

View File

@ -0,0 +1,7 @@
views.argument_default.{{ plugin_id }}:
type: mapping
label: '{{ plugin_label }}'
mapping:
example:
type: string
label: 'Example'

View File

@ -0,0 +1,113 @@
{% import '@lib/di.twig' as di %}
<?php
declare(strict_types=1);
namespace Drupal\{{ machine_name }}\Plugin\views\argument_default;
{% apply sort_namespaces %}
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\views\Attribute\ViewsArgumentDefault;
{% if configurable %}
use Drupal\Core\Form\FormStateInterface;
{% endif %}
use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
{% if services %}
{{ di.use(services) }}
use Symfony\Component\DependencyInjection\ContainerInterface;
{% endif %}
{% endapply %}
/**
* @todo Add plugin description here.
*/
#[ViewsArgumentDefault(
id: '{{ plugin_id }}',
title: new TranslatableMarkup('{{ plugin_label }}'),
)]
final class {{ class }} extends ArgumentDefaultPluginBase implements CacheableDependencyInterface {
{% if services %}
/**
* Constructs a new {{ class }} instance.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
{{ di.signature(services) }}
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
return new self(
$configuration,
$plugin_id,
$plugin_definition,
{{ di.container(services) }}
);
}
{% endif %}
{% if configurable %}
/**
* {@inheritdoc}
*/
protected function defineOptions(): array {
$options = parent::defineOptions();
$options['example'] = ['default' => ''];
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
$form['example'] = [
'#type' => 'textfield',
'#title' => $this->t('Example'),
'#default_value' => $this->options['example'],
];
}
{% endif %}
/**
* {@inheritdoc}
*
* @todo Make sure the return type-hint matches the argument type.
*/
public function getArgument(): int {
// @DCG
// Here is the place where you should create a default argument for the
// contextual filter. The source of this argument depends on your needs.
// For example, the argument can be extracted from the URL or fetched from
// some fields of the currently viewed entity.
$argument = 123;
return $argument;
}
/**
* {@inheritdoc}
*/
public function getCacheMaxAge(): int {
return Cache::PERMANENT;
}
/**
* {@inheritdoc}
*/
public function getCacheContexts(): array {
// @todo Use 'url.path' or 'url.query_args:%key' contexts if the argument
// comes from URL.
return [];
}
}

View File

@ -0,0 +1,108 @@
{% import '@lib/di.twig' as di %}
<?php
declare(strict_types=1);
namespace Drupal\{{ machine_name }}\Plugin\views\field;
{% apply sort_namespaces %}
use Drupal\Component\Render\MarkupInterface;
use Drupal\views\Attribute\ViewsField;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
{% if configurable %}
use Drupal\Core\Form\FormStateInterface;
{% endif %}
{% if services %}
{{ di.use(services) }}
use Symfony\Component\DependencyInjection\ContainerInterface;
{% endif %}
{% endapply %}
/**
* Provides {{ plugin_label }} field handler.
*
* @DCG
* The plugin needs to be assigned to a specific table column through
* hook_views_data() or hook_views_data_alter().
* Put the following code to {{ machine_name }}.views.inc file.
* @code
* function foo_views_data_alter(array &$data): void {
* $data['node']['foo_example']['field'] = [
* 'title' => t('Example'),
* 'help' => t('Custom example field.'),
* 'id' => 'foo_example',
* ];
* }
* @endcode
*/
#[ViewsField('{{ plugin_id }}')]
final class {{ class }} extends FieldPluginBase {
{% if services %}
/**
* Constructs a new {{ class }} instance.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
{{ di.signature(services) }}
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
return new self(
$configuration,
$plugin_id,
$plugin_definition,
{{ di.container(services) }}
);
}
{% endif %}
{% if configurable %}
/**
* {@inheritdoc}
*/
protected function defineOptions(): array {
$options = parent::defineOptions();
$options['example'] = ['default' => ''];
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
parent::buildOptionsForm($form, $form_state);
$form['example'] = [
'#type' => 'textfield',
'#title' => $this->t('Example'),
'#default_value' => $this->options['example'],
];
}
{% endif %}
/**
* {@inheritdoc}
*/
public function query(): void {
// For non-existent columns (i.e. computed fields) this method must be
// empty.
}
/**
* {@inheritdoc}
*/
public function render(ResultRow $values): string|MarkupInterface {
$value = parent::render($values);
// @todo Modify or replace the rendered value here.
return $value;
}
}

View File

@ -0,0 +1,7 @@
views.field.{{ plugin_id }}:
type: views.field.field
label: '{{ plugin_label }}'
mapping:
example:
type: string
label: 'Example'

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/**
* @file
* Primary module hooks for {{ name }} module.
*/
use Drupal\Core\Template\Attribute;
/**
* Prepares variables for views-style-{{ plugin_id|u2h }}.html.twig template.
*/
function template_preprocess_views_style_{{ plugin_id }}(array &$variables): void {
$view = $variables['view'];
$options = $view->style_plugin->options;
{% if configurable %}
// Fetch wrapper classes from handler options.
if ($options['wrapper_class']) {
$variables['attributes']['class'] = explode(' ', $options['wrapper_class']);
}
{% endif %}
$variables['default_row_class'] = $options['default_row_class'];
foreach ($variables['rows'] as $id => $row) {
$variables['rows'][$id] = [
'content' => $row,
'attributes' => new Attribute(),
];
if ($row_class = $view->style_plugin->getRowClass($id)) {
$variables['rows'][$id]['attributes']->addClass($row_class);
}
}
}

View File

@ -0,0 +1,7 @@
views.style.{{ plugin_id }}:
type: views_style
label: '{{ plugin_label }}'
mapping:
wrapper_class:
type: string
label: 'Wrapper class'

View File

@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace Drupal\{{ machine_name }}\Plugin\views\style;
{% apply sort_namespaces %}
{% if configurable %}
use Drupal\Core\Form\FormStateInterface;
{% endif %}
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\views\Attribute\ViewsStyle;
{% endapply %}
/**
* {{ plugin_label }} style plugin.
*/
#[ViewsStyle(
id: '{{ plugin_id }}',
title: new TranslatableMarkup('{{ plugin_label }}'),
help: new TranslatableMarkup('@todo Add help text here.'),
theme: 'views_style_{{ plugin_id }}',
display_types: ['normal'],
)]
final class {{ class }} extends StylePluginBase {
/**
* {@inheritdoc}
*/
protected $usesRowPlugin = TRUE;
/**
* {@inheritdoc}
*/
protected $usesRowClass = TRUE;
{% if configurable %}
/**
* {@inheritdoc}
*/
protected function defineOptions(): array {
$options = parent::defineOptions();
$options['wrapper_class'] = ['default' => 'item-list'];
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
parent::buildOptionsForm($form, $form_state);
$form['wrapper_class'] = [
'#type' => 'textfield',
'#title' => $this->t('Wrapper class'),
'#description' => $this->t('The class to provide on the wrapper, outside rows.'),
'#default_value' => $this->options['wrapper_class'],
];
}
{% endif %}
}

View File

@ -0,0 +1,23 @@
{{ '{#' }}
/**
* @file
* Default theme implementation for a view template to display a list of rows.
*
* Available variables:
* - attributes: HTML attributes for the container.
* - rows: A list of rows.
* - attributes: The row's HTML attributes.
* - content: The row's contents.
* - title: The title of this group of rows. May be empty.
*
* @see template_preprocess_views_style_{{ plugin_id }}()
*/
{{ '#}' }}{% verbatim %}
<div{{ attributes }}>
{% set row_classes = [default_row_class ? 'views-row'] %}
{% for row in rows %}
<div{{ row.attributes.addClass(row_classes) }}>
{{ row.content }}
</div>
{% endfor %}
</div>{% endverbatim %}