diff --git a/config/schema/paragraphs_type.schema.yml b/config/schema/paragraphs_type.schema.yml
index fe853eb..984f301 100644
--- a/config/schema/paragraphs_type.schema.yml
+++ b/config/schema/paragraphs_type.schema.yml
@@ -8,6 +8,19 @@ paragraphs.paragraphs_type.*:
label:
type: label
label: 'Label'
+ feature_plugins:
+ type: sequence
+ label: 'Plugins'
+ sequence:
+ type: mapping
+ label: 'Layout plugins configuration'
+ mapping:
+ enabled:
+ type: boolean
+ label: 'Enabled'
+ weight:
+ type: integer
+ label: 'Weight'
entity_reference_selection.default:paragraph:
type: entity_reference_selection
diff --git a/paragraphs.api.php b/paragraphs.api.php
new file mode 100644
index 0000000..8e01ef3
--- /dev/null
+++ b/paragraphs.api.php
@@ -0,0 +1,28 @@
+getRevisionAuthor()) {
$this->setRevisionAuthorId($this->getOwnerId());
}
+
+ if ($this->unserializedFeatureSettings) {
+ $this->set('feature_settings', serialize($this->unserializedFeatureSettings));
+ }
+ else {
+ $this->set('feature_settings', serialize([]));
+ }
+ }
+
+ /**
+ * Sets the un-serialized feature settings.
+ *
+ * @param $feature_settings
+ * The feature settings from the form.
+ */
+ public function setUnserializedSettings($feature_settings) {
+ // Set feature settings field.
+ $this->unserializedFeatureSettings = $feature_settings;
}
/**
@@ -175,8 +199,20 @@ class Paragraph extends ContentEntityBase implements ParagraphInterface, EntityN
/**
* {@inheritdoc}
*/
- public function getData() {
- return $this->get('data')->value;
+ public function getFeatureSettings($key = array(), $index = NULL) {
+ if ($this->get('feature_settings')->value) {
+ $this->unserializedData = unserialize($this->get('feature_settings')->value);
+ }
+ else {
+ $this->unserializedData = [];
+ }
+ if (empty($key)) {
+ return $this->unserializedData;
+ }
+ if ($index) {
+ $key = array_merge($key, array($index));
+ }
+ return NestedArray::getValue($this->unserializedData, $key);
}
/**
@@ -296,6 +332,10 @@ class Paragraph extends ContentEntityBase implements ParagraphInterface, EntityN
->setSetting('is_ascii', TRUE)
->setSetting('max_length', FieldStorageConfig::NAME_MAX_LENGTH);
+ $fields['feature_settings'] = BaseFieldDefinition::create('string_long')
+ ->setLabel(t('Feature settings'))
+ ->setDescription(t('The feature plugin settings'));
+
return $fields;
}
diff --git a/src/Entity/ParagraphsType.php b/src/Entity/ParagraphsType.php
index b57b337..7b20631 100644
--- a/src/Entity/ParagraphsType.php
+++ b/src/Entity/ParagraphsType.php
@@ -28,6 +28,7 @@ use Drupal\paragraphs\ParagraphsTypeInterface;
* config_export = {
* "id",
* "label",
+ * "feature_plugins",
* },
* bundle_of = "paragraph",
* links = {
@@ -54,4 +55,11 @@ class ParagraphsType extends ConfigEntityBundleBase implements ParagraphsTypeInt
*/
public $label;
+ /**
+ * The ParagraphsType plugins.
+ *
+ * @var array
+ */
+ public $feature_plugins = [];
+
}
diff --git a/src/Form/ParagraphsTypeForm.php b/src/Form/ParagraphsTypeForm.php
index ad63cd9..41359ac 100644
--- a/src/Form/ParagraphsTypeForm.php
+++ b/src/Form/ParagraphsTypeForm.php
@@ -2,9 +2,12 @@
namespace Drupal\paragraphs\Form;
+use Drupal\Component\Utility\Xss;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field_ui\FieldUI;
+use Drupal\paragraphs\ParagraphsTypeFeatureManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Form controller for paragraph type forms.
@@ -12,6 +15,32 @@ use Drupal\field_ui\FieldUI;
class ParagraphsTypeForm extends EntityForm {
/**
+ * The paragraphs type feature plugin manager service.
+ *
+ * @var \Drupal\paragraphs\ParagraphsTypeFeatureManager
+ */
+ protected $paragraphsTypeFeatureManager;
+
+ /**
+ * GeneralSettingsForm constructor.
+ *
+ * @param \Drupal\paragraphs\ParagraphsTypeFeatureManager $paragraphs_type_feature_manager
+ * The paragraphs type feature manager service.
+ */
+ public function __construct(ParagraphsTypeFeatureManager $paragraphs_type_feature_manager) {
+ $this->paragraphsTypeFeatureManager = $paragraphs_type_feature_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('plugin.manager.paragraphs_type.feature')
+ );
+ }
+
+ /**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
@@ -41,7 +70,41 @@ class ParagraphsTypeForm extends EntityForm {
'#disabled' => !$paragraphs_type->isNew(),
);
- // You will need additional form elements for your custom properties.
+ $config = $paragraphs_type->get('feature_plugins');
+ $feature_plugins = $this->paragraphsTypeFeatureManager->getDefinitions();
+ $weight = count($feature_plugins) + 1;
+ $feature_plugins_order = [];
+ foreach ($feature_plugins as $id => $feature_plugin) {
+ $feature_plugins_order[$id] = [
+ 'label' => $feature_plugin['label'],
+ 'enabled' => isset($config[$id]['enabled']) ? $config[$id]['enabled'] : FALSE,
+ 'weight' => isset($config[$id]['weight']) ? $config[$id]['weight'] : $weight,
+ ];
+ $weight++;
+ }
+
+ $form['feature_plugins'] = [
+ '#type' => 'table',
+ '#header' => [t('Feature'), t('Description')],
+ '#empty' => t('There are no plugins yet. Add a plugin.'),
+ '#suffix' => '
' . $this->t('The feature plugins that are enabled to manage Paragraphs display.') .'
',
+ ];
+
+ uasort($feature_plugins_order, 'Drupal\Component\Utility\SortArray::sortByWeightElement');
+
+ foreach ($feature_plugins_order as $id => $feature_plugin) {
+ $description = $this->paragraphsTypeFeatureManager->getDefinition($id)['description'];
+ $form['feature_plugins'][$id]['enabled'] = [
+ '#type' => 'checkbox',
+ '#title' => $feature_plugin['label'],
+ '#title_display' => 'after',
+ '#default_value' => $feature_plugin['enabled'],
+ ];
+ $form['feature_plugins'][$id]['description'] = [
+ '#type' => 'markup',
+ '#markup' => isset($description) ? Xss::filter($description) : '',
+ ];
+ }
return $form;
}
diff --git a/src/ParagraphsTypeFeatureBase.php b/src/ParagraphsTypeFeatureBase.php
new file mode 100644
index 0000000..6e13474
--- /dev/null
+++ b/src/ParagraphsTypeFeatureBase.php
@@ -0,0 +1,110 @@
+configFactory = $config;
+ $this->entityTypeManager = $entity_type_manager;
+ $this->configuration += $this->defaultConfiguration();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+ return new static(
+ $configuration,
+ $plugin_id,
+ $plugin_definition,
+ $container->get('config.factory'),
+ $container->get('entity_type.manager')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defaultConfiguration() {
+ return [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration() {
+ return [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConfiguration(array $configuration) {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ return [];
+ }
+
+}
diff --git a/src/ParagraphsTypeFeatureInterface.php b/src/ParagraphsTypeFeatureInterface.php
new file mode 100644
index 0000000..8143b37
--- /dev/null
+++ b/src/ParagraphsTypeFeatureInterface.php
@@ -0,0 +1,24 @@
+setCacheBackend($cache_backend, 'paragraphs_type_feature_builder_plugins');
+ $this->alterInfo('paragraphs_type_feature_builder_info');
+ $this->entityTypeManager = $entity_type_manager;
+ // @todo define settings for the plugins.
+ $this->config = $config_factory->get('paragraphs.paragraphs_type');
+ }
+
+}
diff --git a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
index 01a5f8d..7818b7c 100644
--- a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
+++ b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
@@ -592,6 +592,18 @@ class InlineParagraphsWidget extends WidgetBase {
$element['subform'] = array();
}
+ $paragraphs_type = paragraphs\Entity\ParagraphsType::load($paragraphs_entity->getType());
+ if ($paragraphs_type) {
+ $config = \Drupal::config('paragraphs.paragraphs_type.' . $paragraphs_type->id());
+ foreach ($config->get('feature_plugins') as $plugin_id => $plugin) {
+ if ($plugin['enabled'] == TRUE) {
+ $plugin_instance = \Drupal::service('plugin.manager.paragraphs_type.feature')->createInstance($plugin_id);
+ $element['feature'][$plugin_id] = [];
+ $display->buildForm($paragraphs_entity, $element['feature'][$plugin_id], $form_state);
+ $element['feature'][$plugin_id] = $plugin_instance->buildFeaturesForm($paragraphs_entity);
+ }
+ }
+ }
$element['subform']['#attributes']['class'][] = 'paragraphs-subform';
$element['subform']['#access'] = $paragraphs_entity->access('update');
@@ -1059,6 +1071,9 @@ class InlineParagraphsWidget extends WidgetBase {
if ($widget_state['paragraphs'][$delta]['mode'] == 'edit') {
// Extract the form values on submit for getting the current paragraph.
$display->extractFormValues($entity, $element['subform'], $form_state);
+ if (isset($item['feature'])) {
+ $display->extractFormValues($entity, $element['feature'], $form_state);
+ }
$display->validateFormValues($entity, $element['subform'], $form_state);
}
}
@@ -1095,7 +1110,6 @@ class InlineParagraphsWidget extends WidgetBase {
&& $widget_state['paragraphs'][$item['_original_delta']]['mode'] != 'remove') {
$paragraphs_entity = $widget_state['paragraphs'][$item['_original_delta']]['entity'];
-
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $display */
$display = $widget_state['paragraphs'][$item['_original_delta']]['display'];
if ($widget_state['paragraphs'][$delta]['mode'] == 'edit') {
@@ -1115,6 +1129,10 @@ class InlineParagraphsWidget extends WidgetBase {
$paragraphs_entity->set($langcode_key, $form_state->get('langcode'));
}
}
+ if (isset($item['feature'])) {
+ $paragraphs_entity->setUnserializedSettings($item['feature']);
+ }
+
$paragraphs_entity->setNeedsSave(TRUE);
$item['entity'] = $paragraphs_entity;
$item['target_id'] = $paragraphs_entity->id();
diff --git a/src/Tests/ParagraphsPluginsTest.php b/src/Tests/ParagraphsPluginsTest.php
new file mode 100644
index 0000000..779fdbc
--- /dev/null
+++ b/src/Tests/ParagraphsPluginsTest.php
@@ -0,0 +1,50 @@
+addParagraphedContentType('paragraphed_test', 'field_paragraphs');
+ $this->loginAsAdmin(['create paragraphed_test content', 'edit any paragraphed_test content']);
+
+ // Add a Paragraph type.
+ $paragraph_type = 'text_paragraph';
+ $this->addParagraphsType($paragraph_type);
+
+ // Add a text field to the text_paragraph type.
+ static::fieldUIAddNewField('admin/structure/paragraphs_type/' . $paragraph_type, 'text', 'Text', 'text_long', [], []);
+
+ // Enable the test plugin.
+ $edit = [
+ 'feature_plugins[test_feature_plugin][enabled]' => TRUE,
+ ];
+ $this->drupalPostForm('admin/structure/paragraphs_type/' . $paragraph_type, $edit, t('Save'));
+
+ // Create a node with a Paragraph.
+ $this->drupalPostAjaxForm('node/add/paragraphed_test', [], 'field_paragraphs_text_paragraph_add_more');
+ $plugin_text = 'plugin_field_text';
+ $edit = [
+ 'title[0][value]' => 'paragraphs_plugins_test',
+ 'field_paragraphs[0][subform][field_text][0][value]' => 'amazing_plugin_test',
+ 'field_paragraphs[0][feature][test_feature_plugin][test_field]' => $plugin_text,
+ ];
+ $this->drupalPostForm(NULL, $edit, t('Save and publish'));
+ $this->clickLink('Edit');
+ // Assert the plugin fields populate the stored values.
+ $this->assertFieldByName('field_paragraphs[0][feature][test_feature_plugin][test_field]', $plugin_text);
+ }
+
+}
diff --git a/src/Tests/ParagraphsTestBase.php b/src/Tests/ParagraphsTestBase.php
index 614c60a..9508aaa 100644
--- a/src/Tests/ParagraphsTestBase.php
+++ b/src/Tests/ParagraphsTestBase.php
@@ -43,6 +43,7 @@ abstract class ParagraphsTestBase extends WebTestBase {
'field',
'field_ui',
'block',
+ 'paragraphs_test',
];
/**
diff --git a/tests/modules/paragraphs_test/paragraphs_test.info.yml b/tests/modules/paragraphs_test/paragraphs_test.info.yml
new file mode 100644
index 0000000..f91e94e
--- /dev/null
+++ b/tests/modules/paragraphs_test/paragraphs_test.info.yml
@@ -0,0 +1,9 @@
+name: Paragraphs test
+type: module
+description: Resources for Paragraphs tests
+core: 8.x
+hidden: true
+package: Paragraphs
+
+dependencies:
+ - paragraphs
diff --git a/tests/modules/paragraphs_test/src/Plugin/paragraphs_type/Feature/TestFeaturePlugin.php b/tests/modules/paragraphs_test/src/Plugin/paragraphs_type/Feature/TestFeaturePlugin.php
new file mode 100644
index 0000000..d64a1a0
--- /dev/null
+++ b/tests/modules/paragraphs_test/src/Plugin/paragraphs_type/Feature/TestFeaturePlugin.php
@@ -0,0 +1,30 @@
+ 'textfield',
+ '#title' => $this->t('Label'),
+ '#maxlength' => 255,
+ '#default_value' => $paragraphs_entity->getFeatureSettings([$this->getPluginId(), 'test_field']),
+ '#description' => $this->t("Label for the Paragraphs type."),
+ ];
+ return $form;
+ }
+
+}