Skip to content

Commit

Permalink
Issue #3391443 by smulvih2: Add modal to content with CKEditor
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Mulvihill authored and sylus committed Oct 22, 2023
1 parent 9fad223 commit 9f048ce
Show file tree
Hide file tree
Showing 13 changed files with 398 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
langcode: en
status: true
dependencies: { }
id: modal
label: Modal
revision: 0
description: ''
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.modal
- field.field.block_content.modal.body
- field.field.block_content.modal.field_modal_id
module:
- text
id: block_content.modal.default
targetEntityType: block_content
bundle: modal
mode: default
content:
body:
type: text_textarea_with_summary
weight: 2
region: content
settings:
rows: 9
summary_rows: 3
placeholder: ''
show_summary: false
third_party_settings: { }
field_modal_id:
type: string_textfield
weight: 1
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
info:
type: string_textfield
weight: 0
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
langcode:
type: language_select
weight: 3
region: content
settings:
include_locked: true
third_party_settings: { }
translation:
weight: 4
region: content
settings: { }
third_party_settings: { }
hidden: { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.modal
- field.field.block_content.modal.body
- field.field.block_content.modal.field_modal_id
module:
- text
id: block_content.modal.default
targetEntityType: block_content
bundle: modal
mode: default
content:
body:
type: text_default
label: hidden
settings: { }
third_party_settings: { }
weight: 0
region: content
hidden:
field_modal_id: true
langcode: true
search_api_excerpt: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.modal
- field.storage.block_content.body
module:
- text
id: block_content.modal.body
field_name: body
entity_type: block_content
bundle: modal
label: Body
description: ''
required: false
translatable: true
default_value: { }
default_value_callback: ''
settings:
display_summary: false
required_summary: false
field_type: text_with_summary
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.modal
- field.storage.block_content.field_modal_id
id: block_content.modal.field_modal_id
field_name: field_modal_id
entity_type: block_content
bundle: modal
label: 'Modal ID'
description: 'A unique ID attribute for this modal, used to activate it.'
required: true
translatable: false
default_value: { }
default_value_callback: ''
settings: { }
field_type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
langcode: en
status: true
dependencies:
module:
- block_content
id: block_content.field_modal_id
field_name: field_modal_id
entity_type: block_content
type: string
settings:
max_length: 255
case_sensitive: false
is_ascii: false
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
langcode: en
status: true
dependencies:
config:
- block_content.type.modal
module:
- content_translation
third_party_settings:
content_translation:
enabled: true
id: block_content.modal
target_entity_type_id: block_content
target_bundle: modal
default_langcode: site_default
language_alterable: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace Drupal\wxt_ext_blocks\Plugin\Filter;

use Drupal\filter\Plugin\FilterBase;
use Drupal\filter\FilterProcessResult;
use Drupal\Core\Url;
use Drupal\block_content\Entity\BlockContent;

/**
* Provides a filter plugin to add modal block markup below a link.
*
* @Filter(
* id = "custom_modal_filter",
* title = @Translation("Modal filter (WxT)"),
* type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE,
* )
*/
class CustomModalFilter extends FilterBase {

private $modalHTML;

/**
* {@inheritdoc}
*/
public function process($text, $langcode) {
// Regular expression to match your link pattern.
$pattern = '/<a[^>]*data-entity-substitution="modal"[^>]*>(.*?)<\/a>/i';

// Process the text using the regular expression.
$text = preg_replace_callback($pattern, [$this, 'processLink'], $text);

if (!empty($this->modalHTML)) {
$text .= $this->modalHTML;
}

return new FilterProcessResult($text);
}

/**
* Callback function to process matched links.
*
* @param array $matches
* An array of matches from the regular expression.
*
* @return string
* The modified link with modal block markup.
*/
protected function processLink($matches) {
// Extract the link content.
$linkContent = $matches[1];

// Extract the entity UUID from the link.
preg_match('/data-entity-uuid="([a-f0-9\-]+)"/i', $matches[0], $uuidMatches);

if (count($uuidMatches) !== 2) {
// If the entity UUID is not found, return the original link.
return $matches[0];
}
$entityUuid = $uuidMatches[1];

// Load the block content entity using the UUID.
$blockContent = \Drupal::entityTypeManager()
->getStorage('block_content')
->loadByProperties([
'uuid' => $entityUuid,
]);

$block = reset($blockContent);

// Check if the block content entity exists.
if ($block) {
// Get the current language.
$language = \Drupal::languageManager()->getCurrentLanguage()->getId();

// Get modal field values.
$modal_id = $block->get('field_modal_id')->value;
$modal_title = $block->getTranslation($language)->label();

// Render the block content entity.
$modalBlockMarkup = \Drupal::entityTypeManager()->getViewBuilder('block_content')->view($block);
$modal_body = \Drupal::service('renderer')->renderRoot($modalBlockMarkup);

$modal_output = "<section id='$modal_id' class='mfp-hide modal-dialog modal-content overlay-def'>
<header class='modal-header'>
<h2 class='modal-title'>" . $modal_title . "</h2>
</header>
<div class='modal-body'>" . $modal_body . "</div>
<button title='" . t('Close overlay (escape key)') . "' type='button' class='mfp-close'>×<span class='wb-inv'> " . t('Close overlay (escape key)') . "</span></button>
</section>";

// Set the modal HTML.
$this->modalHTML .= $modal_output;

// Modify the link and return it.
$modifiedLink = preg_replace('/<a\b(.*?)>/', '<a$1 aria-controls="' . $modal_id . '" class="wb-lbx lbx-modal">', $matches[0]);
return $modifiedLink;
}

// Return the original link if the block content entity doesn't exist.
return $matches[0];
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/**
* @file
* Contains \Drupal\my_linkit\Plugin\Linkit\Matcher\MYLinkitMatcher.
*/

namespace Drupal\wxt_ext_blocks\Plugin\Linkit\Matcher;

use Drupal\linkit\Plugin\Linkit\Matcher\EntityMatcher;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* A LinkIt matcher for block_content
*
* @Matcher(
* id = "entity:block_content",
* label = @Translation("Block content"),
* target_entity = "block_content",
* provider = "wxt_ext_blocks"
* )
*/

class BlockContentMatcher extends EntityMatcher {

/**
* {@inheritdoc}
*/
protected function buildEntityQuery($search_string) {
$langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();

$query = parent::buildEntityQuery($search_string);
$query->condition('status', 1);
$query->condition('langcode', $langcode);

return $query;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Drupal\wxt_ext_blocks\Plugin\Linkit\Substitution;

use Drupal\block_content\Entity\BlockContent;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\GeneratedUrl;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\linkit\SubstitutionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* A substitution plugin for modal blocks.
*
* @Substitution(
* id = "modal",
* label = @Translation("Modal block"),
* )
*/
class Modal extends PluginBase implements SubstitutionInterface, ContainerFactoryPluginInterface {

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager')
);
}

/**
* {@inheritdoc}
*/
public function getUrl(EntityInterface $entity) {
$url = '';

if ($entity instanceof BlockContent) {
if ($entity->hasField('field_modal_id')) {
// Get the value of the 'field_modal_id' field.
$urlValue = '#' . $entity->get('field_modal_id')->value;

// Create a GeneratedUrl object and set the URL value.
$generatedUrl = new GeneratedUrl();
$generatedUrl->setGeneratedUrl($urlValue);

// Return the GeneratedUrl object.
return $generatedUrl;
}
}

return $url;
}

/**
* {@inheritdoc}
*/
public static function isApplicable(EntityTypeInterface $entity_type) {
return $entity_type->hasLinkTemplate('canonical');
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ dependencies:
- toc_filter
- token_filter
- url_embed
- wxt_ext_blocks
- wxt_ext_editor
name: 'Rich Text'
format: rich_text
weight: 1
Expand Down Expand Up @@ -149,3 +151,9 @@ filters:
auto: ''
block: '0'
exclude_above: '1'
custom_modal_filter:
id: custom_modal_filter
provider: wxt_ext_blocks
status: true
weight: 0
settings: { }
Loading

0 comments on commit 9f048ce

Please sign in to comment.