Commit 979d9b6b authored by jrockowitz's avatar jrockowitz

Add block_field_test.module and other tweaks.

parent b9e5994d
Steps for creating a new release
--------------------------------
1. Cleanup code
2. Review code
3. Run tests
4. Generate release notes
5. Tag and create a new release
6. Update project page
1. Cleanup code
---------------
[Convert to short array syntax](https://www.drupal.org/project/short_array_syntax)
drush short-array-syntax block_field
2. Review code
--------------
[Online](http://pareview.sh)
http://git.drupal.org/project/block_field.git 8.x-1.x
[Commandline](https://www.drupal.org/node/1587138)
# Check Drupal coding standards
phpcs --standard=Drupal --extensions=php,module,inc,install,test,profile,theme,js,css,info modules/sandbox/block_field
# Check Drupal best practices
phpcs --standard=DrupalPractice --extensions=php,module,inc,install,test,profile,theme,js,css,info modules/sandbox/block_field
3. Run tests
------------
[SimpleTest](https://www.drupal.org/node/645286)
# Run all tests
php core/scripts/run-tests.sh --url http://localhost/d8_dev --module block_field
4. Generate release notes
-------------------------
[Git Release Notes for Drush](https://www.drupal.org/project/grn)
drush release-notes 8.x-1.0-VERSION 8.x-1.x
5. Tag and create a new release
-------------------------------
[Tag a release](https://www.drupal.org/node/1066342)
git tag 8.x-1.0-VERSION
git push --tags
git push origin tag 8.x-1.0-VERSION
[Create new release](https://www.drupal.org/node/add/project-release/0000000)
6. Update project page
----------------------
[Export README.md](https://www.drupal.org/project/readme)
drush readme-export --project block_field
[Edit project page](https://www.drupal.org/node/0000000/edit)
Contents of this file
---------------------
* About this module
* Use cases
* Demo
* Installation
* Notes
About this Module
-----------------
Provides a field that allows a content entity to create and configure custom
block instances.
Use Cases
---------
- Add blocks to a node's sidebar.
- Add blocks to paragraph.
- Create a carousel of content and configurable blocks.
Demo
----
> Evaluate this project online using [simplytest.me](https://simplytest.me/project/block_field).
Installation
------------
1. Copy/upload the `block_field.module` to the modules directory of your
Drupal installation.
2. Enable the 'Block field' module in 'Extend'. (/admin/modules)
3. Add the 'Block (plugin)' field to any content entity
Notes
-----
- The Block field's block instances are stored as configuration, which is good
thing, since site builders and editors can easily tweak them with impacting
any configuration management.
- All content blocks from the 'Custom Block Library' are available.
Author/Maintainer
-----------------
- [Jacob Rockowitz](http://drupal.org/user/371407)
name: 'Block Field'
type: module
description: 'Provides a field that allows a content entity to create instances of configurable and custom blocks.'
description: 'Provides a field that allows a content entity to create and configure custom block instances.'
package: Field
core: 8.x
......@@ -25,7 +25,7 @@ class BlockFieldFormatter extends FormatterBase {
/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
$block_manager = \Drupal::service('plugin.manager.block');
$elements = array();
$elements = [];
foreach ($items as $delta => $item) {
$plugin_id = $item->id;
$settings = $item->settings;
......
......@@ -28,9 +28,9 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface {
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return array(
return [
'plugin_ids' => [],
) + parent::defaultFieldSettings();
] + parent::defaultFieldSettings();
}
/**
......@@ -58,21 +58,21 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface {
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return array(
'columns' => array(
'id' => array(
return [
'columns' => [
'id' => [
'description' => 'The block plugin id',
'type' => 'varchar',
'length' => 255,
),
'settings' => array(
],
'settings' => [
'description' => 'Serialized array of settings for the block.',
'type' => 'blob',
'size' => 'big',
'serialize' => TRUE,
),
),
);
],
],
];
}
/**
......@@ -94,9 +94,9 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface {
}
$default_value = $field->getSetting('plugin_ids') ?: array_keys($options);
$element = array();
$element = [];
$element['plugin_ids'] = array(
$element['plugin_ids'] = [
'#type' => 'tableselect',
'#title' => $this->t('Blocks'),
'#title_display' => 'invisible',
......@@ -111,7 +111,7 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface {
'#empty' => t('No blocks are available.'),
'#element_validate' => [[get_called_class(), 'validatePluginIds']],
'#default_value' => array_combine($default_value, $default_value),
);
];
return $element;
}
......
......@@ -26,10 +26,10 @@ class BlockFieldWidget extends WidgetBase {
* {@inheritdoc}
*/
public static function defaultSettings() {
return array(
return [
'id' => '',
'settings' => [],
) + parent::defaultSettings();
] + parent::defaultSettings();
}
/**
......@@ -62,7 +62,7 @@ class BlockFieldWidget extends WidgetBase {
$options[$category][$id] = $definition['admin_label'] . ' (' . $id . ')';
}
$element['id'] = array(
$element['id'] = [
'#type' => 'select',
'#title' => $this->t('ID'),
'#options' => $options,
......@@ -70,10 +70,10 @@ class BlockFieldWidget extends WidgetBase {
'#default_value' => $plugin_id,
'#required' => $element['#required'],
'#ajax' => [
'callback' => array($this, 'configurationForm'),
'callback' => [$this, 'configurationForm'],
'wrapper' => $configuration_id,
],
);
];
/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
$block_manager = \Drupal::service('plugin.manager.block');
......@@ -96,12 +96,15 @@ class BlockFieldWidget extends WidgetBase {
}
// DEBUG:
$element['#element_validate'] = array(array($this, 'validate'));
$element['#element_validate'] = [[$this, 'validate']];
}
return $element;
}
/**
* Ajax callback that return block configuration setting form.
*/
public function configurationForm(array $form, FormStateInterface $form_state) {
$trigger_element = $form_state->getTriggeringElement();
$array_parents = $trigger_element['#array_parents'];
......@@ -118,22 +121,29 @@ class BlockFieldWidget extends WidgetBase {
$values = $form_state->getValues();
$plugin_id = NestedArray::getValue($values, $element['id']['#parents']);
$settings = NestedArray::getValue($values, $element['settings']['#parents']);
// Convert label display to FALSE instead of 0. This allow the label to be
// hidden.
if ($settings['label_display'] === 0) {
$settings['label_display'] = FALSE;
}
// Execute block validate configuration.
if (!empty($plugin_id) && $block_manager->hasDefinition($plugin_id)) {
// Clean up configuration settings.
$settings = NestedArray::getValue($values, $element['settings']['#parents']);
// Convert label display to FALSE instead of 0. This allow the label to be
// hidden.
if ($settings['label_display'] === 0) {
$settings['label_display'] = FALSE;
}
// Execute block validate configuration.
$block_instance = $block_manager->createInstance($plugin_id, $settings);
$settings = (new FormState())->setValues($settings);
$block_instance->validateConfigurationForm($form, $settings);
}
NestedArray::setValue($values, $element['settings']['#parents'], $settings->getValues());
$form_state->setValues($values);
NestedArray::setValue($values, $element['settings']['#parents'], $settings->getValues());
$form_state->setValues($values);
}
else {
// Clear all configuration settings.
NestedArray::setValue($values, $element['settings']['#parents'], []);
}
}
}
name: 'Block field module tests'
type: module
description: 'Support module for Block field that provides a working example of a block field.'
package: Testing
core: 8.x
dependencies:
- block_field
- field
- menu_ui
- node
- path
- user
langcode: en
status: true
dependencies:
config:
- field.field.node.block_field_test.field_block_field_test
- node.type.block_field_test
module:
- block_field
- path
id: node.block_field_test.default
targetEntityType: node
bundle: block_field_test
mode: default
content:
created:
type: datetime_timestamp
weight: 10
settings: { }
third_party_settings: { }
field_block_field_test:
weight: 32
settings:
id: ''
settings: { }
third_party_settings: { }
type: block_field_default
path:
type: path
weight: 30
settings: { }
third_party_settings: { }
promote:
type: boolean_checkbox
settings:
display_label: true
weight: 15
third_party_settings: { }
sticky:
type: boolean_checkbox
settings:
display_label: true
weight: 16
third_party_settings: { }
title:
type: string_textfield
weight: -5
settings:
size: 60
placeholder: ''
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
settings:
match_operator: CONTAINS
size: 60
placeholder: ''
third_party_settings: { }
hidden: { }
langcode: en
status: true
dependencies:
config:
- field.field.node.block_field_test.field_block_field_test
- node.type.block_field_test
module:
- block_field
- user
id: node.block_field_test.default
targetEntityType: node
bundle: block_field_test
mode: default
content:
field_block_field_test:
weight: 102
label: above
settings: { }
third_party_settings: { }
type: block_field
links:
weight: 100
hidden: { }
langcode: en
status: true
dependencies:
config:
- core.entity_view_mode.node.teaser
- field.field.node.block_field_test.field_block_field_test
- node.type.block_field_test
module:
- user
id: node.block_field_test.teaser
targetEntityType: node
bundle: block_field_test
mode: teaser
content:
links:
weight: 100
hidden:
field_block_field_test: true
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_block_field_test
- node.type.block_field_test
module:
- block_field
id: node.block_field_test.field_block_field_test
field_name: field_block_field_test
entity_type: node
bundle: block_field_test
label: 'Block field test'
description: ''
required: false
translatable: false
default_value: { }
default_value_callback: ''
settings:
plugin_ids: { }
field_type: block_field
langcode: en
status: true
dependencies:
module:
- block_field
- node
id: node.field_block_field_test
field_name: field_block_field_test
entity_type: node
type: block_field
settings: { }
module: block_field
locked: false
cardinality: -1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
langcode: en
status: true
dependencies:
module:
- menu_ui
third_party_settings:
menu_ui:
available_menus:
- main
parent: 'main:'
name: 'Block field test'
type: block_field_test
description: ''
help: ''
new_revision: false
preview_mode: 1
display_submitted: true
<?php
/**
* @file
* Contains \Drupal\block_field_test\Plugin\Block\BlockFieldTestBlock.
*/
namespace Drupal\block_field_test\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides a 'Block field test' block.
*
* @Block(
* id = "block_field_test",
* admin_label = @Translation("Block field test"),
* category = @Translation("Block field test")
* )
*/
class BlockFieldTestBlock extends BlockBase {
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'content' => $this->t('A default value. This block was created at %time', ['%time' => date('c')]),
];
}
/**
* {@inheritdoc}
*/
public function blockForm($form, FormStateInterface $form_state) {
$form['content'] = [
'#type' => 'textarea',
'#title' => $this->t('Content'),
'#default_value' => $this->configuration['content'],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['content'] = $form_state->getValue('content');
}
/**
* {@inheritdoc}
*/
public function build() {
return [
'#type' => 'markup',
'#markup' => $this->configuration['content'],
];
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment