Dalda '#markup' bağlantısını değiştirmenin bir yolunu bulamadım, ancak render aşamasında değiştirmenin bir yolu var.
Bağlantı işlevini genişleten ve işlenmiş bağlantıya bazı şeyler enjekte edebilen bu küçük modülü yaptım. Yani bazı kod yapalım, yorumlarda açıklayacağım ...
Modül dosya yapısı:
better_link
| - src
| - Element
| BetterLink.php
| - Plugin
| - FieldFormatter
| BetterLinkFormatter.php
| better_link.info.yml
| better_link.module
Dosya içeriği:
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;
}
}
Önemli:
Bu, tüm bağlantı alanlarınız için işe yarayacaktır , elbette, yönetme ekranında biçimlendiricisini değiştirirseniz (düğüm türünüzü düzenler).
Umarım faydalı olabilir.
@Artfulrobot'a istek: Bu modülü test edebilir misiniz? Çeviri sorununun bu şekilde çözülebileceğini düşünüyorum.