# if (file_exists(__DIR__ . '/settings.local.php')) {
# include __DIR__ . '/settings.local.php';
# }
In 3 steps
Create a directory named "montpellier" in the modules directory (root)
type: module
name: 'Montpellier'
description: 'Display Suite test module.'
core: 8.x
package: 'Display Suite'
dependencies:
- ds
And you're ready to go!
In 3 steps
Create a file named "montpellier.layouts.yml"
montpellier:
label: Montpellier one column layout
category: Display Suite
type: partial
theme: montpellier
#icon: images/montpellier.png
#library: montpellier/layout
regions:
main:
label: Main content
Name it montpellier.html.twig
Place it in a directory named "templates"
<{{ main_wrapper }} class="montpellier-1col {{ attributes.class }} clearfix" {{ attributes }} >
{% if title_suffix.contextual_links is not null %}
{{ title_suffix.contextual_links }}
{% endif %}
{{ main }}
</{{ main_wrapper }}>
Enjoy your victory!
In 7 steps
All the DS fields should be placed in the same folder
in order for the system to find them.
It should extend DsFieldBase
/**
* @file
* Contains \Drupal\montpellier\Plugin\DsField\MontpellierTitle.
*/
namespace Drupal\montpellier\Plugin\DsField;
/**
* @todo add annotation
*/
class MontpellierTitle extends DsFieldBase {
}
This is needed to "discover" the plugin
/**
* Plugin that prefixes the title with "Montpellier"
*
* @DsField(
* id = "montpellier_title",
* title = @Translation("Montpellier title"),
* entity_type = "node",
* )
*/
class MontpellierTitle extends DsFieldBase {
}
Not really...
But your field should be visible now in the interface.
class MontpellierTitle extends DsFieldBase {
/**
* {@inheritdoc}
*/
public function build() {
// Fetch the entity
$node = $this->entity();
// Always return a render array!
return array(
'#markup' => $node->title->value,
'#prefix' => 'Montpellier ',
);
}
}
/**
* {@inheritdoc}
*/
public function build() {
$config = $this->getConfiguration();
// Fetch the entity
$node = $this->entity();
// Always return a render array!
return array(
'#markup' => $node->title->value,
'#prefix' => $config['prefix'] . ' ',
);
}
/**
* {@inheritdoc}
*/
public function settingsForm($form, FormStateInterface $form_state) {
$config = $this->getConfiguration();
$settings['prefix'] = array(
'#type' => 'textfield',
'#title' => 'Prefix',
'#default_value' => $config['prefix'],
);
return $settings;
}
/**
* {@inheritdoc}
*/
public function settingsSummary($settings) {
$config = $this->getConfiguration();
$summary = array();
if (!empty($config['prefix'])) {
$summary[] = 'Prefix: ' . $config['prefix'];
}
return $summary;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array(
'prefix' => 'Montpellier',
);
}
/**
* {@inheritdoc}
*/
public function build() {
$config = $this->getConfiguration();
// Fetch formatter
$field = $this->getFieldConfiguration();
$formatter = $field['formatter'];
if ($formatter == 'italic') {
$prefix = '' . $config['prefix'] . '';
}
else {
$prefix = $config['prefix'];
}
// Fetch the entity
$node = $this->entity();
// Always return a render array!
return array(
'#markup' => $node->title->value,
'#prefix' => $prefix . ' ',
);
}
/**
* {@inheritdoc}
*/
public function formatters() {
return array(
'normal' => 'Normal',
'italic' => 'Italic',
);
}
/**
* {@inheritdoc}
*/
public function isAllowed() {
if ($this->bundle() != 'article') {
return FALSE;
}
else if ($this->viewMode() == 'teaser') {
return FALSE;
}
return TRUE;
}
In 4 steps
All the DS field templates should be placed in the same folder in order for the system to find them.
It should extend DsFieldLayoutBase
/**
* @file
* Contains \Drupal\montpellier\Plugin\DsFieldLayout\Montpellier.
*/
namespace Drupal\montpellier\Plugin\DsFieldLayout;
use Drupal\ds\Plugin\DsFieldLayout\DsFieldLayoutBase;
/**
* @todo create the annotation
*/
class Montpellier extends DsFieldLayoutBase {
}
This is needed to "discover" the layout
/**
* @DsFieldLayout(
* id = "montpellier",
* title = @Translation("Montpellier"),
* theme = "theme_ds_field_montpellier",
* )
*/
class Montpellier extends DsFieldLayoutBase {
}
/**
* Wraps the output in a montpellier class
*/
function theme_ds_field_montpellier($variables) {
$output = '';
// Render the label.
if (!$variables['label_hidden']) {
$output .= '' . $variables['label'];
if (\Drupal::config('ds.settings')->get('ft-show-colon')) {
$output .= ':';
}
$output .= '';
}
// Render the items.
foreach ($variables['items'] as $item) {
$output .= drupal_render($item['content']);
}
return '' . $output .'';
}
In 7 steps
All the DS dynamic fields need a form.
It should extend FieldFormBase
/**
* @file
* Contains \Drupal\montpellier\Form\MontpellierFieldForm.
*/
namespace Drupal\montpellier\Form;
use Drupal\Core\Form\FormStateInterface;
use Drupal\ds\Form\FieldFormBase;
/**
* Configures montpellier fields.
*/
class MontpellierFieldForm extends FieldFormBase {
/**
* The type of the dynamic ds field
*/
const TYPE = 'montpellier';
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'ds_field_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $field_key = '') {
$form = parent::buildForm($form, $form_state, $field_key);
$field = $this->field;
$form['content'] = array(
'#type' => 'text_format',
'#title' => t('Field content'),
'#default_value' => isset($field['properties']['content']['value']) ? $field['properties']['content']['value'] : '',
'#format' => isset($field['properties']['content']['format']) ? $field['properties']['content']['format'] : 'plain_text',
'#base_type' => 'textarea',
'#required' => TRUE,
);
return $form;
}
/**
* {@inheritdoc}
*/
public function getProperties(FormStateInterface $form_state) {
return array(
'content' => $form_state->getValue('content'),
);
}
/**
* {@inheritdoc}
*/
public function getType() {
return MontpellierFieldForm::TYPE;
}
/**
* {@inheritdoc}
*/
public function getTypeLabel() {
return 'Montpellier field';
}
}
Placed in a routing.yml file
ds.manage_montpellier_field:
path: 'admin/structure/ds/fields/manage_montpellier/{field_key}'
defaults:
_form: '\Drupal\montpellier\Form\MontpellierFieldForm'
_title: 'Edit a montpellier field'
requirements:
_permission: 'admin fields'
ds.add_montpellier_field:
path: 'admin/structure/ds/fields/manage_montpellier'
defaults:
_form: '\Drupal\montpellier\Form\MontpellierFieldForm'
_title: 'Add a montpellier field'
requirements:
_permission: 'admin fields'
Placed in a links.action.yml file
ds.montpellier_field_add_local_action:
route_name: ds.add_montpellier_field
title: 'Add a montpellier field'
appears_on:
- ds.fields_list
This needed for the magic to happen
It has to extend the DynamicField class of DS
/**
* @file
* Contains \Drupal\montpellier\Plugin\Derivative\DynamicMontpellierField.
*/
namespace Drupal\montpellier\Plugin\Derivative;
use Drupal\montpellier\Form\MontpellierFieldForm;
use Drupal\ds\Plugin\Derivative\DynamicField;
/**
* Retrieves dynamic code field plugin definitions.
*/
class DynamicMontpellierField extends DynamicField {
/**
* {@inheritdoc}
*/
protected function getType() {
return MontpellierFieldForm::TYPE;
}
}
/**
* @file
* Contains \Drupal\montpellier\Plugin\DsField\DynamicMontpellierField.
*/
namespace Drupal\montpellier\Plugin\DsField;
use Drupal\ds\Plugin\DsField\DsFieldBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Defines a generic dynamic montpellier field.
*
* @DsField(
* id = "dynamic_montpellier_field",
* deriver = "Drupal\montpellier\Plugin\Derivative\DynamicMontpellierField"
* )
*/
class DynamicMontpellierField extends DsFieldBase {
/**
* {@inheritdoc}
*/
public function build() {
$content = $this->content();
$format = $this->format();
return array(
'#type' => 'processed_text',
'#text' => $content,
'#format' => $format,
'#filter_types_to_skip' => array(),
'#langcode' => '',
);
}
/**
* {@inheritdoc}
*/
public function content() {
$definition = $this->getPluginDefinition();
return $definition['properties']['content']['value'];
}
/**
* {@inheritdoc}
*/
public function format() {
$definition = $this->getPluginDefinition();
return $definition['properties']['content']['format'];
}
/**
* {@inheritdoc}
*/
public function isAllowed() {
$definition = $this->getPluginDefinition();
return DsFieldBase::dynamicFieldIsAllowed($definition, $this->bundle(), $this->viewMode());
}
}
Got questions?