addfolder
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Annotation;
|
||||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
|
||||
/**
|
||||
* Defines a FieldGroupFormatter annotation object.
|
||||
*
|
||||
* Formatters handle the display of fieldgroups.
|
||||
*
|
||||
* Additional annotation keys for formatters can be defined in
|
||||
* hook_field_group_formatter_info_alter().
|
||||
*
|
||||
* @Annotation
|
||||
*
|
||||
* @see \Drupal\field_group\FieldGroupFormatterPluginManager
|
||||
* @see \Drupal\field_group\FieldGroupFormatterInterface
|
||||
*
|
||||
* @ingroup field_formatter
|
||||
*/
|
||||
class FieldGroupFormatter extends Plugin {
|
||||
|
||||
/**
|
||||
* The plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The human-readable name of the formatter type.
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*
|
||||
* @var \Drupal\Core\Annotation\Translation
|
||||
*/
|
||||
public $label;
|
||||
|
||||
/**
|
||||
* A short description of the formatter type.
|
||||
*
|
||||
* @ingroup plugin_translatable
|
||||
*
|
||||
* @var \Drupal\Core\Annotation\Translation
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* The name of the fieldgroup formatter class.
|
||||
*
|
||||
* This is not provided manually, it will be added by the discovery mechanism.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $class;
|
||||
|
||||
/**
|
||||
* An array of contexts the formatter supports (form / view).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $supported_contexts = array();
|
||||
|
||||
/**
|
||||
* The different format types available for this formatter.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $format_types = array();
|
||||
|
||||
/**
|
||||
* An integer to determine the weight of this formatter relative to other
|
||||
* formatter in the Field UI when selecting a formatter for a given group.
|
||||
*
|
||||
* @var int optional
|
||||
*/
|
||||
public $weight = NULL;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Element;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Render\Element\RenderElement;
|
||||
|
||||
/**
|
||||
* Provides a render element for an accordion.
|
||||
*
|
||||
* @FormElement("field_group_accordion")
|
||||
*/
|
||||
class Accordion extends RenderElement {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInfo() {
|
||||
$class = get_class($this);
|
||||
|
||||
return array(
|
||||
'#process' => array(
|
||||
array($class, 'processAccordion'),
|
||||
),
|
||||
'#theme_wrappers' => array('field_group_accordion'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the accordion item.
|
||||
*
|
||||
* @param array $element
|
||||
* An associative array containing the properties and children of the
|
||||
* details element.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @return array
|
||||
* The processed element.
|
||||
*/
|
||||
public static function processAccordion(&$element, FormStateInterface $form_state) {
|
||||
|
||||
// Add the jQuery UI accordion.
|
||||
$element['#attached']['library'][] = 'field_group/formatter.accordion';
|
||||
|
||||
// Add the effect class.
|
||||
if (isset($element['#effect'])) {
|
||||
if (!isset($element['#attributes']['class'])) {
|
||||
$element['#attributes']['class'] = array();
|
||||
}
|
||||
$element['#attributes']['class'][] = 'effect-' . $element['#effect'];
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Element;
|
||||
|
||||
use Drupal\Core\Render\Element\RenderElement;
|
||||
|
||||
/**
|
||||
* Provides a render element for an accordion item.
|
||||
*
|
||||
* @FormElement("field_group_accordion_item")
|
||||
*/
|
||||
class AccordionItem extends RenderElement {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInfo() {
|
||||
return array(
|
||||
'#open' => TRUE,
|
||||
'#theme_wrappers' => array('field_group_accordion_item'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Element;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Render\Element\RenderElement;
|
||||
|
||||
/**
|
||||
* Provides a render element for horizontal tabs.
|
||||
*
|
||||
* Formats all child details and all non-child details whose #group is
|
||||
* assigned this element's name as horizontal tabs.
|
||||
*
|
||||
* @FormElement("horizontal_tabs")
|
||||
*/
|
||||
class HorizontalTabs extends RenderElement {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInfo() {
|
||||
$class = get_class($this);
|
||||
|
||||
return array(
|
||||
'#default_tab' => '',
|
||||
'#process' => array(
|
||||
array($class, 'processHorizontalTabs'),
|
||||
),
|
||||
'#theme_wrappers' => array('horizontal_tabs'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a group formatted as horizontal tabs.
|
||||
*
|
||||
* @param array $element
|
||||
* An associative array containing the properties and children of the
|
||||
* details element.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
* @param bool $on_form
|
||||
* Are the tabs rendered on a form or not.
|
||||
*
|
||||
* @return array
|
||||
* The processed element.
|
||||
*/
|
||||
public static function processHorizontalTabs(&$element, FormStateInterface $form_state, $on_form = TRUE) {
|
||||
|
||||
// Inject a new details as child, so that form_process_details() processes
|
||||
// this details element like any other details.
|
||||
$element['group'] = array(
|
||||
'#type' => 'details',
|
||||
'#theme_wrappers' => array(),
|
||||
'#parents' => $element['#parents'],
|
||||
);
|
||||
|
||||
// Add an invisible label for accessibility.
|
||||
if (!isset($element['#title'])) {
|
||||
$element['#title'] = t('Horizontal Tabs');
|
||||
$element['#title_display'] = 'invisible';
|
||||
}
|
||||
|
||||
// Add required JavaScript and Stylesheet.
|
||||
$element['#attached']['library'][] = 'field_group/element.horizontal_tabs';
|
||||
|
||||
// Only add forms library on forms.
|
||||
if ($on_form) {
|
||||
$element['#attached']['library'][] = 'core/drupal.form';
|
||||
}
|
||||
|
||||
// The JavaScript stores the currently selected tab in this hidden
|
||||
// field so that the active tab can be restored the next time the
|
||||
// form is rendered, e.g. on preview pages or when form validation
|
||||
// fails.
|
||||
$name = implode('__', $element['#parents']);
|
||||
if ($form_state->hasValue($name . '__active_tab')){
|
||||
$element['#default_tab'] = $form_state->getValue($name . '__active_tab');
|
||||
}
|
||||
$element[$name . '__active_tab'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#default_value' => $element['#default_tab'],
|
||||
'#attributes' => array('class' => array('horizontal-tabs-active-tab')),
|
||||
);
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Element;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Render\Element\RenderElement;
|
||||
|
||||
/**
|
||||
* Provides a render element for a html element.
|
||||
*
|
||||
* @FormElement("field_group_html_element")
|
||||
*/
|
||||
class HtmlElement extends RenderElement {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInfo() {
|
||||
$class = get_class($this);
|
||||
|
||||
return array(
|
||||
'#process' => array(
|
||||
array($class, 'processHtmlElement'),
|
||||
),
|
||||
'#theme_wrappers' => array('field_group_html_element'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a html element
|
||||
*
|
||||
* @param array $element
|
||||
* An associative array containing the properties and children of the
|
||||
* details element.
|
||||
* @param FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @return array
|
||||
* The processed element.
|
||||
*/
|
||||
public static function processHtmlElement(&$element, FormStateInterface $form_state) {
|
||||
|
||||
// If an effect is set, we need to load extra js.
|
||||
if (!empty($element['#effect']) && $element['#effect'] !== 'none') {
|
||||
|
||||
$element['#attached']['library'][] = 'field_group/formatter.html_element';
|
||||
|
||||
// Add the required classes for the js.
|
||||
$element['#attributes']['class'][] = 'fieldgroup-collapsible';
|
||||
$element['#attributes']['class'][] = 'effect-' . $element['#effect'];
|
||||
if (!empty($element['#speed'])) {
|
||||
$element['#attributes']['class'][] = 'speed-' . $element['#speed'];
|
||||
}
|
||||
|
||||
// Add jquery ui effects library for the blind effect.
|
||||
if ($element['#effect'] == 'blind') {
|
||||
$element['#attached']['library'][] = 'core/jquery.ui.effects.blind';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group;
|
||||
|
||||
use Drupal\Core\Field\PluginSettingsBase;
|
||||
|
||||
/**
|
||||
* Base class for 'Fieldgroup formatter' plugin implementations.
|
||||
*
|
||||
* @ingroup field_group_formatter
|
||||
*/
|
||||
abstract class FieldGroupFormatterBase extends PluginSettingsBase implements FieldGroupFormatterInterface {
|
||||
|
||||
/**
|
||||
* The group this formatter needs to render.
|
||||
* @var stdClass
|
||||
*/
|
||||
protected $group;
|
||||
|
||||
/**
|
||||
* The formatter settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* The label display setting.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* The view mode.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $viewMode;
|
||||
|
||||
/**
|
||||
* The context mode.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* Constructs a FieldGroupFormatterBase object.
|
||||
*
|
||||
* @param string $plugin_id
|
||||
* The plugin_id for the formatter.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param $group
|
||||
* The group object.
|
||||
* @param array $settings
|
||||
* The formatter settings.
|
||||
* @param string $label
|
||||
* The formatter label.
|
||||
*/
|
||||
public function __construct($plugin_id, $plugin_definition, $group, array $settings, $label) {
|
||||
parent::__construct(array(), $plugin_id, $plugin_definition);
|
||||
|
||||
$this->group = $group;
|
||||
$this->settings = $settings;
|
||||
$this->label = $label;
|
||||
$this->context = $group->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current label.
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel() {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = array();
|
||||
$form['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Field group label'),
|
||||
'#default_value' => $this->label,
|
||||
'#weight' => -5,
|
||||
);
|
||||
|
||||
$form['id'] = array(
|
||||
'#title' => t('ID'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $this->getSetting('id'),
|
||||
'#weight' => 10,
|
||||
'#element_validate' => array('field_group_validate_id'),
|
||||
);
|
||||
|
||||
$form['classes'] = array(
|
||||
'#title' => t('Extra CSS classes'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $this->getSetting('classes'),
|
||||
'#weight' => 11,
|
||||
'#element_validate' => array('field_group_validate_css_class'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = array();
|
||||
|
||||
if ($this->getSetting('formatter')) {
|
||||
$summary[] = $this->pluginDefinition['label'] . ': ' . $this->getSetting('formatter');
|
||||
}
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$summary[] = $this->t('Id: @id', array('@id' => $this->getSetting('id')));
|
||||
}
|
||||
|
||||
if ($this->getSetting('classes')) {
|
||||
$summary[] = \Drupal::translation()->translate('Extra CSS classes: @classes', array('@classes' => $this->getSetting('classes')));
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultSettings() {
|
||||
return self::defaultContextSettings('view');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
return array(
|
||||
'classes' => '',
|
||||
'id' => '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the classes to add to the group.
|
||||
*/
|
||||
protected function getClasses() {
|
||||
|
||||
$classes = array();
|
||||
// Add a required-fields class to trigger the js.
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$classes[] = 'required-fields';
|
||||
$classes[] = 'field-group-' . str_replace('_', '-', $this->getBaseId());
|
||||
}
|
||||
|
||||
if ($this->getSetting('classes')) {
|
||||
$classes = array_merge($classes, explode(' ', trim($this->getSetting('classes'))));
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
$element['#group_name'] = $this->group->group_name;
|
||||
$element['#entity_type'] = $this->group->entity_type;
|
||||
$element['#bundle'] = $this->group->bundle;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group;
|
||||
|
||||
use Drupal\Component\Plugin\PluginInspectionInterface;
|
||||
|
||||
/**
|
||||
* Interface definition for fieldgroup formatter plugins.
|
||||
*
|
||||
* @ingroup field_group_formatter
|
||||
*/
|
||||
interface FieldGroupFormatterInterface extends PluginInspectionInterface {
|
||||
|
||||
/**
|
||||
* Allows the field group formatter to manipulate the field group array and attach the formatters rendering element.
|
||||
*
|
||||
* @param array $element
|
||||
* The field group render array.
|
||||
* @param object $rendering_object
|
||||
* The object / entity beïng rendered.
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object);
|
||||
|
||||
/**
|
||||
* Returns a form to configure settings for the formatter.
|
||||
*
|
||||
* Invoked in field_group_field_ui_display_form_alter to allow
|
||||
* administrators to configure the formatter. The field_group module takes care
|
||||
* of handling submitted form values.
|
||||
*
|
||||
* @return array
|
||||
* The form elements for the formatter settings.
|
||||
*/
|
||||
public function settingsForm();
|
||||
|
||||
/**
|
||||
* Returns a short summary for the current formatter settings.
|
||||
*
|
||||
* If an empty result is returned, a UI can still be provided to display
|
||||
* a settings form in case the formatter has configurable settings.
|
||||
*
|
||||
* @return array()
|
||||
* A short summary of the formatter settings.
|
||||
*/
|
||||
public function settingsSummary();
|
||||
|
||||
/**
|
||||
* Defines the default settings for this plugin.
|
||||
*
|
||||
* @param string $context
|
||||
* The context to get the default settings for.
|
||||
*
|
||||
* @return array
|
||||
* A list of default settings, keyed by the setting name.
|
||||
*/
|
||||
public static function defaultContextSettings($context);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group;
|
||||
|
||||
use Drupal\Component\Plugin\Factory\DefaultFactory;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
|
||||
/**
|
||||
* Plugin type manager for all fieldgroup formatters.
|
||||
*/
|
||||
class FieldGroupFormatterPluginManager extends DefaultPluginManager {
|
||||
|
||||
/**
|
||||
* Constructs a new FieldGroupFormatterPluginManager object.
|
||||
*
|
||||
* @param \Traversable $namespaces
|
||||
* An object that implements \Traversable which contains the root paths
|
||||
* keyed by the corresponding namespace to look for plugin implementations.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
|
||||
* Cache backend instance to use.
|
||||
* @param \Drupal\Core\Language\LanguageManager $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler to invoke the alter hook with.
|
||||
*/
|
||||
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
|
||||
parent::__construct('Plugin/field_group/FieldGroupFormatter', $namespaces, $module_handler, 'Drupal\field_group\FieldGroupFormatterInterface', 'Drupal\field_group\Annotation\FieldGroupFormatter');
|
||||
|
||||
$this->alterInfo('field_group_formatter_info');
|
||||
$this->setCacheBackend($cache_backend, 'field_group_formatter_info');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createInstance($plugin_id, array $configuration = array()) {
|
||||
$plugin_definition = $this->getDefinition($plugin_id);
|
||||
$plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
|
||||
|
||||
// If the plugin provides a factory method, pass the container to it.
|
||||
if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) {
|
||||
return $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition);
|
||||
}
|
||||
|
||||
return new $plugin_class($plugin_id, $plugin_definition, $configuration['group'], $configuration['settings'], $configuration['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides PluginManagerBase::getInstance().
|
||||
*
|
||||
* @param array $options
|
||||
* An array with the following key/value pairs:
|
||||
* - format_type: The current format type.
|
||||
* - group: The current group.
|
||||
* - prepare: (bool, optional) Whether default values should get merged in
|
||||
* the 'configuration' array. Defaults to TRUE.
|
||||
* - configuration: (array) the configuration for the formatter. The
|
||||
* following key value pairs are allowed, and are all optional if
|
||||
* 'prepare' is TRUE:
|
||||
* - label: (string) Position of the label. The default 'field' theme
|
||||
* implementation supports the values 'inline', 'above' and 'hidden'.
|
||||
* Defaults to 'above'.
|
||||
* - settings: (array) Settings specific to the formatter. Each setting
|
||||
* defaults to the default value specified in the formatter definition.
|
||||
*
|
||||
* @return \Drupal\field_group\FieldGroupFormatterInterface|null
|
||||
* A formatter object or NULL when plugin is not found.
|
||||
*/
|
||||
public function getInstance(array $options) {
|
||||
$configuration = $options['configuration'];
|
||||
$format_type = $options['format_type'];
|
||||
$context = $options['group']->context;
|
||||
|
||||
// Fill in default configuration if needed.
|
||||
if (!isset($options['prepare']) || $options['prepare'] == TRUE) {
|
||||
$configuration = $this->prepareConfiguration($format_type, $context, $configuration);
|
||||
}
|
||||
|
||||
$plugin_id = $format_type;
|
||||
|
||||
// Validate if plugin exists and it's allowed for current context.
|
||||
$definition = $this->getDefinition($format_type, FALSE);
|
||||
if (!isset($definition['class']) || !in_array($context, $definition['supported_contexts'])) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$configuration += array(
|
||||
'group' => $options['group'],
|
||||
);
|
||||
|
||||
return $this->createInstance($plugin_id, $configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges default values for formatter configuration.
|
||||
*
|
||||
* @param string $format_type
|
||||
* The format type
|
||||
* @param string $context
|
||||
* The context to prepare configuration for.
|
||||
* @param array $properties
|
||||
* An array of formatter configuration.
|
||||
*
|
||||
* @return array
|
||||
* The display properties with defaults added.
|
||||
*/
|
||||
public function prepareConfiguration($format_type, $context, array $configuration) {
|
||||
// Fill in defaults for missing properties.
|
||||
$configuration += array(
|
||||
'label' => '',
|
||||
'settings' => array(),
|
||||
);
|
||||
|
||||
// Fill in default settings values for the formatter.
|
||||
$configuration['settings'] += $this->getDefaultSettings($format_type, $context);
|
||||
|
||||
return $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default settings of a field_group formatter.
|
||||
*
|
||||
* @param string $type
|
||||
* A formatter type name.
|
||||
* @param string $context
|
||||
* The context to get default values for.
|
||||
*
|
||||
* @return array
|
||||
* The formatter type's default settings, as provided by the plugin
|
||||
* definition, or an empty array if type or settings are undefined.
|
||||
*/
|
||||
public function getDefaultSettings($type, $context) {
|
||||
$plugin_definition = $this->getDefinition($type, FALSE);
|
||||
if (!empty($plugin_definition['class'])) {
|
||||
$plugin_class = DefaultFactory::getPluginClass($type, $plugin_definition);
|
||||
return $plugin_class::defaultContextSettings($context);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\field_ui\FieldUI;
|
||||
|
||||
/**
|
||||
* Static methods for fieldgroup UI.
|
||||
*/
|
||||
class FieldgroupUi {
|
||||
|
||||
/**
|
||||
* Get the field ui route that should be used for given arguments.
|
||||
* @param stdClass $group
|
||||
* The group to get the field ui route for.
|
||||
*
|
||||
* @return \Drupal\Core\Url
|
||||
* A URL object.
|
||||
*/
|
||||
public static function getFieldUiRoute($group) {
|
||||
|
||||
$entity_type = \Drupal::entityTypeManager()->getDefinition($group->entity_type);
|
||||
if ($entity_type->get('field_ui_base_route')) {
|
||||
|
||||
$context_route_name = "";
|
||||
$mode_route_name = "default";
|
||||
$route_parameters = FieldUI::getRouteBundleParameter($entity_type, $group->bundle);
|
||||
|
||||
// Get correct route name based on context and mode.
|
||||
if ($group->context == 'form') {
|
||||
$context_route_name = 'entity_form_display';
|
||||
|
||||
if ($group->mode != 'default') {
|
||||
$mode_route_name = 'form_mode';
|
||||
$route_parameters['form_mode_name'] = $group->mode;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
$context_route_name = 'entity_view_display';
|
||||
|
||||
if ($group->mode != 'default') {
|
||||
$mode_route_name = 'view_mode';
|
||||
$route_parameters['view_mode_name'] = $group->mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new Url("entity.{$context_route_name}.{$group->entity_type}.{$mode_route_name}", $route_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field group delete route for a given group.
|
||||
* @param \stdClass $group
|
||||
*
|
||||
* @return \Drupal\Core\Url
|
||||
* A URL object.
|
||||
*/
|
||||
public static function getDeleteRoute($group) {
|
||||
|
||||
$entity_type_id = $group->entity_type;
|
||||
$entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
|
||||
if ($entity_type->get('field_ui_base_route')) {
|
||||
|
||||
$mode_route_name = '';
|
||||
$route_parameters = FieldUI::getRouteBundleParameter($entity_type, $group->bundle);
|
||||
$route_parameters['field_group_name'] = $group->group_name;
|
||||
|
||||
// Get correct route name based on context and mode.
|
||||
if ($group->context == 'form') {
|
||||
|
||||
$context_route_name = 'form_display';
|
||||
if ($group->mode != 'default') {
|
||||
$mode_route_name = '.form_mode';
|
||||
$route_parameters['form_mode_name'] = $group->mode;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$context_route_name = 'display';
|
||||
if ($group->mode != 'default') {
|
||||
$mode_route_name = '.view_mode';
|
||||
$route_parameters['view_mode_name'] = $group->mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new Url('field_ui.field_group_delete_' . $entity_type_id . '.' . $context_route_name . $mode_route_name, $route_parameters);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('The given group is not a valid.');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field_group\FieldgroupUi;
|
||||
|
||||
/**
|
||||
* Provides a form for adding a fieldgroup to a bundle.
|
||||
*/
|
||||
class FieldGroupAddForm extends FormBase {
|
||||
|
||||
/**
|
||||
* The prefix for groups.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const GROUP_PREFIX = 'group_';
|
||||
|
||||
/**
|
||||
* The name of the entity type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityTypeId;
|
||||
|
||||
/**
|
||||
* The entity bundle.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $bundle;
|
||||
|
||||
/**
|
||||
* The context for the group.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* The mode for the group.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $mode;
|
||||
|
||||
/**
|
||||
* Current step of the form.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $currentStep;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'field_group_add_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL, $bundle = NULL, $context = NULL) {
|
||||
|
||||
if ($context == 'form') {
|
||||
$this->mode = \Drupal::request()->get('form_mode_name');
|
||||
}
|
||||
else {
|
||||
$this->mode = \Drupal::request()->get('view_mode_name');
|
||||
}
|
||||
|
||||
if (empty($this->mode)) {
|
||||
$this->mode = 'default';
|
||||
}
|
||||
|
||||
if (!$form_state->get('context')) {
|
||||
$form_state->set('context', $context);
|
||||
}
|
||||
if (!$form_state->get('entity_type_id')) {
|
||||
$form_state->set('entity_type_id', $entity_type_id);
|
||||
}
|
||||
if (!$form_state->get('bundle')) {
|
||||
$form_state->set('bundle', $bundle);
|
||||
}
|
||||
if (!$form_state->get('step')) {
|
||||
$form_state->set('step', 'formatter');
|
||||
}
|
||||
|
||||
$this->entityTypeId = $form_state->get('entity_type_id');
|
||||
$this->bundle = $form_state->get('bundle');
|
||||
$this->context = $form_state->get('context');
|
||||
$this->currentStep = $form_state->get('step');
|
||||
|
||||
if ($this->currentStep == 'formatter') {
|
||||
$this->buildFormatterSelectionForm($form, $form_state);
|
||||
}
|
||||
else {
|
||||
$this->buildConfigurationForm($form, $form_state);
|
||||
}
|
||||
|
||||
return $form;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the formatter selection step.
|
||||
*/
|
||||
function buildFormatterSelectionForm(array &$form, FormStateInterface $form_state) {
|
||||
|
||||
// Gather group formatters.
|
||||
$formatter_options = \field_group_field_formatter_options($form_state->get('context'));
|
||||
$form['add'] = array(
|
||||
'#type' => 'container',
|
||||
'#attributes' => array('class' => array('form--inline', 'clearfix')),
|
||||
);
|
||||
|
||||
$form['add']['group_formatter'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Add a new group'),
|
||||
'#options' => $formatter_options,
|
||||
'#empty_option' => $this->t('- Select a group type -'),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
||||
// Field label and field_name.
|
||||
$form['new_group_wrapper'] = array(
|
||||
'#type' => 'container',
|
||||
'#states' => array(
|
||||
'!visible' => array(
|
||||
':input[name="group_formatter"]' => array('value' => ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
$form['new_group_wrapper']['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Label'),
|
||||
'#size' => 15,
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
||||
$form['new_group_wrapper']['group_name'] = array(
|
||||
'#type' => 'machine_name',
|
||||
'#size' => 15,
|
||||
// This field should stay LTR even for RTL languages.
|
||||
'#field_prefix' => '<span dir="ltr">' . self::GROUP_PREFIX,
|
||||
'#field_suffix' => '</span>‎',
|
||||
'#description' => $this->t('A unique machine-readable name containing letters, numbers, and underscores.'),
|
||||
'#maxlength' => FieldStorageConfig::NAME_MAX_LENGTH - strlen(self::GROUP_PREFIX),
|
||||
'#machine_name' => array(
|
||||
'source' => array('new_group_wrapper', 'label'),
|
||||
'exists' => array($this, 'groupNameExists'),
|
||||
),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save and continue'),
|
||||
'#button_type' => 'primary',
|
||||
'#validate' => array(
|
||||
array($this, 'validateFormatterSelection')
|
||||
),
|
||||
);
|
||||
|
||||
$form['#attached']['library'][] = 'field_ui/drupal.field_ui';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the formatter configuration form.
|
||||
*/
|
||||
function buildConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
|
||||
$group = new \stdClass();
|
||||
$group->context = $this->context;
|
||||
$group->entity_type = $this->entityTypeId;
|
||||
$group->bundle = $this->bundle;
|
||||
$group->mode = $this->mode;
|
||||
|
||||
$manager = \Drupal::service('plugin.manager.field_group.formatters');
|
||||
$plugin = $manager->getInstance(array(
|
||||
'format_type' => $form_state->getValue('group_formatter'),
|
||||
'configuration' => [
|
||||
'label' => $form_state->getValue('label'),
|
||||
],
|
||||
'group' => $group,
|
||||
));
|
||||
|
||||
$form['format_settings'] = array(
|
||||
'#type' => 'container',
|
||||
'#tree' => TRUE,
|
||||
);
|
||||
|
||||
$form['format_settings'] += $plugin->settingsForm();
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Create group'),
|
||||
'#button_type' => 'primary',
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the formatter selection step.
|
||||
*/
|
||||
public function validateFormatterSelection(array &$form, FormStateInterface $form_state) {
|
||||
|
||||
$group_name = self::GROUP_PREFIX . $form_state->getValue('group_name');
|
||||
|
||||
// Add the prefix.
|
||||
$form_state->setValueForElement($form['new_group_wrapper']['group_name'], $group_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
|
||||
if ($form_state->get('step') == 'formatter') {
|
||||
$form_state->set('step', 'configuration');
|
||||
$form_state->set('group_label', $form_state->getValue('label'));
|
||||
$form_state->set('group_name', $form_state->getValue('group_name'));
|
||||
$form_state->set('group_formatter', $form_state->getValue('group_formatter'));
|
||||
$form_state->setRebuild();
|
||||
}
|
||||
else {
|
||||
|
||||
$new_group = (object) array(
|
||||
'group_name' => $form_state->get('group_name'),
|
||||
'entity_type' => $this->entityTypeId,
|
||||
'bundle' => $this->bundle,
|
||||
'mode' => $this->mode,
|
||||
'context' => $this->context,
|
||||
'children' =>[],
|
||||
'parent_name' => '',
|
||||
'weight' => 20,
|
||||
'format_type' => $form_state->get('group_formatter'),
|
||||
);
|
||||
|
||||
$new_group->format_settings = $form_state->getValue('format_settings');
|
||||
$new_group->label = $new_group->format_settings['label'];
|
||||
unset($new_group->format_settings['label']);
|
||||
$new_group->format_settings += _field_group_get_default_formatter_settings($form_state->get('group_formatter'), $this->context);
|
||||
|
||||
field_group_group_save($new_group);
|
||||
|
||||
// Store new group information for any additional submit handlers.
|
||||
$groups_added = $form_state->get('groups_added');
|
||||
$groups_added['_add_new_group'] = $new_group->group_name;
|
||||
drupal_set_message(t('New group %label successfully created.', array('%label' => $new_group->label)));
|
||||
|
||||
$form_state->setRedirectUrl(FieldgroupUi::getFieldUiRoute($new_group));
|
||||
\Drupal::cache()->invalidate('field_groups');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a group machine name is taken.
|
||||
*
|
||||
* @param string $value
|
||||
* The machine name, not prefixed.
|
||||
* @param array $element
|
||||
* An array containing the structure of the 'group_name' element.
|
||||
* @param FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*
|
||||
* @return bool
|
||||
* Whether or not the group machine name is taken.
|
||||
*/
|
||||
public function groupNameExists($value, $element, FormStateInterface $form_state) {
|
||||
|
||||
// Add the prefix.
|
||||
$group_name = self::GROUP_PREFIX . $value;
|
||||
$entity_type = $form_state->get('entity_type_id');
|
||||
$bundle = $form_state->get('bundle');
|
||||
$context = $form_state->get('context');
|
||||
$mode = $form_state->get('mode');
|
||||
|
||||
return field_group_exists($group_name, $entity_type, $bundle, $context, $mode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Form;
|
||||
|
||||
use Drupal\Core\Form\ConfirmFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\field_group\FieldgroupUi;
|
||||
|
||||
/**
|
||||
* Provides a form for removing a fieldgroup from a bundle.
|
||||
*/
|
||||
class FieldGroupDeleteForm extends ConfirmFormBase {
|
||||
|
||||
/**
|
||||
* The fieldgroup to delete.
|
||||
*
|
||||
* @var stdClass
|
||||
*/
|
||||
protected $fieldGroup;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'field_group_delete_form';
|
||||
}
|
||||
|
||||
public function buildForm(array $form, FormStateInterface $form_state, $field_group_name = NULL, $entity_type_id = NULL, $bundle = NULL, $context = NULL) {
|
||||
|
||||
if ($context == 'form') {
|
||||
$mode = $this->getRequest()->attributes->get('form_mode_name');
|
||||
}
|
||||
else {
|
||||
$mode = $this->getRequest()->attributes->get('view_mode_name');
|
||||
}
|
||||
|
||||
if (empty($mode)) {
|
||||
$mode = 'default';
|
||||
}
|
||||
|
||||
$this->fieldGroup = field_group_load_field_group($field_group_name, $entity_type_id, $bundle, $context, $mode);
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$bundles = entity_get_bundles();
|
||||
$bundle_label = $bundles[$this->fieldGroup->entity_type][$this->fieldGroup->bundle]['label'];
|
||||
|
||||
field_group_group_delete($this->fieldGroup);
|
||||
|
||||
drupal_set_message(t('The group %group has been deleted from the %type content type.', array('%group' => t($this->fieldGroup->label), '%type' => $bundle_label)));
|
||||
|
||||
// Redirect.
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getQuestion() {
|
||||
return $this->t('Are you sure you want to delete the group %group?', array('%group' => t($this->fieldGroup->label)));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConfirmText() {
|
||||
return $this->t('Delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCancelUrl() {
|
||||
return FieldgroupUi::getFieldUiRoute($this->fieldGroup);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\Derivative;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
|
||||
/**
|
||||
* Provides local action definitions for all entity bundles.
|
||||
*/
|
||||
class FieldGroupLocalAction extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The route provider.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a FieldUiLocalAction object.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
|
||||
* The route provider to load routes by name.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(RouteProviderInterface $route_provider, EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->routeProvider = $route_provider;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('router.route_provider'),
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$this->derivatives = array();
|
||||
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
if ($entity_type->get('field_ui_base_route')) {
|
||||
|
||||
$default_options = [
|
||||
'title' => $this->t('Add group'),
|
||||
];
|
||||
|
||||
$this->derivatives['field_group_add_' . $entity_type_id . '_form_display'] = [
|
||||
'route_name' => "field_ui.field_group_add_$entity_type_id.form_display",
|
||||
'appears_on' => [
|
||||
"entity.entity_form_display.{$entity_type_id}.default",
|
||||
],
|
||||
] + $default_options;
|
||||
|
||||
$this->derivatives['field_group_add_' . $entity_type_id . '_form_display_form_mode'] = [
|
||||
'route_name' => "field_ui.field_group_add_$entity_type_id.form_display.form_mode",
|
||||
'appears_on' => [
|
||||
"entity.entity_form_display.{$entity_type_id}.form_mode",
|
||||
],
|
||||
] + $default_options;
|
||||
|
||||
$this->derivatives['field_group_add_' . $entity_type_id . '_display'] = [
|
||||
'route_name' => "field_ui.field_group_add_$entity_type_id.display",
|
||||
'appears_on' => [
|
||||
"entity.entity_view_display.{$entity_type_id}.default",
|
||||
],
|
||||
] + $default_options;
|
||||
|
||||
$this->derivatives['field_group_add_' . $entity_type_id . '_display_view_mode'] = [
|
||||
'route_name' => "field_ui.field_group_add_$entity_type_id.display.view_mode",
|
||||
'appears_on' => [
|
||||
"entity.entity_view_display.{$entity_type_id}.view_mode",
|
||||
],
|
||||
] + $default_options;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->derivatives as &$entry) {
|
||||
$entry += $base_plugin_definition;
|
||||
}
|
||||
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'accordion' formatter.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "accordion",
|
||||
* label = @Translation("Accordion"),
|
||||
* description = @Translation("This fieldgroup renders child groups as jQuery accordion."),
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Accordion extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
parent::preRender($element, $rendering_object);
|
||||
|
||||
$form_state = new FormState();
|
||||
|
||||
$element += array(
|
||||
'#type' => 'field_group_accordion',
|
||||
'#effect' => $this->getSetting('effect'),
|
||||
);
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$element['#id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
|
||||
$classes = $this->getClasses();
|
||||
if (!empty($classes)) {
|
||||
$element += array('#attributes' => array('class' => $classes));
|
||||
}
|
||||
|
||||
\Drupal\field_group\Element\Accordion::processAccordion($element, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['effect'] = array(
|
||||
'#title' => $this->t('Effect'),
|
||||
'#type' => 'select',
|
||||
'#options' => array('none' => $this->t('None'), 'bounceslide' => $this->t('Bounce slide')),
|
||||
'#default_value' => $this->getSetting('effect'),
|
||||
'#weight' => 2,
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = array();
|
||||
$summary[] = $this->t('Effect : @effect',
|
||||
array('@effect' => $this->getSetting('effect'))
|
||||
);
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
return array(
|
||||
'effect' => 'none',
|
||||
) + parent::defaultSettings($context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'accordion_item' formatter.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "accordion_item",
|
||||
* label = @Translation("Accordion Item"),
|
||||
* description = @Translation("This fieldgroup renders the content in a div, part of accordion group."),
|
||||
* format_types = {
|
||||
* "open",
|
||||
* "closed",
|
||||
* },
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view",
|
||||
* },
|
||||
* )
|
||||
*/
|
||||
class AccordionItem extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
parent::preRender($element, $rendering_object);
|
||||
|
||||
$element += array(
|
||||
'#type' => 'field_group_accordion_item',
|
||||
'#open' => $this->getSetting('formatter') == 'open' ? TRUE : FALSE,
|
||||
'#description' => $this->getSetting('description'),
|
||||
'#title' => Drupal::translation()->translate($this->getLabel()),
|
||||
);
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$element['#id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
|
||||
$classes = $this->getClasses();
|
||||
if (!empty($classes)) {
|
||||
$element += array('#attributes' => array('class' => $classes));
|
||||
}
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$element['#attached']['library'][] = 'field_group/formatter.details';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['formatter'] = array(
|
||||
'#title' => $this->t('Default state'),
|
||||
'#type' => 'select',
|
||||
'#options' => array_combine($this->pluginDefinition['format_types'], $this->pluginDefinition['format_types']),
|
||||
'#default_value' => $this->getSetting('formatter'),
|
||||
'#weight' => -4,
|
||||
);
|
||||
|
||||
if ($this->context == 'form') {
|
||||
$form['required_fields'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Mark group as required if it contains required fields.'),
|
||||
'#default_value' => $this->getSetting('required_fields'),
|
||||
'#weight' => 2,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = array();
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$summary[] = $this->t('Mark as required');
|
||||
}
|
||||
|
||||
if ($this->getSetting('description')) {
|
||||
$summary[] = $this->t('Description : @description',
|
||||
array('@description' => $this->getSetting('description'))
|
||||
);
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
$defaults = array(
|
||||
'formatter' => 'closed',
|
||||
'description' => '',
|
||||
) + parent::defaultSettings($context);
|
||||
|
||||
if ($context == 'form') {
|
||||
$defaults['required_fields'] = 1;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Details element.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "details",
|
||||
* label = @Translation("Details"),
|
||||
* description = @Translation("Add a details element"),
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view"
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Details extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
parent::preRender($element, $rendering_object);
|
||||
|
||||
$element += array(
|
||||
'#type' => 'details',
|
||||
'#title' => Html::escape($this->t($this->getLabel())),
|
||||
'#open' => $this->getSetting('open')
|
||||
);
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$element['#id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
|
||||
$classes = $this->getClasses();
|
||||
if (!empty($classes)) {
|
||||
$element += array(
|
||||
'#attributes' => array('class' => $classes),
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getSetting('description')) {
|
||||
$element += array(
|
||||
'#description' => $this->getSetting('description'),
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$element['#attached']['library'][] = 'field_group/formatter.details';
|
||||
$element['#attached']['library'][] = 'field_group/core';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['open'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Display element open by default.'),
|
||||
'#default_value' => $this->getSetting('open'),
|
||||
);
|
||||
|
||||
if ($this->context == 'form') {
|
||||
$form['required_fields'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Mark group as required if it contains required fields.'),
|
||||
'#default_value' => $this->getSetting('required_fields'),
|
||||
'#weight' => 2,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = array();
|
||||
if ($this->getSetting('open')) {
|
||||
$summary[] = $this->t('Default state open');
|
||||
}
|
||||
else {
|
||||
$summary[] = $this->t('Default state closed');
|
||||
}
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$summary[] = $this->t('Mark as required');
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
$defaults = array(
|
||||
'open' => FALSE,
|
||||
'required_fields' => $context == 'form',
|
||||
) + parent::defaultSettings($context);
|
||||
|
||||
if ($context == 'form') {
|
||||
$defaults['required_fields'] = 1;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'fieldset' formatter.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "fieldset",
|
||||
* label = @Translation("Fieldset"),
|
||||
* description = @Translation("This fieldgroup renders the inner content in a fieldset with the title as legend."),
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Fieldset extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
|
||||
$element += array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => Html::escape($this->t($this->getLabel())),
|
||||
'#pre_render' => array(),
|
||||
'#attributes' => array(),
|
||||
);
|
||||
|
||||
if ($this->getSetting('description')) {
|
||||
$element += array(
|
||||
'#description' => $this->getSetting('description'),
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$element['#id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
|
||||
$classes = $this->getClasses();
|
||||
if (!empty($classes)) {
|
||||
$element['#attributes'] += array('class' => $classes);
|
||||
}
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$element['#attached']['library'][] = 'field_group/formatter.fieldset';
|
||||
$element['#attached']['library'][] = 'field_group/core';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['description'] = array(
|
||||
'#title' => $this->t('Description'),
|
||||
'#type' => 'textarea',
|
||||
'#default_value' => $this->getSetting('description'),
|
||||
'#weight' => -4,
|
||||
);
|
||||
|
||||
if ($this->context == 'form') {
|
||||
$form['required_fields'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Mark group as required if it contains required fields.'),
|
||||
'#default_value' => $this->getSetting('required_fields'),
|
||||
'#weight' => 2,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = parent::settingsSummary();
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$summary[] = $this->t('Mark as required');
|
||||
}
|
||||
|
||||
if ($this->getSetting('description')) {
|
||||
$summary[] = $this->t('Description : @description',
|
||||
array('@description' => $this->getSetting('description'))
|
||||
);
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
$defaults = array(
|
||||
'description' => '',
|
||||
) + parent::defaultSettings($context);
|
||||
|
||||
if ($context == 'form') {
|
||||
$defaults['required_fields'] = 1;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Template\Attribute;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'html_element' formatter.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "html_element",
|
||||
* label = @Translation("HTML element"),
|
||||
* description = @Translation("This fieldgroup renders the inner content in a HTML element with classes and attributes."),
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class HtmlElement extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
parent::preRender($element, $rendering_object);
|
||||
|
||||
$element_attributes = new Attribute();
|
||||
|
||||
if ($this->getSetting('attributes')) {
|
||||
|
||||
// This regex split the attributes string so that we can pass that
|
||||
// later to drupal_attributes().
|
||||
preg_match_all('/([^\s=]+)="([^"]+)"/', $this->getSetting('attributes'), $matches);
|
||||
|
||||
// Put the attribute and the value together.
|
||||
foreach ($matches[1] as $key => $attribute) {
|
||||
$element_attributes[$attribute] = $matches[2][$key];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add the id to the attributes array.
|
||||
if ($this->getSetting('id')) {
|
||||
$element_attributes['id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
|
||||
// Add the classes to the attributes array.
|
||||
$classes = $this->getClasses();
|
||||
if (!empty($classes)) {
|
||||
if (!isset($element_attributes['class'])) {
|
||||
$element_attributes['class'] = array();
|
||||
}
|
||||
// If user also entered class in the attributes textfield, force it to an array.
|
||||
else {
|
||||
$element_attributes['class'] = array($element_attributes['class']);
|
||||
}
|
||||
$element_attributes['class'] = array_merge($classes, $element_attributes['class']->value());
|
||||
}
|
||||
|
||||
$element['#effect'] = $this->getSetting('effect');
|
||||
$element['#speed'] = $this->getSetting('speed');
|
||||
$element['#type'] = 'field_group_html_element';
|
||||
$element['#wrapper_element'] = $this->getSetting('element');
|
||||
$element['#attributes'] = $element_attributes;
|
||||
if ($this->getSetting('show_label')) {
|
||||
$element['#title_element'] = $this->getSetting('label_element');
|
||||
$element['#title'] = Html::escape($this->t($this->getLabel()));
|
||||
}
|
||||
|
||||
$form_state = new FormState();
|
||||
\Drupal\field_group\Element\HtmlElement::processHtmlElement($element, $form_state);
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$element['#attached']['library'][] = 'field_group/formatter.html_element';
|
||||
$element['#attached']['library'][] = 'field_group/core';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['element'] = array(
|
||||
'#title' => $this->t('Element'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $this->getSetting('element'),
|
||||
'#description' => $this->t('E.g. div, section, aside etc.'),
|
||||
'#weight' => 1,
|
||||
);
|
||||
|
||||
$form['show_label'] = array(
|
||||
'#title' => $this->t('Show label'),
|
||||
'#type' => 'select',
|
||||
'#options' => array(0 => $this->t('No'), 1 => $this->t('Yes')),
|
||||
'#default_value' => $this->getSetting('show_label'),
|
||||
'#weight' => 2,
|
||||
'#attributes' => array(
|
||||
'data-fieldgroup-selector' => 'show_label'
|
||||
),
|
||||
);
|
||||
|
||||
$form['label_element'] = array(
|
||||
'#title' => $this->t('Label element'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $this->getSetting('label_element'),
|
||||
'#weight' => 3,
|
||||
'#states' => array(
|
||||
'visible' => array(
|
||||
':input[data-fieldgroup-selector="show_label"]' => array('value' => 1),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if ($this->context == 'form') {
|
||||
$form['required_fields'] = array(
|
||||
'#title' => $this->t('Mark group as required if it contains required fields.'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => $this->getSetting('required_fields'),
|
||||
'#weight' => 4,
|
||||
);
|
||||
}
|
||||
|
||||
$form['attributes'] = array(
|
||||
'#title' => $this->t('Attributes'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $this->getSetting('attributes'),
|
||||
'#description' => $this->t('E.g. name="anchor"'),
|
||||
'#weight' => 5,
|
||||
);
|
||||
|
||||
$form['effect'] = array(
|
||||
'#title' => $this->t('Effect'),
|
||||
'#type' => 'select',
|
||||
'#options' => array(
|
||||
'none' => $this->t('None'),
|
||||
'collapsible' => $this->t('Collapsible'),
|
||||
'blind' => $this->t('Blind')
|
||||
),
|
||||
'#default_value' => $this->getSetting('effect'),
|
||||
'#weight' => 6,
|
||||
'#attributes' => array(
|
||||
'data-fieldgroup-selector' => 'effect'
|
||||
),
|
||||
);
|
||||
|
||||
$form['speed'] = array(
|
||||
'#title' => $this->t('Speed'),
|
||||
'#type' => 'select',
|
||||
'#options' => array('slow' => $this->t('Slow'), 'fast' => $this->t('Fast')),
|
||||
'#default_value' => $this->getSetting('speed'),
|
||||
'#weight' => 7,
|
||||
'#states' => array(
|
||||
'!visible' => array(
|
||||
':input[data-fieldgroup-selector="effect"]' => array('value' => 'none'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = parent::settingsSummary();
|
||||
$summary[] = $this->t('Element: @element',
|
||||
array('@element' => $this->getSetting('element'))
|
||||
);
|
||||
|
||||
if ($this->getSetting('show_label')) {
|
||||
$summary[] = $this->t('Label element: @element',
|
||||
array('@element' => $this->getSetting('label_element'))
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getSetting('attributes')) {
|
||||
$summary[] = $this->t('Attributes: @attributes',
|
||||
array('@attributes' => $this->getSetting('attributes'))
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$summary[] = $this->t('Mark as required');
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
$defaults = array(
|
||||
'element' => 'div',
|
||||
'show_label' => 0,
|
||||
'label_element' => 'h3',
|
||||
'effect' => 'none',
|
||||
'speed' => 'fast',
|
||||
'attributes' => '',
|
||||
) + parent::defaultSettings($context);
|
||||
|
||||
if ($context == 'form') {
|
||||
$defaults['required_fields'] = 1;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'tab' formatter.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "tab",
|
||||
* label = @Translation("Tab"),
|
||||
* description = @Translation("This fieldgroup renders the content as a tab."),
|
||||
* format_types = {
|
||||
* "open",
|
||||
* "closed",
|
||||
* },
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view",
|
||||
* },
|
||||
* )
|
||||
*/
|
||||
class Tab extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
parent::preRender($element, $rendering_object);
|
||||
|
||||
$add = array(
|
||||
'#type' => 'details',
|
||||
'#title' => Html::escape($this->t($this->getLabel())),
|
||||
'#description' => $this->getSetting('description'),
|
||||
);
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$add['#id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
else {
|
||||
$add['#id'] = Html::getId('edit-' . $this->group->group_name);
|
||||
}
|
||||
|
||||
$classes = $this->getClasses();
|
||||
if (!empty($classes)) {
|
||||
$element += array(
|
||||
'#attributes' => array('class' => $classes),
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getSetting('formatter') == 'open') {
|
||||
$element['#open'] = TRUE;
|
||||
}
|
||||
|
||||
// Front-end and back-end on configuration will lead
|
||||
// to vertical tabs nested in a separate vertical group.
|
||||
if (!empty($this->group->parent_name)) {
|
||||
$add['#group'] = $this->group->parent_name;
|
||||
$add['#parents'] = array($add['#group']);
|
||||
}
|
||||
|
||||
if ($this->getSetting('required_fields')) {
|
||||
$element['#attached']['library'][] = 'field_group/formatter.tabs';
|
||||
$element['#attached']['library'][] = 'field_group/core';
|
||||
}
|
||||
|
||||
$element += $add;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['formatter'] = array(
|
||||
'#title' => $this->t('Default state'),
|
||||
'#type' => 'select',
|
||||
'#options' => array_combine($this->pluginDefinition['format_types'], $this->pluginDefinition['format_types']),
|
||||
'#default_value' => $this->getSetting('formatter'),
|
||||
'#weight' => -4,
|
||||
);
|
||||
|
||||
$form['description'] = array(
|
||||
'#title' => $this->t('Description'),
|
||||
'#type' => 'textarea',
|
||||
'#default_value' => $this->getSetting('description'),
|
||||
'#weight' => -4,
|
||||
);
|
||||
|
||||
if ($this->context == 'form') {
|
||||
$form['required_fields'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Mark group as required if it contains required fields.'),
|
||||
'#default_value' => $this->getSetting('required_fields'),
|
||||
'#weight' => 2,
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
$defaults = array(
|
||||
'formatter' => 'closed',
|
||||
'description' => '',
|
||||
) + parent::defaultSettings($context);
|
||||
|
||||
if ($context == 'form') {
|
||||
$defaults['required_fields'] = 1;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Render\Element\VerticalTabs;
|
||||
use Drupal\field_group\Element\HorizontalTabs;
|
||||
use Drupal\field_group\FieldGroupFormatterBase;
|
||||
|
||||
/**
|
||||
* Plugin implementation of the 'horizontal_tabs' formatter.
|
||||
*
|
||||
* @FieldGroupFormatter(
|
||||
* id = "tabs",
|
||||
* label = @Translation("Tabs"),
|
||||
* description = @Translation("This fieldgroup renders child groups in its own tabs wrapper."),
|
||||
* supported_contexts = {
|
||||
* "form",
|
||||
* "view",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Tabs extends FieldGroupFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function preRender(&$element, $rendering_object) {
|
||||
parent::preRender($element, $rendering_object);
|
||||
|
||||
$element += array(
|
||||
'#prefix' => '<div class=" ' . implode(' ' , $this->getClasses()) . '">',
|
||||
'#suffix' => '</div>',
|
||||
'#tree' => TRUE,
|
||||
'#parents' => array($this->group->group_name),
|
||||
'#default_tab' => '',
|
||||
);
|
||||
|
||||
if ($this->getSetting('id')) {
|
||||
$element['#id'] = Html::getId($this->getSetting('id'));
|
||||
}
|
||||
|
||||
// By default tabs don't have titles but you can override it in the theme.
|
||||
if ($this->getLabel()) {
|
||||
$element['#title'] = Html::escape($this->getLabel());
|
||||
}
|
||||
|
||||
$form_state = new FormState();
|
||||
|
||||
if ($this->getSetting('direction') == 'vertical') {
|
||||
|
||||
$element += array(
|
||||
'#type' => 'vertical_tabs',
|
||||
'#theme_wrappers' => array('vertical_tabs'),
|
||||
);
|
||||
$complete_form = array();
|
||||
$element = VerticalTabs::processVerticalTabs($element, $form_state, $complete_form);
|
||||
}
|
||||
else {
|
||||
$element += array(
|
||||
'#type' => 'horizontal_tabs',
|
||||
'#theme_wrappers' => array('horizontal_tabs'),
|
||||
);
|
||||
$on_form = $this->context == 'form';
|
||||
$element = HorizontalTabs::processHorizontalTabs($element, $form_state, $on_form);
|
||||
}
|
||||
|
||||
// Make sure the group has 1 child. This is needed to succeed at form_pre_render_vertical_tabs().
|
||||
// Skipping this would force us to move all child groups to this array, making it an un-nestable.
|
||||
$element['group']['#groups'][$this->group->group_name] = array(0 => array());
|
||||
$element['group']['#groups'][$this->group->group_name]['#group_exists'] = TRUE;
|
||||
|
||||
// Search for a tab that was marked as open. First one wins.
|
||||
foreach (Element::children($element) as $tab_name) {
|
||||
if (!empty($element[$tab_name]['#open'])) {
|
||||
$element[$this->group->group_name . '__active_tab']['#default_value'] = $tab_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm() {
|
||||
|
||||
$form = parent::settingsForm();
|
||||
|
||||
$form['direction'] = array(
|
||||
'#title' => $this->t('Direction'),
|
||||
'#type' => 'select',
|
||||
'#options' => array(
|
||||
'vertical' => $this->t('Vertical'),
|
||||
'horizontal' => $this->t('Horizontal'),
|
||||
),
|
||||
'#default_value' => $this->getSetting('direction'),
|
||||
'#weight' => 1,
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsSummary() {
|
||||
|
||||
$summary = parent::settingsSummary();
|
||||
$summary[] = $this->t('Direction: @direction',
|
||||
array('@direction' => $this->getSetting('direction'))
|
||||
);
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function defaultContextSettings($context) {
|
||||
return array(
|
||||
'direction' => 'vertical',
|
||||
) + parent::defaultContextSettings($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClasses() {
|
||||
|
||||
$classes = parent::getClasses();
|
||||
$classes[] = 'field-group-' . $this->group->format_type . '-wrapper';
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Routing;
|
||||
|
||||
use Drupal\Core\ParamConverter\ParamConverterInterface;
|
||||
|
||||
/**
|
||||
* Parameter converter for upcasting fieldgroup config ids to fieldgroup object.
|
||||
*/
|
||||
class FieldGroupConverter implements ParamConverterInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies($definition, $name, \Symfony\Component\Routing\Route $route) {
|
||||
return isset($definition['type']) && $definition['type'] == 'field_group';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults) {
|
||||
$identifiers = explode('.', $value);
|
||||
if (count($identifiers) != 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
return field_group_load_field_group($identifiers[4], $identifiers[0], $identifiers[1], $identifiers[2], $identifiers[3]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Routing;
|
||||
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Routing\RouteSubscriberBase;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Subscriber for Field group routes.
|
||||
*/
|
||||
class RouteSubscriber extends RouteSubscriberBase {
|
||||
|
||||
/**
|
||||
* The entity type manager
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* Constructs a RouteSubscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $manager) {
|
||||
$this->manager = $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterRoutes(RouteCollection $collection) {
|
||||
|
||||
// Create fieldgroup routes for every entity.
|
||||
foreach ($this->manager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
$defaults = array();
|
||||
if ($route_name = $entity_type->get('field_ui_base_route')) {
|
||||
// Try to get the route from the current collection.
|
||||
if (!$entity_route = $collection->get($route_name)) {
|
||||
continue;
|
||||
}
|
||||
$path = $entity_route->getPath();
|
||||
|
||||
$options = $entity_route->getOptions();
|
||||
|
||||
// Special parameter used to easily recognize all Field UI routes.
|
||||
$options['_field_ui'] = TRUE;
|
||||
|
||||
if (($bundle_entity_type = $entity_type->getBundleEntityType()) && $bundle_entity_type !== 'bundle') {
|
||||
$options['parameters'][$entity_type->getBundleEntityType()] = array(
|
||||
'type' => 'entity:' . $entity_type->getBundleEntityType(),
|
||||
);
|
||||
}
|
||||
|
||||
$options['parameters']['field_group'] = array(
|
||||
'type' => 'field_group',
|
||||
'entity_type' => $entity_type->getBundleEntityType(),
|
||||
);
|
||||
|
||||
$defaults_delete = [
|
||||
'entity_type_id' => $entity_type_id,
|
||||
'_form' => '\Drupal\field_group\Form\FieldGroupDeleteForm',
|
||||
];
|
||||
$defaults_add = [
|
||||
'entity_type_id' => $entity_type_id,
|
||||
'_form' => '\Drupal\field_group\Form\FieldGroupAddForm',
|
||||
'_title' => 'Add group',
|
||||
];
|
||||
|
||||
// If the entity type has no bundles and it doesn't use {bundle} in its
|
||||
// admin path, use the entity type.
|
||||
if (strpos($path, '{bundle}') === FALSE) {
|
||||
$defaults_add['bundle'] = !$entity_type->hasKey('bundle') ? $entity_type_id : '';
|
||||
$defaults_delete['bundle'] = $defaults_add['bundle'];
|
||||
}
|
||||
|
||||
// Routes to delete field groups.
|
||||
$route = new Route(
|
||||
"$path/form-display/{field_group_name}/delete",
|
||||
['context' => 'form'] + $defaults_delete,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' form display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_delete_$entity_type_id.form_display", $route);
|
||||
|
||||
$route = new Route(
|
||||
"$path/form-display/{form_mode_name}/{field_group_name}/delete",
|
||||
['context' => 'form'] + $defaults_delete,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' form display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_delete_$entity_type_id.form_display.form_mode", $route);
|
||||
|
||||
$route = new Route(
|
||||
"$path/display/{field_group_name}/delete",
|
||||
['context' => 'view'] + $defaults_delete,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_delete_$entity_type_id.display", $route);
|
||||
|
||||
$route = new Route(
|
||||
"$path/display/{view_mode_name}/{field_group_name}/delete",
|
||||
['context' => 'view'] + $defaults_delete,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_delete_$entity_type_id.display.view_mode", $route);
|
||||
|
||||
// Routes to add field groups.
|
||||
$route = new Route(
|
||||
"$path/form-display/add-group",
|
||||
['context' => 'form'] + $defaults_add,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' form display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_add_$entity_type_id.form_display", $route);
|
||||
|
||||
$route = new Route(
|
||||
"$path/form-display/{form_mode_name}/add-group",
|
||||
['context' => 'form'] + $defaults_add,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' form display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_add_$entity_type_id.form_display.form_mode", $route);
|
||||
|
||||
$route = new Route(
|
||||
"$path/display/add-group",
|
||||
['context' => 'view'] + $defaults_add,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_add_$entity_type_id.display", $route);
|
||||
|
||||
$route = new Route(
|
||||
"$path/display/{view_mode_name}/add-group",
|
||||
['context' => 'view'] + $defaults_add,
|
||||
array('_permission' => 'administer ' . $entity_type_id . ' display'),
|
||||
$options
|
||||
);
|
||||
$collection->add("field_ui.field_group_add_$entity_type_id.display.view_mode", $route);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
//$events = parent::getSubscribedEvents();
|
||||
// Come after field_ui, config_translation.
|
||||
$events[RoutingEvents::ALTER] = array('onAlterRoutes', -210);
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Tests;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests for displaying entities.
|
||||
*
|
||||
* @group field_group
|
||||
*/
|
||||
class EntityDisplayTest extends WebTestBase {
|
||||
|
||||
use FieldGroupTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'field_test', 'field_ui', 'field_group', 'field_group_test');
|
||||
|
||||
function setUp() {
|
||||
|
||||
parent::setUp();
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'bypass node access'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create content type, with underscores.
|
||||
$type_name = strtolower($this->randomMachineName(8)) . '_test';
|
||||
$type = $this->drupalCreateContentType(array('name' => $type_name, 'type' => $type_name));
|
||||
$this->type = $type->id();
|
||||
$display = entity_get_display('node', $type_name, 'default');
|
||||
|
||||
// Create a node.
|
||||
$node_values = array('type' => $type_name);
|
||||
|
||||
// Create test fields.
|
||||
$test_fields = array('field_test', 'field_test_2', 'field_no_access');
|
||||
foreach ($test_fields as $field_name) {
|
||||
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'test_field',
|
||||
]);
|
||||
$field_storage->save();
|
||||
|
||||
$instance = FieldConfig::create([
|
||||
'field_storage' => $field_storage,
|
||||
'bundle' => $type_name,
|
||||
'label' => $this->randomMachineName(),
|
||||
]);
|
||||
$instance->save();
|
||||
|
||||
// Assign a test value for the field.
|
||||
$node_values[$field_name][0]['value'] = mt_rand(1, 127);
|
||||
|
||||
// Set the field visible on the display object.
|
||||
$display_options = array(
|
||||
'label' => 'above',
|
||||
'type' => 'field_test_default',
|
||||
'settings' => array(
|
||||
'test_formatter_setting' => $this->randomMachineName(),
|
||||
),
|
||||
);
|
||||
$display->setComponent($field_name, $display_options);
|
||||
}
|
||||
|
||||
// Save display + create node.
|
||||
$display->save();
|
||||
$this->node = $this->drupalCreateNode($node_values);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if an fieldgroup that only contains fields
|
||||
* that has no access is not shown.
|
||||
*/
|
||||
function testFieldAccess() {
|
||||
|
||||
$data = array(
|
||||
'label' => 'Wrapper',
|
||||
'children' => array(
|
||||
0 => 'field_no_access',
|
||||
),
|
||||
'format_type' => 'html_element',
|
||||
'format_settings' => array(
|
||||
'element' => 'div',
|
||||
'id' => 'wrapper-id',
|
||||
),
|
||||
);
|
||||
|
||||
$this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
|
||||
// Test if group is not shown.
|
||||
$this->assertNoFieldByXPath("//div[contains(@id, 'wrapper-id')]", NULL, t('Div that contains fields with no access is not shown.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the html element formatter.
|
||||
*/
|
||||
function testHtmlElement() {
|
||||
|
||||
$data = array(
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => 'field_test',
|
||||
1 => 'body',
|
||||
),
|
||||
'label' => 'Link',
|
||||
'format_type' => 'html_element',
|
||||
'format_settings' => array(
|
||||
'label' => 'Link',
|
||||
'element' => 'div',
|
||||
'id' => 'wrapper-id',
|
||||
'classes' => 'test-class',
|
||||
),
|
||||
);
|
||||
$group = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
//$groups = field_group_info_groups('node', 'article', 'view', 'default', TRUE);
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
|
||||
// Test group ids and classes.
|
||||
$this->assertFieldByXPath("//div[contains(@id, 'wrapper-id')]", NULL, t('Wrapper id set on wrapper div'));
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class')]", NULL, t('Test class set on wrapper div') . 'class="' . $group->group_name . ' test-class');
|
||||
|
||||
// Test group label.
|
||||
$this->assertNoRaw('<h3><span>' . $data['label'] . '</span></h3>', t('Label is not shown'));
|
||||
|
||||
// Set show label to true.
|
||||
$group->format_settings['show_label'] = TRUE;
|
||||
$group->format_settings['label_element'] = 'h3';
|
||||
field_group_group_save($group);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
$this->assertRaw('<h3>' . $data['label'] . '</h3>', t('Label is shown'));
|
||||
|
||||
// Change to collapsible with blink effect.
|
||||
$group->format_settings['effect'] = 'blink';
|
||||
$group->format_settings['speed'] = 'fast';
|
||||
field_group_group_save($group);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'speed-fast')]", NULL, t('Speed class is set'));
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'effect-blink')]", NULL, t('Effect class is set'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the fieldset formatter.
|
||||
*/
|
||||
function testFieldset() {
|
||||
|
||||
$data = array(
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => 'field_test',
|
||||
1 => 'body',
|
||||
),
|
||||
'label' => 'Test Fieldset',
|
||||
'format_type' => 'fieldset',
|
||||
'format_settings' => array(
|
||||
'id' => 'fieldset-id',
|
||||
'classes' => 'test-class',
|
||||
'description' => 'test description',
|
||||
),
|
||||
);
|
||||
$group = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
|
||||
// Test group ids and classes.
|
||||
$this->assertFieldByXPath("//fieldset[contains(@id, 'fieldset-id')]", NULL, t('Correct id set on the fieldset'));
|
||||
$this->assertFieldByXPath("//fieldset[contains(@class, 'test-class')]", NULL, t('Test class set on the fieldset'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the tabs formatter.
|
||||
*/
|
||||
function testTabs() {
|
||||
|
||||
$data = array(
|
||||
'label' => 'Tab 1',
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => 'field_test',
|
||||
),
|
||||
'format_type' => 'tab',
|
||||
'format_settings' => array(
|
||||
'label' => 'Tab 1',
|
||||
'classes' => 'test-class',
|
||||
'description' => '',
|
||||
'formatter' => 'open',
|
||||
),
|
||||
);
|
||||
$first_tab = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
$data = array(
|
||||
'label' => 'Tab 2',
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => 'field_test_2',
|
||||
),
|
||||
'format_type' => 'tab',
|
||||
'format_settings' => array(
|
||||
'label' => 'Tab 1',
|
||||
'classes' => 'test-class-2',
|
||||
'description' => 'description of second tab',
|
||||
'formatter' => 'closed',
|
||||
),
|
||||
);
|
||||
$second_tab = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
$data = array(
|
||||
'label' => 'Tabs',
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => $first_tab->group_name,
|
||||
1 => $second_tab->group_name,
|
||||
),
|
||||
'format_type' => 'tabs',
|
||||
'format_settings' => array(
|
||||
'direction' => 'vertical',
|
||||
'label' => 'Tab 1',
|
||||
'classes' => 'test-class-wrapper',
|
||||
),
|
||||
);
|
||||
$tabs_group = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
|
||||
// Test properties.
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-wrapper')]", NULL, t('Test class set on tabs wrapper'));
|
||||
$this->assertFieldByXPath("//details[contains(@class, 'test-class-2')]", NULL, t('Test class set on second tab'));
|
||||
$this->assertRaw('<div class="details-description">description of second tab</div>', t('Description of tab is shown'));
|
||||
|
||||
// Test if correctly nested.
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-wrapper')]//details[contains(@class, 'test-class')]", NULL, 'First tab is displayed as child of the wrapper.');
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-wrapper')]//details[contains(@class, 'test-class-2')]", NULL, 'Second tab is displayed as child of the wrapper.');
|
||||
|
||||
// Test if it's a vertical tab.
|
||||
$this->assertFieldByXPath('//div[@data-vertical-tabs-panes=""]', NULL, 'Tabs are shown vertical.');
|
||||
|
||||
// Switch to horizontal
|
||||
$tabs_group->format_settings['direction'] = 'horizontal';
|
||||
field_group_group_save($tabs_group);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
|
||||
// Test if it's a horizontal tab.
|
||||
$this->assertFieldByXPath('//div[@data-horizontal-tabs-panes=""]', NULL, 'Tabs are shown horizontal.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the accordion formatter.
|
||||
*/
|
||||
function testAccordion() {
|
||||
|
||||
$data = array(
|
||||
'label' => 'Accordion item 1',
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => 'field_test',
|
||||
),
|
||||
'format_type' => 'accordion_item',
|
||||
'format_settings' => array(
|
||||
'label' => 'Accordion item 1',
|
||||
'classes' => 'test-class',
|
||||
'formatter' => 'closed',
|
||||
),
|
||||
);
|
||||
$first_item = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
$first_item_id = 'node_article_full_' . $first_item->group_name;
|
||||
|
||||
$data = array(
|
||||
'label' => 'Accordion item 2',
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => 'field_test_2',
|
||||
),
|
||||
'format_type' => 'accordion_item',
|
||||
'format_settings' => array(
|
||||
'label' => 'Tab 2',
|
||||
'classes' => 'test-class-2',
|
||||
'formatter' => 'open',
|
||||
),
|
||||
);
|
||||
$second_item = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
$second_item_id = 'node_article_full_' . $second_item->group_name;
|
||||
|
||||
$data = array(
|
||||
'label' => 'Accordion',
|
||||
'weight' => '1',
|
||||
'children' => array(
|
||||
0 => $first_item->group_name,
|
||||
1 => $second_item->group_name,
|
||||
),
|
||||
'format_type' => 'accordion',
|
||||
'format_settings' => array(
|
||||
'label' => 'Tab 1',
|
||||
'classes' => 'test-class-wrapper',
|
||||
'effect' => 'bounceslide'
|
||||
),
|
||||
);
|
||||
$accordion = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
|
||||
// Test properties.
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-wrapper')]", NULL, t('Test class set on tabs wrapper'));
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'effect-bounceslide')]", NULL, t('Correct effect is set on the accordion'));
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class')]", NULL, t('Accordion item with test-class is shown'));
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-2')]", NULL, t('Accordion item with test-class-2 is shown'));
|
||||
$this->assertFieldByXPath("//h3[contains(@class, 'field-group-accordion-active')]", NULL, t('Accordion item 2 was set active'));
|
||||
|
||||
// Test if correctly nested
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-wrapper')]//div[contains(@class, 'test-class')]", NULL, 'First item is displayed as child of the wrapper.');
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'test-class-wrapper')]//div[contains(@class, 'test-class-2')]", NULL, 'Second item is displayed as child of the wrapper.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Provides common functionality for the FieldGroup test classes.
|
||||
*/
|
||||
trait FieldGroupTestTrait {
|
||||
|
||||
/**
|
||||
* Create a new group.
|
||||
* @param array $data
|
||||
* Data for the field group.
|
||||
*/
|
||||
function createGroup($entity_type, $bundle, $context, $mode, array $data) {
|
||||
|
||||
if (!isset($data['format_settings'])) {
|
||||
$data['format_settings'] = array();
|
||||
}
|
||||
|
||||
$data['format_settings'] += _field_group_get_default_formatter_settings($data['format_type'], $context);
|
||||
|
||||
$group_name = 'group_' . Unicode::strtolower($this->randomMachineName());
|
||||
|
||||
$field_group = (object) array(
|
||||
'group_name' => $group_name,
|
||||
'entity_type' => $entity_type,
|
||||
'bundle' => $bundle,
|
||||
'mode' => $mode,
|
||||
'context' => $context,
|
||||
'children' => isset($data['children']) ? $data['children'] : array(),
|
||||
'parent_name' => isset($data['parent']) ? $data['parent'] : '',
|
||||
'weight' => isset($data['weight']) ? $data['weight'] : 0,
|
||||
'label' => isset($data['label']) ? $data['label'] : $this->randomString(8),
|
||||
'format_type' => $data['format_type'],
|
||||
'format_settings' => $data['format_settings'],
|
||||
);
|
||||
|
||||
field_group_group_save($field_group);
|
||||
|
||||
return $field_group;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test field_group without field_ui.
|
||||
*
|
||||
* @group field_group
|
||||
*/
|
||||
class FieldGroupWithoutFieldUiTest extends WebTestBase {
|
||||
|
||||
protected static $modules = ['field_group', 'block'];
|
||||
|
||||
public function testLocalActions() {
|
||||
// Local actions of field_group should not depend on field_ui
|
||||
// @see https://www.drupal.org/node/2719569
|
||||
$this->placeBlock('local_actions_block', ['id' => 'local_actions_block']);
|
||||
$this->drupalGet(Url::fromRoute('user.login'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\field_group\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests for managing display of entities.
|
||||
*
|
||||
* @group field_group
|
||||
*/
|
||||
class ManageDisplayTest extends WebTestBase {
|
||||
|
||||
use FieldGroupTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node', 'field_ui', 'field_group');
|
||||
|
||||
function setUp() {
|
||||
|
||||
parent::setUp();
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'bypass node access'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create content type, with underscores.
|
||||
$type_name = Unicode::strtolower($this->randomMachineName(8)) . '_test';
|
||||
$type = $this->drupalCreateContentType(array('name' => $type_name, 'type' => $type_name));
|
||||
$this->type = $type->id();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the creation a group on the article content type.
|
||||
*/
|
||||
function testCreateGroup() {
|
||||
|
||||
// Create random group name.
|
||||
$this->group_label = $this->randomString(8);
|
||||
$this->group_name_input = Unicode::strtolower($this->randomMachineName());
|
||||
$this->group_name = 'group_' . $this->group_name_input;
|
||||
$this->group_formatter = 'details';
|
||||
|
||||
// Setup new group.
|
||||
$group = array(
|
||||
'group_formatter' => $this->group_formatter,
|
||||
'label' => $this->group_label,
|
||||
);
|
||||
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/form-display/add-group', $group, t('Save and continue'));
|
||||
$this->assertText('Machine-readable name field is required.');
|
||||
|
||||
// Setup new group.
|
||||
$group = array(
|
||||
'group_formatter' => $this->group_formatter,
|
||||
'label' => $this->group_label,
|
||||
'group_name' => $this->group_name_input,
|
||||
);
|
||||
|
||||
// Add new group on the 'Manage form display' page.
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/form-display/add-group', $group, t('Save and continue'));
|
||||
$this->drupalPostForm(NULL, [], t('Create group'));
|
||||
|
||||
$this->assertRaw(t('New group %label successfully created.', array('%label' => $this->group_label)), t('Group message displayed on screen.'));
|
||||
|
||||
// Test if group is in the $groups array.
|
||||
$this->group = field_group_load_field_group($this->group_name, 'node', $this->type, 'form', 'default');
|
||||
$this->assertNotNull($this->group, t('Group was loaded'));
|
||||
|
||||
// Add new group on the 'Manage display' page.
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display/add-group', $group, t('Save and continue'));
|
||||
$this->drupalPostForm(NULL, [], t('Create group'));
|
||||
|
||||
$this->assertRaw(t('New group %label successfully created.', array('%label' => $this->group_label)), t('Group message displayed on screen.'));
|
||||
|
||||
// Test if group is in the $groups array.
|
||||
$loaded_group = field_group_load_field_group($this->group_name, 'node', $this->type, 'view', 'default');
|
||||
$this->assertNotNull($loaded_group, t('Group was loaded'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a group.
|
||||
*/
|
||||
function testDeleteGroup() {
|
||||
|
||||
$data = array(
|
||||
'format_type' => 'fieldset',
|
||||
'label' => 'testing',
|
||||
);
|
||||
|
||||
$group = $this->createGroup('node', $this->type, 'form', 'default', $data);
|
||||
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/form-display/' . $group->group_name . '/delete', array(), t('Delete'));
|
||||
$this->assertRaw(t('The group %label has been deleted from the %type content type.', array('%label' => $group->label, '%type' => $this->type)), t('Group removal message displayed on screen.'));
|
||||
|
||||
$display = EntityFormDisplay::load($group->entity_type . '.' . $group->bundle . '.' . $group->mode);
|
||||
$data = $display->getThirdPartySettings('field_group');
|
||||
|
||||
// Test that group is not in the $groups array.
|
||||
\Drupal::entityTypeManager()->getStorage('entity_form_display')->resetCache();
|
||||
$loaded_group = field_group_load_field_group($group->group_name, 'node', $this->type, 'form', 'default');
|
||||
$this->assertNull($loaded_group, t('Group not found after deleting'));
|
||||
|
||||
$data = array(
|
||||
'format_type' => 'fieldset',
|
||||
'label' => 'testing',
|
||||
);
|
||||
|
||||
$group = $this->createGroup('node', $this->type, 'view', 'default', $data);
|
||||
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/display/' . $group->group_name . '/delete', array(), t('Delete'));
|
||||
$this->assertRaw(t('The group %label has been deleted from the %type content type.', array('%label' => $group->label, '%type' => $this->type)), t('Group removal message displayed on screen.'));
|
||||
|
||||
// Test that group is not in the $groups array.
|
||||
\Drupal::entityTypeManager()->getStorage('entity_view_display')->resetCache();
|
||||
$loaded_group = field_group_load_field_group($group->group_name, 'node', $this->type, 'view', 'default');
|
||||
$this->assertNull($loaded_group, t('Group not found after deleting'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Nest a field underneath a group.
|
||||
*/
|
||||
function testNestField() {
|
||||
|
||||
$data = array(
|
||||
'format_type' => 'fieldset',
|
||||
);
|
||||
|
||||
$group = $this->createGroup('node', $this->type, 'form', 'default', $data);
|
||||
|
||||
$edit = array(
|
||||
'fields[body][parent]' => $group->group_name,
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $this->type . '/form-display', $edit, t('Save'));
|
||||
$this->assertRaw(t('Your settings have been saved.'), t('Settings saved'));
|
||||
|
||||
$group = field_group_load_field_group($group->group_name, 'node', $this->type, 'form', 'default');
|
||||
$this->assertTrue(in_array('body', $group->children), t('Body is a child of %group', array('%group' => $group->group_name)));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user