Smart Link needs to hold the URL, and have additional values for the title.
Generate Field W/ Drush
Use drush to generate a custom field in the Smart Link module. This will create the field storage, widget, and formatter plugins.
andrew@InfoBox:~/Sites/mantra/web/sites/classes$ drush gen field
Welcome to field generator!
–––––––––––––––––––––––––––––
Module machine name:
➤ smart_link
Field label [Example]:
➤ Smart link
Field ID [smart_link_smart_link]:
➤ smart_link
How many sub-fields would you like to create? [3]:
➤ 1
–––––––––––––––––––––––––––––––––––––––––––––––––––
Label for sub-field #1 [Value 1]:
➤ URL
Machine name for sub-field #1 [url]:
➤
Type of sub-field #1 [Text]:
[1 ] Boolean
[2 ] Text
[3 ] Text (long)
[4 ] Integer
[5 ] Float
[6 ] Numeric
[7 ] Email
[8 ] Telephone
[9 ] Url
[10] Date
➤➤➤ 9
Limit allowed values for sub-field #1? [No]:
➤ y
Make sub-field #1 required? [No]:
➤ y
–––––––––––––––––––––––––––––––––––––––––––––––––––
Would you like to create field storage settings form? [No]:
➤ y
Would you like to create field instance settings form? [No]:
➤ y
Would you like to create field widget settings form? [No]:
➤ y
Would you like to create field formatter settings form? [No]:
➤ y
Would you like to create table formatter? [No]:
➤ y
Would you like to create key-value formatter? [No]:
➤ y
The following directories and files have been created or updated:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• sites/classes/modules/custom/smart_link/config/schema/smart_link.schema.yml
• sites/classes/modules/custom/smart_link/css/smart-link-widget.css
• sites/classes/modules/custom/smart_link/smart_link.libraries.yml
• sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldFormatter/SmartLinkDefaultFormatter.php
• sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldFormatter/SmartLinkKeyValueFormatter.php
• sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldFormatter/SmartLinkTableFormatter.php
• sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldType/SmartLinkItem.php
• sites/classes/modules/custom/smart_link/src/Plugin/Field/FieldWidget/SmartLinkWidget.php
Schema and Property Definitions
Let's look at the LinkItem class, which is a FieldType plugin.
These two functions control the field properties and database storage.
LinkItem.php
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['uri'] = DataDefinition::create('uri')
->setLabel(t('URI'));
$properties['title'] = DataDefinition::create('string')
->setLabel(t('Link text'));
$properties['options'] = MapDataDefinition::create()
->setLabel(t('Options'));
return $properties;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'uri' => [
'description' => 'The URI of the link.',
'type' => 'varchar',
'length' => 2048,
],
'title' => [
'description' => 'The link text.',
'type' => 'varchar',
'length' => 255,
],
'options' => [
'description' => 'Serialized array of options for the link.',
'type' => 'blob',
'size' => 'big',
'serialize' => TRUE,
],
],
'indexes' => [
'uri' => [['uri', 30]],
],
];
}
Let's modify this to store the uri, title, domain, and h1 values we'll fetch from the link.
SmartLinkItem.php
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['uri'] = DataDefinition::create('uri')
->setLabel(t('URI'));
$properties['title'] = DataDefinition::create('string')
->setLabel(t('Link title'));
$properties['domain'] = DataDefinition::create('string')
->setLabel(t('Link domain'));
$properties['h1'] = DataDefinition::create('string')
->setLabel(t('First h1'));
return $properties;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'uri' => [
'description' => 'The URI of the link.',
'type' => 'varchar',
'length' => 2048,
],
'title' => [
'description' => 'The link title.',
'type' => 'varchar',
'length' => 255,
],
'domain' => [
'description' => 'The link domain.',
'type' => 'varchar',
'length' => 255,
],
'h1' => [
'description' => 'The first h1.',
'type' => 'varchar',
'length' => 255,
],
],
'indexes' => [
'uri' => [['uri', 30]],
],
];
}
Widget Form Element
We need to define the field form elements in a FieldWidget plugin.
SmartLinkWidget.php
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element['uri'] = [
'#type' => 'url',
'#title' => $this->t('URL'),
'#default_value' => isset($items[$delta]->uri) ? $items[$delta]->uri : NULL,
'#maxlength' => 2048,
'#required' => $element['#required'],
];
$element['title'] = [
'#type' => 'textfield',
'#title' => $this->t('Link title'),
'#default_value' => isset($items[$delta]->title) ? $items[$delta]->title : NULL,
];
$element['domain'] = [
'#type' => 'textfield',
'#title' => $this->t('Link domain'),
'#default_value' => isset($items[$delta]->domain) ? $items[$delta]->domain : NULL,
];
$element['h1'] = [
'#type' => 'textfield',
'#title' => $this->t('First h1'),
'#default_value' => isset($items[$delta]->h1) ? $items[$delta]->h1 : NULL,
];
return $element;
}
Now there are some form fields we can see.
Field Formatter
The formatter just puts the values into a render array.
SmartLinkDefaultFormatter.php
public function viewElements(FieldItemListInterface $items, $langcode) {
$element = [];
foreach ($items as $delta => $item) {
if ($item->domain) {
$element[$delta]['url'] = [
'#type' => 'item',
'#title' => $this->t('URL'),
'#markup' => $item->url
];
}
if ($item->domain) {
$element[$delta]['domain'] = [
'#type' => 'item',
'#title' => $this->t('Domain'),
'#markup' => $item->domain
];
}
if ($item->path) {
$element[$delta]['path'] = [
'#type' => 'item',
'#title' => $this->t('Path'),
'#markup' => $item->path
];
}
if ($item->title) {
$element[$delta]['title'] = [
'#type' => 'item',
'#title' => $this->t('Title'),
'#markup' => $item->title
];
}
if ($item->description) {
$element[$delta]['description'] = [
'#type' => 'item',
'#title' => $this->t('Description'),
'#markup' => $item->description
];
}
if ($item->h1) {
$element[$delta]['h1'] = [
'#type' => 'item',
'#title' => $this->t('H1'),
'#markup' => $item->h1
];
}
}
return $element;
}
Topics