Issue #1535868 by EclipseGc, tim.plunkett, xjm, Jody Lynn, sdboyer, naxoc, tizzo, effulgentsia, dawehner, disasm, beejeebus: Convert all blocks into plugins.
2013-01-04 17:05:13 +00:00
< ? php
/**
* @ file
2023-04-17 08:50:08 +00:00
* Allows the creation of content blocks through the user interface .
Issue #1535868 by EclipseGc, tim.plunkett, xjm, Jody Lynn, sdboyer, naxoc, tizzo, effulgentsia, dawehner, disasm, beejeebus: Convert all blocks into plugins.
2013-01-04 17:05:13 +00:00
*/
2019-04-16 05:38:27 +00:00
use Drupal\Core\Url ;
2014-06-30 03:33:08 +00:00
use Drupal\Core\Routing\RouteMatchInterface ;
2014-09-20 02:45:52 +00:00
use Drupal\field\Entity\FieldConfig ;
2014-07-18 18:56:27 +00:00
use Drupal\field\Entity\FieldStorageConfig ;
2018-07-16 22:43:44 +00:00
use Drupal\Core\Database\Query\SelectInterface ;
use Drupal\Core\Database\Query\AlterableInterface ;
use Drupal\Core\Database\Query\ConditionInterface ;
2013-02-18 22:17:49 +00:00
2013-08-13 20:25:21 +00:00
/**
* Implements hook_help () .
*/
2014-06-30 03:33:08 +00:00
function block_content_help ( $route_name , RouteMatchInterface $route_match ) {
2014-05-07 02:04:53 +00:00
switch ( $route_name ) {
2014-06-09 20:19:08 +00:00
case 'help.page.block_content' :
2019-04-16 05:38:27 +00:00
$field_ui = \Drupal :: moduleHandler () -> moduleExists ( 'field_ui' ) ? Url :: fromRoute ( 'help.page' , [ 'name' => 'field_ui' ]) -> toString () : '#' ;
2013-10-18 06:23:38 +00:00
$output = '' ;
$output .= '<h3>' . t ( 'About' ) . '</h3>' ;
2023-04-17 08:50:08 +00:00
$output .= '<p>' . t ( 'The Block Content module allows you to create and manage custom <em>block types</em> and <em>content-containing blocks</em>. For more information, see the <a href=":online-help">online documentation for the Block Content module</a>.' , [ ':online-help' => 'https://www.drupal.org/documentation/modules/block_content' ]) . '</p>' ;
2013-10-18 06:23:38 +00:00
$output .= '<h3>' . t ( 'Uses' ) . '</h3>' ;
$output .= '<dl>' ;
2023-04-17 08:50:08 +00:00
$output .= '<dt>' . t ( 'Creating and managing block types' ) . '</dt>' ;
$output .= '<dd>' . t ( 'Users with the <em>Administer blocks</em> permission can create and edit block types with fields and display settings, from the <a href=":types">Block types</a> page under the Structure menu. For more information about managing fields and display settings, see the <a href=":field-ui">Field UI module help</a> and <a href=":field">Field module help</a>.' , [ ':types' => Url :: fromRoute ( 'entity.block_content_type.collection' ) -> toString (), ':field-ui' => $field_ui , ':field' => Url :: fromRoute ( 'help.page' , [ 'name' => 'field' ]) -> toString ()]) . '</dd>' ;
$output .= '<dt>' . t ( 'Creating content blocks' ) . '</dt>' ;
$output .= '<dd>' . t ( 'Users with the <em>Administer blocks</em> permission can create, edit, and delete content blocks of each defined block type, from the <a href=":block-library">Content blocks page</a>. After creating a block, place it in a region from the <a href=":blocks">Block layout page</a>, just like blocks provided by other modules.' , [ ':blocks' => Url :: fromRoute ( 'block.admin_display' ) -> toString (), ':block-library' => Url :: fromRoute ( 'entity.block_content.collection' ) -> toString ()]) . '</dd>' ;
2013-10-18 06:23:38 +00:00
$output .= '</dl>' ;
return $output ;
2013-08-13 20:25:21 +00:00
}
}
Issue #1535868 by EclipseGc, tim.plunkett, xjm, Jody Lynn, sdboyer, naxoc, tizzo, effulgentsia, dawehner, disasm, beejeebus: Convert all blocks into plugins.
2013-01-04 17:05:13 +00:00
/**
* Implements hook_theme () .
*/
2014-06-09 20:19:08 +00:00
function block_content_theme ( $existing , $type , $theme , $path ) {
2017-03-04 01:20:24 +00:00
return [
'block_content_add_list' => [
'variables' => [ 'content' => NULL ],
2014-06-09 20:19:08 +00:00
'file' => 'block_content.pages.inc' ,
2017-03-04 01:20:24 +00:00
],
];
Issue #1535868 by EclipseGc, tim.plunkett, xjm, Jody Lynn, sdboyer, naxoc, tizzo, effulgentsia, dawehner, disasm, beejeebus: Convert all blocks into plugins.
2013-01-04 17:05:13 +00:00
}
2013-02-18 22:17:49 +00:00
/**
2014-02-20 10:04:54 +00:00
* Implements hook_entity_type_alter () .
2013-02-18 22:17:49 +00:00
*/
2014-06-09 20:19:08 +00:00
function block_content_entity_type_alter ( array & $entity_types ) {
2021-05-20 20:47:18 +00:00
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
2013-02-18 22:17:49 +00:00
// Add a translation handler for fields if the language module is enabled.
2013-10-16 12:17:55 +00:00
if ( \Drupal :: moduleHandler () -> moduleExists ( 'language' )) {
2014-06-09 20:19:08 +00:00
$translation = $entity_types [ 'block_content' ] -> get ( 'translation' );
$translation [ 'block_content' ] = TRUE ;
$entity_types [ 'block_content' ] -> set ( 'translation' , $translation );
2013-02-18 22:17:49 +00:00
}
Issue #3053881 by Luke.Leber, bkosborne, tyler-paavola, Sam152, Rishi Kulshreshtha, Odai Atieh, chrisolof, acbramley, ethomas08, Oscaner, kyberman, aarti zikre, joshua1234511, larowlan, catch: Reverting entity revisions that contain custom blocks erroneously triggers EntityChangedConstraint
2022-08-21 16:33:05 +00:00
// Swap out the default EntityChanged constraint with a custom one with
// different logic for inline blocks.
$constraints = $entity_types [ 'block_content' ] -> getConstraints ();
unset ( $constraints [ 'EntityChanged' ]);
$constraints [ 'BlockContentEntityChanged' ] = NULL ;
$entity_types [ 'block_content' ] -> setConstraints ( $constraints );
2013-02-18 22:17:49 +00:00
}
/**
2023-04-17 08:50:08 +00:00
* Adds the default body field to a block type .
2013-02-18 22:17:49 +00:00
*
* @ param string $block_type_id
* Id of the block type .
* @ param string $label
2014-05-05 08:15:33 +00:00
* ( optional ) The label for the body instance . Defaults to 'Body'
2013-02-18 22:17:49 +00:00
*
2015-10-19 17:46:56 +00:00
* @ return \Drupal\field\Entity\FieldConfig
* A Body field object .
2013-02-18 22:17:49 +00:00
*/
2014-06-09 20:19:08 +00:00
function block_content_add_body_field ( $block_type_id , $label = 'Body' ) {
2013-02-18 22:17:49 +00:00
// Add or remove the body field, as needed.
2014-09-20 02:45:52 +00:00
$field = FieldConfig :: loadByName ( 'block_content' , $block_type_id , 'body' );
if ( empty ( $field )) {
2016-02-16 11:13:36 +00:00
$field = FieldConfig :: create ([
2016-04-29 11:02:20 +00:00
'field_storage' => FieldStorageConfig :: loadByName ( 'block_content' , 'body' ),
2013-02-18 22:17:49 +00:00
'bundle' => $block_type_id ,
'label' => $label ,
Issue #784672 by smustgrave, floretan, lokapujya, joegraduate, jcnventura, AndyF, joelpittet, darvanen, c960657, eiriksm, viappidu, jungle, ravi.shankar, DanielVeza, Meenakshi_j, gordon, raman.b, mohit_aghera, vsujeetkumar, aleevas, vakulrai, bruvers, larowlan, vpeltot, wjaspers, Sonal.Sangale, jan.stoeckler, jofitz, vdsh, minorOffense, LewisNyman, mgifford, Berdir, tstoeckler, Luke.Leber, Hanno, alexpott, andypost, yannickoo, hchonov, quietone, David_Rothstein, fgm, mr.baileys, MaxMendez, mpp: Allow text field to enforce a specific text format
2022-11-29 11:37:35 +00:00
'settings' => [
'display_summary' => FALSE ,
'allowed_formats' => [],
],
2016-02-16 11:13:36 +00:00
]);
2014-09-20 02:45:52 +00:00
$field -> save ();
2013-02-18 22:17:49 +00:00
Issue #2367933 by phenaproxima, mikelutz, Berdir, voleger, amateescu, chr.fritsch, johndevman, Jo Fitzgerald, andypost, larowlan, alexpott: Move entity_get_(form_)display() to the entity display repository
2019-04-26 02:51:29 +00:00
/** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
$display_repository = \Drupal :: service ( 'entity_display.repository' );
// Assign widget settings for the default form mode.
$display_repository -> getFormDisplay ( 'block_content' , $block_type_id )
2017-03-04 01:20:24 +00:00
-> setComponent ( 'body' , [
2013-05-19 20:02:16 +00:00
'type' => 'text_textarea_with_summary' ,
2017-03-04 01:20:24 +00:00
])
2013-05-19 20:02:16 +00:00
-> save ();
Issue #2367933 by phenaproxima, mikelutz, Berdir, voleger, amateescu, chr.fritsch, johndevman, Jo Fitzgerald, andypost, larowlan, alexpott: Move entity_get_(form_)display() to the entity display repository
2019-04-26 02:51:29 +00:00
// Assign display settings for default view mode.
$display_repository -> getViewDisplay ( 'block_content' , $block_type_id )
2017-03-04 01:20:24 +00:00
-> setComponent ( 'body' , [
2013-02-18 22:17:49 +00:00
'label' => 'hidden' ,
'type' => 'text_default' ,
2017-03-04 01:20:24 +00:00
])
2013-02-18 22:17:49 +00:00
-> save ();
}
2014-09-20 02:45:52 +00:00
return $field ;
2013-02-18 22:17:49 +00:00
}
2018-07-16 22:43:44 +00:00
/**
* Implements hook_query_TAG_alter () .
*
* Alters any 'entity_reference' query where the entity type is
* 'block_content' and the query has the tag 'block_content_access' .
*
* These queries should only return reusable blocks unless a condition on
* 'reusable' is explicitly set .
*
2019-12-12 12:45:12 +00:00
* Block_content entities that are not reusable should by default not be
* selectable as entity reference values . A module can still create an instance
* of \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface
2018-07-16 22:43:44 +00:00
* that will allow selection of non - reusable blocks by explicitly setting
* a condition on the 'reusable' field .
*
* @ see \Drupal\block_content\BlockContentAccessControlHandler
*/
function block_content_query_entity_reference_alter ( AlterableInterface $query ) {
if ( $query instanceof SelectInterface && $query -> getMetaData ( 'entity_type' ) === 'block_content' && $query -> hasTag ( 'block_content_access' )) {
$data_table = \Drupal :: entityTypeManager () -> getDefinition ( 'block_content' ) -> getDataTable ();
if ( array_key_exists ( $data_table , $query -> getTables ()) && ! _block_content_has_reusable_condition ( $query -> conditions (), $query -> getTables ())) {
$query -> condition ( " $data_table .reusable " , TRUE );
}
}
}
/**
* Utility function to find nested conditions using the reusable field .
*
* @ todo Replace this function with a call to the API in
* https :// www . drupal . org / project / drupal / issues / 2984930
*
* @ param array $condition
* The condition or condition group to check .
* @ param array $tables
* The tables from the related select query .
*
* @ see \Drupal\Core\Database\Query\SelectInterface :: getTables
*
* @ return bool
* Whether the conditions contain any condition using the reusable field .
*/
function _block_content_has_reusable_condition ( array $condition , array $tables ) {
// If this is a condition group call this function recursively for each nested
// condition until a condition is found that return TRUE.
if ( isset ( $condition [ '#conjunction' ])) {
foreach ( array_filter ( $condition , 'is_array' ) as $nested_condition ) {
if ( _block_content_has_reusable_condition ( $nested_condition , $tables )) {
return TRUE ;
}
}
return FALSE ;
}
if ( isset ( $condition [ 'field' ])) {
$field = $condition [ 'field' ];
if ( is_object ( $field ) && $field instanceof ConditionInterface ) {
return _block_content_has_reusable_condition ( $field -> conditions (), $tables );
}
$field_parts = explode ( '.' , $field );
$data_table = \Drupal :: entityTypeManager () -> getDefinition ( 'block_content' ) -> getDataTable ();
foreach ( $tables as $table ) {
if ( $table [ 'table' ] === $data_table && $field_parts [ 0 ] === $table [ 'alias' ] && $field_parts [ 1 ] === 'reusable' ) {
return TRUE ;
}
}
}
return FALSE ;
}