CCK Field Type with Several Form Fields

Specs

Version
Drupal 8
Tools
Field API
Created
28 Feb 2016

Summary

En este ejemplo se implementa un tipo de campo que se puede utilizar para almacenar fragmentos de código. Se almacena la siguiente información que se debe utilizar como un campo de valor múltiple con valores ilimitadas.

  • Nombre de la sección
  • Nombre del archivo
  • Ruta de archivo
  • Idioma
  • Descripción
  • Código

Esto es en realidad el tipo de campo que he implementado para los fragmentos de este sitio. Con el tiempo, planeo escribir la funcionalidad que va a generar automáticamente los módulos y comandos Drush partir de los datos.

Code

1. Module File

MODULE_NAME.module
Basic module file that stores options for the field.
          
/**
 * @file
 * Module file for MODULE_NAME.
 */

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\image\Entity\ImageStyle;
use Drupal\core\Entity;
use Drupal\Core\Url;

define('MODULE_NAME_INCLUDE', 1);
define('MODULE_NAME_NO_INCLUDE', 2);

/*
 * Stores language options
 */
function MODULE_NAME_language_options() {
  return array(
    'php' => t('PHP'),
    'js' => t('JS'),
    'css' => t('CSS'),
    'html' => t('HTML'),
    'yaml' => t('YAML'),
  );
}

/*
 * Stores linker include options
 */
function MODULE_NAME_include_options() {
  return array(
    MODULE_NAME_INCLUDE => t('Include in Linker'),
    MODULE_NAME_NO_INCLUDE => t('Do not include in Linker'),
  );
}
          
          

2. CCK Field Type Plugin

CodeItem.php
MODULE_PATH/src/Plugin/Field/FieldType
Defines the code field type.
          
/**
 * @file
 * Contains \Drupal\MODULE_NAME\Plugin\Field\FieldType\Code.
 */

namespace Drupal\MODULE_NAME\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\TypedData\DataDefinition;

/**
 * Plugin implementation of the 'MODULE_NAME' field type.
 *
 * @FieldType(
 *   id = "code",
 *   label = @Translation("Code"),
 *   description = @Translation("This field is used to store sections of code."),
 *   category = @Translation("Text"),
 *   default_widget = "code",
 *   default_formatter = "code_default"
 * )
 */
class CodeItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {

    $properties['value'] = DataDefinition::create('string')
      ->setLabel(t('Code'))
      ->setRequired(TRUE);

      $properties['section_name'] = DataDefinition::create('string')
      ->setLabel(t('Section Name'))
      ->setRequired(TRUE);

    $properties['file_name'] = DataDefinition::create('string')
      ->setLabel(t('File Name'));

    $properties['file_path'] = DataDefinition::create('string')
      ->setLabel(t('File Path'));

    $properties['language'] = DataDefinition::create('string')
      ->setLabel(t('Language'));

    $properties['description'] = DataDefinition::create('string')
      ->setLabel(t('Description'));

    $properties['include'] = DataDefinition::create('string')
      ->setLabel(t('Include'));

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return array(
      'columns' => array(
        'value' => array(
          'type' => 'text',
          'size' => 'big',
        ),
        'section_name' => array(
          'type' => 'text',
          'size' => 'big',
        ),
        'file_name' => array(
          'type' => 'text',
          'size' => 'big',
        ),
        'file_path' => array(
          'type' => 'text',
          'size' => 'big',
        ),
        'language' => array(
          'type' => 'text',
          'size' => 'big',
        ),
        'description' => array(
          'type' => 'text',
          'size' => 'big',
        ),
        'include' => array(
          'type' => 'int',
        ),
      ),
    );
  }

  /**
  * {@inheritdoc}
  */
  public function isEmpty() {
    $value = $this->get('value')->getValue();
    return $value === NULL || $value === '';
  }

}

          
          

3. CCK Field Widget

CodeWidget.php
MODULE_PATH/src/Plugin/Field/FieldWidget
Defines the code field widget.
          
/**
 * @file
 * Contains \Drupal\MODULE_NAME\Plugin\Field\FieldWidget\TextareaWidget.
 */

namespace Drupal\MODULE_NAME\Plugin\Field\FieldWidget;

use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\Validator\ConstraintViolationInterface;

/**
 * Plugin implementation of the 'code' widget.
 *
 * @FieldWidget(
 *   id = "code",
 *   label = @Translation("Code Field Widget"),
 *   field_types = {
 *     "code"
 *   }
 * )
 */
class CodeWidget extends WidgetBase {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {

    $element['section_name'] = array(
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->section_name,
      '#title' => t('Section Name'),
      '#attached' => array(
        'library' => array('text/drupal.text'),
      ),
    );

    $element['file_name'] = array(
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->file_name,
      '#title' => t('File Name'),
      '#attached' => array(
        'library' => array('text/drupal.text'),
      ),
    );

    $element['file_path'] = array(
      '#type' => 'textfield',
      '#default_value' => $items[$delta]->file_path,
      '#title' => t('File Path'),
      '#attached' => array(
        'library' => array('text/drupal.text'),
      ),
    );

    $element['language'] = array(
      '#type' => 'radios',
      '#default_value' => !empty($items[$delta]->language) ? $items[$delta]->language : 'php',
      '#title' => t('Language'),
      '#options' => MODULE_NAME_language_options(),
    );

    $element['include'] = array(
      '#type' => 'radios',
      '#default_value' => !empty($items[$delta]->include) ? $items[$delta]->include : MODULE_NAME_INCLUDE,
      '#title' => t('Linker Include Method'),
      '#options' => MODULE_NAME_include_options(),
    );

    $element['description'] = array(
      '#type' => 'textarea',
      '#default_value' => $items[$delta]->description,
      '#title' => t('Description'),
      '#rows' => 4,
      '#attached' => array(
        'library' => array('text/drupal.text'),
      ),
    );

    $element['value'] = array(
      '#type' => 'textarea',
      '#default_value' => $items[$delta]->value,
      '#title' => t('Code'),
      '#rows' => 20,
      '#attached' => array(
        'library' => array('text/drupal.text'),
      ),
      '#resizeable' => TRUE,
    );

    return $element;
  }

}

          
          

Comments

Placeholder: I'll extend node comments with ajax and other functionality here.