Move all files to 2017/

This commit is contained in:
Oliver Davies 2025-09-29 22:25:17 +01:00
parent ac7370f67f
commit 2875863330
15717 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,88 @@
<?php
namespace Drupal\contextual;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Site\Settings;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
/**
* Returns responses for Contextual module routes.
*/
class ContextualController implements ContainerInjectionInterface {
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* Constructors a new ContextualController.
*
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(RendererInterface $renderer) {
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('renderer')
);
}
/**
* Returns the requested rendered contextual links.
*
* Given a list of contextual links IDs, render them. Hence this must be
* robust to handle arbitrary input.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The Symfony request object.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* The JSON response.
*
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
* Thrown when the request contains no ids.
*
* @see contextual_preprocess()
*/
public function render(Request $request) {
$ids = $request->request->get('ids');
if (!isset($ids)) {
throw new BadRequestHttpException(t('No contextual ids specified.'));
}
$tokens = $request->request->get('tokens');
if (!isset($tokens)) {
throw new BadRequestHttpException(t('No contextual ID tokens specified.'));
}
$rendered = [];
foreach ($ids as $key => $id) {
if (!isset($tokens[$key]) || !Crypt::hashEquals($tokens[$key], Crypt::hmacBase64($id, Settings::getHashSalt() . \Drupal::service('private_key')->get()))) {
throw new BadRequestHttpException('Invalid contextual ID specified.');
}
$element = [
'#type' => 'contextual_links',
'#contextual_links' => _contextual_id_to_links($id),
];
$rendered[$id] = $this->renderer->renderRoot($element);
}
return new JsonResponse($rendered);
}
}

View file

@ -0,0 +1,115 @@
<?php
namespace Drupal\contextual\Element;
use Drupal\Component\Utility\Html;
use Drupal\Core\Render\Element\RenderElement;
use Drupal\Core\Url;
/**
* Provides a contextual_links element.
*
* @RenderElement("contextual_links")
*/
class ContextualLinks extends RenderElement {
/**
* {@inheritdoc}
*/
public function getInfo() {
$class = get_class($this);
return [
'#pre_render' => [
[$class, 'preRenderLinks'],
],
'#theme' => 'links__contextual',
'#links' => [],
'#attributes' => ['class' => ['contextual-links']],
'#attached' => [
'library' => [
'contextual/drupal.contextual-links',
],
],
];
}
/**
* Pre-render callback: Builds a renderable array for contextual links.
*
* @param array $element
* A renderable array containing a #contextual_links property, which is a
* keyed array. Each key is the name of the group of contextual links to
* render (based on the 'group' key in the *.links.contextual.yml files for
* all enabled modules). The value contains an associative array containing
* the following keys:
* - route_parameters: The route parameters passed to the url generator.
* - metadata: Any additional data needed in order to alter the link.
* @code
* array('#contextual_links' => array(
* 'block' => array(
* 'route_parameters' => array('block' => 'system.menu-tools'),
* ),
* 'menu' => array(
* 'route_parameters' => array('menu' => 'tools'),
* ),
* ))
* @endcode
*
* @return array
* A renderable array representing contextual links.
*/
public static function preRenderLinks(array $element) {
// Retrieve contextual menu links.
$items = [];
$contextual_links_manager = static::contextualLinkManager();
foreach ($element['#contextual_links'] as $group => $args) {
$args += [
'route_parameters' => [],
'metadata' => [],
];
$items += $contextual_links_manager->getContextualLinksArrayByGroup($group, $args['route_parameters'], $args['metadata']);
}
// Transform contextual links into parameters suitable for links.html.twig.
$links = [];
foreach ($items as $class => $item) {
$class = Html::getClass($class);
$links[$class] = [
'title' => $item['title'],
'url' => Url::fromRoute(isset($item['route_name']) ? $item['route_name'] : '', isset($item['route_parameters']) ? $item['route_parameters'] : [], $item['localized_options']),
];
}
$element['#links'] = $links;
// Allow modules to alter the renderable contextual links element.
static::moduleHandler()->alter('contextual_links_view', $element, $items);
// If there are no links, tell drupal_render() to abort rendering.
if (empty($element['#links'])) {
$element['#printed'] = TRUE;
}
return $element;
}
/**
* Wraps the contextual link manager.
*
* @return \Drupal\Core\Menu\ContextualLinkManager
*/
protected static function contextualLinkManager() {
return \Drupal::service('plugin.manager.menu.contextual_link');
}
/**
* Wraps the module handler.
*
* @return \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected static function moduleHandler() {
return \Drupal::moduleHandler();
}
}

View file

@ -0,0 +1,58 @@
<?php
namespace Drupal\contextual\Element;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Site\Settings;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Render\Element\RenderElement;
use Drupal\Component\Render\FormattableMarkup;
/**
* Provides a contextual_links_placeholder element.
*
* @RenderElement("contextual_links_placeholder")
*/
class ContextualLinksPlaceholder extends RenderElement {
/**
* {@inheritdoc}
*/
public function getInfo() {
$class = get_class($this);
return [
'#pre_render' => [
[$class, 'preRenderPlaceholder'],
],
'#id' => NULL,
];
}
/**
* Pre-render callback: Renders a contextual links placeholder into #markup.
*
* Renders an empty (hence invisible) placeholder div with a data-attribute
* that contains an identifier ("contextual id"), which allows the JavaScript
* of the drupal.contextual-links library to dynamically render contextual
* links.
*
* @param array $element
* A structured array with #id containing a "contextual id".
*
* @return array
* The passed-in element with a contextual link placeholder in '#markup'.
*
* @see _contextual_links_to_id()
*/
public static function preRenderPlaceholder(array $element) {
$token = Crypt::hmacBase64($element['#id'], Settings::getHashSalt() . \Drupal::service('private_key')->get());
$attribute = new Attribute([
'data-contextual-id' => $element['#id'],
'data-contextual-token' => $token,
]);
$element['#markup'] = new FormattableMarkup('<div@attributes></div>', ['@attributes' => $attribute]);
return $element;
}
}

View file

@ -0,0 +1,153 @@
<?php
namespace Drupal\contextual\Plugin\views\field;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\Core\Url;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
/**
* Provides a handler that adds contextual links.
*
* @ingroup views_field_handlers
*
* @ViewsField("contextual_links")
*/
class ContextualLinks extends FieldPluginBase {
use RedirectDestinationTrait;
/**
* {@inheritdoc}
*/
public function usesGroupBy() {
return FALSE;
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['fields'] = ['default' => []];
$options['destination'] = ['default' => 1];
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$all_fields = $this->view->display_handler->getFieldLabels();
// Offer to include only those fields that follow this one.
$field_options = array_slice($all_fields, 0, array_search($this->options['id'], array_keys($all_fields)));
$form['fields'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Fields'),
'#description' => $this->t('Fields to be included as contextual links.'),
'#options' => $field_options,
'#default_value' => $this->options['fields'],
];
$form['destination'] = [
'#type' => 'select',
'#title' => $this->t('Include destination'),
'#description' => $this->t('Include a "destination" parameter in the link to return the user to the original view upon completing the contextual action.'),
'#options' => [
'0' => $this->t('No'),
'1' => $this->t('Yes'),
],
'#default_value' => $this->options['destination'],
];
}
/**
* {@inheritdoc}
*/
public function preRender(&$values) {
// Add a row plugin css class for the contextual link.
$class = 'contextual-region';
if (!empty($this->view->style_plugin->options['row_class'])) {
$this->view->style_plugin->options['row_class'] .= " $class";
}
else {
$this->view->style_plugin->options['row_class'] = $class;
}
}
/**
* Overrides \Drupal\views\Plugin\views\field\FieldPluginBase::render().
*
* Renders the contextual fields.
*
* @param \Drupal\views\ResultRow $values
* The values retrieved from a single row of a view's query result.
*
* @see contextual_preprocess()
* @see contextual_contextual_links_view_alter()
*/
public function render(ResultRow $values) {
$links = [];
foreach ($this->options['fields'] as $field) {
$rendered_field = $this->view->style_plugin->getField($values->index, $field);
if (empty($rendered_field)) {
continue;
}
$title = $this->view->field[$field]->last_render_text;
$path = '';
if (!empty($this->view->field[$field]->options['alter']['path'])) {
$path = $this->view->field[$field]->options['alter']['path'];
}
elseif (!empty($this->view->field[$field]->options['alter']['url']) && $this->view->field[$field]->options['alter']['url'] instanceof Url) {
$path = $this->view->field[$field]->options['alter']['url']->toString();
}
if (!empty($title) && !empty($path)) {
// Make sure that tokens are replaced for this paths as well.
$tokens = $this->getRenderTokens([]);
$path = strip_tags(Html::decodeEntities(strtr($path, $tokens)));
$links[$field] = [
'href' => $path,
'title' => $title,
];
if (!empty($this->options['destination'])) {
$links[$field]['query'] = $this->getDestinationArray();
}
}
}
// Renders a contextual links placeholder.
if (!empty($links)) {
$contextual_links = [
'contextual' => [
'',
[],
[
'contextual-views-field-links' => UrlHelper::encodePath(Json::encode($links)),
],
],
];
$element = [
'#type' => 'contextual_links_placeholder',
'#id' => _contextual_links_to_id($contextual_links),
];
return \Drupal::service('renderer')->render($element);
}
else {
return '';
}
}
/**
* {@inheritdoc}
*/
public function query() {}
}