मुझे टहनी में लिंक '#markup' बदलने का कोई तरीका नहीं मिला है, लेकिन रेंडर चरण में इसे बदलने का एक तरीका है।
मैंने इस छोटे मॉड्यूल को बनाया जो लिंक कार्यक्षमता का विस्तार करता है और प्रदान किए गए लिंक पर कुछ सामान इंजेक्ट करने में सक्षम बनाता है। तो कुछ कोड करते हैं, मैं टिप्पणियों में समझाऊंगा ...
मॉड्यूल फ़ाइल संरचना:
better_link
| - src
| - Element
| BetterLink.php
| - Plugin
| - FieldFormatter
| BetterLinkFormatter.php
| better_link.info.yml
| better_link.module
फ़ाइल सामग्री:
better_link.info.yml
name: 'Better link'
type: module
package: 'Field types'
description: 'A very nice better link'
core: '8.x'
dependencies:
- field
- link
better_link.module
<?php
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
* Just some words about the module.
*/
function better_link_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.better_link':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Provide a improved link formatter and renderer for a custom link markup.') . '</p>';
$output .= '<p>' . t('Will be added a span html tag right before link content.') . '</p>';
$output .= '<p>' . t(' - Link class can be added throught manage display.') . '</p>';
$output .= '<p>' . t(' - Span class can be added throught manage display.') . '</p>';
return $output;
}
}
BetterLinkFormatter.php
<?php
/**
* @file
* Contains \Drupal\better_link\Plugin\Field\FieldFormatter\BetterLinkFormatter.
*/
namespace Drupal\better_link\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Form\FormStateInterface;
use Drupal\link\Plugin\Field\FieldFormatter\LinkFormatter;
/**
* Plugin implementation of the 'better_link' formatter.
*
* @FieldFormatter(
* id = "better_link",
* label = @Translation("Better Link"),
* field_types = {
* "link"
* }
* )
*/
class BetterLinkFormatter extends LinkFormatter {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
$settings = parent::defaultSettings();
//Keeping simple...
$settings['span_class'] = '';
$settings['link_class'] = '';
//... but feel free to add, tag_name, buble_class, wraper_or_inside
return $settings;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form = parent::settingsForm($form, $form_state);
//Make sure that you always store a name that can be used as class
$settings['link_class'] = Html::cleanCssIdentifier(Unicode::strtolower($this->getSetting('link_class')));
$settings['span_class'] = Html::cleanCssIdentifier(Unicode::strtolower($this->getSetting('span_class')));
$this->setSettings($settings);
$form['link_class'] = array(
'#title' => $this->t('Inject this class to link'),
'#type' => 'textfield',
'#default_value' => $settings['link_class'],
);
$form['span_class'] = array(
'#title' => $this->t('Inject this class to span'),
'#type' => 'textfield',
'#default_value' => $settings['span_class'],
);
return $form;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = parent::settingsSummary();
//Same here. Somehow if you use setSettings here don't reflect in settingsForm
$settings['link_class'] = Html::cleanCssIdentifier(Unicode::strtolower($this->getSetting('link_class')));
$settings['span_class'] = Html::cleanCssIdentifier(Unicode::strtolower($this->getSetting('span_class')));
$this->setSettings($settings);
//Summary is located in the right side of your field (in manage display)
if (!empty($settings['link_class'])) {
$summary[] = t("Class '@class' will be used in link element.", array('@class' => $settings['link_class']));
}
else {
$summary[] = t('No class is defined for link element.');
}
if (!empty($settings['span_class'])) {
$summary[] = t("Class '@class' will be used in span element.", array('@class' => $settings['span_class']));
}
else {
$summary[] = t('No class is defined for span element.');
}
return $summary;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = parent::viewElements($items, $langcode);
//Yeah, here too, same 'problem'.
$settings['link_class'] = Html::cleanCssIdentifier(Unicode::strtolower($this->getSetting('link_class')));
$settings['span_class'] = Html::cleanCssIdentifier(Unicode::strtolower($this->getSetting('span_class')));
foreach ($items as $delta => $item) {
//Lets change the render element type and inject some options that will
//be used in render phase
if (isset($elements[$delta]['#type'])) {
$elements[$delta]['#type'] = 'better_link';
$elements[$delta]['#options']['#link_class'] = $settings['link_class'];
$elements[$delta]['#options']['#span_class'] = $settings['span_class'];
}
}
//Next step, render phase, see ya...
return $elements;
}
}
BetterLink.php
<?php
/**
* @file
* Contains \Drupal\better_link\Element\BetterLink.
*/
namespace Drupal\better_link\Element;
use Drupal\Core\Render\Element\Link;
/**
* Provides a better_link render element. Almost the same as link.
*
* @RenderElement("better_link")
*/
class BetterLink extends Link {
/**
* {@inheritdoc}
*/
public function getInfo() {
$class = get_class($this);
return array(
'#pre_render' => array(
array($class, 'preRenderLink'),
),
);
}
/**
* {@inheritdoc}
*/
public static function preRenderLink($element) {
//Hello again. Lets work.
//Before Drupal create the rendered link element lets inject our stuff...
//...Our class to link
$element['#options']['attributes']['class'][] = $element['#options']['#link_class'];
//...Build span classes
$span_classes = $element['#options']['#span_class'] . ' ' . $element['#options']['#link_class'];
//...And get rid them.
unset($element['#options']['#link_class']);
unset($element['#options']['#span_class']);
//Lets Drupal do the hard work
$element = parent::preRenderLink($element);
//Here is where the magic happens ;)
if (!empty($element['#markup'])) {
//Inject our span right before link content.
$element['#markup'] = str_replace('">', "\"><span class='$span_classes'></span>", $element['#markup']);
//Side comment - Thank you spaceless, str_replace can be used here
}
//Now, whatever you change in your url or another object will not maintain,
//the only thing that will be returned in the end is
//$element['#markup'], so this is the only thing you can change.
return $element;
}
}
महत्वपूर्ण:
यह आपके सभी लिंक फ़ील्ड के लिए काम करेगा , निश्चित रूप से, यदि आप इसके फॉर्मेटर को मैनेज डिस्प्ले (अपने नोड प्रकार को संपादित करते हुए) में बदलते हैं।
मुझे उम्मीद है कि यह उपयोगी हो सकता है।
@Artfulrobot से अनुरोध: क्या आप इस मॉड्यूल का परीक्षण कर सकते हैं? मुझे लगता है कि अनुवाद के मुद्दे को इस तरह से हल किया जा सकता है।