Skip to content

Commit

Permalink
Merge pull request #944 from UN-OCHA/berliner/HPC-9391
Browse files Browse the repository at this point in the history
HPC-9391: Use Optional link trait logic also in carousel element
  • Loading branch information
berliner authored Mar 20, 2024
2 parents 4adc4d0 + aa1d11e commit abb61b0
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 66 deletions.
78 changes: 20 additions & 58 deletions html/modules/custom/ghi_blocks/src/Element/CarouselItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

namespace Drupal\ghi_blocks\Element;

use Drupal\Core\Entity\Element\EntityAutocomplete;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\FormElement;
use Drupal\ghi_form_elements\Traits\OptionalLinkTrait;
use Drupal\link\LinkItemInterface;
use Drupal\link\Plugin\Field\FieldWidget\LinkWidget;

/**
Expand All @@ -15,6 +16,8 @@
*/
class CarouselItem extends FormElement {

use OptionalLinkTrait;

const THUMBNAIL_DIRECTORY = 'public://content-panes/carousel-items/';

/**
Expand Down Expand Up @@ -77,11 +80,13 @@ public static function processCarouselItem(array &$element, FormStateInterface $
'#type' => 'textfield',
'#title' => t('Tag line'),
'#default_value' => $element['#default_value']['tag_line'] ?? NULL,
'#description' => t('Enter a tag line that will appear above the title.'),
];
$element['description'] = [
'#type' => 'textarea',
'#title' => t('Description'),
'#default_value' => $element['#default_value']['description'] ?? NULL,
'#description' => t('Enter a short description for this link.'),
];
$element['image'] = [
'#type' => 'managed_file',
Expand All @@ -96,17 +101,29 @@ public static function processCarouselItem(array &$element, FormStateInterface $
'#type' => 'textfield',
'#title' => t('Image credit'),
'#default_value' => $element['#default_value']['image_credit'] ?? NULL,
'#description' => t('Enter a credit for the image. This will appear on top of the image.'),
];
$element['image_caption'] = [
'#type' => 'textfield',
'#title' => t('Image caption'),
'#default_value' => $element['#default_value']['image_caption'] ?? NULL,
'#description' => t('Enter a caption for the image. This will appear together with the image credit on top of the image.'),
];
$element['url'] = [
'#type' => 'path',
'#type' => 'entity_autocomplete',
'#title' => t('Url'),
'#default_value' => static::getUriAsDisplayableString($element['#default_value']['url']) ?? NULL,
'#default_value' => self::getUriAsDisplayableString($element['#default_value']['url']) ?? NULL,
'#description' => t('Start typing the title of a piece of content to select it. You can also enter an external URL such as %url.', [
'%url' => 'http://example.com',
]),
'#link_type' => LinkItemInterface::LINK_GENERIC,
'#target_type' => 'node',
'#attributes' => [
'data-autocomplete-first-character-blacklist' => '/#?',
],
'#process_default_value' => FALSE,
'#element_validate' => [[LinkWidget::class, 'validateUriElement']],
'#maxlength' => 256,
];
$element['button_label'] = [
'#type' => 'textfield',
Expand All @@ -130,59 +147,4 @@ public static function preRenderCarouselItem(array $element) {
return $element;
}

/**
* Gets the URI without the 'internal:' or 'entity:' scheme.
*
* The following two forms of URIs are transformed:
* - 'entity:' URIs: to entity autocomplete ("label (entity id)") strings;
* - 'internal:' URIs: the scheme is stripped.
*
* This method is the inverse of ::getUserEnteredStringAsUri().
*
* This method has been copied from LinkWidget::getUriAsDisplayableString().
*
* @param string $uri
* The URI to get the displayable string for.
*
* @return string
* The uri as a displayable (human-readably) string.
*
* @see LinkWidget::getUserEnteredStringAsUri()
*/
protected static function getUriAsDisplayableString($uri) {
$scheme = parse_url($uri, PHP_URL_SCHEME);

// By default, the displayable string is the URI.
$displayable_string = $uri;

// A different displayable string may be chosen in case of the 'internal:'
// or 'entity:' built-in schemes.
if ($scheme === 'internal') {
$uri_reference = explode(':', $uri, 2)[1];

// @todo '<front>' is valid input for BC reasons, may be removed by
// https://www.drupal.org/node/2421941
$path = parse_url($uri, PHP_URL_PATH);
if ($path === '/') {
$uri_reference = '<front>' . substr($uri_reference, 1);
}

$displayable_string = $uri_reference;
}
elseif ($scheme === 'entity') {
[$entity_type, $entity_id] = explode('/', substr($uri, 7), 2);
// Show the 'entity:' URI as the entity autocomplete would.
// @todo Support entity types other than 'node'. Will be fixed in
// https://www.drupal.org/node/2423093.
if ($entity_type == 'node' && $entity = \Drupal::entityTypeManager()->getStorage($entity_type)->load($entity_id)) {
$displayable_string = EntityAutocomplete::getEntityLabels([$entity]);
}
}
elseif ($scheme === 'route') {
$displayable_string = ltrim($displayable_string, 'route:');
}

return $displayable_string;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Markup;
use Drupal\file\Entity\File;
use Drupal\ghi_blocks\Interfaces\ConfigurableTableBlockInterface;
use Drupal\ghi_blocks\Plugin\Block\GHIBlockBase;
use Drupal\ghi_blocks\Plugin\Block\ImageProviderBlockInterface;
use Drupal\ghi_blocks\Plugin\ConfigurationContainerItem\CarouselItem;
use Drupal\ghi_blocks\Traits\ManagedFileBlockTrait;
use Drupal\ghi_form_elements\Traits\ConfigurationContainerTrait;
use Drupal\ghi_form_elements\Traits\OptionalLinkTrait;
use Drupal\hpc_api\Query\EndpointQuery;
use Drupal\hpc_common\Helpers\ArrayHelper;

Expand All @@ -29,6 +30,7 @@ class LinkCarousel extends GHIBlockBase implements ConfigurableTableBlockInterfa

use ConfigurationContainerTrait;
use ManagedFileBlockTrait;
use OptionalLinkTrait;

/**
* {@inheritdoc}
Expand Down Expand Up @@ -62,18 +64,19 @@ public function buildContent() {

/** @var \Drupal\ghi_blocks\Plugin\ConfigurationContainerItem\CarouselItem $item_type */
$item_type = $this->getItemTypePluginForColumn($item, $context);
if (!$item_type instanceof CarouselItem) {
continue;
}

$file = $item_type->getImage();
if (!$file) {
continue;
}

$link = Link::fromTextAndUrl($item_type->getButtonLabel() ?? $this->t('Read more'), $item_type->getUrl());
$link->getUrl()->setOptions([
'attributes' => [
'class' => ['cd-button', 'read-more'],
],
]);
$link = $item_type->getLink();
$attributes = $link->getUrl()->getOption('attributes');
$attributes['class'] = ['cd-button', 'read-more'];
$link->getUrl()->setOption('attributes', $attributes);
$carousel_items[] = [
'tag_line' => Markup::create($item_type->getTagLine()),
'title' => Markup::create($item_type->getLabel()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\ghi_form_elements\ConfigurationContainerItemPluginBase;
use Drupal\ghi_form_elements\Traits\OptionalLinkTrait;

/**
* Provides a carousel item for configuration containers.
Expand All @@ -19,6 +20,8 @@
*/
class CarouselItem extends ConfigurationContainerItemPluginBase {

use OptionalLinkTrait;

/**
* {@inheritdoc}
*/
Expand All @@ -29,9 +32,37 @@ public function buildForm($element, FormStateInterface $form_state) {
'#type' => 'carousel_item',
'#default_value' => array_key_exists('value', $this->config) ? $this->config['value'] : NULL,
];

$element['#element_validate'] = [
[static::class, 'validateElement'],
];
return $element;
}

/**
* Validate the link form element.
*
* @param array $element
* The element build in ::buildForm().
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
* @param array $complete_form
* The complete form that contains the element.
*/
public static function validateElement(&$element, FormStateInterface $form_state, &$complete_form) {
// @todo This repeats logic from
// \Drupal\ghi_form_elements\Element\OptionalLink::elementValidate().
$url = $form_state->getValue($element['#parents'])['value']['url'];
$transformed_url = self::transformUrl($url);
if (!$transformed_url) {
$form_state->setError($element['value']['url'], t('The link URL must be valid and accessible.'));
}
if (!$form_state->hasAnyErrors() && $transformed_url !== $url) {
$form_state->setValue(array_merge($element['#parents'], ['value', 'url']), $transformed_url);
}

}

/**
* Get the tag line.
*/
Expand Down Expand Up @@ -84,6 +115,17 @@ public function getImageCaption() {
return $caption ?? NULL;
}

/**
* Get the link.
*
* @return \Drupal\Core\Link
* A link object.
*/
public function getLink() {
$label = $this->getButtonLabel() ?? $this->t('Read more');
return $this->getLinkFromUri($this->config['value']['url'], $label);
}

/**
* Get the url.
*
Expand All @@ -92,7 +134,8 @@ public function getImageCaption() {
*/
public function getUrl() {
try {
return Url::fromUri($this->config['value']['url']);
$link = $this->getLink();
return $link->getUrl();
}
catch (\InvalidArgumentException $e) {
return NULL;
Expand Down

0 comments on commit abb61b0

Please sign in to comment.