Initial Drupal 11 with DDEV setup
This commit is contained in:
		@ -0,0 +1,7 @@
 | 
			
		||||
name: "Content Block module tests"
 | 
			
		||||
type: module
 | 
			
		||||
description: "Support module for content block related testing."
 | 
			
		||||
package: Testing
 | 
			
		||||
version: VERSION
 | 
			
		||||
dependencies:
 | 
			
		||||
  - drupal:block_content
 | 
			
		||||
@ -0,0 +1,6 @@
 | 
			
		||||
block_content_test.block_content_view:
 | 
			
		||||
  path: '/block-content/{block_content}'
 | 
			
		||||
  defaults:
 | 
			
		||||
    _entity_view: 'block_content'
 | 
			
		||||
  requirements:
 | 
			
		||||
    _entity_access: 'block_content.view'
 | 
			
		||||
@ -0,0 +1,26 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
  theme:
 | 
			
		||||
    - stark
 | 
			
		||||
id: foobar_gorilla
 | 
			
		||||
theme: stark
 | 
			
		||||
region: content
 | 
			
		||||
weight: 0
 | 
			
		||||
provider: null
 | 
			
		||||
plugin: 'block_content:fb5e8434-3617-4a1d-a252-8273e95ec30e'
 | 
			
		||||
settings:
 | 
			
		||||
  id: 'block_content:fb5e8434-3617-4a1d-a252-8273e95ec30e'
 | 
			
		||||
  label: 'Foobar Gorilla'
 | 
			
		||||
  label_display: visible
 | 
			
		||||
  provider: block_content
 | 
			
		||||
  status: true
 | 
			
		||||
  info: ''
 | 
			
		||||
  view_mode: full
 | 
			
		||||
visibility:
 | 
			
		||||
  request_path:
 | 
			
		||||
    id: request_path
 | 
			
		||||
    negate: false
 | 
			
		||||
    pages: ''
 | 
			
		||||
@ -0,0 +1,75 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\block_content_test\Hook;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Core\Hook\Attribute\Hook;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook implementations for block_content_test.
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTestHooks {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_view().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('block_content_view')]
 | 
			
		||||
  public function blockContentView(array &$build, BlockContent $block_content, $view_mode): void {
 | 
			
		||||
    // Add extra content.
 | 
			
		||||
    $build['extra_content'] = ['#markup' => '<blink>Wow</blink>'];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_presave().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('block_content_presave')]
 | 
			
		||||
  public function blockContentPresave(BlockContent $block_content): void {
 | 
			
		||||
    if ($block_content->label() == 'testing_block_content_presave') {
 | 
			
		||||
      $block_content->setInfo($block_content->label() . '_presave');
 | 
			
		||||
    }
 | 
			
		||||
    // Determine changes.
 | 
			
		||||
    if ($block_content->getOriginal() && $block_content->getOriginal()->label() == 'test_changes') {
 | 
			
		||||
      if ($block_content->getOriginal()->label() != $block_content->label()) {
 | 
			
		||||
        $block_content->setInfo($block_content->label() . '_presave');
 | 
			
		||||
        // Drupal 1.0 release.
 | 
			
		||||
        $block_content->changed = 979534800;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_update().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('block_content_update')]
 | 
			
		||||
  public function blockContentUpdate(BlockContent $block_content): void {
 | 
			
		||||
    // Determine changes on update.
 | 
			
		||||
    if ($block_content->getOriginal() && $block_content->getOriginal()->label() == 'test_changes') {
 | 
			
		||||
      if ($block_content->getOriginal()->label() != $block_content->label()) {
 | 
			
		||||
        $block_content->setInfo($block_content->label() . '_update');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_ENTITY_TYPE_insert().
 | 
			
		||||
   *
 | 
			
		||||
   * This tests saving a block_content on block_content insert.
 | 
			
		||||
   *
 | 
			
		||||
   * @see \Drupal\block_content\Tests\BlockContentSaveTest::testBlockContentSaveOnInsert()
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('block_content_insert')]
 | 
			
		||||
  public function blockContentInsert(BlockContent $block_content): void {
 | 
			
		||||
    // Set the block_content title to the block_content ID and save.
 | 
			
		||||
    if ($block_content->label() == 'new') {
 | 
			
		||||
      $block_content->setInfo('BlockContent ' . $block_content->id());
 | 
			
		||||
      $block_content->setNewRevision(FALSE);
 | 
			
		||||
      $block_content->save();
 | 
			
		||||
    }
 | 
			
		||||
    if ($block_content->label() == 'fail_creation') {
 | 
			
		||||
      throw new \Exception('Test exception for rollback.');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,82 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\block_content_test\Plugin\EntityReferenceSelection;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test EntityReferenceSelection with conditions on the 'reusable' field.
 | 
			
		||||
 */
 | 
			
		||||
class TestSelection extends DefaultSelection {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The condition type.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $conditionType;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether to set the condition for reusable or non-reusable blocks.
 | 
			
		||||
   *
 | 
			
		||||
   * @var bool
 | 
			
		||||
   */
 | 
			
		||||
  protected $isReusable;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the test mode.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $condition_type
 | 
			
		||||
   *   The condition type.
 | 
			
		||||
   * @param bool $is_reusable
 | 
			
		||||
   *   Whether to set the condition for reusable or non-reusable blocks.
 | 
			
		||||
   */
 | 
			
		||||
  public function setTestMode($condition_type = NULL, $is_reusable = NULL) {
 | 
			
		||||
    $this->conditionType = $condition_type;
 | 
			
		||||
    $this->isReusable = $is_reusable;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
 | 
			
		||||
    $query = parent::buildEntityQuery($match, $match_operator);
 | 
			
		||||
    if ($this->conditionType) {
 | 
			
		||||
      /** @var \Drupal\Core\Database\Query\ConditionInterface $add_condition */
 | 
			
		||||
      $add_condition = NULL;
 | 
			
		||||
      switch ($this->conditionType) {
 | 
			
		||||
        case 'base':
 | 
			
		||||
          $add_condition = $query;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 'group':
 | 
			
		||||
          $group = $query->andConditionGroup()
 | 
			
		||||
            ->exists('type');
 | 
			
		||||
          $add_condition = $group;
 | 
			
		||||
          $query->condition($group);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case "nested_group":
 | 
			
		||||
          $query->exists('type');
 | 
			
		||||
          $sub_group = $query->andConditionGroup()
 | 
			
		||||
            ->exists('type');
 | 
			
		||||
          $add_condition = $sub_group;
 | 
			
		||||
          $group = $query->andConditionGroup()
 | 
			
		||||
            ->exists('type')
 | 
			
		||||
            ->condition($sub_group);
 | 
			
		||||
          $query->condition($group);
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
      if ($this->isReusable) {
 | 
			
		||||
        $add_condition->condition('reusable', 1);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $add_condition->condition('reusable', 0);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $query;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
name: 'Block Content test views'
 | 
			
		||||
type: module
 | 
			
		||||
description: 'Provides default views for views block_content tests.'
 | 
			
		||||
package: Testing
 | 
			
		||||
version: VERSION
 | 
			
		||||
dependencies:
 | 
			
		||||
  - drupal:block_content
 | 
			
		||||
  - drupal:views
 | 
			
		||||
@ -0,0 +1,234 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
id: test_block_content_redirect_destination
 | 
			
		||||
label: 'Redirect destination'
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_data
 | 
			
		||||
base_field: id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    id: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    position: 0
 | 
			
		||||
    display_options:
 | 
			
		||||
      access:
 | 
			
		||||
        type: none
 | 
			
		||||
        options: {  }
 | 
			
		||||
      cache:
 | 
			
		||||
        type: tag
 | 
			
		||||
        options: {  }
 | 
			
		||||
      query:
 | 
			
		||||
        type: views_query
 | 
			
		||||
        options:
 | 
			
		||||
          disable_sql_rewrite: false
 | 
			
		||||
          distinct: false
 | 
			
		||||
          replica: false
 | 
			
		||||
          query_comment: ''
 | 
			
		||||
          query_tags: {  }
 | 
			
		||||
      exposed_form:
 | 
			
		||||
        type: basic
 | 
			
		||||
        options:
 | 
			
		||||
          submit_button: Apply
 | 
			
		||||
          reset_button: false
 | 
			
		||||
          reset_button_label: Reset
 | 
			
		||||
          exposed_sorts_label: 'Sort by'
 | 
			
		||||
          expose_sort_order: true
 | 
			
		||||
          sort_asc_label: Asc
 | 
			
		||||
          sort_desc_label: Desc
 | 
			
		||||
      pager:
 | 
			
		||||
        type: mini
 | 
			
		||||
        options:
 | 
			
		||||
          items_per_page: 10
 | 
			
		||||
          offset: 0
 | 
			
		||||
          id: 0
 | 
			
		||||
          total_pages: null
 | 
			
		||||
          expose:
 | 
			
		||||
            items_per_page: false
 | 
			
		||||
            items_per_page_label: 'Items per page'
 | 
			
		||||
            items_per_page_options: '5, 10, 25, 50'
 | 
			
		||||
            items_per_page_options_all: false
 | 
			
		||||
            items_per_page_options_all_label: '- All -'
 | 
			
		||||
            offset: false
 | 
			
		||||
            offset_label: Offset
 | 
			
		||||
          tags:
 | 
			
		||||
            previous: ‹‹
 | 
			
		||||
            next: ››
 | 
			
		||||
      style:
 | 
			
		||||
        type: table
 | 
			
		||||
        options:
 | 
			
		||||
          grouping: {  }
 | 
			
		||||
          class: ''
 | 
			
		||||
          row_class: ''
 | 
			
		||||
          default_row_class: true
 | 
			
		||||
          override: true
 | 
			
		||||
          sticky: false
 | 
			
		||||
          caption: ''
 | 
			
		||||
          summary: ''
 | 
			
		||||
          description: ''
 | 
			
		||||
          columns:
 | 
			
		||||
            info: info
 | 
			
		||||
          info:
 | 
			
		||||
            info:
 | 
			
		||||
              sortable: false
 | 
			
		||||
              default_sort_order: asc
 | 
			
		||||
              align: ''
 | 
			
		||||
              separator: ''
 | 
			
		||||
              empty_column: false
 | 
			
		||||
              responsive: ''
 | 
			
		||||
          default: '-1'
 | 
			
		||||
          empty_table: false
 | 
			
		||||
      row:
 | 
			
		||||
        type: 'entity:block_content'
 | 
			
		||||
      fields:
 | 
			
		||||
        info:
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: info
 | 
			
		||||
          id: info
 | 
			
		||||
          entity_type: null
 | 
			
		||||
          entity_field: info
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          label: ''
 | 
			
		||||
          exclude: false
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
            path_case: none
 | 
			
		||||
            trim_whitespace: false
 | 
			
		||||
            alt: ''
 | 
			
		||||
            rel: ''
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
            ellipsis: true
 | 
			
		||||
            more_link: false
 | 
			
		||||
            more_link_text: ''
 | 
			
		||||
            more_link_path: ''
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            preserve_tags: ''
 | 
			
		||||
            html: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: true
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          click_sort_column: value
 | 
			
		||||
          type: string
 | 
			
		||||
          settings: {  }
 | 
			
		||||
          group_column: value
 | 
			
		||||
          group_columns: {  }
 | 
			
		||||
          group_rows: true
 | 
			
		||||
          delta_limit: 0
 | 
			
		||||
          delta_offset: 0
 | 
			
		||||
          delta_reversed: false
 | 
			
		||||
          delta_first_last: false
 | 
			
		||||
          multi_type: separator
 | 
			
		||||
          separator: ', '
 | 
			
		||||
          field_api_classes: false
 | 
			
		||||
        operations:
 | 
			
		||||
          id: operations
 | 
			
		||||
          table: block_content
 | 
			
		||||
          field: operations
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          label: 'Operations links'
 | 
			
		||||
          exclude: false
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
            path_case: none
 | 
			
		||||
            trim_whitespace: false
 | 
			
		||||
            alt: ''
 | 
			
		||||
            rel: ''
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
            ellipsis: true
 | 
			
		||||
            more_link: false
 | 
			
		||||
            more_link_text: ''
 | 
			
		||||
            more_link_path: ''
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            preserve_tags: ''
 | 
			
		||||
            html: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: true
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          destination: true
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          plugin_id: entity_operations
 | 
			
		||||
      filters: {  }
 | 
			
		||||
      sorts: {  }
 | 
			
		||||
      title: 'Redirect destination'
 | 
			
		||||
      header: {  }
 | 
			
		||||
      footer: {  }
 | 
			
		||||
      empty: {  }
 | 
			
		||||
      relationships: {  }
 | 
			
		||||
      arguments: {  }
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
    cache_metadata:
 | 
			
		||||
      max-age: 0
 | 
			
		||||
      contexts:
 | 
			
		||||
        - 'languages:language_content'
 | 
			
		||||
        - 'languages:language_interface'
 | 
			
		||||
        - url.query_args
 | 
			
		||||
      tags: {  }
 | 
			
		||||
  page_1:
 | 
			
		||||
    display_plugin: page
 | 
			
		||||
    id: page_1
 | 
			
		||||
    display_title: Page
 | 
			
		||||
    position: 1
 | 
			
		||||
    display_options:
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
      path: /admin/content/redirect_destination
 | 
			
		||||
    cache_metadata:
 | 
			
		||||
      max-age: 0
 | 
			
		||||
      contexts:
 | 
			
		||||
        - 'languages:language_content'
 | 
			
		||||
        - 'languages:language_interface'
 | 
			
		||||
        - url.query_args
 | 
			
		||||
      tags: {  }
 | 
			
		||||
@ -0,0 +1,66 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
id: test_block_content_revision_id
 | 
			
		||||
label: test_block_content_revision_id
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_revision
 | 
			
		||||
base_field: revision_id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_options:
 | 
			
		||||
      relationships:
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: id
 | 
			
		||||
          required: true
 | 
			
		||||
          plugin_id: standard
 | 
			
		||||
      fields:
 | 
			
		||||
        revision_id:
 | 
			
		||||
          id: revision_id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: revision_id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_id
 | 
			
		||||
        id_1:
 | 
			
		||||
          id: id_1
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: id
 | 
			
		||||
          relationship: id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
      arguments:
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: id
 | 
			
		||||
          plugin_id: numeric
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
      sorts:
 | 
			
		||||
        revision_id:
 | 
			
		||||
          id: revision_id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: revision_id
 | 
			
		||||
          order: ASC
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_id
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    id: default
 | 
			
		||||
    position: 0
 | 
			
		||||
@ -0,0 +1,69 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
id: test_block_content_revision_revision_id
 | 
			
		||||
label: test_block_content_revision_revision_id
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_revision
 | 
			
		||||
base_field: revision_id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_options:
 | 
			
		||||
      relationships:
 | 
			
		||||
        revision_id:
 | 
			
		||||
          id: revision_id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: revision_id
 | 
			
		||||
          required: true
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_id
 | 
			
		||||
          plugin_id: standard
 | 
			
		||||
      fields:
 | 
			
		||||
        revision_id:
 | 
			
		||||
          id: revision_id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: revision_id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_id
 | 
			
		||||
        id_1:
 | 
			
		||||
          id: id_1
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: id
 | 
			
		||||
          relationship: revision_id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
      arguments:
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: id
 | 
			
		||||
          plugin_id: block_content_id
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
      sorts:
 | 
			
		||||
        revision_id:
 | 
			
		||||
          id: revision_id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: revision_id
 | 
			
		||||
          order: ASC
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_id
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    id: default
 | 
			
		||||
    position: 0
 | 
			
		||||
@ -0,0 +1,322 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
    - user
 | 
			
		||||
id: test_block_content_revision_user
 | 
			
		||||
label: 'Test block content revision user'
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_data
 | 
			
		||||
base_field: id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    id: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    position: 0
 | 
			
		||||
    display_options:
 | 
			
		||||
      access:
 | 
			
		||||
        type: perm
 | 
			
		||||
        options:
 | 
			
		||||
          perm: 'access content'
 | 
			
		||||
      cache:
 | 
			
		||||
        type: tag
 | 
			
		||||
        options: {  }
 | 
			
		||||
      query:
 | 
			
		||||
        type: views_query
 | 
			
		||||
        options:
 | 
			
		||||
          disable_sql_rewrite: false
 | 
			
		||||
          distinct: false
 | 
			
		||||
          replica: false
 | 
			
		||||
          query_comment: ''
 | 
			
		||||
          query_tags: {  }
 | 
			
		||||
      exposed_form:
 | 
			
		||||
        type: basic
 | 
			
		||||
        options:
 | 
			
		||||
          submit_button: Apply
 | 
			
		||||
          reset_button: false
 | 
			
		||||
          reset_button_label: Reset
 | 
			
		||||
          exposed_sorts_label: 'Sort by'
 | 
			
		||||
          expose_sort_order: true
 | 
			
		||||
          sort_asc_label: Asc
 | 
			
		||||
          sort_desc_label: Desc
 | 
			
		||||
      pager:
 | 
			
		||||
        type: none
 | 
			
		||||
        options:
 | 
			
		||||
          offset: 0
 | 
			
		||||
      style:
 | 
			
		||||
        type: default
 | 
			
		||||
        options:
 | 
			
		||||
          grouping: {  }
 | 
			
		||||
          row_class: ''
 | 
			
		||||
          default_row_class: true
 | 
			
		||||
          uses_fields: false
 | 
			
		||||
      row:
 | 
			
		||||
        type: fields
 | 
			
		||||
        options:
 | 
			
		||||
          inline: {  }
 | 
			
		||||
          separator: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          default_field_elements: true
 | 
			
		||||
      fields:
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: id
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          label: ''
 | 
			
		||||
          exclude: false
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
            path_case: none
 | 
			
		||||
            trim_whitespace: false
 | 
			
		||||
            alt: ''
 | 
			
		||||
            rel: ''
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
            ellipsis: true
 | 
			
		||||
            more_link: false
 | 
			
		||||
            more_link_text: ''
 | 
			
		||||
            more_link_path: ''
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            preserve_tags: ''
 | 
			
		||||
            html: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: false
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          click_sort_column: value
 | 
			
		||||
          type: number_integer
 | 
			
		||||
          settings:
 | 
			
		||||
            thousand_separator: ''
 | 
			
		||||
            prefix_suffix: false
 | 
			
		||||
          group_column: value
 | 
			
		||||
          group_columns: {  }
 | 
			
		||||
          group_rows: true
 | 
			
		||||
          delta_limit: 0
 | 
			
		||||
          delta_offset: 0
 | 
			
		||||
          delta_reversed: false
 | 
			
		||||
          delta_first_last: false
 | 
			
		||||
          multi_type: separator
 | 
			
		||||
          separator: ', '
 | 
			
		||||
          field_api_classes: false
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
        revision_id:
 | 
			
		||||
          id: revision_id
 | 
			
		||||
          table: block_content_field_revision
 | 
			
		||||
          field: revision_id
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          label: ''
 | 
			
		||||
          exclude: false
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
            path_case: none
 | 
			
		||||
            trim_whitespace: false
 | 
			
		||||
            alt: ''
 | 
			
		||||
            rel: ''
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
            ellipsis: true
 | 
			
		||||
            more_link: false
 | 
			
		||||
            more_link_text: ''
 | 
			
		||||
            more_link_path: ''
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            preserve_tags: ''
 | 
			
		||||
            html: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: false
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          click_sort_column: value
 | 
			
		||||
          type: number_integer
 | 
			
		||||
          settings:
 | 
			
		||||
            thousand_separator: ''
 | 
			
		||||
            prefix_suffix: false
 | 
			
		||||
          group_column: value
 | 
			
		||||
          group_columns: {  }
 | 
			
		||||
          group_rows: true
 | 
			
		||||
          delta_limit: 0
 | 
			
		||||
          delta_offset: 0
 | 
			
		||||
          delta_reversed: false
 | 
			
		||||
          delta_first_last: false
 | 
			
		||||
          multi_type: separator
 | 
			
		||||
          separator: ', '
 | 
			
		||||
          field_api_classes: false
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_id
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
        revision_user:
 | 
			
		||||
          id: revision_user
 | 
			
		||||
          table: block_content_revision
 | 
			
		||||
          field: revision_user
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          label: ''
 | 
			
		||||
          exclude: false
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
            path_case: none
 | 
			
		||||
            trim_whitespace: false
 | 
			
		||||
            alt: ''
 | 
			
		||||
            rel: ''
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
            ellipsis: true
 | 
			
		||||
            more_link: false
 | 
			
		||||
            more_link_text: ''
 | 
			
		||||
            more_link_path: ''
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            preserve_tags: ''
 | 
			
		||||
            html: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: false
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          click_sort_column: target_id
 | 
			
		||||
          type: entity_reference_label
 | 
			
		||||
          settings:
 | 
			
		||||
            link: false
 | 
			
		||||
          group_column: target_id
 | 
			
		||||
          group_columns: {  }
 | 
			
		||||
          group_rows: true
 | 
			
		||||
          delta_limit: 0
 | 
			
		||||
          delta_offset: 0
 | 
			
		||||
          delta_reversed: false
 | 
			
		||||
          delta_first_last: false
 | 
			
		||||
          multi_type: separator
 | 
			
		||||
          separator: ', '
 | 
			
		||||
          field_api_classes: false
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_user
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
      filters:
 | 
			
		||||
        revision_user:
 | 
			
		||||
          id: revision_user
 | 
			
		||||
          table: block_content_revision
 | 
			
		||||
          field: revision_user
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          operator: in
 | 
			
		||||
          value: {  }
 | 
			
		||||
          group: 1
 | 
			
		||||
          exposed: true
 | 
			
		||||
          expose:
 | 
			
		||||
            operator_id: revision_user_op
 | 
			
		||||
            label: 'Revision user'
 | 
			
		||||
            description: ''
 | 
			
		||||
            use_operator: false
 | 
			
		||||
            operator: revision_user_op
 | 
			
		||||
            operator_limit_selection: false
 | 
			
		||||
            operator_list: {  }
 | 
			
		||||
            identifier: revision_user
 | 
			
		||||
            required: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember_roles:
 | 
			
		||||
              authenticated: authenticated
 | 
			
		||||
            reduce: false
 | 
			
		||||
          is_grouped: false
 | 
			
		||||
          group_info:
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            optional: true
 | 
			
		||||
            widget: select
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            default_group: All
 | 
			
		||||
            default_group_multiple: {  }
 | 
			
		||||
            group_items: {  }
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: revision_user
 | 
			
		||||
          plugin_id: user_name
 | 
			
		||||
      sorts: {  }
 | 
			
		||||
      header: {  }
 | 
			
		||||
      footer: {  }
 | 
			
		||||
      empty: {  }
 | 
			
		||||
      relationships: {  }
 | 
			
		||||
      arguments: {  }
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
      filter_groups:
 | 
			
		||||
        operator: AND
 | 
			
		||||
        groups: {  }
 | 
			
		||||
    cache_metadata:
 | 
			
		||||
      max-age: -1
 | 
			
		||||
      contexts:
 | 
			
		||||
        - 'languages:language_content'
 | 
			
		||||
        - 'languages:language_interface'
 | 
			
		||||
        - url
 | 
			
		||||
        - 'user.block_content_grants:view'
 | 
			
		||||
        - user.permissions
 | 
			
		||||
      tags: {  }
 | 
			
		||||
@ -0,0 +1,190 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
id: test_block_content_view
 | 
			
		||||
label: test_block_content_view
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_data
 | 
			
		||||
base_field: id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    id: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    position: null
 | 
			
		||||
    display_options:
 | 
			
		||||
      access:
 | 
			
		||||
        type: none
 | 
			
		||||
        options: {  }
 | 
			
		||||
      cache:
 | 
			
		||||
        type: tag
 | 
			
		||||
        options: {  }
 | 
			
		||||
      query:
 | 
			
		||||
        type: views_query
 | 
			
		||||
        options:
 | 
			
		||||
          disable_sql_rewrite: false
 | 
			
		||||
          distinct: false
 | 
			
		||||
          replica: false
 | 
			
		||||
          query_comment: ''
 | 
			
		||||
          query_tags: {  }
 | 
			
		||||
      exposed_form:
 | 
			
		||||
        type: basic
 | 
			
		||||
        options:
 | 
			
		||||
          submit_button: Apply
 | 
			
		||||
          reset_button: false
 | 
			
		||||
          reset_button_label: Reset
 | 
			
		||||
          exposed_sorts_label: 'Sort by'
 | 
			
		||||
          expose_sort_order: true
 | 
			
		||||
          sort_asc_label: Asc
 | 
			
		||||
          sort_desc_label: Desc
 | 
			
		||||
      pager:
 | 
			
		||||
        type: full
 | 
			
		||||
        options:
 | 
			
		||||
          items_per_page: 10
 | 
			
		||||
          offset: 0
 | 
			
		||||
          id: 0
 | 
			
		||||
          total_pages: null
 | 
			
		||||
          expose:
 | 
			
		||||
            items_per_page: false
 | 
			
		||||
            items_per_page_label: 'Items per page'
 | 
			
		||||
            items_per_page_options: '5, 10, 25, 50'
 | 
			
		||||
            items_per_page_options_all: false
 | 
			
		||||
            items_per_page_options_all_label: '- All -'
 | 
			
		||||
            offset: false
 | 
			
		||||
            offset_label: Offset
 | 
			
		||||
          tags:
 | 
			
		||||
            previous: '‹ Previous'
 | 
			
		||||
            next: 'Next ›'
 | 
			
		||||
            first: '« First'
 | 
			
		||||
            last: 'Last »'
 | 
			
		||||
          quantity: 9
 | 
			
		||||
      style:
 | 
			
		||||
        type: default
 | 
			
		||||
      row:
 | 
			
		||||
        type: fields
 | 
			
		||||
      fields:
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: id
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          label: Id
 | 
			
		||||
          exclude: false
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
            path_case: none
 | 
			
		||||
            trim_whitespace: false
 | 
			
		||||
            alt: ''
 | 
			
		||||
            rel: ''
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
            ellipsis: true
 | 
			
		||||
            more_link: false
 | 
			
		||||
            more_link_text: ''
 | 
			
		||||
            more_link_path: ''
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            preserve_tags: ''
 | 
			
		||||
            html: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: true
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
      sorts:
 | 
			
		||||
        id:
 | 
			
		||||
          id: id
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: id
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          order: ASC
 | 
			
		||||
          exposed: false
 | 
			
		||||
          expose:
 | 
			
		||||
            label: ''
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: id
 | 
			
		||||
          plugin_id: standard
 | 
			
		||||
      title: test_block_content_view
 | 
			
		||||
      header: {  }
 | 
			
		||||
      footer: {  }
 | 
			
		||||
      empty: {  }
 | 
			
		||||
      relationships: {  }
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
      arguments:
 | 
			
		||||
        type:
 | 
			
		||||
          id: type
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: type
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          default_action: 'not found'
 | 
			
		||||
          exception:
 | 
			
		||||
            value: all
 | 
			
		||||
            title_enable: false
 | 
			
		||||
            title: All
 | 
			
		||||
          title_enable: false
 | 
			
		||||
          title: ''
 | 
			
		||||
          default_argument_type: fixed
 | 
			
		||||
          default_argument_options:
 | 
			
		||||
            argument: ''
 | 
			
		||||
          summary_options:
 | 
			
		||||
            base_path: ''
 | 
			
		||||
            count: true
 | 
			
		||||
            items_per_page: 25
 | 
			
		||||
            override: false
 | 
			
		||||
          summary:
 | 
			
		||||
            sort_order: asc
 | 
			
		||||
            number_of_records: 0
 | 
			
		||||
            format: default_summary
 | 
			
		||||
          specify_validation: false
 | 
			
		||||
          validate:
 | 
			
		||||
            type: none
 | 
			
		||||
            fail: 'not found'
 | 
			
		||||
          validate_options: {  }
 | 
			
		||||
          glossary: false
 | 
			
		||||
          limit: 0
 | 
			
		||||
          case: none
 | 
			
		||||
          path_case: none
 | 
			
		||||
          transform_dash: false
 | 
			
		||||
          break_phrase: false
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: type
 | 
			
		||||
          plugin_id: string
 | 
			
		||||
  page_1:
 | 
			
		||||
    display_plugin: page
 | 
			
		||||
    id: page_1
 | 
			
		||||
    display_title: Page
 | 
			
		||||
    position: null
 | 
			
		||||
    display_options:
 | 
			
		||||
      path: test-block_content-view
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
@ -0,0 +1,338 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
id: test_field_filters
 | 
			
		||||
label: 'Test field filters'
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_data
 | 
			
		||||
base_field: id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    id: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    position: 0
 | 
			
		||||
    display_options:
 | 
			
		||||
      access:
 | 
			
		||||
        type: none
 | 
			
		||||
        options: {  }
 | 
			
		||||
      cache:
 | 
			
		||||
        type: tag
 | 
			
		||||
        options: {  }
 | 
			
		||||
      query:
 | 
			
		||||
        type: views_query
 | 
			
		||||
        options:
 | 
			
		||||
          disable_sql_rewrite: false
 | 
			
		||||
          distinct: false
 | 
			
		||||
          replica: false
 | 
			
		||||
          query_comment: ''
 | 
			
		||||
          query_tags: {  }
 | 
			
		||||
      exposed_form:
 | 
			
		||||
        type: basic
 | 
			
		||||
        options:
 | 
			
		||||
          submit_button: Apply
 | 
			
		||||
          reset_button: false
 | 
			
		||||
          reset_button_label: Reset
 | 
			
		||||
          exposed_sorts_label: 'Sort by'
 | 
			
		||||
          expose_sort_order: true
 | 
			
		||||
          sort_asc_label: Asc
 | 
			
		||||
          sort_desc_label: Desc
 | 
			
		||||
      pager:
 | 
			
		||||
        type: none
 | 
			
		||||
        options:
 | 
			
		||||
          items_per_page: 0
 | 
			
		||||
          offset: 0
 | 
			
		||||
      style:
 | 
			
		||||
        type: default
 | 
			
		||||
      row:
 | 
			
		||||
        type: 'entity:block_content'
 | 
			
		||||
        options:
 | 
			
		||||
          relationship: none
 | 
			
		||||
          view_mode: default
 | 
			
		||||
      fields:
 | 
			
		||||
        info:
 | 
			
		||||
          id: info
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: info
 | 
			
		||||
          label: ''
 | 
			
		||||
          alter:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            make_link: false
 | 
			
		||||
            absolute: false
 | 
			
		||||
            trim: false
 | 
			
		||||
            word_boundary: false
 | 
			
		||||
            ellipsis: false
 | 
			
		||||
            strip_tags: false
 | 
			
		||||
            html: false
 | 
			
		||||
          hide_empty: false
 | 
			
		||||
          empty_zero: false
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          exclude: false
 | 
			
		||||
          element_type: ''
 | 
			
		||||
          element_class: ''
 | 
			
		||||
          element_label_type: ''
 | 
			
		||||
          element_label_class: ''
 | 
			
		||||
          element_label_colon: true
 | 
			
		||||
          element_wrapper_type: ''
 | 
			
		||||
          element_wrapper_class: ''
 | 
			
		||||
          element_default_classes: true
 | 
			
		||||
          empty: ''
 | 
			
		||||
          hide_alter_empty: true
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          type: string
 | 
			
		||||
          settings:
 | 
			
		||||
            link_to_entity: true
 | 
			
		||||
          entity_field: title
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
      filters:
 | 
			
		||||
        info:
 | 
			
		||||
          id: info
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: info
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          operator: contains
 | 
			
		||||
          value: Paris
 | 
			
		||||
          group: 1
 | 
			
		||||
          exposed: false
 | 
			
		||||
          expose:
 | 
			
		||||
            operator_id: ''
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            use_operator: false
 | 
			
		||||
            operator: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            required: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember_roles:
 | 
			
		||||
              authenticated: authenticated
 | 
			
		||||
          is_grouped: false
 | 
			
		||||
          group_info:
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            optional: true
 | 
			
		||||
            widget: select
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            default_group: All
 | 
			
		||||
            default_group_multiple: {  }
 | 
			
		||||
            group_items: {  }
 | 
			
		||||
          plugin_id: string
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: info
 | 
			
		||||
      sorts:
 | 
			
		||||
        changed:
 | 
			
		||||
          id: changed
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: changed
 | 
			
		||||
          order: DESC
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          exposed: false
 | 
			
		||||
          expose:
 | 
			
		||||
            label: ''
 | 
			
		||||
          granularity: second
 | 
			
		||||
          plugin_id: date
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: changed
 | 
			
		||||
      title: 'Test field filters'
 | 
			
		||||
      header: {  }
 | 
			
		||||
      footer: {  }
 | 
			
		||||
      empty: {  }
 | 
			
		||||
      relationships: {  }
 | 
			
		||||
      arguments: {  }
 | 
			
		||||
      rendering_language: '***LANGUAGE_entity_translation***'
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
  page_bf:
 | 
			
		||||
    display_plugin: page
 | 
			
		||||
    id: page_bf
 | 
			
		||||
    display_title: 'Body filter page'
 | 
			
		||||
    position: 1
 | 
			
		||||
    display_options:
 | 
			
		||||
      path: test-body-filter
 | 
			
		||||
      display_description: ''
 | 
			
		||||
      title: 'Test body filters'
 | 
			
		||||
      defaults:
 | 
			
		||||
        title: false
 | 
			
		||||
        filters: false
 | 
			
		||||
        filter_groups: false
 | 
			
		||||
      filters:
 | 
			
		||||
        body_value:
 | 
			
		||||
          id: body_value
 | 
			
		||||
          table: block_content__body
 | 
			
		||||
          field: body_value
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          operator: contains
 | 
			
		||||
          value: Comida
 | 
			
		||||
          group: 1
 | 
			
		||||
          exposed: false
 | 
			
		||||
          expose:
 | 
			
		||||
            operator_id: ''
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            use_operator: false
 | 
			
		||||
            operator: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            required: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember_roles:
 | 
			
		||||
              authenticated: authenticated
 | 
			
		||||
          is_grouped: false
 | 
			
		||||
          group_info:
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            optional: true
 | 
			
		||||
            widget: select
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            default_group: All
 | 
			
		||||
            default_group_multiple: {  }
 | 
			
		||||
            group_items: {  }
 | 
			
		||||
          plugin_id: string
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: body
 | 
			
		||||
      filter_groups:
 | 
			
		||||
        operator: AND
 | 
			
		||||
        groups:
 | 
			
		||||
          1: AND
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
  page_bfp:
 | 
			
		||||
    display_plugin: page
 | 
			
		||||
    id: page_bfp
 | 
			
		||||
    display_title: 'Body filter page Paris'
 | 
			
		||||
    position: 1
 | 
			
		||||
    display_options:
 | 
			
		||||
      path: test-body-paris
 | 
			
		||||
      display_description: ''
 | 
			
		||||
      title: 'Test body filters'
 | 
			
		||||
      defaults:
 | 
			
		||||
        title: false
 | 
			
		||||
        filters: false
 | 
			
		||||
        filter_groups: false
 | 
			
		||||
      filters:
 | 
			
		||||
        body_value:
 | 
			
		||||
          id: body_value
 | 
			
		||||
          table: block_content__body
 | 
			
		||||
          field: body_value
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          operator: contains
 | 
			
		||||
          value: Paris
 | 
			
		||||
          group: 1
 | 
			
		||||
          exposed: false
 | 
			
		||||
          expose:
 | 
			
		||||
            operator_id: ''
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            use_operator: false
 | 
			
		||||
            operator: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            required: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember_roles:
 | 
			
		||||
              authenticated: authenticated
 | 
			
		||||
          is_grouped: false
 | 
			
		||||
          group_info:
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            optional: true
 | 
			
		||||
            widget: select
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            default_group: All
 | 
			
		||||
            default_group_multiple: {  }
 | 
			
		||||
            group_items: {  }
 | 
			
		||||
          plugin_id: string
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: body
 | 
			
		||||
      filter_groups:
 | 
			
		||||
        operator: AND
 | 
			
		||||
        groups:
 | 
			
		||||
          1: AND
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
  page_if:
 | 
			
		||||
    display_plugin: page
 | 
			
		||||
    id: page_if
 | 
			
		||||
    display_title: 'Info filter page'
 | 
			
		||||
    position: 1
 | 
			
		||||
    display_options:
 | 
			
		||||
      path: test-info-filter
 | 
			
		||||
      display_description: ''
 | 
			
		||||
      title: 'Test info filter'
 | 
			
		||||
      defaults:
 | 
			
		||||
        title: false
 | 
			
		||||
        filters: false
 | 
			
		||||
        filter_groups: false
 | 
			
		||||
      filters:
 | 
			
		||||
        info:
 | 
			
		||||
          id: info
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          field: info
 | 
			
		||||
          relationship: none
 | 
			
		||||
          group_type: group
 | 
			
		||||
          admin_label: ''
 | 
			
		||||
          operator: contains
 | 
			
		||||
          value: Comida
 | 
			
		||||
          group: 1
 | 
			
		||||
          exposed: false
 | 
			
		||||
          expose:
 | 
			
		||||
            operator_id: ''
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            use_operator: false
 | 
			
		||||
            operator: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            required: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember_roles:
 | 
			
		||||
              authenticated: authenticated
 | 
			
		||||
          is_grouped: false
 | 
			
		||||
          group_info:
 | 
			
		||||
            label: ''
 | 
			
		||||
            description: ''
 | 
			
		||||
            identifier: ''
 | 
			
		||||
            optional: true
 | 
			
		||||
            widget: select
 | 
			
		||||
            multiple: false
 | 
			
		||||
            remember: false
 | 
			
		||||
            default_group: All
 | 
			
		||||
            default_group_multiple: {  }
 | 
			
		||||
            group_items: {  }
 | 
			
		||||
          plugin_id: string
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: info
 | 
			
		||||
      filter_groups:
 | 
			
		||||
        operator: AND
 | 
			
		||||
        groups:
 | 
			
		||||
          1: AND
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
  page_ifp:
 | 
			
		||||
    display_plugin: page
 | 
			
		||||
    id: page_ifp
 | 
			
		||||
    display_title: 'Info filter page Paris'
 | 
			
		||||
    position: 1
 | 
			
		||||
    display_options:
 | 
			
		||||
      path: test-info-paris
 | 
			
		||||
      display_description: ''
 | 
			
		||||
      title: 'Test info filter'
 | 
			
		||||
      defaults:
 | 
			
		||||
        title: false
 | 
			
		||||
      display_extenders: {  }
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
langcode: en
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_content
 | 
			
		||||
id: test_field_type
 | 
			
		||||
label: test_field_type
 | 
			
		||||
module: views
 | 
			
		||||
description: ''
 | 
			
		||||
tag: ''
 | 
			
		||||
base_table: block_content_field_data
 | 
			
		||||
base_field: id
 | 
			
		||||
display:
 | 
			
		||||
  default:
 | 
			
		||||
    display_options:
 | 
			
		||||
      fields:
 | 
			
		||||
        type:
 | 
			
		||||
          field: type
 | 
			
		||||
          id: type
 | 
			
		||||
          table: block_content_field_data
 | 
			
		||||
          plugin_id: field
 | 
			
		||||
          entity_type: block_content
 | 
			
		||||
          entity_field: type
 | 
			
		||||
    display_plugin: default
 | 
			
		||||
    display_title: Default
 | 
			
		||||
    id: default
 | 
			
		||||
    position: 0
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
name: 'Block Content Theme Suggestions Test'
 | 
			
		||||
type: module
 | 
			
		||||
description: 'Support module for testing.'
 | 
			
		||||
package: Testing
 | 
			
		||||
version: VERSION
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * Support module for testing.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\BlockContentInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_preprocess_block().
 | 
			
		||||
 */
 | 
			
		||||
function block_content_theme_suggestions_test_preprocess_block(&$variables): void {
 | 
			
		||||
  $block_content = $variables['elements']['content']['#block_content'] ?? NULL;
 | 
			
		||||
  if ($block_content instanceof BlockContentInterface) {
 | 
			
		||||
    $variables['label'] = $block_content->label();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,65 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\block_content_theme_suggestions_test\Hook;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
 | 
			
		||||
use Drupal\Core\Entity\EntityInterface;
 | 
			
		||||
use Drupal\Core\Hook\Attribute\Hook;
 | 
			
		||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook implementations for block_content_theme_suggestions_test.
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentThemeSuggestionsTestHooks {
 | 
			
		||||
 | 
			
		||||
  use StringTranslationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_entity_extra_field_info().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('entity_extra_field_info')]
 | 
			
		||||
  public function entityExtraFieldInfo(): array {
 | 
			
		||||
    // Add an extra field to the test bundle.
 | 
			
		||||
    $extra['node']['bundle_with_extra_field']['display']['block_content_extra_field_test'] = [
 | 
			
		||||
      'label' => $this->t('Extra field'),
 | 
			
		||||
      'description' => $this->t('Extra field description'),
 | 
			
		||||
      'weight' => 0,
 | 
			
		||||
    ];
 | 
			
		||||
    return $extra;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_node_view().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('node_view')]
 | 
			
		||||
  public function nodeView(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, string $view_mode): void {
 | 
			
		||||
    // Provide content for the extra field in the form of a content block.
 | 
			
		||||
    if ($display->getComponent('block_content_extra_field_test')) {
 | 
			
		||||
      $entity_type_manager = \Drupal::entityTypeManager();
 | 
			
		||||
      // Load a block content entity with a known UUID created by test setup.
 | 
			
		||||
      // @see \Drupal\Tests\block_content\Functional\BlockContentThemeSuggestionsTest::setUp()
 | 
			
		||||
      $block_content = $entity_type_manager->getStorage('block_content')->loadByProperties([
 | 
			
		||||
        'uuid' => 'b22c881a-bcfd-4d0c-a41d-3573327705df',
 | 
			
		||||
      ]);
 | 
			
		||||
      $block_content = reset($block_content);
 | 
			
		||||
      $build['block_content_extra_field_test'] = $entity_type_manager->getViewBuilder('block_content')->view($block_content);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Implements hook_theme().
 | 
			
		||||
   */
 | 
			
		||||
  #[Hook('theme')]
 | 
			
		||||
  public function theme(): array {
 | 
			
		||||
    // It is necessary to explicitly register the template via hook_theme()
 | 
			
		||||
    // because it is added via a module, not a theme.
 | 
			
		||||
    return [
 | 
			
		||||
      'block__block_content__view_type__basic__full' => [
 | 
			
		||||
        'base hook' => 'block',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,3 @@
 | 
			
		||||
{{ label }}
 | 
			
		||||
 | 
			
		||||
<h1>I am a block content template for a specific bundle and view mode!</h1>
 | 
			
		||||
@ -0,0 +1,100 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Core\Cache\Cache;
 | 
			
		||||
use Drupal\Core\Cache\CacheableMetadata;
 | 
			
		||||
use Drupal\Core\Entity\EntityInterface;
 | 
			
		||||
use Drupal\Tests\system\Functional\Entity\EntityCacheTagsTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the Content Block entity's cache tags.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentCacheTagsTest extends EntityCacheTagsTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function createEntity() {
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'basic',
 | 
			
		||||
      'revision' => FALSE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
    block_content_add_body_field($block_content_type->id());
 | 
			
		||||
 | 
			
		||||
    // Create a "Llama" content block.
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Llama',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'body' => [
 | 
			
		||||
        'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
 | 
			
		||||
        'format' => 'plain_text',
 | 
			
		||||
      ],
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    return $block_content;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   *
 | 
			
		||||
   * @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess()
 | 
			
		||||
   */
 | 
			
		||||
  protected function getAccessCacheContextsForEntity(EntityInterface $entity): array {
 | 
			
		||||
    return [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   *
 | 
			
		||||
   * Each comment must have a comment body, which always has a text format.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getAdditionalCacheTagsForEntity(EntityInterface $entity): array {
 | 
			
		||||
    return ['config:filter.format.plain_text'];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests that the block is cached with the correct contexts and tags.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlock(): void {
 | 
			
		||||
    $block = $this->drupalPlaceBlock('block_content:' . $this->entity->uuid());
 | 
			
		||||
    $build = $this->container->get('entity_type.manager')->getViewBuilder('block')->view($block, 'block');
 | 
			
		||||
 | 
			
		||||
    // Render the block.
 | 
			
		||||
    $this->container->get('renderer')->renderRoot($build);
 | 
			
		||||
 | 
			
		||||
    // Expected keys, contexts, and tags for the block.
 | 
			
		||||
    // @see \Drupal\block\BlockViewBuilder::viewMultiple()
 | 
			
		||||
    $expected_block_cache_keys = ['entity_view', 'block', $block->id()];
 | 
			
		||||
    $expected_block_cache_tags = Cache::mergeTags(['block_view', 'rendered'], $block->getCacheTags());
 | 
			
		||||
    $expected_block_cache_tags = Cache::mergeTags($expected_block_cache_tags, $block->getPlugin()->getCacheTags());
 | 
			
		||||
 | 
			
		||||
    // Expected contexts and tags for the BlockContent entity.
 | 
			
		||||
    // @see \Drupal\Core\Entity\EntityViewBuilder::getBuildDefaults().
 | 
			
		||||
    $expected_entity_cache_tags = Cache::mergeTags(['block_content_view'], $this->entity->getCacheTags());
 | 
			
		||||
    $expected_entity_cache_tags = Cache::mergeTags($expected_entity_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity));
 | 
			
		||||
 | 
			
		||||
    // Verify that what was render cached matches the above expectations.
 | 
			
		||||
    $this->verifyRenderCache($expected_block_cache_keys, Cache::mergeTags($expected_block_cache_tags, $expected_entity_cache_tags), CacheableMetadata::createFromRenderArray($build));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,44 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests views contextual links on block content.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentContextualLinksTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'contextual',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests contextual links.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentContextualLinks(): void {
 | 
			
		||||
    $block_content = $this->createBlockContent();
 | 
			
		||||
 | 
			
		||||
    $block = $this->placeBlock('block_content:' . $block_content->uuid());
 | 
			
		||||
 | 
			
		||||
    $user = $this->drupalCreateUser([
 | 
			
		||||
      'administer blocks',
 | 
			
		||||
      'access contextual links',
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->drupalLogin($user);
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $this->assertSession()->elementAttributeContains('css', 'div[data-contextual-id]', 'data-contextual-id', 'block:block=' . $block->id() . ':langcode=en|block_content:block_content=' . $block_content->id() . ':');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,339 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\BlockContentInterface;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Core\Database\Database;
 | 
			
		||||
 | 
			
		||||
// cspell:ignore testblock
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a block and test saving it.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentCreationTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Modules to install.
 | 
			
		||||
   *
 | 
			
		||||
   * Enable dummy module that implements hook_block_insert() for exceptions and
 | 
			
		||||
   * field_ui to edit display settings.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content_test', 'dblog', 'field_ui'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Permissions to grant admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'administer blocks',
 | 
			
		||||
    'administer block_content display',
 | 
			
		||||
    'access block library',
 | 
			
		||||
    'administer block content',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the test up.
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a "Basic block" block and verifies its consistency in the database.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentCreation(): void {
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
 | 
			
		||||
    // Create a block.
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = 'Test Block';
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Check that the Basic block has been created.
 | 
			
		||||
    $this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
 | 
			
		||||
 | 
			
		||||
    // Check that the view mode setting is hidden because only one exists.
 | 
			
		||||
    $this->assertSession()->fieldNotExists('settings[view_mode]');
 | 
			
		||||
 | 
			
		||||
    // Check that the block exists in the database.
 | 
			
		||||
    $block = $this->getBlockByLabel($edit['info[0][value]']);
 | 
			
		||||
    $this->assertNotEmpty($block, 'Content Block found in database.');
 | 
			
		||||
 | 
			
		||||
    // Ensure a user with just the create permission can access the page.
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser([
 | 
			
		||||
      'create basic block content',
 | 
			
		||||
    ]));
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a "Basic page" block with multiple view modes.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentCreationMultipleViewModes(): void {
 | 
			
		||||
    // Add a new view mode and verify if it is selected as expected.
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser(['administer display modes']));
 | 
			
		||||
    $this->drupalGet('admin/structure/display-modes/view/add/block_content');
 | 
			
		||||
    $edit = [
 | 
			
		||||
      'id' => 'test_view_mode',
 | 
			
		||||
      'label' => 'Test View Mode',
 | 
			
		||||
    ];
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Saved the ' . $edit['label'] . ' view mode.');
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
 | 
			
		||||
    // Create a block.
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = 'Test Block';
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit, 'Save and configure');
 | 
			
		||||
 | 
			
		||||
    // Save our block permanently
 | 
			
		||||
    $this->submitForm(['region' => 'content'], 'Save block');
 | 
			
		||||
 | 
			
		||||
    // Set test_view_mode as a custom display to be available on the list.
 | 
			
		||||
    $this->drupalGet('admin/structure/block-content/manage/basic/display');
 | 
			
		||||
    $custom_view_mode = [
 | 
			
		||||
      'display_modes_custom[test_view_mode]' => 1,
 | 
			
		||||
    ];
 | 
			
		||||
    $this->submitForm($custom_view_mode, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Go to the configure page and change the view mode.
 | 
			
		||||
    $this->drupalGet('admin/structure/block/manage/stark_testblock');
 | 
			
		||||
 | 
			
		||||
    // Test the available view mode options.
 | 
			
		||||
    // Verify that the default view mode is available.
 | 
			
		||||
    $this->assertSession()->optionExists('edit-settings-view-mode', 'default');
 | 
			
		||||
    // Verify that the test view mode is available.
 | 
			
		||||
    $this->assertSession()->optionExists('edit-settings-view-mode', 'test_view_mode');
 | 
			
		||||
 | 
			
		||||
    $view_mode['settings[view_mode]'] = 'test_view_mode';
 | 
			
		||||
    $this->submitForm($view_mode, 'Save block');
 | 
			
		||||
 | 
			
		||||
    // Check that the view mode setting is shown because more than one exists.
 | 
			
		||||
    $this->drupalGet('admin/structure/block/manage/stark_testblock');
 | 
			
		||||
    $this->assertSession()->fieldExists('settings[view_mode]');
 | 
			
		||||
 | 
			
		||||
    // Change the view mode.
 | 
			
		||||
    $view_mode['region'] = 'content';
 | 
			
		||||
    $view_mode['settings[view_mode]'] = 'test_view_mode';
 | 
			
		||||
    $this->submitForm($view_mode, 'Save block');
 | 
			
		||||
 | 
			
		||||
    // Go to the configure page and verify the view mode has changed.
 | 
			
		||||
    $this->drupalGet('admin/structure/block/manage/stark_testblock');
 | 
			
		||||
    $this->assertSession()->fieldValueEquals('settings[view_mode]', 'test_view_mode');
 | 
			
		||||
 | 
			
		||||
    // Check that the block exists in the database.
 | 
			
		||||
    $block = $this->getBlockByLabel($edit['info[0][value]']);
 | 
			
		||||
    $this->assertNotEmpty($block, 'Content Block found in database.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the redirect workflow of creating a block_content and block.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentFormSubmitHandlers(): void {
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
 | 
			
		||||
    // Create a block and place in block layout.
 | 
			
		||||
    $this->drupalGet('/admin/content/block');
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->assertSession()->addressEquals('/block/add/basic');
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = 'Test Block';
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->submitForm($edit, 'Save and configure');
 | 
			
		||||
    $this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Configure block');
 | 
			
		||||
 | 
			
		||||
    // Verify when editing a block "Save and configure" does not appear.
 | 
			
		||||
    $this->drupalGet('/admin/content/block/1');
 | 
			
		||||
    $this->assertSession()->buttonNotExists('Save and configure');
 | 
			
		||||
 | 
			
		||||
    // Create a block but go back to block library.
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = 'Test Block';
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
    // Check that the Basic block has been created.
 | 
			
		||||
    $this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
 | 
			
		||||
    $this->assertSession()->addressEquals('/admin/content/block');
 | 
			
		||||
 | 
			
		||||
    // Check that the user is redirected to the block library on edit.
 | 
			
		||||
    $block = $this->getBlockByLabel($edit['info[0][value]']);
 | 
			
		||||
    $this->drupalGet($block->toUrl('edit-form'));
 | 
			
		||||
    $this->submitForm([
 | 
			
		||||
      'info[0][value]' => 'Test Block Updated',
 | 
			
		||||
    ], 'Save');
 | 
			
		||||
    $this->assertSession()->addressEquals('admin/content/block');
 | 
			
		||||
 | 
			
		||||
    // Test with user who doesn't have permission to place a block.
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser(['administer block content']));
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->assertSession()->buttonNotExists('Save and configure');
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a default content block.
 | 
			
		||||
   *
 | 
			
		||||
   * Creates a content block from defaults and ensures that the 'basic block'
 | 
			
		||||
   * type is being used.
 | 
			
		||||
   */
 | 
			
		||||
  public function testDefaultBlockContentCreation(): void {
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = $this->randomMachineName(8);
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    // Don't pass the content block type in the URL so the default is forced.
 | 
			
		||||
    $this->drupalGet('block/add');
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Check that the block has been created and that it is a basic block.
 | 
			
		||||
    $this->assertSession()->pageTextContains('basic ' . $edit['info[0][value]'] . ' has been created.');
 | 
			
		||||
 | 
			
		||||
    // Check that the block exists in the database.
 | 
			
		||||
    $block = $this->getBlockByLabel($edit['info[0][value]']);
 | 
			
		||||
    $this->assertNotEmpty($block, 'Default Content Block found in database.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Verifies that a transaction rolls back the failed creation.
 | 
			
		||||
   */
 | 
			
		||||
  public function testFailedBlockCreation(): void {
 | 
			
		||||
    // Create a block.
 | 
			
		||||
    try {
 | 
			
		||||
      $this->createBlockContent('fail_creation');
 | 
			
		||||
      $this->fail('Expected exception has not been thrown.');
 | 
			
		||||
    }
 | 
			
		||||
    catch (\Exception) {
 | 
			
		||||
      // Expected exception; just continue testing.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $connection = Database::getConnection();
 | 
			
		||||
 | 
			
		||||
    // Check that the block does not exist in the database.
 | 
			
		||||
    $id = $connection->select('block_content_field_data', 'b')
 | 
			
		||||
      ->fields('b', ['id'])
 | 
			
		||||
      ->condition('info', 'fail_creation')
 | 
			
		||||
      ->execute()
 | 
			
		||||
      ->fetchField();
 | 
			
		||||
    $this->assertFalse($id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests deleting a block.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockDelete(): void {
 | 
			
		||||
    // Create a block.
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = $this->randomMachineName(8);
 | 
			
		||||
    $body = $this->randomMachineName(16);
 | 
			
		||||
    $edit['body[0][value]'] = $body;
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Place the block.
 | 
			
		||||
    $instance = [
 | 
			
		||||
      'id' => mb_strtolower($edit['info[0][value]']),
 | 
			
		||||
      'settings[label]' => $edit['info[0][value]'],
 | 
			
		||||
      'region' => 'sidebar_first',
 | 
			
		||||
    ];
 | 
			
		||||
    $block = BlockContent::load(1);
 | 
			
		||||
    $url = 'admin/structure/block/add/block_content:' . $block->uuid() . '/' . $this->config('system.theme')->get('default');
 | 
			
		||||
    $this->drupalGet($url);
 | 
			
		||||
    $this->submitForm($instance, 'Save block');
 | 
			
		||||
 | 
			
		||||
    $block = BlockContent::load(1);
 | 
			
		||||
 | 
			
		||||
    // Test getInstances method.
 | 
			
		||||
    $this->assertCount(1, $block->getInstances());
 | 
			
		||||
 | 
			
		||||
    // Navigate to home page.
 | 
			
		||||
    $this->drupalGet('');
 | 
			
		||||
    $this->assertSession()->pageTextContains($body);
 | 
			
		||||
 | 
			
		||||
    // Delete the block.
 | 
			
		||||
    $this->drupalGet('admin/content/block/1/delete');
 | 
			
		||||
    $this->assertSession()->pageTextContains('This will also remove 1 placed block instance.');
 | 
			
		||||
 | 
			
		||||
    $this->submitForm([], 'Delete');
 | 
			
		||||
    $this->assertSession()->pageTextContains('The content block ' . $edit['info[0][value]'] . ' has been deleted.');
 | 
			
		||||
 | 
			
		||||
    // Create another block and force the plugin cache to flush.
 | 
			
		||||
    $edit2 = [];
 | 
			
		||||
    $edit2['info[0][value]'] = $this->randomMachineName(8);
 | 
			
		||||
    $body2 = $this->randomMachineName(16);
 | 
			
		||||
    $edit2['body[0][value]'] = $body2;
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit2, 'Save');
 | 
			
		||||
 | 
			
		||||
    $this->assertSession()->responseNotContains('Error message');
 | 
			
		||||
 | 
			
		||||
    // Create another block with no instances, and test we don't get a
 | 
			
		||||
    // confirmation message about deleting instances.
 | 
			
		||||
    $edit3 = [];
 | 
			
		||||
    $edit3['info[0][value]'] = $this->randomMachineName(8);
 | 
			
		||||
    $body = $this->randomMachineName(16);
 | 
			
		||||
    $edit3['body[0][value]'] = $body;
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit3, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Show the delete confirm form.
 | 
			
		||||
    $this->drupalGet('admin/content/block/3/delete');
 | 
			
		||||
    $this->assertSession()->pageTextNotContains('This will also remove');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests placed content blocks create a dependency in the block placement.
 | 
			
		||||
   */
 | 
			
		||||
  public function testConfigDependencies(): void {
 | 
			
		||||
    $block = $this->createBlockContent();
 | 
			
		||||
    // Place the block.
 | 
			
		||||
    $block_placement_id = mb_strtolower($block->label());
 | 
			
		||||
    $instance = [
 | 
			
		||||
      'id' => $block_placement_id,
 | 
			
		||||
      'settings[label]' => $block->label(),
 | 
			
		||||
      'region' => 'sidebar_first',
 | 
			
		||||
    ];
 | 
			
		||||
    $block = BlockContent::load(1);
 | 
			
		||||
    $url = 'admin/structure/block/add/block_content:' . $block->uuid() . '/' . $this->config('system.theme')->get('default');
 | 
			
		||||
    $this->drupalGet($url);
 | 
			
		||||
    $this->submitForm($instance, 'Save block');
 | 
			
		||||
 | 
			
		||||
    $dependencies = \Drupal::service('config.manager')->findConfigEntityDependenciesAsEntities('content', [$block->getConfigDependencyName()]);
 | 
			
		||||
    $block_placement = reset($dependencies);
 | 
			
		||||
    $this->assertEquals($block_placement_id, $block_placement->id(), "The block placement config entity has a dependency on the block content entity.");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Load a block based on the label.
 | 
			
		||||
   */
 | 
			
		||||
  private function getBlockByLabel(string $label): ?BlockContentInterface {
 | 
			
		||||
    $blocks = \Drupal::entityTypeManager()
 | 
			
		||||
      ->getStorage('block_content')
 | 
			
		||||
      ->loadByProperties(['info' => $label]);
 | 
			
		||||
    if (empty($blocks)) {
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    return reset($blocks);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,202 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the listing of content blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * Tests the fallback block content list when Views is disabled.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 * @see \Drupal\block\BlockContentListBuilder
 | 
			
		||||
 * @see \Drupal\block_content\Tests\BlockContentListViewsTest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentListTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with 'access block library' permission.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\UserInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $baseUser1;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with access to create and edit custom basic blocks.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\UserInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $baseUser2;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Permissions to grant admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'administer blocks',
 | 
			
		||||
    'access block library',
 | 
			
		||||
    'create basic block content',
 | 
			
		||||
    'edit any basic block content',
 | 
			
		||||
    'delete any basic block content',
 | 
			
		||||
    'translate configuration',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'config_translation'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->baseUser1 = $this->drupalCreateUser(['access block library']);
 | 
			
		||||
    $this->baseUser2 = $this->drupalCreateUser([
 | 
			
		||||
      'access block library',
 | 
			
		||||
      'create basic block content',
 | 
			
		||||
      'edit any basic block content',
 | 
			
		||||
      'delete any basic block content',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the region value when a new block is saved.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockRegionPlacement(): void {
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser($this->permissions));
 | 
			
		||||
    $this->drupalGet("admin/structure/block/library/stark", ['query' => ['region' => 'content']]);
 | 
			
		||||
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $edit = [
 | 
			
		||||
      'info[0][value]' => 'foo',
 | 
			
		||||
    ];
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
    $this->assertSession()->fieldValueEquals('region', 'content');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the content block listing page with different permissions.
 | 
			
		||||
   */
 | 
			
		||||
  public function testListing(): void {
 | 
			
		||||
    // Test with the admin user.
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser(['access block library', 'administer block content']));
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
 | 
			
		||||
    // Test for the page title.
 | 
			
		||||
    $this->assertSession()->titleEquals('Content blocks | Drupal');
 | 
			
		||||
 | 
			
		||||
    // Test for the table.
 | 
			
		||||
    $this->assertSession()->elementExists('xpath', '//div[@class="layout-content"]//table');
 | 
			
		||||
 | 
			
		||||
    // Test the table header, two cells should be present.
 | 
			
		||||
    $this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/thead/tr/th', 2);
 | 
			
		||||
 | 
			
		||||
    // Test the contents of each th cell.
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[1]', 'Block description');
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[2]', 'Operations');
 | 
			
		||||
 | 
			
		||||
    $label = 'Antelope';
 | 
			
		||||
    $new_label = 'Albatross';
 | 
			
		||||
    // Add a new entity using the operations link.
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = $label;
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Confirm that once the user returns to the listing, the text of the label
 | 
			
		||||
    // (versus elsewhere on the page).
 | 
			
		||||
    $this->assertSession()->elementTextContains('xpath', '//td', $label);
 | 
			
		||||
 | 
			
		||||
    // Check the number of table row cells.
 | 
			
		||||
    $this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/tbody/tr[1]/td', 2);
 | 
			
		||||
    // Check the contents of the row. The first cell contains the label,
 | 
			
		||||
    // and the second contains the operations list.
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/tbody/tr[1]/td[1]', $label);
 | 
			
		||||
 | 
			
		||||
    // Edit the entity using the operations link.
 | 
			
		||||
    $blocks = $this->container
 | 
			
		||||
      ->get('entity_type.manager')
 | 
			
		||||
      ->getStorage('block_content')
 | 
			
		||||
      ->loadByProperties(['info' => $label]);
 | 
			
		||||
    $block = reset($blocks);
 | 
			
		||||
    if (!empty($block)) {
 | 
			
		||||
      $this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id());
 | 
			
		||||
      $this->clickLink('Edit');
 | 
			
		||||
      $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
      $this->assertSession()->titleEquals("Edit content block $label | Drupal");
 | 
			
		||||
      $edit = ['info[0][value]' => $new_label];
 | 
			
		||||
      $this->submitForm($edit, 'Save');
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->fail('Did not find Albatross block in the database.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Confirm that once the user returns to the listing, the text of the label
 | 
			
		||||
    // (versus elsewhere on the page).
 | 
			
		||||
    $this->assertSession()->elementTextContains('xpath', '//td', $new_label);
 | 
			
		||||
 | 
			
		||||
    // Delete the added entity using the operations link.
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id() . '/delete');
 | 
			
		||||
    $this->clickLink('Delete');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->titleEquals("Are you sure you want to delete the content block $new_label? | Drupal");
 | 
			
		||||
    $this->submitForm([], 'Delete');
 | 
			
		||||
 | 
			
		||||
    // Verify that the text of the label and machine name does not appear in
 | 
			
		||||
    // the list (though it may appear elsewhere on the page).
 | 
			
		||||
    $this->assertSession()->elementTextNotContains('xpath', '//td', $new_label);
 | 
			
		||||
 | 
			
		||||
    // Confirm that the empty text is displayed.
 | 
			
		||||
    $this->assertSession()->pageTextContains('There are no content blocks yet.');
 | 
			
		||||
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Non-reusable block',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'reusable' => FALSE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    // Confirm that the empty text is displayed.
 | 
			
		||||
    $this->assertSession()->pageTextContains('There are no content blocks yet.');
 | 
			
		||||
    // Confirm the non-reusable block is not on the page.
 | 
			
		||||
    $this->assertSession()->pageTextNotContains('Non-reusable block');
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogout();
 | 
			
		||||
 | 
			
		||||
    // Create test block for other user tests.
 | 
			
		||||
    $test_block = $this->createBlockContent($label);
 | 
			
		||||
 | 
			
		||||
    // Test as a user with view only permissions.
 | 
			
		||||
    $this->drupalLogin($this->baseUser1);
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->linkNotExists('Add content block');
 | 
			
		||||
    $this->assertSession()->linkByHrefNotExists('admin/content/block/' . $test_block->id());
 | 
			
		||||
    $this->assertSession()->linkByHrefNotExists('admin/content/block/' . $test_block->id() . '/delete');
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogout();
 | 
			
		||||
 | 
			
		||||
    // Test as a user with permission to create/edit/delete basic blocks.
 | 
			
		||||
    $this->drupalLogin($this->baseUser2);
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->linkExists('Add content block');
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id());
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id() . '/delete');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,204 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the Views-powered listing of content blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 * @see \Drupal\block\BlockContentListBuilder
 | 
			
		||||
 * @see \Drupal\block_content\Tests\BlockContentListTest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentListViewsTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with 'access block library' permission.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\UserInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $baseUser1;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A user with access to create and edit custom basic blocks.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\UserInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $baseUser2;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Permissions to grant admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'administer blocks',
 | 
			
		||||
    'access block library',
 | 
			
		||||
    'create basic block content',
 | 
			
		||||
    'edit any basic block content',
 | 
			
		||||
    'delete any basic block content',
 | 
			
		||||
    'translate configuration',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'config_translation',
 | 
			
		||||
    'views',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->baseUser1 = $this->drupalCreateUser(['access block library']);
 | 
			
		||||
    $this->baseUser2 = $this->drupalCreateUser([
 | 
			
		||||
      'access block library',
 | 
			
		||||
      'create basic block content',
 | 
			
		||||
      'edit any basic block content',
 | 
			
		||||
      'delete any basic block content',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the content block listing page.
 | 
			
		||||
   */
 | 
			
		||||
  public function testListing(): void {
 | 
			
		||||
    // Test with an admin user.
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
 | 
			
		||||
    // Test for the page title.
 | 
			
		||||
    $this->assertSession()->titleEquals('Content blocks | Drupal');
 | 
			
		||||
 | 
			
		||||
    // Test for the exposed filters.
 | 
			
		||||
    $this->assertSession()->fieldExists('info');
 | 
			
		||||
    $this->assertSession()->fieldExists('type');
 | 
			
		||||
 | 
			
		||||
    // Test for the table.
 | 
			
		||||
    $this->assertSession()->elementExists('xpath', '//div[@class="layout-content"]//table');
 | 
			
		||||
 | 
			
		||||
    // Test the table header, four cells should be present.
 | 
			
		||||
    $this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/thead/tr/th', 4);
 | 
			
		||||
 | 
			
		||||
    // Test the contents of each th cell.
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[1]', 'Block description');
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[2]', 'Block type');
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[3]', 'Updated Sort ascending');
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/thead/tr/th[4]', 'Operations');
 | 
			
		||||
 | 
			
		||||
    $label = 'Antelope';
 | 
			
		||||
    $new_label = 'Albatross';
 | 
			
		||||
    // Add a new entity using the operations link.
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = $label;
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Confirm that once the user returns to the listing, the text of the label
 | 
			
		||||
    // (versus elsewhere on the page).
 | 
			
		||||
    $this->assertSession()->elementTextContains('xpath', '//td/a', $label);
 | 
			
		||||
 | 
			
		||||
    // Check the number of table row cells.
 | 
			
		||||
    $this->assertSession()->elementsCount('xpath', '//div[@class="layout-content"]//table/tbody/tr/td', 4);
 | 
			
		||||
    // Check the contents of each row cell. The first cell contains the label,
 | 
			
		||||
    // the second contains the machine name, and the third contains the
 | 
			
		||||
    // operations list.
 | 
			
		||||
    $this->assertSession()->elementTextEquals('xpath', '//div[@class="layout-content"]//table/tbody/tr/td/a', $label);
 | 
			
		||||
 | 
			
		||||
    // Edit the entity using the operations link.
 | 
			
		||||
    $blocks = $this->container
 | 
			
		||||
      ->get('entity_type.manager')
 | 
			
		||||
      ->getStorage('block_content')
 | 
			
		||||
      ->loadByProperties(['info' => $label]);
 | 
			
		||||
    $block = reset($blocks);
 | 
			
		||||
    if (!empty($block)) {
 | 
			
		||||
      $this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id());
 | 
			
		||||
      $this->clickLink('Edit');
 | 
			
		||||
      $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
      $this->assertSession()->titleEquals("Edit content block $label | Drupal");
 | 
			
		||||
      $edit = ['info[0][value]' => $new_label];
 | 
			
		||||
      $this->submitForm($edit, 'Save');
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->fail('Did not find Albatross block in the database.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Confirm that once the user returns to the listing, the text of the label
 | 
			
		||||
    // (versus elsewhere on the page).
 | 
			
		||||
    $this->assertSession()->elementTextContains('xpath', '//td/a', $new_label);
 | 
			
		||||
 | 
			
		||||
    // Delete the added entity using the operations link.
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $block->id() . '/delete');
 | 
			
		||||
    $this->clickLink('Delete');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->titleEquals("Are you sure you want to delete the content block $new_label? | Drupal");
 | 
			
		||||
    $this->submitForm([], 'Delete');
 | 
			
		||||
 | 
			
		||||
    // Verify that the text of the label and machine name does not appear in
 | 
			
		||||
    // the list (though it may appear elsewhere on the page).
 | 
			
		||||
    $this->assertSession()->elementTextNotContains('xpath', '//td', $new_label);
 | 
			
		||||
 | 
			
		||||
    // Confirm that the empty text is displayed.
 | 
			
		||||
    $this->assertSession()->pageTextContains('There are no content blocks available.');
 | 
			
		||||
    $this->assertSession()->linkExists('content block');
 | 
			
		||||
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Non-reusable block',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'reusable' => FALSE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    // Confirm that the empty text is displayed.
 | 
			
		||||
    $this->assertSession()->pageTextContains('There are no content blocks available.');
 | 
			
		||||
    // Confirm the non-reusable block is not on the page.
 | 
			
		||||
    $this->assertSession()->pageTextNotContains('Non-reusable block');
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogout();
 | 
			
		||||
 | 
			
		||||
    // Create test block for other user tests.
 | 
			
		||||
    $test_block = $this->createBlockContent($label);
 | 
			
		||||
 | 
			
		||||
    // Test as a user with view only permissions.
 | 
			
		||||
    $this->drupalLogin($this->baseUser1);
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->linkNotExists('Add content block');
 | 
			
		||||
    $matches = $this->xpath('//td[1]');
 | 
			
		||||
    $actual = $matches[0]->getText();
 | 
			
		||||
    $this->assertEquals($label, $actual, 'Label found for test block.');
 | 
			
		||||
    $this->assertSession()->linkNotExists('Edit');
 | 
			
		||||
    $this->assertSession()->linkNotExists('Delete');
 | 
			
		||||
    $this->assertSession()->linkByHrefNotExists('admin/content/block/' . $test_block->id() . '/delete');
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogout();
 | 
			
		||||
 | 
			
		||||
    // Test as a user with permission to create/edit/delete basic blocks.
 | 
			
		||||
    $this->drupalLogin($this->baseUser2);
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->linkExists('Add content block');
 | 
			
		||||
    $matches = $this->xpath('//td/a');
 | 
			
		||||
    $actual = $matches[0]->getText();
 | 
			
		||||
    $this->assertEquals($label, $actual, 'Label found for test block.');
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id());
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $test_block->id() . '/delete');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,40 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a block and test block access by attempting to view the block.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentPageViewTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content_test'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks block edit and fallback functionality.
 | 
			
		||||
   */
 | 
			
		||||
  public function testPageEdit(): void {
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    $block = $this->createBlockContent();
 | 
			
		||||
 | 
			
		||||
    // Attempt to view the block.
 | 
			
		||||
    $this->drupalGet('block-content/' . $block->id());
 | 
			
		||||
 | 
			
		||||
    // Ensure user was able to view the block.
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $this->assertSession()->pageTextContains('This block is broken or missing. You may be missing content or you might need to install the original module.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,96 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Block content revision delete form test.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 * @coversDefaultClass \Drupal\Core\Entity\Form\RevisionDeleteForm
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentRevisionDeleteTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'view any basic block content history',
 | 
			
		||||
    'delete any basic block content revisions',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    $this->drupalPlaceBlock('page_title_block');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests revision delete.
 | 
			
		||||
   */
 | 
			
		||||
  public function testDeleteForm(): void {
 | 
			
		||||
    $entity = $this->createBlockContent(save: FALSE)
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 4pm'))->getTimestamp())
 | 
			
		||||
      ->setRevisionTranslationAffected(TRUE);
 | 
			
		||||
    $entity->setNewRevision();
 | 
			
		||||
    $entity->save();
 | 
			
		||||
    $revisionId = $entity->getRevisionId();
 | 
			
		||||
 | 
			
		||||
    // Cannot delete latest revision.
 | 
			
		||||
    $this->drupalGet($entity->toUrl('revision-delete-form'));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(403);
 | 
			
		||||
 | 
			
		||||
    // Create a new non default revision.
 | 
			
		||||
    $entity
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 5pm'))->getTimestamp())
 | 
			
		||||
      ->setRevisionTranslationAffected(TRUE)
 | 
			
		||||
      ->setNewRevision();
 | 
			
		||||
    $entity->isDefaultRevision(FALSE);
 | 
			
		||||
    $entity->save();
 | 
			
		||||
    $nonDefaultRevisionId = $entity->getRevisionId();
 | 
			
		||||
 | 
			
		||||
    // Reload the default entity.
 | 
			
		||||
    $revision = \Drupal::entityTypeManager()->getStorage('block_content')
 | 
			
		||||
      ->loadRevision($revisionId);
 | 
			
		||||
    // Cannot delete default revision.
 | 
			
		||||
    $this->drupalGet($revision->toUrl('revision-delete-form'));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(403);
 | 
			
		||||
    $this->assertFalse($revision->access('delete revision', $this->adminUser, FALSE));
 | 
			
		||||
 | 
			
		||||
    // Reload the non default entity.
 | 
			
		||||
    $revision2 = \Drupal::entityTypeManager()->getStorage('block_content')
 | 
			
		||||
      ->loadRevision($nonDefaultRevisionId);
 | 
			
		||||
    $this->drupalGet($revision2->toUrl('revision-delete-form'));
 | 
			
		||||
    $this->assertSession()->pageTextContains('Are you sure you want to delete the revision from Sun, 11 Jan 2009 - 17:00?');
 | 
			
		||||
    $this->assertSession()->buttonExists('Delete');
 | 
			
		||||
    $this->assertSession()->linkExists('Cancel');
 | 
			
		||||
    $this->assertTrue($revision2->access('delete revision', $this->adminUser, FALSE));
 | 
			
		||||
 | 
			
		||||
    $countRevisions = static function (): int {
 | 
			
		||||
      return (int) \Drupal::entityTypeManager()->getStorage('block_content')
 | 
			
		||||
        ->getQuery()
 | 
			
		||||
        ->accessCheck(FALSE)
 | 
			
		||||
        ->allRevisions()
 | 
			
		||||
        ->count()
 | 
			
		||||
        ->execute();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $count = $countRevisions();
 | 
			
		||||
    $this->submitForm([], 'Delete');
 | 
			
		||||
    $this->assertEquals($count - 1, $countRevisions());
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->addressEquals(sprintf('admin/content/block/%s/revisions', $entity->id()));
 | 
			
		||||
    $this->assertSession()->pageTextContains(sprintf('Revision from Sun, 11 Jan 2009 - 17:00 of basic %s has been deleted.', $entity->label()));
 | 
			
		||||
    $this->assertSession()->elementsCount('css', 'table tbody tr', 1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,98 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Block content revision form test.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 * @coversDefaultClass \Drupal\Core\Entity\Form\RevisionRevertForm
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentRevisionRevertTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'view any basic block content history',
 | 
			
		||||
    'revert any basic block content revisions',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    $this->drupalPlaceBlock('page_title_block');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests revision revert.
 | 
			
		||||
   */
 | 
			
		||||
  public function testRevertForm(): void {
 | 
			
		||||
    $entity = $this->createBlockContent(save: FALSE)
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 4pm'))->getTimestamp())
 | 
			
		||||
      ->setRevisionTranslationAffected(TRUE);
 | 
			
		||||
    $entity->setNewRevision();
 | 
			
		||||
    $entity->save();
 | 
			
		||||
    $revisionId = $entity->getRevisionId();
 | 
			
		||||
 | 
			
		||||
    // Cannot revert latest revision.
 | 
			
		||||
    $this->drupalGet($entity->toUrl('revision-revert-form'));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(403);
 | 
			
		||||
 | 
			
		||||
    // Create a new non default revision.
 | 
			
		||||
    $entity
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 5pm'))->getTimestamp())
 | 
			
		||||
      ->setRevisionTranslationAffected(TRUE)
 | 
			
		||||
      ->setNewRevision();
 | 
			
		||||
    $entity->isDefaultRevision(FALSE);
 | 
			
		||||
    $entity->save();
 | 
			
		||||
    $nonDefaultRevisionId = $entity->getRevisionId();
 | 
			
		||||
 | 
			
		||||
    // Reload the default entity.
 | 
			
		||||
    $revision = \Drupal::entityTypeManager()->getStorage('block_content')
 | 
			
		||||
      ->loadRevision($revisionId);
 | 
			
		||||
    // Cannot revert default revision.
 | 
			
		||||
    $this->drupalGet($revision->toUrl('revision-revert-form'));
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(403);
 | 
			
		||||
    $this->assertFalse($revision->access('revert', $this->adminUser, FALSE));
 | 
			
		||||
 | 
			
		||||
    // Reload the non default entity.
 | 
			
		||||
    $revision2 = \Drupal::entityTypeManager()->getStorage('block_content')
 | 
			
		||||
      ->loadRevision($nonDefaultRevisionId);
 | 
			
		||||
    $this->drupalGet($revision2->toUrl('revision-revert-form'));
 | 
			
		||||
    $this->assertSession()->pageTextContains('Are you sure you want to revert to the revision from Sun, 11 Jan 2009 - 17:00?');
 | 
			
		||||
    $this->assertSession()->buttonExists('Revert');
 | 
			
		||||
    $this->assertSession()->linkExists('Cancel');
 | 
			
		||||
    $this->assertTrue($revision2->access('revert', $this->adminUser, FALSE));
 | 
			
		||||
 | 
			
		||||
    $countRevisions = static function (): int {
 | 
			
		||||
      return (int) \Drupal::entityTypeManager()->getStorage('block_content')
 | 
			
		||||
        ->getQuery()
 | 
			
		||||
        ->accessCheck(FALSE)
 | 
			
		||||
        ->allRevisions()
 | 
			
		||||
        ->count()
 | 
			
		||||
        ->execute();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $count = $countRevisions();
 | 
			
		||||
    $this->submitForm([], 'Revert');
 | 
			
		||||
    $this->assertEquals($count + 1, $countRevisions());
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->addressEquals(sprintf('admin/content/block/%s/revisions', $entity->id()));
 | 
			
		||||
    $this->assertSession()->pageTextContains(sprintf('basic %s has been reverted to the revision from Sun, 11 Jan 2009 - 17:00.', $entity->label()));
 | 
			
		||||
    // Three rows, from the top: the newly reverted revision, the revision from
 | 
			
		||||
    // 5pm, and the revision from 4pm.
 | 
			
		||||
    $this->assertSession()->elementsCount('css', 'table tbody tr', 3);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,94 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Block content version history test.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 * @coversDefaultClass \Drupal\Core\Entity\Controller\VersionHistoryController
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentRevisionVersionHistoryTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'view any basic block content history',
 | 
			
		||||
    'revert any basic block content revisions',
 | 
			
		||||
    'delete any basic block content revisions',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests version history page.
 | 
			
		||||
   */
 | 
			
		||||
  public function testVersionHistory(): void {
 | 
			
		||||
    $entity = $this->createBlockContent(save: FALSE);
 | 
			
		||||
 | 
			
		||||
    $entity
 | 
			
		||||
      ->setInfo('first revision')
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('1st June 2020 7am'))->getTimestamp())
 | 
			
		||||
      ->setRevisionLogMessage('first revision log')
 | 
			
		||||
      ->setRevisionUser($this->drupalCreateUser(name: 'first author'))
 | 
			
		||||
      ->setNewRevision();
 | 
			
		||||
    $entity->save();
 | 
			
		||||
 | 
			
		||||
    $entity
 | 
			
		||||
      ->setInfo('second revision')
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('2nd June 2020 8am'))->getTimestamp())
 | 
			
		||||
      ->setRevisionLogMessage('second revision log')
 | 
			
		||||
      ->setRevisionUser($this->drupalCreateUser(name: 'second author'))
 | 
			
		||||
      ->setNewRevision();
 | 
			
		||||
    $entity->save();
 | 
			
		||||
 | 
			
		||||
    $entity
 | 
			
		||||
      ->setInfo('third revision')
 | 
			
		||||
      ->setRevisionCreationTime((new \DateTimeImmutable('3rd June 2020 9am'))->getTimestamp())
 | 
			
		||||
      ->setRevisionLogMessage('third revision log')
 | 
			
		||||
      ->setRevisionUser($this->drupalCreateUser(name: 'third author'))
 | 
			
		||||
      ->setNewRevision();
 | 
			
		||||
    $entity->save();
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet($entity->toUrl('version-history'));
 | 
			
		||||
    $this->assertSession()->elementsCount('css', 'table tbody tr', 3);
 | 
			
		||||
 | 
			
		||||
    // Order is newest to oldest revision by creation order.
 | 
			
		||||
    $row1 = $this->assertSession()->elementExists('css', 'table tbody tr:nth-child(1)');
 | 
			
		||||
    // Latest revision does not have revert or delete revision operation.
 | 
			
		||||
    $this->assertSession()->elementNotExists('named', ['link', 'Revert'], $row1);
 | 
			
		||||
    $this->assertSession()->elementNotExists('named', ['link', 'Delete'], $row1);
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(1)', 'Current revision');
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(1)', 'third revision log');
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(1)', '3 Jun 2020 - 09:00 by third author');
 | 
			
		||||
 | 
			
		||||
    $row2 = $this->assertSession()->elementExists('css', 'table tbody tr:nth-child(2)');
 | 
			
		||||
    $this->assertSession()->elementExists('named', ['link', 'Revert'], $row2);
 | 
			
		||||
    $this->assertSession()->elementExists('named', ['link', 'Delete'], $row2);
 | 
			
		||||
    $this->assertSession()->elementTextNotContains('css', 'table tbody tr:nth-child(2)', 'Current revision');
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(2)', 'second revision log');
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(2)', '2 Jun 2020 - 08:00 by second author');
 | 
			
		||||
 | 
			
		||||
    $row3 = $this->assertSession()->elementExists('css', 'table tbody tr:nth-child(3)');
 | 
			
		||||
    $this->assertSession()->elementExists('named', ['link', 'Revert'], $row3);
 | 
			
		||||
    $this->assertSession()->elementExists('named', ['link', 'Delete'], $row3);
 | 
			
		||||
    $this->assertSession()->elementTextNotContains('css', 'table tbody tr:nth-child(2)', 'Current revision');
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(3)', 'first revision log');
 | 
			
		||||
    $this->assertSession()->elementTextContains('css', 'table tbody tr:nth-child(3)', '1 Jun 2020 - 07:00 by first author');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,112 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests $block_content->save() for saving content.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentSaveTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content_test'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the test up.
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks whether content block IDs are saved properly during an import.
 | 
			
		||||
   */
 | 
			
		||||
  public function testImport(): void {
 | 
			
		||||
    // Content block ID must be a number that is not in the database.
 | 
			
		||||
    $max_id = (int) \Drupal::entityQueryAggregate('block_content')
 | 
			
		||||
      ->accessCheck(FALSE)
 | 
			
		||||
      ->aggregate('id', 'max')
 | 
			
		||||
      ->execute()[0]['id_max'];
 | 
			
		||||
    $test_id = $max_id + mt_rand(1000, 1000000);
 | 
			
		||||
    $info = $this->randomMachineName(8);
 | 
			
		||||
    $block_array = [
 | 
			
		||||
      'info' => $info,
 | 
			
		||||
      'body' => ['value' => $this->randomMachineName(32)],
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'id' => $test_id,
 | 
			
		||||
    ];
 | 
			
		||||
    $block = BlockContent::create($block_array);
 | 
			
		||||
    $block->enforceIsNew(TRUE);
 | 
			
		||||
    $block->save();
 | 
			
		||||
 | 
			
		||||
    // Verify that block_submit did not wipe the provided id.
 | 
			
		||||
    $this->assertEquals($test_id, $block->id(), 'Block imported using provide id');
 | 
			
		||||
 | 
			
		||||
    // Test the import saved.
 | 
			
		||||
    $block_by_id = BlockContent::load($test_id);
 | 
			
		||||
    $this->assertNotEmpty($block_by_id, 'Content block load by block ID.');
 | 
			
		||||
    $this->assertSame($block_array['body']['value'], $block_by_id->body->value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests determining changes in hook_block_presave().
 | 
			
		||||
   *
 | 
			
		||||
   * Verifies the static block load cache is cleared upon save.
 | 
			
		||||
   */
 | 
			
		||||
  public function testDeterminingChanges(): void {
 | 
			
		||||
    // Initial creation.
 | 
			
		||||
    $block = $this->createBlockContent('test_changes');
 | 
			
		||||
    // Creating a block should set the changed date to the current time
 | 
			
		||||
    // which is always greater than the time set by hooks we're testing.
 | 
			
		||||
    $this->assertGreaterThan(979534800, $block->getChangedTime(), 'Creating a block sets default "changed" timestamp.');
 | 
			
		||||
 | 
			
		||||
    // Update the block without applying changes.
 | 
			
		||||
    $block->save();
 | 
			
		||||
    $this->assertEquals('test_changes', $block->label(), 'No changes have been determined.');
 | 
			
		||||
 | 
			
		||||
    // Apply changes.
 | 
			
		||||
    $block->setInfo('updated');
 | 
			
		||||
    $block->save();
 | 
			
		||||
 | 
			
		||||
    // The hook implementations block_content_test_block_content_presave() and
 | 
			
		||||
    // block_content_test_block_content_update() determine changes and change
 | 
			
		||||
    // the title as well as programmatically set the 'changed' timestamp.
 | 
			
		||||
    $this->assertEquals('updated_presave_update', $block->label(), 'Changes have been determined.');
 | 
			
		||||
    $this->assertEquals(979534800, $block->getChangedTime(), 'Saving a content block uses "changed" timestamp set in presave hook.');
 | 
			
		||||
 | 
			
		||||
    // Test the static block load cache to be cleared.
 | 
			
		||||
    $block = BlockContent::load($block->id());
 | 
			
		||||
    $this->assertEquals('updated_presave', $block->label(), 'Static cache has been cleared.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests saving a block on block insert.
 | 
			
		||||
   *
 | 
			
		||||
   * This test ensures that a block has been fully saved when
 | 
			
		||||
   * hook_block_content_insert() is invoked, so that the block can be saved
 | 
			
		||||
   * again in a hook implementation without errors.
 | 
			
		||||
   *
 | 
			
		||||
   * @see block_test_block_insert()
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentSaveOnInsert(): void {
 | 
			
		||||
    // block_content_test_block_content_insert() triggers a save on insert if
 | 
			
		||||
    // the title equals 'new'.
 | 
			
		||||
    $block = $this->createBlockContent('new');
 | 
			
		||||
    $this->assertEquals('BlockContent ' . $block->id(), $block->label(), 'Content block saved on block insert.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,143 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sets up block content types.
 | 
			
		||||
 */
 | 
			
		||||
abstract class BlockContentTestBase extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Profile to use.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  protected $profile = 'testing';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\UserInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $adminUser;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Permissions to grant admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'administer blocks',
 | 
			
		||||
    'access block library',
 | 
			
		||||
    'administer block types',
 | 
			
		||||
    'administer block content',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether or not to auto-create the basic block type during setup.
 | 
			
		||||
   *
 | 
			
		||||
   * @var bool
 | 
			
		||||
   */
 | 
			
		||||
  protected $autoCreateBasicBlockType = TRUE;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sets the test up.
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    if ($this->autoCreateBasicBlockType) {
 | 
			
		||||
      $this->createBlockContentType(['id' => 'basic'], TRUE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $this->adminUser = $this->drupalCreateUser($this->permissions);
 | 
			
		||||
    $this->drupalPlaceBlock('local_actions_block');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a content block.
 | 
			
		||||
   *
 | 
			
		||||
   * @param bool|string $title
 | 
			
		||||
   *   (optional) Title of block. When no value is given uses a random name.
 | 
			
		||||
   *   Defaults to FALSE.
 | 
			
		||||
   * @param string $bundle
 | 
			
		||||
   *   (optional) Bundle name. Defaults to 'basic'.
 | 
			
		||||
   * @param bool $save
 | 
			
		||||
   *   (optional) Whether to save the block. Defaults to TRUE.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\block_content\Entity\BlockContent
 | 
			
		||||
   *   Created content block.
 | 
			
		||||
   */
 | 
			
		||||
  protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) {
 | 
			
		||||
    $title = $title ?: $this->randomMachineName();
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => $title,
 | 
			
		||||
      'type' => $bundle,
 | 
			
		||||
      'langcode' => 'en',
 | 
			
		||||
    ]);
 | 
			
		||||
    if ($block_content && $save === TRUE) {
 | 
			
		||||
      $block_content->save();
 | 
			
		||||
    }
 | 
			
		||||
    return $block_content;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a block type (bundle).
 | 
			
		||||
   *
 | 
			
		||||
   * @param array|string $values
 | 
			
		||||
   *   (deprecated) The variable $values as string is deprecated. Provide as an
 | 
			
		||||
   *   array as parameter. The value to create the block content type. If
 | 
			
		||||
   *   $values is an array it should be like: ['id' => 'foo', 'label' => 'Foo'].
 | 
			
		||||
   *   If $values is a string, it will be considered that it represents the
 | 
			
		||||
   *   label.
 | 
			
		||||
   * @param bool $create_body
 | 
			
		||||
   *   Whether or not to create the body field.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\block_content\Entity\BlockContentType
 | 
			
		||||
   *   Created block type.
 | 
			
		||||
   */
 | 
			
		||||
  protected function createBlockContentType($values, $create_body = FALSE) {
 | 
			
		||||
    if (is_string($values)) {
 | 
			
		||||
      @trigger_error('Using the variable $values as string is deprecated in drupal:11.1.0 and is removed from drupal:12.0.0. Provide an array as parameter. See https://www.drupal.org/node/3473739', E_USER_DEPRECATED);
 | 
			
		||||
    }
 | 
			
		||||
    if (is_array($values)) {
 | 
			
		||||
      if (!isset($values['id'])) {
 | 
			
		||||
        do {
 | 
			
		||||
          $id = $this->randomMachineName(8);
 | 
			
		||||
        } while (BlockContentType::load($id));
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        $id = $values['id'];
 | 
			
		||||
      }
 | 
			
		||||
      $values += [
 | 
			
		||||
        'id' => $id,
 | 
			
		||||
        'label' => $id,
 | 
			
		||||
        'revision' => FALSE,
 | 
			
		||||
      ];
 | 
			
		||||
      $bundle = BlockContentType::create($values);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $bundle = BlockContentType::create([
 | 
			
		||||
        'id' => $values,
 | 
			
		||||
        'label' => $values,
 | 
			
		||||
        'revision' => FALSE,
 | 
			
		||||
      ]);
 | 
			
		||||
    }
 | 
			
		||||
    $bundle->save();
 | 
			
		||||
    if ($create_body) {
 | 
			
		||||
      block_content_add_body_field($bundle->id());
 | 
			
		||||
    }
 | 
			
		||||
    return $bundle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,92 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests block content theme suggestions.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentThemeSuggestionsTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Path prefix for the field UI for the test bundle.
 | 
			
		||||
   *
 | 
			
		||||
   * @var string
 | 
			
		||||
   */
 | 
			
		||||
  const FIELD_UI_PREFIX = 'admin/structure/types/manage/bundle_with_extra_field';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The UUID for a block content entity.
 | 
			
		||||
   */
 | 
			
		||||
  protected string $uuid = 'b22c881a-bcfd-4d0c-a41d-3573327705df';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'field_ui',
 | 
			
		||||
    'layout_builder',
 | 
			
		||||
    'node',
 | 
			
		||||
    'block_content_theme_suggestions_test',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    // Create a block with a known UUID.
 | 
			
		||||
    $block = $this->createBlockContent('Example block!', 'basic', FALSE);
 | 
			
		||||
    $block->set('uuid', $this->uuid);
 | 
			
		||||
    $block->save();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test suggestions for content blocks.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentThemeSuggestionsContent(): void {
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    $this->drupalPlaceBlock('block_content:' . $this->uuid);
 | 
			
		||||
    $this->drupalGet('');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->pageTextContains('Example block!');
 | 
			
		||||
    $this->assertSession()->pageTextContainsOnce('I am a block content template for a specific bundle and view mode!');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test suggestions for content blocks within extra fields blocks.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentThemeSuggestionsExtraField(): void {
 | 
			
		||||
    // Extra field blocks are a block plugin provided by layout builder, so
 | 
			
		||||
    // enable layouts for the test bundle and view a node of that bundle.
 | 
			
		||||
    // A test module injects an extra field referencing a block content entity.
 | 
			
		||||
    // @see block_content_theme_suggestions_test.module
 | 
			
		||||
    // @see \Drupal\block_content_theme_suggestions_test\Hook\BlockContentThemeSuggestionsTestHooks
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser([
 | 
			
		||||
      'configure any layout',
 | 
			
		||||
      'administer node display',
 | 
			
		||||
    ]));
 | 
			
		||||
    $this->createContentType(['type' => 'bundle_with_extra_field']);
 | 
			
		||||
    $this->drupalGet(static::FIELD_UI_PREFIX . '/display/default');
 | 
			
		||||
    $this->submitForm(['layout[enabled]' => TRUE], 'Save');
 | 
			
		||||
    $node = $this->createNode([
 | 
			
		||||
      'type' => 'bundle_with_extra_field',
 | 
			
		||||
      'title' => 'The first node title',
 | 
			
		||||
    ]);
 | 
			
		||||
    $node->save();
 | 
			
		||||
    $this->drupalGet('/node/' . $node->id());
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->pageTextContains('Example block!');
 | 
			
		||||
    $this->assertSession()->pageTextContains('I am a block content template for a specific bundle and view mode!');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,157 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the block content translation UI.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTranslationUITest extends ContentTranslationUITestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'language',
 | 
			
		||||
    'content_translation',
 | 
			
		||||
    'block',
 | 
			
		||||
    'field_ui',
 | 
			
		||||
    'block_content',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultCacheContexts = [
 | 
			
		||||
    'languages:language_interface',
 | 
			
		||||
    'session',
 | 
			
		||||
    'theme',
 | 
			
		||||
    'url.path',
 | 
			
		||||
    'url.query_args',
 | 
			
		||||
    'user.permissions',
 | 
			
		||||
    'user.roles:authenticated',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    $this->entityTypeId = 'block_content';
 | 
			
		||||
    $this->bundle = 'basic';
 | 
			
		||||
    $this->testLanguageSelector = FALSE;
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->doSetup();
 | 
			
		||||
 | 
			
		||||
    $this->drupalPlaceBlock('page_title_block');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setupBundle(): void {
 | 
			
		||||
    // Create the basic bundle since it is provided by standard.
 | 
			
		||||
    $bundle = BlockContentType::create([
 | 
			
		||||
      'id' => $this->bundle,
 | 
			
		||||
      'label' => $this->bundle,
 | 
			
		||||
      'revision' => FALSE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $bundle->save();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function getTranslatorPermissions() {
 | 
			
		||||
    return array_merge(parent::getTranslatorPermissions(), [
 | 
			
		||||
      'translate any entity',
 | 
			
		||||
      'access administration pages',
 | 
			
		||||
      'administer blocks',
 | 
			
		||||
      'administer block_content fields',
 | 
			
		||||
      'access block library',
 | 
			
		||||
      'create basic block content',
 | 
			
		||||
      'edit any basic block content',
 | 
			
		||||
      'delete any basic block content',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getNewEntityValues($langcode) {
 | 
			
		||||
    return ['info' => $this->randomMachineName()] + parent::getNewEntityValues($langcode);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns an edit array containing the values to be posted.
 | 
			
		||||
   */
 | 
			
		||||
  protected function getEditValues($values, $langcode, $new = FALSE) {
 | 
			
		||||
    $edit = parent::getEditValues($values, $langcode, $new);
 | 
			
		||||
    foreach ($edit as $property => $value) {
 | 
			
		||||
      if ($property == 'info') {
 | 
			
		||||
        $edit['info[0][value]'] = $value;
 | 
			
		||||
        unset($edit[$property]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $edit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function doTestBasicTranslation(): void {
 | 
			
		||||
    parent::doTestBasicTranslation();
 | 
			
		||||
 | 
			
		||||
    // Ensure that a block translation can be created using the same description
 | 
			
		||||
    // as in the original language.
 | 
			
		||||
    $default_langcode = $this->langcodes[0];
 | 
			
		||||
    $values = $this->getNewEntityValues($default_langcode);
 | 
			
		||||
    $storage = \Drupal::entityTypeManager()->getStorage($this->entityTypeId);
 | 
			
		||||
    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
 | 
			
		||||
    $entity = $storage->create(['type' => 'basic'] + $values);
 | 
			
		||||
    $entity->save();
 | 
			
		||||
    $entity->addTranslation('it', $values);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      $entity->save();
 | 
			
		||||
    }
 | 
			
		||||
    catch (\Exception) {
 | 
			
		||||
      $this->fail('Blocks can have translations with the same "info" value.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check that the translate operation link is shown.
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    $this->assertSession()->linkByHrefExists('admin/content/block/' . $entity->id() . '/translations');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function doTestTranslationEdit(): void {
 | 
			
		||||
    $storage = $this->container->get('entity_type.manager')
 | 
			
		||||
      ->getStorage($this->entityTypeId);
 | 
			
		||||
    $entity = $storage->load($this->entityId);
 | 
			
		||||
    $languages = $this->container->get('language_manager')->getLanguages();
 | 
			
		||||
 | 
			
		||||
    foreach ($this->langcodes as $langcode) {
 | 
			
		||||
      // We only want to test the title for non-english translations.
 | 
			
		||||
      if ($langcode != 'en') {
 | 
			
		||||
        $options = ['language' => $languages[$langcode]];
 | 
			
		||||
        $url = $entity->toUrl('edit-form', $options);
 | 
			
		||||
        $this->drupalGet($url);
 | 
			
		||||
        $this->assertSession()->pageTextContains("Edit {$entity->bundle()} {$entity->getTranslation($langcode)->label()} [{$languages[$langcode]->getName()} translation]");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,266 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Component\Utility\Html;
 | 
			
		||||
use Drupal\Core\Url;
 | 
			
		||||
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Ensures that block type functions work correctly.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  use AssertBreadcrumbTrait;
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['field_ui'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Permissions to grant admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'administer block content',
 | 
			
		||||
    'administer blocks',
 | 
			
		||||
    'administer block_content fields',
 | 
			
		||||
    'administer block types',
 | 
			
		||||
    'administer block content',
 | 
			
		||||
    'access block library',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether or not to create an initial block type.
 | 
			
		||||
   *
 | 
			
		||||
   * @var bool
 | 
			
		||||
   */
 | 
			
		||||
  protected $autoCreateBasicBlockType = FALSE;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $this->drupalPlaceBlock('page_title_block');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the order of the block content types on the add page.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentAddPageOrder(): void {
 | 
			
		||||
    $this->createBlockContentType(['id' => 'bundle_1', 'label' => 'Bundle 1']);
 | 
			
		||||
    $this->createBlockContentType(['id' => 'bundle_2', 'label' => 'Aaa Bundle 2']);
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    $this->drupalGet('block/add');
 | 
			
		||||
    $this->assertSession()->pageTextMatches('/Aaa Bundle 2(.*)Bundle 1/');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests creating a block type programmatically and via a form.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentTypeCreation(): void {
 | 
			
		||||
    // Log in a test user.
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
 | 
			
		||||
    // Test the page with no block-types.
 | 
			
		||||
    $this->drupalGet('block/add');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->pageTextContains('You have not created any block types yet');
 | 
			
		||||
    $this->clickLink('block type creation page');
 | 
			
		||||
 | 
			
		||||
    // Create a block type via the user interface.
 | 
			
		||||
    $edit = [
 | 
			
		||||
      'id' => 'foo',
 | 
			
		||||
      'label' => 'title for foo',
 | 
			
		||||
    ];
 | 
			
		||||
    $this->submitForm($edit, 'Save and manage fields');
 | 
			
		||||
 | 
			
		||||
    // Asserts that form submit redirects to the expected manage fields page.
 | 
			
		||||
    $this->assertSession()->addressEquals('admin/structure/block-content/manage/' . $edit['id'] . '/fields');
 | 
			
		||||
 | 
			
		||||
    $block_type = BlockContentType::load('foo');
 | 
			
		||||
    $this->assertInstanceOf(BlockContentType::class, $block_type);
 | 
			
		||||
 | 
			
		||||
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'foo');
 | 
			
		||||
    $this->assertTrue(isset($field_definitions['body']), 'Body field created when using the UI to create block content types.');
 | 
			
		||||
 | 
			
		||||
    // Check that the block type was created in site default language.
 | 
			
		||||
    $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
 | 
			
		||||
    $this->assertEquals($block_type->language()->getId(), $default_langcode);
 | 
			
		||||
 | 
			
		||||
    // Create block types programmatically.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'basic'], TRUE);
 | 
			
		||||
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'basic');
 | 
			
		||||
    $this->assertTrue(isset($field_definitions['body']), "Body field for 'basic' block type created when using the testing API to create block content types.");
 | 
			
		||||
 | 
			
		||||
    $this->createBlockContentType(['id' => 'other']);
 | 
			
		||||
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'other');
 | 
			
		||||
    $this->assertFalse(isset($field_definitions['body']), "Body field for 'other' block type not created when using the testing API to create block content types.");
 | 
			
		||||
 | 
			
		||||
    $block_type = BlockContentType::load('other');
 | 
			
		||||
    $this->assertInstanceOf(BlockContentType::class, $block_type);
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('block/add/' . $block_type->id());
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests editing a block type using the UI.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentTypeEditing(): void {
 | 
			
		||||
    $this->drupalPlaceBlock('system_breadcrumb_block');
 | 
			
		||||
    // Now create an initial block-type.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'basic'], TRUE);
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    // We need two block types to prevent /block/add redirecting.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'other']);
 | 
			
		||||
 | 
			
		||||
    $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('block_content', 'other');
 | 
			
		||||
    $this->assertFalse(isset($field_definitions['body']), 'Body field was not created when using the API to create block content types.');
 | 
			
		||||
 | 
			
		||||
    // Verify that title and body fields are displayed.
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Block description');
 | 
			
		||||
    $this->assertNotEmpty($this->cssSelect('#edit-body-0-value'), 'Body field was found.');
 | 
			
		||||
 | 
			
		||||
    // Change the block type name.
 | 
			
		||||
    $edit = [
 | 
			
		||||
      'label' => 'Bar',
 | 
			
		||||
    ];
 | 
			
		||||
    $this->drupalGet('admin/structure/block-content/manage/basic');
 | 
			
		||||
    $this->assertSession()->titleEquals('Edit basic block type | Drupal');
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
    $front_page_path = Url::fromRoute('<front>')->toString();
 | 
			
		||||
    $this->assertBreadcrumb('admin/structure/block-content/manage/basic/fields', [
 | 
			
		||||
      $front_page_path => 'Home',
 | 
			
		||||
      'admin/structure/block-content' => 'Block types',
 | 
			
		||||
      'admin/structure/block-content/manage/basic' => 'Edit Bar',
 | 
			
		||||
    ]);
 | 
			
		||||
    \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('block/add');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Bar');
 | 
			
		||||
    $this->clickLink('Bar');
 | 
			
		||||
    // Verify that the original machine name was used in the URL.
 | 
			
		||||
    $this->assertSession()->addressEquals(Url::fromRoute('block_content.add_form', ['block_content_type' => 'basic']));
 | 
			
		||||
 | 
			
		||||
    // Remove the body field.
 | 
			
		||||
    $this->drupalGet('admin/structure/block-content/manage/basic/fields/block_content.basic.body/delete');
 | 
			
		||||
    $this->submitForm([], 'Delete');
 | 
			
		||||
    // Resave the settings for this type.
 | 
			
		||||
    $this->drupalGet('admin/structure/block-content/manage/basic');
 | 
			
		||||
    $this->submitForm([], 'Save');
 | 
			
		||||
    // Check that the body field doesn't exist.
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->assertEmpty($this->cssSelect('#edit-body-0-value'), 'Body field was not found.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests deleting a block type that still has content.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentTypeDeletion(): void {
 | 
			
		||||
    // Now create an initial block-type.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'basic'], TRUE);
 | 
			
		||||
 | 
			
		||||
    // Create a block type programmatically.
 | 
			
		||||
    $type = $this->createBlockContentType(['id' => 'foo']);
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
 | 
			
		||||
    // Add a new block of this type.
 | 
			
		||||
    $block = $this->createBlockContent(FALSE, 'foo');
 | 
			
		||||
    // Attempt to delete the block type, which should not be allowed.
 | 
			
		||||
    $this->drupalGet('admin/structure/block-content/manage/' . $type->id() . '/delete');
 | 
			
		||||
    $this->assertSession()->pageTextContains($type->label() . ' is used by 1 content block on your site. You can not remove this block type until you have removed all of the ' . $type->label() . ' blocks.');
 | 
			
		||||
    $this->assertSession()->pageTextNotContains('This action cannot be undone.');
 | 
			
		||||
 | 
			
		||||
    // Delete the block.
 | 
			
		||||
    $block->delete();
 | 
			
		||||
    // Attempt to delete the block type, which should now be allowed.
 | 
			
		||||
    $this->drupalGet('admin/structure/block-content/manage/' . $type->id() . '/delete');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Are you sure you want to delete the block type ' . $type->id() . '?');
 | 
			
		||||
    $this->assertSession()->pageTextContains('This action cannot be undone.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests that redirects work as expected when multiple block types exist.
 | 
			
		||||
   */
 | 
			
		||||
  public function testsBlockContentAddTypes(): void {
 | 
			
		||||
    // Now create an initial block-type.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'basic'], TRUE);
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
    // Create two block types programmatically.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'foo']);
 | 
			
		||||
    $this->createBlockContentType(['id' => 'bar']);
 | 
			
		||||
 | 
			
		||||
    // Get the content block storage.
 | 
			
		||||
    $storage = $this->container
 | 
			
		||||
      ->get('entity_type.manager')
 | 
			
		||||
      ->getStorage('block_content');
 | 
			
		||||
 | 
			
		||||
    // Install all themes.
 | 
			
		||||
    $themes = ['olivero', 'stark', 'claro'];
 | 
			
		||||
    \Drupal::service('theme_installer')->install($themes);
 | 
			
		||||
    $theme_settings = $this->config('system.theme');
 | 
			
		||||
    foreach ($themes as $default_theme) {
 | 
			
		||||
      // Change the default theme.
 | 
			
		||||
      $theme_settings->set('default', $default_theme)->save();
 | 
			
		||||
      $this->drupalPlaceBlock('local_actions_block');
 | 
			
		||||
 | 
			
		||||
      // For each installed theme, go to its block page and test the redirects.
 | 
			
		||||
      foreach ($themes as $theme) {
 | 
			
		||||
        // Test that adding a block from the 'place blocks' form sends you to
 | 
			
		||||
        // the block configure form.
 | 
			
		||||
        $path = $theme == $default_theme ? 'admin/structure/block' : "admin/structure/block/list/$theme";
 | 
			
		||||
        $this->drupalGet($path);
 | 
			
		||||
        $this->clickLink('Place block');
 | 
			
		||||
        $this->clickLink('Add content block');
 | 
			
		||||
        $this->clickLink('foo');
 | 
			
		||||
        // Create a new block.
 | 
			
		||||
        $edit = ['info[0][value]' => $this->randomMachineName(8)];
 | 
			
		||||
        $this->submitForm($edit, 'Save and configure');
 | 
			
		||||
        $blocks = $storage->loadByProperties(['info' => $edit['info[0][value]']]);
 | 
			
		||||
        if (!empty($blocks)) {
 | 
			
		||||
          $block = reset($blocks);
 | 
			
		||||
          $this->assertSession()->addressEquals(Url::fromRoute('block.admin_add', ['plugin_id' => 'block_content:' . $block->uuid(), 'theme' => $theme]));
 | 
			
		||||
          $this->submitForm(['region' => 'content'], 'Save block');
 | 
			
		||||
          $this->assertSession()->addressEquals(Url::fromRoute('block.admin_display_theme', ['theme' => $theme], ['query' => ['block-placement' => $theme . '-' . Html::getClass($edit['info[0][value]'])]]));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          $this->fail('Could not load created block.');
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test that adding a block from the 'content blocks list' doesn't send you
 | 
			
		||||
    // to the block configure form.
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->clickLink('foo');
 | 
			
		||||
    $edit = ['info[0][value]' => $this->randomMachineName(8)];
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
    $blocks = $storage->loadByProperties(['info' => $edit['info[0][value]']]);
 | 
			
		||||
    if (!empty($blocks)) {
 | 
			
		||||
      $this->assertSession()->addressEquals(Url::fromRoute('entity.block_content.collection'));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $this->fail('Could not load created block.');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\system\Functional\Module\GenericModuleTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generic module test for block_content.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class GenericTest extends GenericModuleTestBase {}
 | 
			
		||||
@ -0,0 +1,53 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests block_content local action links.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class LocalActionTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the block_content_add_action link.
 | 
			
		||||
   */
 | 
			
		||||
  public function testAddContentBlockLink(): void {
 | 
			
		||||
    // Verify that the link takes you straight to the block form if there's only
 | 
			
		||||
    // one type.
 | 
			
		||||
    $this->drupalGet('/admin/content/block');
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->addressEquals('/block/add/basic');
 | 
			
		||||
 | 
			
		||||
    $type = $this->randomMachineName();
 | 
			
		||||
    $this->createBlockContentType([
 | 
			
		||||
      'id' => $type,
 | 
			
		||||
      'label' => $type,
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // Verify that the link takes you to the block add page if there's more than
 | 
			
		||||
    // one type.
 | 
			
		||||
    $this->drupalGet('/admin/content/block');
 | 
			
		||||
    $this->clickLink('Add content block');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertSession()->addressEquals('/block/add');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,97 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a block and test block edit functionality.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class PageEditTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  use AssertBreadcrumbTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $this->drupalPlaceBlock('page_title_block');
 | 
			
		||||
    $this->drupalPlaceBlock('system_breadcrumb_block');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks block edit functionality.
 | 
			
		||||
   */
 | 
			
		||||
  public function testPageEdit(): void {
 | 
			
		||||
    $this->drupalLogin($this->adminUser);
 | 
			
		||||
 | 
			
		||||
    $title_key = 'info[0][value]';
 | 
			
		||||
    $body_key = 'body[0][value]';
 | 
			
		||||
    // Create block to edit.
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = $this->randomMachineName(8);
 | 
			
		||||
    $edit[$body_key] = $this->randomMachineName(16);
 | 
			
		||||
    $this->drupalGet('block/add/basic');
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Check that the block exists in the database.
 | 
			
		||||
    $blocks = \Drupal::entityQuery('block_content')
 | 
			
		||||
      ->accessCheck(FALSE)
 | 
			
		||||
      ->condition('info', $edit['info[0][value]'])
 | 
			
		||||
      ->execute();
 | 
			
		||||
    $block = BlockContent::load(reset($blocks));
 | 
			
		||||
    $this->assertNotEmpty($block, 'Content block found in database.');
 | 
			
		||||
 | 
			
		||||
    // Load the edit page.
 | 
			
		||||
    $this->drupalGet('admin/content/block/' . $block->id());
 | 
			
		||||
    $this->assertSession()->fieldValueEquals($title_key, $edit[$title_key]);
 | 
			
		||||
    $this->assertSession()->fieldValueEquals($body_key, $edit[$body_key]);
 | 
			
		||||
 | 
			
		||||
    // Edit the content of the block.
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit[$title_key] = $this->randomMachineName(8);
 | 
			
		||||
    $edit[$body_key] = $this->randomMachineName(16);
 | 
			
		||||
    // Stay on the current page, without reloading.
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Edit the same block, creating a new revision.
 | 
			
		||||
    $this->drupalGet("admin/content/block/" . $block->id());
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = $this->randomMachineName(8);
 | 
			
		||||
    $edit[$body_key] = $this->randomMachineName(16);
 | 
			
		||||
    $edit['revision'] = TRUE;
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Ensure that the block revision has been created.
 | 
			
		||||
    $revised_block = BlockContent::load($block->id());
 | 
			
		||||
    $this->assertNotSame($block->getRevisionId(), $revised_block->getRevisionId(), 'A new revision has been created.');
 | 
			
		||||
 | 
			
		||||
    // Test deleting the block.
 | 
			
		||||
    $this->drupalGet("admin/content/block/" . $revised_block->id());
 | 
			
		||||
    $this->clickLink('Delete');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Are you sure you want to delete the content block ' . $revised_block->label() . '?');
 | 
			
		||||
 | 
			
		||||
    // Test breadcrumb.
 | 
			
		||||
    $trail = [
 | 
			
		||||
      '' => 'Home',
 | 
			
		||||
      'admin/content/block' => 'Content blocks',
 | 
			
		||||
      'admin/content/block/' . $revised_block->id() => $revised_block->label(),
 | 
			
		||||
    ];
 | 
			
		||||
    $this->assertBreadcrumb(
 | 
			
		||||
      'admin/content/block/' . $revised_block->id() . '/delete', $trail
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentJsonAnonTest extends BlockContentResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use AnonResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'application/json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentJsonBasicAuthTest extends BlockContentResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use BasicAuthResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['basic_auth'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'application/json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'basic_auth';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentJsonCookieTest extends BlockContentResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use CookieResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'application/json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'cookie';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,239 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Core\Cache\Cache;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Resource test base for BlockContent entity.
 | 
			
		||||
 */
 | 
			
		||||
abstract class BlockContentResourceTestBase extends EntityResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content', 'content_translation'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $entityTypeId = 'block_content';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $patchProtectedFieldNames = [
 | 
			
		||||
    'changed' => NULL,
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @var \Drupal\block_content\BlockContentInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $entity;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUpAuthorization($method) {
 | 
			
		||||
    switch ($method) {
 | 
			
		||||
      case 'GET':
 | 
			
		||||
      case 'PATCH':
 | 
			
		||||
        $this->grantPermissionsToTestedRole(['access block library', 'edit any basic block content']);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 'POST':
 | 
			
		||||
        $this->grantPermissionsToTestedRole(['create basic block content']);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case 'DELETE':
 | 
			
		||||
        $this->grantPermissionsToTestedRole(['delete any basic block content']);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
        $this->grantPermissionsToTestedRole(['administer block content']);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function createEntity() {
 | 
			
		||||
    if (!BlockContentType::load('basic')) {
 | 
			
		||||
      $block_content_type = BlockContentType::create([
 | 
			
		||||
        'id' => 'basic',
 | 
			
		||||
        'label' => 'basic',
 | 
			
		||||
        'revision' => TRUE,
 | 
			
		||||
      ]);
 | 
			
		||||
      $block_content_type->save();
 | 
			
		||||
      block_content_add_body_field($block_content_type->id());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create a "Llama" content block.
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Llama',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'body' => [
 | 
			
		||||
        'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
 | 
			
		||||
        'format' => 'plain_text',
 | 
			
		||||
      ],
 | 
			
		||||
    ])
 | 
			
		||||
      ->setUnpublished();
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
    return $block_content;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getExpectedNormalizedEntity() {
 | 
			
		||||
    return [
 | 
			
		||||
      'id' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => 1,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'uuid' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => $this->entity->uuid(),
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'langcode' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => 'en',
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'reusable' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => TRUE,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'type' => [
 | 
			
		||||
        [
 | 
			
		||||
          'target_id' => 'basic',
 | 
			
		||||
          'target_type' => 'block_content_type',
 | 
			
		||||
          'target_uuid' => BlockContentType::load('basic')->uuid(),
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'info' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => 'Llama',
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'revision_log' => [],
 | 
			
		||||
      'changed' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => (new \DateTime())->setTimestamp((int) $this->entity->getChangedTime())
 | 
			
		||||
            ->setTimezone(new \DateTimeZone('UTC'))
 | 
			
		||||
            ->format(\DateTime::RFC3339),
 | 
			
		||||
          'format' => \DateTime::RFC3339,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'revision_id' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => 1,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'revision_created' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => (new \DateTime())->setTimestamp((int) $this->entity->getRevisionCreationTime())
 | 
			
		||||
            ->setTimezone(new \DateTimeZone('UTC'))
 | 
			
		||||
            ->format(\DateTime::RFC3339),
 | 
			
		||||
          'format' => \DateTime::RFC3339,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'revision_user' => [],
 | 
			
		||||
      'revision_translation_affected' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => TRUE,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'default_langcode' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => TRUE,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'body' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => 'The name "llama" was adopted by European settlers from native Peruvians.',
 | 
			
		||||
          'format' => 'plain_text',
 | 
			
		||||
          'summary' => NULL,
 | 
			
		||||
          'processed' => "<p>The name "llama" was adopted by European settlers from native Peruvians.</p>\n",
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'status' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => FALSE,
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getNormalizedPostEntity() {
 | 
			
		||||
    return [
 | 
			
		||||
      'type' => [
 | 
			
		||||
        [
 | 
			
		||||
          'target_id' => 'basic',
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'info' => [
 | 
			
		||||
        [
 | 
			
		||||
          'value' => 'Drama llama',
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getExpectedUnauthorizedAccessMessage($method) {
 | 
			
		||||
    if (!$this->resourceConfigStorage->load(static::$resourceConfigId)) {
 | 
			
		||||
      return match ($method) {
 | 
			
		||||
        'GET', 'PATCH' => "The 'edit any basic block content' permission is required.",
 | 
			
		||||
        'POST' => "The following permissions are required: 'create basic block content' OR 'administer block content'.",
 | 
			
		||||
        'DELETE' => "The 'delete any basic block content' permission is required.",
 | 
			
		||||
        default => parent::getExpectedUnauthorizedAccessMessage($method),
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    return match ($method) {
 | 
			
		||||
      'GET' => "The 'access block library' permission is required.",
 | 
			
		||||
      'PATCH' => "The 'edit any basic block content' permission is required.",
 | 
			
		||||
      'POST' => "The following permissions are required: 'create basic block content' OR 'administer block content'.",
 | 
			
		||||
      'DELETE' => "The 'delete any basic block content' permission is required.",
 | 
			
		||||
      default => parent::getExpectedUnauthorizedAccessMessage($method),
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getExpectedUnauthorizedEntityAccessCacheability($is_authenticated) {
 | 
			
		||||
    // @see \Drupal\block_content\BlockContentAccessControlHandler()
 | 
			
		||||
    return parent::getExpectedUnauthorizedEntityAccessCacheability($is_authenticated)
 | 
			
		||||
      ->addCacheTags(['block_content:1']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getExpectedCacheTags() {
 | 
			
		||||
    return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getExpectedCacheContexts() {
 | 
			
		||||
    return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeJsonAnonTest extends BlockContentTypeResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use AnonResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'application/json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeJsonBasicAuthTest extends BlockContentTypeResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use BasicAuthResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['basic_auth'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'application/json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'basic_auth';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeJsonCookieTest extends BlockContentTypeResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use CookieResourceTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'application/json';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'cookie';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,77 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\ConfigEntityResourceTestBase;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Resource test base for the BlockContentType entity.
 | 
			
		||||
 */
 | 
			
		||||
abstract class BlockContentTypeResourceTestBase extends ConfigEntityResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $entityTypeId = 'block_content_type';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @var \Drupal\block_content\BlockContentTypeInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $entity;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUpAuthorization($method) {
 | 
			
		||||
    $this->grantPermissionsToTestedRole(['administer block types']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function createEntity() {
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'pascal',
 | 
			
		||||
      'label' => 'Pascal',
 | 
			
		||||
      'revision' => FALSE,
 | 
			
		||||
      'description' => 'Provides a competitive alternative to the "basic" type',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
 | 
			
		||||
    return $block_content_type;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getExpectedNormalizedEntity() {
 | 
			
		||||
    return [
 | 
			
		||||
      'dependencies' => [],
 | 
			
		||||
      'description' => 'Provides a competitive alternative to the "basic" type',
 | 
			
		||||
      'id' => 'pascal',
 | 
			
		||||
      'label' => 'Pascal',
 | 
			
		||||
      'langcode' => 'en',
 | 
			
		||||
      'revision' => FALSE,
 | 
			
		||||
      'status' => TRUE,
 | 
			
		||||
      'uuid' => $this->entity->uuid(),
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function getNormalizedPostEntity() {
 | 
			
		||||
    // @todo Update in https://www.drupal.org/node/2300677.
 | 
			
		||||
    return [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeXmlAnonTest extends BlockContentTypeResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use AnonResourceTestTrait;
 | 
			
		||||
  use XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'xml';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'text/xml; charset=UTF-8';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeXmlBasicAuthTest extends BlockContentTypeResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use BasicAuthResourceTestTrait;
 | 
			
		||||
  use XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['basic_auth'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'xml';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'text/xml; charset=UTF-8';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'basic_auth';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeXmlCookieTest extends BlockContentTypeResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use CookieResourceTestTrait;
 | 
			
		||||
  use XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'xml';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'text/xml; charset=UTF-8';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'cookie';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentXmlAnonTest extends BlockContentResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use AnonResourceTestTrait;
 | 
			
		||||
  use XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'xml';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'text/xml; charset=UTF-8';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentXmlBasicAuthTest extends BlockContentResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use BasicAuthResourceTestTrait;
 | 
			
		||||
  use XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['basic_auth'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'xml';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'text/xml; charset=UTF-8';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'basic_auth';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Rest;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
 | 
			
		||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @group rest
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentXmlCookieTest extends BlockContentResourceTestBase {
 | 
			
		||||
 | 
			
		||||
  use CookieResourceTestTrait;
 | 
			
		||||
  use XmlEntityNormalizationQuirksTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $format = 'xml';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $mimeType = 'text/xml; charset=UTF-8';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $auth = 'cookie';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,54 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Tests\block\Traits\BlockCreationTrait;
 | 
			
		||||
use Drupal\Tests\BrowserTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests unpublishing of block_content entities.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class UnpublishedBlockTest extends BrowserTestBase {
 | 
			
		||||
 | 
			
		||||
  use BlockCreationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests unpublishing of block_content entities.
 | 
			
		||||
   */
 | 
			
		||||
  public function testViewShowsCorrectStates(): void {
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Test block',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $block = $this->placeBlock('block_content:' . $block_content->uuid());
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $page = $this->getSession()->getPage();
 | 
			
		||||
    $this->assertTrue($page->has('css', '#block-' . $block->id()));
 | 
			
		||||
 | 
			
		||||
    $block_content->setUnpublished();
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('<front>');
 | 
			
		||||
    $page = $this->getSession()->getPage();
 | 
			
		||||
    $this->assertFalse($page->has('css', '#block-' . $block->id()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,117 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Views;
 | 
			
		||||
 | 
			
		||||
use Drupal\field\Entity\FieldStorageConfig;
 | 
			
		||||
use Drupal\language\Entity\ConfigurableLanguage;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests block_content field filters with translations.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentFieldFilterTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['language'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Views used by this test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $testViews = ['test_field_filters'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * List of block_content infos by language.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public $blockContentInfos = [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp($import_test_views = TRUE, $modules = ['block_content_test_views']): void {
 | 
			
		||||
    parent::setUp($import_test_views, $modules);
 | 
			
		||||
 | 
			
		||||
    // Add two new languages.
 | 
			
		||||
    ConfigurableLanguage::createFromLangcode('fr')->save();
 | 
			
		||||
    ConfigurableLanguage::createFromLangcode('es')->save();
 | 
			
		||||
 | 
			
		||||
    // Make the body field translatable. The info is already translatable by
 | 
			
		||||
    // definition.
 | 
			
		||||
    $field_storage = FieldStorageConfig::loadByName('block_content', 'body');
 | 
			
		||||
    $field_storage->setTranslatable(TRUE);
 | 
			
		||||
    $field_storage->save();
 | 
			
		||||
 | 
			
		||||
    // Set up block_content infos.
 | 
			
		||||
    $this->blockContentInfos = [
 | 
			
		||||
      'en' => 'Food in Paris',
 | 
			
		||||
      'es' => 'Comida en Paris',
 | 
			
		||||
      'fr' => 'Nourriture en Paris',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // Create block_content with translations.
 | 
			
		||||
    $block_content = $this->createBlockContent(['info' => $this->blockContentInfos['en'], 'langcode' => 'en', 'type' => 'basic', 'body' => [['value' => $this->blockContentInfos['en']]]]);
 | 
			
		||||
    foreach (['es', 'fr'] as $langcode) {
 | 
			
		||||
      $translation = $block_content->addTranslation($langcode, ['info' => $this->blockContentInfos[$langcode]]);
 | 
			
		||||
      $translation->body->value = $this->blockContentInfos[$langcode];
 | 
			
		||||
    }
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests body and info filters.
 | 
			
		||||
   */
 | 
			
		||||
  public function testFilters(): void {
 | 
			
		||||
    // Test the info filter page, which filters for info contains 'Comida'.
 | 
			
		||||
    // Should show just the Spanish translation, once.
 | 
			
		||||
    $this->assertPageCounts('test-info-filter', ['es' => 1, 'fr' => 0, 'en' => 0], 'Comida info filter');
 | 
			
		||||
 | 
			
		||||
    // Test the body filter page, which filters for body contains 'Comida'.
 | 
			
		||||
    // Should show just the Spanish translation, once.
 | 
			
		||||
    $this->assertPageCounts('test-body-filter', ['es' => 1, 'fr' => 0, 'en' => 0], 'Comida body filter');
 | 
			
		||||
 | 
			
		||||
    // Test the info Paris filter page, which filters for info contains
 | 
			
		||||
    // 'Paris'. Should show each translation once.
 | 
			
		||||
    $this->assertPageCounts('test-info-paris', ['es' => 1, 'fr' => 1, 'en' => 1], 'Paris info filter');
 | 
			
		||||
 | 
			
		||||
    // Test the body Paris filter page, which filters for body contains
 | 
			
		||||
    // 'Paris'. Should show each translation once.
 | 
			
		||||
    $this->assertPageCounts('test-body-paris', ['es' => 1, 'fr' => 1, 'en' => 1], 'Paris body filter');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Asserts that the given block_content translation counts are correct.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $path
 | 
			
		||||
   *   Path of the page to test.
 | 
			
		||||
   * @param array $counts
 | 
			
		||||
   *   Array whose keys are languages, and values are the number of times
 | 
			
		||||
   *   that translation should be shown on the given page.
 | 
			
		||||
   * @param string $message
 | 
			
		||||
   *   Message suffix to display.
 | 
			
		||||
   *
 | 
			
		||||
   * @internal
 | 
			
		||||
   */
 | 
			
		||||
  protected function assertPageCounts(string $path, array $counts, string $message): void {
 | 
			
		||||
    // Get the text of the page.
 | 
			
		||||
    $this->drupalGet($path);
 | 
			
		||||
    $text = $this->getTextContent();
 | 
			
		||||
 | 
			
		||||
    foreach ($counts as $langcode => $count) {
 | 
			
		||||
      $this->assertEquals($count, substr_count($text, $this->blockContentInfos[$langcode]), 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,76 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Views;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the block_content integration into views.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentIntegrationTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Views used by this test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $testViews = ['test_block_content_view'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests basic block_content view with a block_content_type argument.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentViewTypeArgument(): void {
 | 
			
		||||
    // Create two content types with three block_contents each.
 | 
			
		||||
    $types = [];
 | 
			
		||||
    $all_ids = [];
 | 
			
		||||
    $block_contents = [];
 | 
			
		||||
    for ($i = 0; $i < 2; $i++) {
 | 
			
		||||
      $type = $this->createBlockContentType();
 | 
			
		||||
      $types[] = $type;
 | 
			
		||||
 | 
			
		||||
      for ($j = 0; $j < 5; $j++) {
 | 
			
		||||
        // Ensure the right order of the block_contents.
 | 
			
		||||
        $block_content = $this->createBlockContent(['type' => $type->id()]);
 | 
			
		||||
        $block_contents[$type->id()][$block_content->id()] = $block_content;
 | 
			
		||||
        $all_ids[] = $block_content->id();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('test-block_content-view');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(404);
 | 
			
		||||
 | 
			
		||||
    $this->drupalGet('test-block_content-view/all');
 | 
			
		||||
    $this->assertSession()->statusCodeEquals(200);
 | 
			
		||||
    $this->assertIds($all_ids);
 | 
			
		||||
    /** @var \Drupal\block_content\Entity\BlockContentType[] $types*/
 | 
			
		||||
    foreach ($types as $type) {
 | 
			
		||||
      $this->drupalGet("test-block_content-view/{$type->id()}");
 | 
			
		||||
      $this->assertIds(array_keys($block_contents[$type->id()]));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Ensures that a list of block_contents appear on the page.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $expected_ids
 | 
			
		||||
   *   An array of block_content IDs.
 | 
			
		||||
   *
 | 
			
		||||
   * @internal
 | 
			
		||||
   */
 | 
			
		||||
  protected function assertIds(array $expected_ids = []): void {
 | 
			
		||||
    $result = $this->xpath('//span[@class="field-content"]');
 | 
			
		||||
    $ids = [];
 | 
			
		||||
    foreach ($result as $element) {
 | 
			
		||||
      $ids[] = $element->getText();
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertEquals($expected_ids, $ids);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Views;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the redirect destination on block content on entity operations.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentRedirectTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Views used by this test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $testViews = ['test_block_content_redirect_destination'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'views'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the redirect destination when editing block content.
 | 
			
		||||
   */
 | 
			
		||||
  public function testRedirectDestination(): void {
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser(['access block library', 'administer block content']));
 | 
			
		||||
    $this->drupalGet('admin/content/block');
 | 
			
		||||
 | 
			
		||||
    // Create a content block.
 | 
			
		||||
    $this->clickLink('content block');
 | 
			
		||||
    $edit = [];
 | 
			
		||||
    $edit['info[0][value]'] = 'Test redirect destination';
 | 
			
		||||
    $edit['body[0][value]'] = $this->randomMachineName(16);
 | 
			
		||||
    $this->submitForm($edit, 'Save');
 | 
			
		||||
 | 
			
		||||
    // Check the block content is present in the view redirect destination.
 | 
			
		||||
    $this->drupalGet('admin/content/redirect_destination');
 | 
			
		||||
    $this->assertSession()->pageTextContains('Test redirect destination');
 | 
			
		||||
 | 
			
		||||
    // Edit the created block and save.
 | 
			
		||||
    $this->clickLink('Edit');
 | 
			
		||||
    $this->submitForm([], 'Save');
 | 
			
		||||
    $this->assertSession()->addressEquals('admin/content/redirect_destination');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,109 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Views;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Tests\views\Functional\ViewTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Base class for all block_content tests.
 | 
			
		||||
 */
 | 
			
		||||
abstract class BlockContentTestBase extends ViewTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var object
 | 
			
		||||
   */
 | 
			
		||||
  protected $adminUser;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Permissions to grant admin user.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissions = [
 | 
			
		||||
    'administer blocks',
 | 
			
		||||
    'administer block content',
 | 
			
		||||
    'access block library',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'block_content_test_views',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp($import_test_views = TRUE, $modules = ['block_content_test_views']): void {
 | 
			
		||||
    parent::setUp($import_test_views, $modules);
 | 
			
		||||
    // Ensure the basic bundle exists. This is provided by the standard profile.
 | 
			
		||||
    $this->createBlockContentType(['id' => 'basic']);
 | 
			
		||||
 | 
			
		||||
    $this->adminUser = $this->drupalCreateUser($this->permissions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a content block.
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $values
 | 
			
		||||
   *   (optional) The values for the block_content entity.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\block_content\Entity\BlockContent
 | 
			
		||||
   *   Created content block.
 | 
			
		||||
   */
 | 
			
		||||
  protected function createBlockContent(array $values = []) {
 | 
			
		||||
    $status = 0;
 | 
			
		||||
    $values += [
 | 
			
		||||
      'info' => $this->randomMachineName(),
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'langcode' => 'en',
 | 
			
		||||
    ];
 | 
			
		||||
    if ($block_content = BlockContent::create($values)) {
 | 
			
		||||
      $status = $block_content->save();
 | 
			
		||||
    }
 | 
			
		||||
    $this->assertEquals(SAVED_NEW, $status, "Created block content {$block_content->label()}.");
 | 
			
		||||
    return $block_content;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates a block type (bundle).
 | 
			
		||||
   *
 | 
			
		||||
   * @param array $values
 | 
			
		||||
   *   An array of settings to change from the defaults.
 | 
			
		||||
   *
 | 
			
		||||
   * @return \Drupal\block_content\Entity\BlockContentType
 | 
			
		||||
   *   Created block type.
 | 
			
		||||
   */
 | 
			
		||||
  protected function createBlockContentType(array $values = []) {
 | 
			
		||||
    // Find a non-existent random type name.
 | 
			
		||||
    if (!isset($values['id'])) {
 | 
			
		||||
      do {
 | 
			
		||||
        $id = $this->randomMachineName(8);
 | 
			
		||||
      } while (BlockContentType::load($id));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      $id = $values['id'];
 | 
			
		||||
    }
 | 
			
		||||
    $values += [
 | 
			
		||||
      'id' => $id,
 | 
			
		||||
      'label' => $id,
 | 
			
		||||
      'revision' => FALSE,
 | 
			
		||||
    ];
 | 
			
		||||
    $bundle = BlockContentType::create($values);
 | 
			
		||||
    $status = $bundle->save();
 | 
			
		||||
    block_content_add_body_field($bundle->id());
 | 
			
		||||
 | 
			
		||||
    $this->assertEquals(SAVED_NEW, $status, sprintf('Created block content type %s.', $bundle->id()));
 | 
			
		||||
    return $bundle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Functional\Views;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\block_content\Functional\BlockContentTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests block_content wizard and generic entity integration.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentWizardTest extends BlockContentTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content', 'views_ui'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected $defaultTheme = 'stark';
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->drupalLogin($this->drupalCreateUser(['administer views']));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests creating a 'block_content' entity view.
 | 
			
		||||
   */
 | 
			
		||||
  public function testViewAddBlockContent(): void {
 | 
			
		||||
    $view = [];
 | 
			
		||||
    $view['label'] = $this->randomMachineName(16);
 | 
			
		||||
    $view['id'] = $this->randomMachineName(16);
 | 
			
		||||
    $view['description'] = $this->randomMachineName(16);
 | 
			
		||||
    $view['page[create]'] = FALSE;
 | 
			
		||||
    $view['show[wizard_key]'] = 'block_content';
 | 
			
		||||
    $this->drupalGet('admin/structure/views/add');
 | 
			
		||||
    $this->submitForm($view, 'Save and edit');
 | 
			
		||||
 | 
			
		||||
    $view_storage_controller = $this->container->get('entity_type.manager')->getStorage('view');
 | 
			
		||||
    /** @var \Drupal\views\Entity\View $view */
 | 
			
		||||
    $view = $view_storage_controller->load($view['id']);
 | 
			
		||||
 | 
			
		||||
    $display_options = $view->getDisplay('default')['display_options'];
 | 
			
		||||
 | 
			
		||||
    $this->assertEquals('block_content', $display_options['filters']['reusable']['entity_type']);
 | 
			
		||||
    $this->assertEquals('reusable', $display_options['filters']['reusable']['entity_field']);
 | 
			
		||||
    $this->assertEquals('boolean', $display_options['filters']['reusable']['plugin_id']);
 | 
			
		||||
    $this->assertEquals('1', $display_options['filters']['reusable']['value']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,621 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\BlockContentAccessControlHandler;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Core\Access\AccessibleInterface;
 | 
			
		||||
use Drupal\Core\Access\AccessResultAllowed;
 | 
			
		||||
use Drupal\Core\Access\AccessResultForbidden;
 | 
			
		||||
use Drupal\Core\Access\AccessResultNeutral;
 | 
			
		||||
use Drupal\Core\Access\AccessResultReasonInterface;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\Tests\user\Traits\UserCreationTrait;
 | 
			
		||||
use Drupal\user\Entity\Role;
 | 
			
		||||
use Drupal\user\Entity\User;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the block content entity access handler.
 | 
			
		||||
 *
 | 
			
		||||
 * @coversDefaultClass \Drupal\block_content\BlockContentAccessControlHandler
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentAccessHandlerTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  use UserCreationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'system',
 | 
			
		||||
    'user',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The BlockContent access controller to test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content\BlockContentAccessControlHandler
 | 
			
		||||
   */
 | 
			
		||||
  protected $accessControlHandler;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The BlockContent entity used for testing.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content\Entity\BlockContent
 | 
			
		||||
   */
 | 
			
		||||
  protected $blockEntity;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The test role.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\RoleInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $role;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installSchema('user', ['users_data']);
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
 | 
			
		||||
    // Create a basic block content type.
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'A basic block type',
 | 
			
		||||
      'description' => "Provides a block type that is basic.",
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
 | 
			
		||||
    // Create a square block content type.
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'square',
 | 
			
		||||
      'label' => 'A square block type',
 | 
			
		||||
      'description' => "Provides a block type that is square.",
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
 | 
			
		||||
    $this->blockEntity = BlockContent::create([
 | 
			
		||||
      'info' => 'The Block',
 | 
			
		||||
      'type' => 'square',
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->blockEntity->save();
 | 
			
		||||
 | 
			
		||||
    // Create user 1 test does not have all permissions.
 | 
			
		||||
    User::create([
 | 
			
		||||
      'name' => 'admin',
 | 
			
		||||
    ])->save();
 | 
			
		||||
 | 
			
		||||
    $this->role = Role::create([
 | 
			
		||||
      'id' => 'test',
 | 
			
		||||
      'label' => 'test role',
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->role->save();
 | 
			
		||||
    $this->accessControlHandler = new BlockContentAccessControlHandler(\Drupal::entityTypeManager()->getDefinition('block_content'), \Drupal::service('event_dispatcher'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test block content entity access.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $operation
 | 
			
		||||
   *   The entity operation to test.
 | 
			
		||||
   * @param bool $published
 | 
			
		||||
   *   Whether the latest revision should be published.
 | 
			
		||||
   * @param bool $reusable
 | 
			
		||||
   *   Whether the block content should be reusable. Non-reusable blocks are
 | 
			
		||||
   *   typically used in Layout Builder.
 | 
			
		||||
   * @param array $permissions
 | 
			
		||||
   *   Permissions to grant to the test user.
 | 
			
		||||
   * @param bool $isLatest
 | 
			
		||||
   *   Whether the block content should be the latest revision when checking
 | 
			
		||||
   *   access. If FALSE, multiple revisions will be created, and an older
 | 
			
		||||
   *   revision will be loaded before checking access.
 | 
			
		||||
   * @param string|null $parent_access
 | 
			
		||||
   *   Whether the test user has access to the parent entity, valid values are
 | 
			
		||||
   *   class names of classes implementing AccessResultInterface. Set to NULL to
 | 
			
		||||
   *   assert parent will not be called.
 | 
			
		||||
   * @param string $expected_access
 | 
			
		||||
   *   The expected access for the user and block content. Valid values are
 | 
			
		||||
   *   class names of classes implementing AccessResultInterface.
 | 
			
		||||
   * @param string|null $expected_access_message
 | 
			
		||||
   *   The expected access message.
 | 
			
		||||
   *
 | 
			
		||||
   * @covers ::checkAccess
 | 
			
		||||
   *
 | 
			
		||||
   * @dataProvider providerTestAccess
 | 
			
		||||
   *
 | 
			
		||||
   * @phpstan-param class-string<\Drupal\Core\Access\AccessResultInterface>|null $parent_access
 | 
			
		||||
   * @phpstan-param class-string<\Drupal\Core\Access\AccessResultInterface> $expected_access
 | 
			
		||||
   */
 | 
			
		||||
  public function testAccess(string $operation, bool $published, bool $reusable, array $permissions, bool $isLatest, ?string $parent_access, string $expected_access, ?string $expected_access_message = NULL): void {
 | 
			
		||||
    /** @var \Drupal\Core\Entity\RevisionableStorageInterface $entityStorage */
 | 
			
		||||
    $entityStorage = \Drupal::entityTypeManager()->getStorage('block_content');
 | 
			
		||||
 | 
			
		||||
    $loadRevisionId = NULL;
 | 
			
		||||
    if (!$isLatest) {
 | 
			
		||||
      // Save a historical revision, then setup for a new revision to be saved.
 | 
			
		||||
      $this->blockEntity->save();
 | 
			
		||||
      $loadRevisionId = $this->blockEntity->getRevisionId();
 | 
			
		||||
      $this->blockEntity = $entityStorage->createRevision($this->blockEntity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $published ? $this->blockEntity->setPublished() : $this->blockEntity->setUnpublished();
 | 
			
		||||
    $reusable ? $this->blockEntity->setReusable() : $this->blockEntity->setNonReusable();
 | 
			
		||||
 | 
			
		||||
    $user = User::create([
 | 
			
		||||
      'name' => 'Someone',
 | 
			
		||||
      'mail' => 'hi@example.com',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    if ($permissions) {
 | 
			
		||||
      foreach ($permissions as $permission) {
 | 
			
		||||
        $this->role->grantPermission($permission);
 | 
			
		||||
      }
 | 
			
		||||
      $this->role->save();
 | 
			
		||||
    }
 | 
			
		||||
    $user->addRole($this->role->id())->save();
 | 
			
		||||
 | 
			
		||||
    if ($parent_access !== NULL) {
 | 
			
		||||
      $parent_entity = $this->prophesize(AccessibleInterface::class);
 | 
			
		||||
      $expected_parent_result = new ($parent_access)();
 | 
			
		||||
      $parent_entity->access($operation, $user, TRUE)
 | 
			
		||||
        ->willReturn($expected_parent_result)
 | 
			
		||||
        ->shouldBeCalled();
 | 
			
		||||
 | 
			
		||||
      $this->blockEntity->setAccessDependency($parent_entity->reveal());
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    $this->blockEntity->save();
 | 
			
		||||
 | 
			
		||||
    // Reload a previous revision.
 | 
			
		||||
    if ($loadRevisionId !== NULL) {
 | 
			
		||||
      $this->blockEntity = $entityStorage->loadRevision($loadRevisionId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $result = $this->accessControlHandler->access($this->blockEntity, $operation, $user, TRUE);
 | 
			
		||||
    $this->assertInstanceOf($expected_access, $result);
 | 
			
		||||
    if ($expected_access_message !== NULL) {
 | 
			
		||||
      $this->assertInstanceOf(AccessResultReasonInterface::class, $result);
 | 
			
		||||
      $this->assertEquals($expected_access_message, $result->getReason());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Data provider for testAccess().
 | 
			
		||||
   */
 | 
			
		||||
  public static function providerTestAccess(): array {
 | 
			
		||||
    $cases = [
 | 
			
		||||
      'view:published:reusable' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        [],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:unpublished:reusable' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        FALSE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        [],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultNeutral::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:unpublished:reusable:admin' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        FALSE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['access block library'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:unpublished:reusable:per-block-editor:basic' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        FALSE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['edit any basic block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultNeutral::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:unpublished:reusable:per-block-editor:square' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        FALSE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['access block library', 'edit any basic block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:reusable:admin' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['access block library'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:reusable:per-block-editor:basic' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['access block library', 'edit any basic block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:reusable:per-block-editor:square' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['access block library', 'edit any square block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:non_reusable' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        FALSE,
 | 
			
		||||
        [],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultForbidden::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:non_reusable:parent_allowed' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        FALSE,
 | 
			
		||||
        [],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:non_reusable:parent_neutral' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        FALSE,
 | 
			
		||||
        [],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        AccessResultNeutral::class,
 | 
			
		||||
        AccessResultNeutral::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'view:published:non_reusable:parent_forbidden' => [
 | 
			
		||||
        'view',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        FALSE,
 | 
			
		||||
        [],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        AccessResultForbidden::class,
 | 
			
		||||
        AccessResultForbidden::class,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    foreach (['update', 'delete'] as $operation) {
 | 
			
		||||
      $label = $operation === 'update' ? 'edit' : 'delete';
 | 
			
		||||
      $cases += [
 | 
			
		||||
        $operation . ':published:reusable' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          [],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':unpublished:reusable' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          [],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':unpublished:reusable:admin' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          [$label . ' any square block content'],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultAllowed::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':published:reusable:admin' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          [$label . ' any square block content'],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultAllowed::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':published:non_reusable' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          [],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultForbidden::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':published:non_reusable:parent_allowed' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          [],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          AccessResultAllowed::class,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':published:non_reusable:parent_neutral' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          [],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':published:non_reusable:parent_forbidden' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          [],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          AccessResultForbidden::class,
 | 
			
		||||
          AccessResultForbidden::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':unpublished:reusable:per-block-editor:basic' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          FALSE,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          ['edit any basic block content'],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
        ],
 | 
			
		||||
        $operation . ':published:reusable:per-block-editor:basic' => [
 | 
			
		||||
          $operation,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          TRUE,
 | 
			
		||||
          ['edit any basic block content'],
 | 
			
		||||
          TRUE,
 | 
			
		||||
          NULL,
 | 
			
		||||
          AccessResultNeutral::class,
 | 
			
		||||
        ],
 | 
			
		||||
      ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $cases += [
 | 
			
		||||
      'update:unpublished:reusable:per-block-editor:square' => [
 | 
			
		||||
        'update',
 | 
			
		||||
        FALSE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['edit any square block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'update:published:reusable:per-block-editor:square' => [
 | 
			
		||||
        'update',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['edit any square block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultAllowed::class,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $cases += [
 | 
			
		||||
      'delete:unpublished:reusable:per-block-editor:square' => [
 | 
			
		||||
        'delete',
 | 
			
		||||
        FALSE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['edit any square block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultNeutral::class,
 | 
			
		||||
      ],
 | 
			
		||||
      'delete:published:reusable:per-block-editor:square' => [
 | 
			
		||||
        'delete',
 | 
			
		||||
        TRUE,
 | 
			
		||||
        TRUE,
 | 
			
		||||
        ['edit any square block content'],
 | 
			
		||||
        TRUE,
 | 
			
		||||
        NULL,
 | 
			
		||||
        AccessResultNeutral::class,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // View all revisions:
 | 
			
		||||
    $cases['view all revisions:none'] = [
 | 
			
		||||
      'view all revisions',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      [],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultNeutral::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['view all revisions:view any bundle history'] = [
 | 
			
		||||
      'view all revisions',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['view any square block content history'],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultAllowed::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['view all revisions:administer block content'] = [
 | 
			
		||||
      'view all revisions',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['administer block content'],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultAllowed::class,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // Revert revisions:
 | 
			
		||||
    $cases['revert:none:latest'] = [
 | 
			
		||||
      'revert',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      [],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['revert:none:historical'] = [
 | 
			
		||||
      'revert',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      [],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultNeutral::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['revert:revert bundle:historical'] = [
 | 
			
		||||
      'revert',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['revert any square block content revisions'],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultAllowed::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['revert:administer block content:latest'] = [
 | 
			
		||||
      'revert',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['administer block content'],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['revert:administer block content:historical'] = [
 | 
			
		||||
      'revert',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['administer block content'],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultAllowed::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['revert:revert bundle:historical:non reusable'] = [
 | 
			
		||||
      'revert',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      FALSE,
 | 
			
		||||
      ['revert any square block content revisions'],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
      'Block content must be reusable to use `revert` operation',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // Delete revisions:
 | 
			
		||||
    $cases['delete revision:none:latest'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      [],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['delete revision:none:historical'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      [],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultNeutral::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['delete revision:administer block content:latest'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['administer block content'],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['delete revision:administer block content:historical'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['administer block content'],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultAllowed::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['delete revision:delete bundle:latest'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['administer block content'],
 | 
			
		||||
      TRUE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['delete revision:delete bundle:historical'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      TRUE,
 | 
			
		||||
      ['delete any square block content revisions'],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultAllowed::class,
 | 
			
		||||
    ];
 | 
			
		||||
    $cases['delete revision:delete bundle:historical:non reusable'] = [
 | 
			
		||||
      'delete revision',
 | 
			
		||||
      TRUE,
 | 
			
		||||
      FALSE,
 | 
			
		||||
      ['delete any square block content revisions'],
 | 
			
		||||
      FALSE,
 | 
			
		||||
      NULL,
 | 
			
		||||
      AccessResultForbidden::class,
 | 
			
		||||
      'Block content must be reusable to use `delete revision` operation',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return $cases;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests revision log access.
 | 
			
		||||
   */
 | 
			
		||||
  public function testRevisionLogAccess(): void {
 | 
			
		||||
    $admin = $this->createUser([
 | 
			
		||||
      'administer block content',
 | 
			
		||||
      'access content',
 | 
			
		||||
    ]);
 | 
			
		||||
    $editor = $this->createUser([
 | 
			
		||||
      'access content',
 | 
			
		||||
      'access block library',
 | 
			
		||||
      'view any square block content history',
 | 
			
		||||
    ]);
 | 
			
		||||
    $viewer = $this->createUser([
 | 
			
		||||
      'access content',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    $this->assertTrue($this->blockEntity->get('revision_log')->access('view', $admin));
 | 
			
		||||
    $this->assertTrue($this->blockEntity->get('revision_log')->access('view', $editor));
 | 
			
		||||
    $this->assertFalse($this->blockEntity->get('revision_log')->access('view', $viewer));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,87 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Component\Plugin\PluginBase;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\Tests\block\Traits\BlockCreationTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests that deleting a block clears the cached definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentDeletionTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  use BlockCreationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'field', 'system', 'text', 'user'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(['block_content']);
 | 
			
		||||
    $this->container->get('theme_installer')->install(['stark']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests deleting a block_content updates the discovered block plugin.
 | 
			
		||||
   */
 | 
			
		||||
  public function testDeletingBlockContentShouldClearPluginCache(): void {
 | 
			
		||||
    // Create a block content type.
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'spiffy',
 | 
			
		||||
      'label' => 'Very spiffy',
 | 
			
		||||
      'description' => "Provides a block type that increases your site's spiffy rating by upto 11%",
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
    // And a block content entity.
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Spiffy prototype',
 | 
			
		||||
      'type' => 'spiffy',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    // Make sure the block content provides a derivative block plugin in the
 | 
			
		||||
    // block repository.
 | 
			
		||||
    /** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
 | 
			
		||||
    $block_manager = $this->container->get('plugin.manager.block');
 | 
			
		||||
    $plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
 | 
			
		||||
    $this->assertTrue($block_manager->hasDefinition($plugin_id));
 | 
			
		||||
 | 
			
		||||
    // Now delete the block content entity.
 | 
			
		||||
    $block_content->delete();
 | 
			
		||||
    // The plugin should no longer exist.
 | 
			
		||||
    $this->assertFalse($block_manager->hasDefinition($plugin_id));
 | 
			
		||||
 | 
			
		||||
    // Create another block content entity.
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Spiffy prototype',
 | 
			
		||||
      'type' => 'spiffy',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
 | 
			
		||||
    $block = $this->placeBlock($plugin_id, ['region' => 'content', 'theme' => 'stark']);
 | 
			
		||||
 | 
			
		||||
    // Delete it via storage.
 | 
			
		||||
    $storage = $this->container->get('entity_type.manager')->getStorage('block_content');
 | 
			
		||||
    $storage->delete([$block_content]);
 | 
			
		||||
    // The plugin should no longer exist.
 | 
			
		||||
    $this->assertFalse($block_manager->hasDefinition($plugin_id));
 | 
			
		||||
 | 
			
		||||
    $this->assertNull($this->container->get('entity_type.manager')->getStorage('block')->loadUnchanged($block->id()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,124 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\block_content\Plugin\Derivative\BlockContent as DerivativeBlockContent;
 | 
			
		||||
use Drupal\Component\Plugin\PluginBase;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests block content plugin deriver.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentDeriverTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'system', 'user'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The definition array of the base plugin.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $baseDefinition = [
 | 
			
		||||
    'id' => 'block_content',
 | 
			
		||||
    'provider' => 'block_content',
 | 
			
		||||
    'class' => '\Drupal\block_content\Plugin\Block\BlockContentBlock',
 | 
			
		||||
    'deriver' => '\Drupal\block_content\Plugin\Derivative\BlockContent',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The block content storage.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Core\Entity\EntityStorageInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $blockContentStorage;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The tested block content derivative class.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content\Plugin\Derivative\BlockContent
 | 
			
		||||
   */
 | 
			
		||||
  protected $blockContentDerivative;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
 | 
			
		||||
    $this->blockContentStorage = \Drupal::entityTypeManager()->getStorage('block_content');
 | 
			
		||||
    $this->blockContentDerivative = new DerivativeBlockContent($this->blockContentStorage);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests that only reusable blocks are derived.
 | 
			
		||||
   */
 | 
			
		||||
  public function testReusableBlocksOnlyAreDerived(): void {
 | 
			
		||||
    // Create a block content type.
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'spiffy',
 | 
			
		||||
      'label' => 'Very spiffy',
 | 
			
		||||
      'description' => "Provides a block type that increases your site's spiffy rating by up to 11%",
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
    // And a block content entity.
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Spiffy prototype',
 | 
			
		||||
      'type' => 'spiffy',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    // Ensure the reusable block content is provided as a derivative block
 | 
			
		||||
    // plugin.
 | 
			
		||||
    /** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
 | 
			
		||||
    $block_manager = $this->container->get('plugin.manager.block');
 | 
			
		||||
    $plugin_id = 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid();
 | 
			
		||||
    $this->assertTrue($block_manager->hasDefinition($plugin_id));
 | 
			
		||||
 | 
			
		||||
    // Set the block not to be reusable.
 | 
			
		||||
    $block_content->setNonReusable();
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    // Ensure the non-reusable block content is not provided a derivative block
 | 
			
		||||
    // plugin.
 | 
			
		||||
    $this->assertFalse($block_manager->hasDefinition($plugin_id));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the admin labels of derivative definitions.
 | 
			
		||||
   */
 | 
			
		||||
  public function testGetDerivativeDefinitionsAdminLabels(): void {
 | 
			
		||||
    $blockContentType = BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'Basic Block',
 | 
			
		||||
    ]);
 | 
			
		||||
    $blockContentType->save();
 | 
			
		||||
    $blockContentWithLabel = BlockContent::create([
 | 
			
		||||
      'info' => 'Basic prototype',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
    ]);
 | 
			
		||||
    $blockContentWithLabel->save();
 | 
			
		||||
    $blockContentNoLabel = BlockContent::create([
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
    ]);
 | 
			
		||||
    $blockContentNoLabel->save();
 | 
			
		||||
 | 
			
		||||
    $blockPluginManager = \Drupal::service('plugin.manager.block');
 | 
			
		||||
    $plugin = $blockPluginManager->createInstance('block_content:' . $blockContentWithLabel->uuid());
 | 
			
		||||
    $this->assertEquals('Basic prototype', $plugin->getPluginDefinition()['admin_label']);
 | 
			
		||||
 | 
			
		||||
    $plugin = $blockPluginManager->createInstance('block_content:' . $blockContentNoLabel->uuid());
 | 
			
		||||
    $this->assertEquals('Basic Block: ' . $blockContentNoLabel->id(), $plugin->getPluginDefinition()['admin_label']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,195 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\block_content_test\Plugin\EntityReferenceSelection\TestSelection;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests EntityReference selection handlers don't return non-reusable blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * @see block_content_query_entity_reference_alter()
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentEntityReferenceSelectionTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'block_content_test',
 | 
			
		||||
    'system',
 | 
			
		||||
    'user',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The entity type manager.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $entityTypeManager;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test reusable block.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content\BlockContentInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $blockReusable;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test non-reusable block.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content\BlockContentInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $blockNonReusable;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test selection handler.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content_test\Plugin\EntityReferenceSelection\TestSelection
 | 
			
		||||
   */
 | 
			
		||||
  protected $selectionHandler;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Test block expectations.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  protected $expectations;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
 | 
			
		||||
    // Create a block content type.
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'spiffy',
 | 
			
		||||
      'label' => 'Very spiffy',
 | 
			
		||||
      'description' => "Provides a block type that increases your site's spiffy rating by up to 11%",
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
    $this->entityTypeManager = $this->container->get('entity_type.manager');
 | 
			
		||||
 | 
			
		||||
    // And reusable block content entities.
 | 
			
		||||
    $this->blockReusable = BlockContent::create([
 | 
			
		||||
      'info' => 'Reusable Block',
 | 
			
		||||
      'type' => 'spiffy',
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->blockReusable->save();
 | 
			
		||||
    $this->blockNonReusable = BlockContent::create([
 | 
			
		||||
      'info' => 'Non-reusable Block',
 | 
			
		||||
      'type' => 'spiffy',
 | 
			
		||||
      'reusable' => FALSE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->blockNonReusable->save();
 | 
			
		||||
 | 
			
		||||
    $configuration = [
 | 
			
		||||
      'target_type' => 'block_content',
 | 
			
		||||
      'target_bundles' => ['spiffy' => 'spiffy'],
 | 
			
		||||
      'sort' => ['field' => '_none'],
 | 
			
		||||
    ];
 | 
			
		||||
    $this->selectionHandler = new TestSelection($configuration, '', '', $this->container->get('entity_type.manager'), $this->container->get('module_handler'), \Drupal::currentUser(), \Drupal::service('entity_field.manager'), \Drupal::service('entity_type.bundle.info'), \Drupal::service('entity.repository'));
 | 
			
		||||
 | 
			
		||||
    // Setup the 3 expectation cases.
 | 
			
		||||
    $this->expectations = [
 | 
			
		||||
      'both_blocks' => [
 | 
			
		||||
        'spiffy' => [
 | 
			
		||||
          $this->blockReusable->id() => $this->blockReusable->label(),
 | 
			
		||||
          $this->blockNonReusable->id() => $this->blockNonReusable->label(),
 | 
			
		||||
        ],
 | 
			
		||||
      ],
 | 
			
		||||
      'block_reusable' => ['spiffy' => [$this->blockReusable->id() => $this->blockReusable->label()]],
 | 
			
		||||
      'block_non_reusable' => ['spiffy' => [$this->blockNonReusable->id() => $this->blockNonReusable->label()]],
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests to make sure queries without the expected tags are not altered.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
 | 
			
		||||
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
 | 
			
		||||
   */
 | 
			
		||||
  public function testQueriesNotAltered(): void {
 | 
			
		||||
    // Ensure that queries without all the tags are not altered.
 | 
			
		||||
    $query = $this->entityTypeManager->getStorage('block_content')
 | 
			
		||||
      ->getQuery()
 | 
			
		||||
      ->accessCheck(FALSE);
 | 
			
		||||
    $this->assertCount(2, $query->execute());
 | 
			
		||||
 | 
			
		||||
    $query = $this->entityTypeManager->getStorage('block_content')
 | 
			
		||||
      ->getQuery()
 | 
			
		||||
      ->accessCheck(FALSE);
 | 
			
		||||
    $query->addTag('block_content_access');
 | 
			
		||||
    $this->assertCount(2, $query->execute());
 | 
			
		||||
 | 
			
		||||
    $query = $this->entityTypeManager->getStorage('block_content')
 | 
			
		||||
      ->getQuery()
 | 
			
		||||
      ->accessCheck(FALSE);
 | 
			
		||||
    $query->addTag('entity_query_block_content');
 | 
			
		||||
    $this->assertCount(2, $query->execute());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests with no conditions set.
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Drupal\Core\Entity\EntityStorageException
 | 
			
		||||
   */
 | 
			
		||||
  public function testNoConditions(): void {
 | 
			
		||||
    $this->assertEquals(
 | 
			
		||||
      $this->expectations['block_reusable'],
 | 
			
		||||
      $this->selectionHandler->getReferenceableEntities()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    $this->blockNonReusable->setReusable();
 | 
			
		||||
    $this->blockNonReusable->save();
 | 
			
		||||
 | 
			
		||||
    // Ensure that the block is now returned as a referenceable entity.
 | 
			
		||||
    $this->assertEquals(
 | 
			
		||||
      $this->expectations['both_blocks'],
 | 
			
		||||
      $this->selectionHandler->getReferenceableEntities()
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests setting 'reusable' condition on different levels.
 | 
			
		||||
   *
 | 
			
		||||
   * @dataProvider fieldConditionProvider
 | 
			
		||||
   *
 | 
			
		||||
   * @throws \Exception
 | 
			
		||||
   */
 | 
			
		||||
  public function testFieldConditions($condition_type, $is_reusable): void {
 | 
			
		||||
    $this->selectionHandler->setTestMode($condition_type, $is_reusable);
 | 
			
		||||
    $this->assertEquals(
 | 
			
		||||
      $is_reusable ? $this->expectations['block_reusable'] : $this->expectations['block_non_reusable'],
 | 
			
		||||
      $this->selectionHandler->getReferenceableEntities()
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Provides possible fields and condition types.
 | 
			
		||||
   */
 | 
			
		||||
  public static function fieldConditionProvider() {
 | 
			
		||||
    $cases = [];
 | 
			
		||||
    foreach (['base', 'group', 'nested_group'] as $condition_type) {
 | 
			
		||||
      foreach ([TRUE, FALSE] as $reusable) {
 | 
			
		||||
        $cases["$condition_type:" . ($reusable ? 'reusable' : 'non-reusable')] = [
 | 
			
		||||
          $condition_type,
 | 
			
		||||
          $reusable,
 | 
			
		||||
        ];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $cases;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,87 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the permissions of content blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * @coversDefaultClass \Drupal\block_content\BlockContentPermissions
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentPermissionsTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'block_content_test',
 | 
			
		||||
    'system',
 | 
			
		||||
    'user',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The permission handler.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\user\PermissionHandlerInterface
 | 
			
		||||
   */
 | 
			
		||||
  protected $permissionHandler;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
 | 
			
		||||
    $this->permissionHandler = $this->container->get('user.permissions');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @covers ::blockTypePermissions
 | 
			
		||||
   */
 | 
			
		||||
  public function testDynamicPermissions(): void {
 | 
			
		||||
    $permissions = $this->permissionHandler->getPermissions();
 | 
			
		||||
    $this->assertArrayNotHasKey('edit any basic block content', $permissions, 'The per-block-type permission does not exist.');
 | 
			
		||||
    $this->assertArrayNotHasKey('edit any square block content', $permissions, 'The per-block-type permission does not exist.');
 | 
			
		||||
 | 
			
		||||
    // Create a basic block content type.
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id'          => 'basic',
 | 
			
		||||
      'label'       => 'A basic block type',
 | 
			
		||||
      'description' => 'Provides a basic block type',
 | 
			
		||||
    ])->save();
 | 
			
		||||
 | 
			
		||||
    // Create a square block content type.
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id'          => 'square',
 | 
			
		||||
      'label'       => 'A square block type',
 | 
			
		||||
      'description' => 'Provides a block type that is square',
 | 
			
		||||
    ])->save();
 | 
			
		||||
 | 
			
		||||
    $permissions = $this->permissionHandler->getPermissions();
 | 
			
		||||
 | 
			
		||||
    // Assert the basic permission has been created.
 | 
			
		||||
    $this->assertArrayHasKey('edit any basic block content', $permissions, 'The per-block-type permission exists.');
 | 
			
		||||
    $this->assertEquals(
 | 
			
		||||
      '<em class="placeholder">A basic block type</em>: Edit content block',
 | 
			
		||||
      $permissions['edit any basic block content']['title']->render()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Assert the square permission has been created.
 | 
			
		||||
    $this->assertArrayHasKey('edit any square block content', $permissions, 'The per-block-type permission exists.');
 | 
			
		||||
    $this->assertEquals(
 | 
			
		||||
      '<em class="placeholder">A square block type</em>: Edit content block',
 | 
			
		||||
      $permissions['edit any square block content']['title']->render()
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests revision based functions for Block Content.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentRevisionsTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'system',
 | 
			
		||||
    'user',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests block content revision user id doesn't throw error with null field.
 | 
			
		||||
   */
 | 
			
		||||
  public function testNullRevisionUser(): void {
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'A basic block type',
 | 
			
		||||
    ])->save();
 | 
			
		||||
 | 
			
		||||
    $block = BlockContent::create([
 | 
			
		||||
      'info' => 'Test',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'revision_user' => NULL,
 | 
			
		||||
    ]);
 | 
			
		||||
    $block->save();
 | 
			
		||||
    $this->assertNull($block->getRevisionUserId());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,79 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block\Entity\Block;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Component\Plugin\PluginBase;
 | 
			
		||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\Tests\user\Traits\UserCreationTrait;
 | 
			
		||||
use Drupal\block_content\Hook\BlockContentHooks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the block content.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  use UserCreationTrait;
 | 
			
		||||
  use StringTranslationTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'system', 'user'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the editing links for BlockContentBlock.
 | 
			
		||||
   */
 | 
			
		||||
  public function testOperationLinks(): void {
 | 
			
		||||
    // Create a block content type.
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id' => 'spiffy',
 | 
			
		||||
      'label' => 'Very spiffy',
 | 
			
		||||
      'description' => "Provides a block type that increases your site's spiffy rating by up to 11%",
 | 
			
		||||
    ])->save();
 | 
			
		||||
    // And a block content entity.
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Spiffy prototype',
 | 
			
		||||
      'type' => 'spiffy',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
    $block = Block::create([
 | 
			
		||||
      'plugin' => 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid(),
 | 
			
		||||
      'region' => 'content',
 | 
			
		||||
      'id' => 'machine_name',
 | 
			
		||||
      'theme' => 'stark',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    // The anonymous user doesn't have the "administer block" permission.
 | 
			
		||||
    $blockContentEntityOperation = new BlockContentHooks();
 | 
			
		||||
    $this->assertEmpty($blockContentEntityOperation->entityOperation($block));
 | 
			
		||||
 | 
			
		||||
    $this->setUpCurrentUser(['uid' => 1], ['edit any spiffy block content', 'administer blocks']);
 | 
			
		||||
 | 
			
		||||
    // The admin user does have the "administer block" permission.
 | 
			
		||||
    $this->assertEquals([
 | 
			
		||||
      'block-edit' => [
 | 
			
		||||
        'title' => 'Edit block',
 | 
			
		||||
        'url' => $block_content->toUrl('edit-form')->setOptions([]),
 | 
			
		||||
        'weight' => 50,
 | 
			
		||||
      ],
 | 
			
		||||
    ], $blockContentEntityOperation->entityOperation($block));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\KernelTests\Core\Config\ConfigEntityValidationTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests validation of block_content_type entities.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 * @group #slow
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentTypeValidationTest extends ConfigEntityValidationTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static array $propertiesWithOptionalValues = ['description'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $this->entity = BlockContentType::create([
 | 
			
		||||
      'id' => 'test',
 | 
			
		||||
      'label' => 'Test',
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->entity->save();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel;
 | 
			
		||||
 | 
			
		||||
use Drupal\block\Entity\Block;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\block_content\Hook\BlockContentHooks;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the block_content_theme_suggestions_block() function.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockTemplateSuggestionsTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'user',
 | 
			
		||||
    'block',
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'system',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The BlockContent entity used for testing.
 | 
			
		||||
   *
 | 
			
		||||
   * @var \Drupal\block_content\Entity\BlockContent
 | 
			
		||||
   */
 | 
			
		||||
  protected $blockContent;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
 | 
			
		||||
    // Create a block content type.
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'test_block',
 | 
			
		||||
      'label' => 'A test block type',
 | 
			
		||||
      'description' => "Provides a test block type.",
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
 | 
			
		||||
    $this->blockContent = BlockContent::create([
 | 
			
		||||
      'info' => 'The Test Block',
 | 
			
		||||
      'type' => 'test_block',
 | 
			
		||||
    ]);
 | 
			
		||||
    $this->blockContent->save();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests template suggestions from block_content_theme_suggestions_block().
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockThemeHookSuggestions(): void {
 | 
			
		||||
    // Create a block using a block_content plugin.
 | 
			
		||||
    $block = Block::create([
 | 
			
		||||
      'plugin' => 'block_content:' . $this->blockContent->uuid(),
 | 
			
		||||
      'region' => 'footer',
 | 
			
		||||
      'id' => 'machine_name',
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    $variables['elements']['#id'] = $block->id();
 | 
			
		||||
    $variables['elements']['content']['#block_content'] = $this->blockContent;
 | 
			
		||||
    $variables['elements']['content']['#view_mode'] = 'full';
 | 
			
		||||
    $suggestions = [];
 | 
			
		||||
    $suggestions[] = 'block__block_content__' . $block->uuid();
 | 
			
		||||
    $blockTemplateSuggestionsAlter = new BlockContentHooks();
 | 
			
		||||
    $blockTemplateSuggestionsAlter->themeSuggestionsBlockAlter($suggestions, $variables);
 | 
			
		||||
 | 
			
		||||
    $this->assertSame([
 | 
			
		||||
      'block__block_content__' . $block->uuid(),
 | 
			
		||||
      'block__block_content__view__full',
 | 
			
		||||
      'block__block_content__type__test_block',
 | 
			
		||||
      'block__block_content__view_type__test_block__full',
 | 
			
		||||
      'block__block_content__id__machine_name',
 | 
			
		||||
      'block__block_content__id_view__machine_name__full',
 | 
			
		||||
    ], $suggestions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,58 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
 | 
			
		||||
 | 
			
		||||
use Drupal\field\Entity\FieldConfig;
 | 
			
		||||
use Drupal\field\Entity\FieldStorageConfig;
 | 
			
		||||
use Drupal\field\FieldConfigInterface;
 | 
			
		||||
use Drupal\field\FieldStorageConfigInterface;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Attaches a body field to the block type.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class MigrateBlockContentBodyFieldTest extends MigrateDrupal7TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'filter', 'text'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(['block_content']);
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the block content body field migration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentBodyFieldMigration(): void {
 | 
			
		||||
    /** @var \Drupal\field\FieldStorageConfigInterface $storage */
 | 
			
		||||
    $storage = FieldStorageConfig::load('block_content.body');
 | 
			
		||||
    $this->assertInstanceOf(FieldStorageConfigInterface::class, $storage);
 | 
			
		||||
    $this->assertSame('block_content', $storage->getTargetEntityTypeId());
 | 
			
		||||
    $this->assertSame(['basic'], array_values($storage->getBundles()));
 | 
			
		||||
    $this->assertSame('body', $storage->getName());
 | 
			
		||||
 | 
			
		||||
    /** @var \Drupal\field\FieldConfigInterface $field */
 | 
			
		||||
    $field = FieldConfig::load('block_content.basic.body');
 | 
			
		||||
    $this->assertInstanceOf(FieldConfigInterface::class, $field);
 | 
			
		||||
    $this->assertSame('block_content', $field->getTargetEntityTypeId());
 | 
			
		||||
    $this->assertSame('basic', $field->getTargetBundle());
 | 
			
		||||
    $this->assertSame('body', $field->getName());
 | 
			
		||||
    $this->assertSame('Body', $field->getLabel());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests migration of block content body field display configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class MigrateBlockContentEntityDisplayTest extends MigrateDrupal7TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'filter', 'text'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(static::$modules);
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
      'block_content_entity_display',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Asserts a display entity.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $id
 | 
			
		||||
   *   The entity ID.
 | 
			
		||||
   * @param string $component_id
 | 
			
		||||
   *   The ID of the display component.
 | 
			
		||||
   *
 | 
			
		||||
   * @internal
 | 
			
		||||
   */
 | 
			
		||||
  protected function assertDisplay(string $id, string $component_id): void {
 | 
			
		||||
    $component = EntityViewDisplay::load($id)->getComponent($component_id);
 | 
			
		||||
    $this->assertIsArray($component);
 | 
			
		||||
    $this->assertSame('hidden', $component['label']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the migrated display configuration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testMigration(): void {
 | 
			
		||||
    $this->assertDisplay('block_content.basic.default', 'body');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests migration of block content body field form display configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class MigrateBlockContentEntityFormDisplayTest extends MigrateDrupal7TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'filter', 'text'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(static::$modules);
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
      'block_content_entity_form_display',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Asserts a display entity.
 | 
			
		||||
   *
 | 
			
		||||
   * @param string $id
 | 
			
		||||
   *   The entity ID.
 | 
			
		||||
   * @param string $component_id
 | 
			
		||||
   *   The ID of the form component.
 | 
			
		||||
   *
 | 
			
		||||
   * @internal
 | 
			
		||||
   */
 | 
			
		||||
  protected function assertDisplay(string $id, string $component_id): void {
 | 
			
		||||
    $component = EntityFormDisplay::load($id)->getComponent($component_id);
 | 
			
		||||
    $this->assertIsArray($component);
 | 
			
		||||
    $this->assertSame('text_textarea_with_summary', $component['type']);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the migrated display configuration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testMigration(): void {
 | 
			
		||||
    $this->assertDisplay('block_content.basic.default', 'body');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\migrate\MigrateException;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
 | 
			
		||||
use Drupal\migrate_drupal\Tests\StubTestTrait;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test stub creation for block_content entities.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class MigrateBlockContentStubTest extends MigrateDrupalTestBase {
 | 
			
		||||
 | 
			
		||||
  use StubTestTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests creation of block content stubs with no block_content_type available.
 | 
			
		||||
   */
 | 
			
		||||
  public function testStubFailure(): void {
 | 
			
		||||
    // Expected MigrateException thrown when no bundles exist.
 | 
			
		||||
    $this->expectException(MigrateException::class);
 | 
			
		||||
    $this->expectExceptionMessage('Stubbing failed, no bundles available for entity type: block_content');
 | 
			
		||||
    $this->createEntityStub('block_content');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests creation of block content stubs when there is a block_content_type.
 | 
			
		||||
   */
 | 
			
		||||
  public function testStubSuccess(): void {
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id' => 'test_block_content_type',
 | 
			
		||||
      'label' => 'Test block content type',
 | 
			
		||||
    ])->save();
 | 
			
		||||
    $this->performStubTest('block_content');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,43 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\BlockContentTypeInterface;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests migration of the basic block content type.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class MigrateBlockContentTypeTest extends MigrateDrupal7TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content', 'filter', 'text'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(['block_content']);
 | 
			
		||||
    $this->executeMigration('block_content_type');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the block content type migration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentTypeMigration(): void {
 | 
			
		||||
    /** @var \Drupal\block_content\BlockContentTypeInterface $entity */
 | 
			
		||||
    $entity = BlockContentType::load('basic');
 | 
			
		||||
    $this->assertInstanceOf(BlockContentTypeInterface::class, $entity);
 | 
			
		||||
    $this->assertSame('Basic', $entity->label());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,62 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Upgrade content blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * @group migrate_drupal_6
 | 
			
		||||
 */
 | 
			
		||||
class MigrateBlockContentTest extends MigrateDrupal6TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block', 'block_content'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(['block_content']);
 | 
			
		||||
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'd6_filter_format',
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
      'd6_custom_block',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the Drupal 6 content block to Drupal 8 migration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockMigration(): void {
 | 
			
		||||
    /** @var \Drupal\block_content\Entity\BlockContent $block */
 | 
			
		||||
    $block = BlockContent::load(1);
 | 
			
		||||
    $this->assertSame('My block 1', $block->label());
 | 
			
		||||
    $requestTime = \Drupal::time()->getRequestTime();
 | 
			
		||||
    $this->assertGreaterThanOrEqual($requestTime, (int) $block->getChangedTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('en', $block->language()->getId());
 | 
			
		||||
    $this->assertSame('<h3>My first content block body</h3>', $block->body->value);
 | 
			
		||||
    $this->assertSame('full_html', $block->body->format);
 | 
			
		||||
 | 
			
		||||
    $block = BlockContent::load(2);
 | 
			
		||||
    $this->assertSame('My block 2', $block->label());
 | 
			
		||||
    $this->assertGreaterThanOrEqual($requestTime, (int) $block->getChangedTime());
 | 
			
		||||
    $this->assertGreaterThanOrEqual($requestTime, (int) $block->getChangedTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('en', $block->language()->getId());
 | 
			
		||||
    $this->assertSame('<h3>My second content block body</h3>', $block->body->value);
 | 
			
		||||
    $this->assertSame('full_html', $block->body->format);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,73 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d6;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests migration of i18n content block strings.
 | 
			
		||||
 *
 | 
			
		||||
 * @group migrate_drupal_6
 | 
			
		||||
 */
 | 
			
		||||
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal6TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'content_translation',
 | 
			
		||||
    'language',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(['block_content']);
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'language',
 | 
			
		||||
      'd6_filter_format',
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
      'd6_custom_block',
 | 
			
		||||
      'd6_custom_block_translation',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the Drupal 6 i18n content block strings to Drupal 8 migration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testCustomBlockContentTranslation(): void {
 | 
			
		||||
    /** @var \Drupal\block_content\Entity\BlockContent $block */
 | 
			
		||||
    $block = BlockContent::load(1)->getTranslation('fr');
 | 
			
		||||
    $this->assertSame('fr - Static Block', $block->label());
 | 
			
		||||
    $this->assertGreaterThanOrEqual(\Drupal::time()->getRequestTime(), $block->getChangedTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('fr', $block->language()->getId());
 | 
			
		||||
    $this->assertSame('<h3>fr - My first content block body</h3>', $block->body->value);
 | 
			
		||||
    $this->assertSame('full_html', $block->body->format);
 | 
			
		||||
 | 
			
		||||
    $block = $block->getTranslation('zu');
 | 
			
		||||
    $this->assertSame('My block 1', $block->label());
 | 
			
		||||
    $this->assertGreaterThanOrEqual(\Drupal::time()->getRequestTime(), $block->getChangedTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('zu', $block->language()->getId());
 | 
			
		||||
    $this->assertSame('<h3>zu - My first content block body</h3>', $block->body->value);
 | 
			
		||||
    $this->assertSame('full_html', $block->body->format);
 | 
			
		||||
 | 
			
		||||
    $block = BlockContent::load(2)->getTranslation('fr');
 | 
			
		||||
    $this->assertSame('Encore un bloc statique', $block->label());
 | 
			
		||||
    $this->assertGreaterThanOrEqual(\Drupal::time()->getRequestTime(), $block->getChangedTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('fr', $block->language()->getId());
 | 
			
		||||
    $this->assertSame('Nom de vocabulaire beaucoup plus long que trente-deux caractères', $block->body->value);
 | 
			
		||||
    $this->assertSame('full_html', $block->body->format);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,69 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d7;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests migration of i18n content block strings.
 | 
			
		||||
 *
 | 
			
		||||
 * @group migrate_drupal_7
 | 
			
		||||
 */
 | 
			
		||||
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal7TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'content_translation',
 | 
			
		||||
    'filter',
 | 
			
		||||
    'language',
 | 
			
		||||
    'text',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(['block_content']);
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'language',
 | 
			
		||||
      'd7_filter_format',
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
      'd7_custom_block',
 | 
			
		||||
      'd7_custom_block_translation',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the Drupal 7 i18n content block strings to Drupal 8 migration.
 | 
			
		||||
   */
 | 
			
		||||
  public function testCustomBlockContentTranslation(): void {
 | 
			
		||||
    /** @var \Drupal\block_content\Entity\BlockContent $block */
 | 
			
		||||
    $block = BlockContent::load(1)->getTranslation('fr');
 | 
			
		||||
    $this->assertSame('fr - Mildly amusing limerick of the day', $block->label());
 | 
			
		||||
    $this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('fr', $block->language()->getId());
 | 
			
		||||
    $translation = "fr - A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
 | 
			
		||||
    $this->assertSame($translation, $block->body->value);
 | 
			
		||||
    $this->assertSame('filtered_html', $block->body->format);
 | 
			
		||||
 | 
			
		||||
    $block = $block->getTranslation('is');
 | 
			
		||||
    $this->assertSame('is - Mildly amusing limerick of the day', $block->label());
 | 
			
		||||
    $this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
 | 
			
		||||
    $this->assertLessThanOrEqual(time(), $block->getChangedTime());
 | 
			
		||||
    $this->assertSame('is', $block->language()->getId());
 | 
			
		||||
    $text = "A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
 | 
			
		||||
    $this->assertSame($text, $block->body->value);
 | 
			
		||||
    $this->assertSame('filtered_html', $block->body->format);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,57 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d7;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\BlockContentInterface;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests migration of content blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class MigrateCustomBlockTest extends MigrateDrupal7TestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'filter',
 | 
			
		||||
    'text',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installConfig(static::$modules);
 | 
			
		||||
 | 
			
		||||
    $this->executeMigrations([
 | 
			
		||||
      'd7_filter_format',
 | 
			
		||||
      'block_content_type',
 | 
			
		||||
      'block_content_body_field',
 | 
			
		||||
      'd7_custom_block',
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests migration of content blocks from Drupal 7 to Drupal 8.
 | 
			
		||||
   */
 | 
			
		||||
  public function testCustomBlockMigration(): void {
 | 
			
		||||
    $block = BlockContent::load(1);
 | 
			
		||||
    $this->assertInstanceOf(BlockContentInterface::class, $block);
 | 
			
		||||
    /** @var \Drupal\block_content\BlockContentInterface $block */
 | 
			
		||||
    $this->assertSame('Limerick', $block->label());
 | 
			
		||||
 | 
			
		||||
    $expected_body = "A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
 | 
			
		||||
    $this->assertSame($expected_body, $block->body->value);
 | 
			
		||||
    $this->assertSame('filtered_html', $block->body->format);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,48 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests D6 block boxes source plugin.
 | 
			
		||||
 *
 | 
			
		||||
 * @covers \Drupal\block_content\Plugin\migrate\source\d6\Box
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BoxTest extends MigrateSqlSourceTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content', 'migrate_drupal'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public static function providerSource() {
 | 
			
		||||
    $tests = [];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['boxes'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 1,
 | 
			
		||||
        'body' => '<p>I made some custom content.</p>',
 | 
			
		||||
        'info' => 'Static Block',
 | 
			
		||||
        'format' => 1,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 2,
 | 
			
		||||
        'body' => '<p>I made some more custom content.</p>',
 | 
			
		||||
        'info' => 'Test Content',
 | 
			
		||||
        'format' => 1,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    // The expected results are identical to the source data.
 | 
			
		||||
    $tests[0]['expected_data'] = $tests[0]['source_data']['boxes'];
 | 
			
		||||
 | 
			
		||||
    return $tests;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,143 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d6;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
 | 
			
		||||
 | 
			
		||||
// cspell:ignore objectid objectindex plid
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests i18n content block translations source plugin.
 | 
			
		||||
 *
 | 
			
		||||
 * @covers \Drupal\block_content\Plugin\migrate\source\d6\BoxTranslation
 | 
			
		||||
 *
 | 
			
		||||
 * @group content_translation
 | 
			
		||||
 */
 | 
			
		||||
class BoxTranslationTest extends MigrateSqlSourceTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content', 'migrate_drupal'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public static function providerSource() {
 | 
			
		||||
    $tests = [];
 | 
			
		||||
 | 
			
		||||
    // The source data.
 | 
			
		||||
    $tests[0]['source_data']['boxes'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 1,
 | 
			
		||||
        'body' => 'box 1 body',
 | 
			
		||||
        'info' => 'box 1 title',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 2,
 | 
			
		||||
        'body' => 'box 2 body',
 | 
			
		||||
        'info' => 'box 2 title',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['i18n_strings'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 1,
 | 
			
		||||
        'objectid' => 1,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'title',
 | 
			
		||||
        'objectindex' => 1,
 | 
			
		||||
        'format' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 2,
 | 
			
		||||
        'objectid' => 1,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'objectindex' => 1,
 | 
			
		||||
        'format' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 3,
 | 
			
		||||
        'objectid' => 2,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'objectindex' => 2,
 | 
			
		||||
        'format' => 2,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['locales_target'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 1,
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - title translation',
 | 
			
		||||
        'plid' => 0,
 | 
			
		||||
        'plural' => 0,
 | 
			
		||||
        'i18n_status' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 2,
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - body translation',
 | 
			
		||||
        'plid' => 0,
 | 
			
		||||
        'plural' => 0,
 | 
			
		||||
        'i18n_status' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 3,
 | 
			
		||||
        'language' => 'zu',
 | 
			
		||||
        'translation' => 'zu - body translation',
 | 
			
		||||
        'plid' => 0,
 | 
			
		||||
        'plural' => 0,
 | 
			
		||||
        'i18n_status' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['expected_data'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => '1',
 | 
			
		||||
        'property' => 'title',
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - title translation',
 | 
			
		||||
        'bid' => '1',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
        'title_translated' => 'fr - title translation',
 | 
			
		||||
        'body_translated' => 'fr - body translation',
 | 
			
		||||
        'title' => 'box 1 title',
 | 
			
		||||
        'body' => 'box 1 body',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => '2',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - body translation',
 | 
			
		||||
        'bid' => '1',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
        'title_translated' => 'fr - title translation',
 | 
			
		||||
        'body_translated' => 'fr - body translation',
 | 
			
		||||
        'title' => 'box 1 title',
 | 
			
		||||
        'body' => 'box 1 body',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => '3',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'language' => 'zu',
 | 
			
		||||
        'translation' => 'zu - body translation',
 | 
			
		||||
        'bid' => '2',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
        'title_translated' => NULL,
 | 
			
		||||
        'body_translated' => 'zu - body translation',
 | 
			
		||||
        'title' => 'box 2 title',
 | 
			
		||||
        'body' => 'box 2 body',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return $tests;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests d7_block_custom source plugin.
 | 
			
		||||
 *
 | 
			
		||||
 * @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustom
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockCustomTest extends MigrateSqlSourceTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content', 'migrate_drupal'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public static function providerSource() {
 | 
			
		||||
    $tests = [];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['block_custom'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => '1',
 | 
			
		||||
        'body' => "I don't feel creative enough to write anything clever here.",
 | 
			
		||||
        'info' => 'Meh',
 | 
			
		||||
        'format' => 'filtered_html',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    // The expected results are identical to the source data.
 | 
			
		||||
    $tests[0]['expected_data'] = $tests[0]['source_data']['block_custom'];
 | 
			
		||||
 | 
			
		||||
    return $tests;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,166 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
 | 
			
		||||
 | 
			
		||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
 | 
			
		||||
 | 
			
		||||
// cspell:ignore objectid objectindex plid
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests i18n content block translations source plugin.
 | 
			
		||||
 *
 | 
			
		||||
 * @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustomTranslation
 | 
			
		||||
 *
 | 
			
		||||
 * @group content_translation
 | 
			
		||||
 */
 | 
			
		||||
class BlockCustomTranslationTest extends MigrateSqlSourceTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = ['block_content', 'migrate_drupal'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public static function providerSource() {
 | 
			
		||||
    $tests = [];
 | 
			
		||||
 | 
			
		||||
    // The source data.
 | 
			
		||||
    $tests[0]['source_data']['block_custom'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 1,
 | 
			
		||||
        'body' => 'box 1 body',
 | 
			
		||||
        'info' => 'box 1 title',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 2,
 | 
			
		||||
        'body' => 'box 2 body',
 | 
			
		||||
        'info' => 'box 2 title',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'bid' => 4,
 | 
			
		||||
        'body' => 'box 2 body',
 | 
			
		||||
        'info' => 'box 2 title',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['i18n_string'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 1,
 | 
			
		||||
        'objectid' => 1,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'title',
 | 
			
		||||
        'objectindex' => 1,
 | 
			
		||||
        'format' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 2,
 | 
			
		||||
        'objectid' => 1,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'objectindex' => 1,
 | 
			
		||||
        'format' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 3,
 | 
			
		||||
        'objectid' => 2,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'objectindex' => 2,
 | 
			
		||||
        'format' => 2,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 4,
 | 
			
		||||
        'objectid' => 4,
 | 
			
		||||
        'type' => 'block',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'objectindex' => 4,
 | 
			
		||||
        'format' => 2,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['locales_target'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 1,
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - title translation',
 | 
			
		||||
        'plid' => 0,
 | 
			
		||||
        'plural' => 0,
 | 
			
		||||
        'i18n_status' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 2,
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - body translation',
 | 
			
		||||
        'plid' => 0,
 | 
			
		||||
        'plural' => 0,
 | 
			
		||||
        'i18n_status' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => 3,
 | 
			
		||||
        'language' => 'zu',
 | 
			
		||||
        'translation' => 'zu - body translation',
 | 
			
		||||
        'plid' => 0,
 | 
			
		||||
        'plural' => 0,
 | 
			
		||||
        'i18n_status' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['source_data']['system'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'type' => 'module',
 | 
			
		||||
        'name' => 'system',
 | 
			
		||||
        'schema_version' => '7001',
 | 
			
		||||
        'status' => '1',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $tests[0]['expected_data'] = [
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => '1',
 | 
			
		||||
        'property' => 'title',
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - title translation',
 | 
			
		||||
        'bid' => '1',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
        'title_translated' => 'fr - title translation',
 | 
			
		||||
        'body_translated' => 'fr - body translation',
 | 
			
		||||
        'title' => 'box 1 title',
 | 
			
		||||
        'body' => 'box 1 body',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => '2',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'language' => 'fr',
 | 
			
		||||
        'translation' => 'fr - body translation',
 | 
			
		||||
        'bid' => '1',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
        'title_translated' => 'fr - title translation',
 | 
			
		||||
        'body_translated' => 'fr - body translation',
 | 
			
		||||
        'title' => 'box 1 title',
 | 
			
		||||
        'body' => 'box 1 body',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'lid' => '3',
 | 
			
		||||
        'property' => 'body',
 | 
			
		||||
        'language' => 'zu',
 | 
			
		||||
        'translation' => 'zu - body translation',
 | 
			
		||||
        'bid' => '2',
 | 
			
		||||
        'format' => '2',
 | 
			
		||||
        'title_translated' => NULL,
 | 
			
		||||
        'body_translated' => 'zu - body translation',
 | 
			
		||||
        'title' => 'box 2 title',
 | 
			
		||||
        'body' => 'box 2 body',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return $tests;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,77 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Views;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
 | 
			
		||||
use Drupal\views\Tests\ViewTestData;
 | 
			
		||||
use Drupal\views\Views;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the Drupal\block_content\Plugin\views\field\Type handler.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class FieldTypeTest extends ViewsKernelTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'block_content_test_views',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Views used by this test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $testViews = ['test_field_type'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp($import_test_views = TRUE): void {
 | 
			
		||||
    parent::setUp($import_test_views);
 | 
			
		||||
 | 
			
		||||
    if ($import_test_views) {
 | 
			
		||||
      ViewTestData::createTestViews(get_class($this), ['block_content_test_views']);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the field type.
 | 
			
		||||
   */
 | 
			
		||||
  public function testFieldType(): void {
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'basic',
 | 
			
		||||
      'revision' => FALSE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => $this->randomMachineName(),
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'langcode' => 'en',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $expected_result[] = [
 | 
			
		||||
      'id' => $block_content->id(),
 | 
			
		||||
      'type' => $block_content->bundle(),
 | 
			
		||||
    ];
 | 
			
		||||
    $column_map = [
 | 
			
		||||
      'id' => 'id',
 | 
			
		||||
      'type:target_id' => 'type',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    $view = Views::getView('test_field_type');
 | 
			
		||||
    $this->executeView($view);
 | 
			
		||||
    $this->assertIdenticalResultset($view, $expected_result, $column_map, 'The correct block_content type was displayed.');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,102 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Views;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\KernelTests\KernelTestBase;
 | 
			
		||||
use Drupal\views\Tests\ViewResultAssertionTrait;
 | 
			
		||||
use Drupal\views\Tests\ViewTestData;
 | 
			
		||||
use Drupal\views\Views;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the integration of block_content_revision table.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class RevisionRelationshipsTest extends KernelTestBase {
 | 
			
		||||
 | 
			
		||||
  use ViewResultAssertionTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'block_content_test_views',
 | 
			
		||||
    'system',
 | 
			
		||||
    'user',
 | 
			
		||||
    'views',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Views used by this test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $testViews = [
 | 
			
		||||
    'test_block_content_revision_id',
 | 
			
		||||
    'test_block_content_revision_revision_id',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a block_content with revision and rest result count for both views.
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentRevisionRelationship(): void {
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    ViewTestData::createTestViews(static::class, ['block_content_test_views']);
 | 
			
		||||
 | 
			
		||||
    BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'basic',
 | 
			
		||||
      'revision' => TRUE,
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => $this->randomMachineName(),
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
      'langcode' => 'en',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
    // Create revision of the block_content.
 | 
			
		||||
    $block_content_revision = clone $block_content;
 | 
			
		||||
    $block_content_revision->setNewRevision();
 | 
			
		||||
    $block_content_revision->save();
 | 
			
		||||
    $column_map = [
 | 
			
		||||
      'revision_id' => 'revision_id',
 | 
			
		||||
      'id_1' => 'id_1',
 | 
			
		||||
      'block_content_field_data_block_content_field_revision_id' => 'block_content_field_data_block_content_field_revision_id',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    // Here should be two rows.
 | 
			
		||||
    $view = Views::getView('test_block_content_revision_id');
 | 
			
		||||
    $view->preview(NULL, [$block_content->id()]);
 | 
			
		||||
    $resultset_id = [
 | 
			
		||||
      [
 | 
			
		||||
        'revision_id' => '1',
 | 
			
		||||
        'id_1' => '1',
 | 
			
		||||
        'block_content_field_data_block_content_field_revision_id' => '1',
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'revision_id' => '2',
 | 
			
		||||
        'id_1' => '1',
 | 
			
		||||
        'block_content_field_data_block_content_field_revision_id' => '1',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    $this->assertIdenticalResultset($view, $resultset_id, $column_map);
 | 
			
		||||
 | 
			
		||||
    // There should be only one row with active revision 2.
 | 
			
		||||
    $view_revision = Views::getView('test_block_content_revision_revision_id');
 | 
			
		||||
    $view_revision->preview(NULL, [$block_content->id()]);
 | 
			
		||||
    $resultset_revision_id = [
 | 
			
		||||
      [
 | 
			
		||||
        'revision_id' => '2',
 | 
			
		||||
        'id_1' => '1',
 | 
			
		||||
        'block_content_field_data_block_content_field_revision_id' => '1',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    $this->assertIdenticalResultset($view_revision, $resultset_revision_id, $column_map);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,153 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Kernel\Views;
 | 
			
		||||
 | 
			
		||||
use Drupal\block_content\Entity\BlockContent;
 | 
			
		||||
use Drupal\block_content\Entity\BlockContentType;
 | 
			
		||||
use Drupal\Tests\user\Traits\UserCreationTrait;
 | 
			
		||||
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
 | 
			
		||||
use Drupal\views\Tests\ViewResultAssertionTrait;
 | 
			
		||||
use Drupal\views\Tests\ViewTestData;
 | 
			
		||||
use Drupal\views\Views;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the block_content_revision_user field.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class RevisionUserTest extends ViewsKernelTestBase {
 | 
			
		||||
 | 
			
		||||
  use UserCreationTrait;
 | 
			
		||||
  use ViewResultAssertionTrait;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected static $modules = [
 | 
			
		||||
    'block_content',
 | 
			
		||||
    'block_content_test_views',
 | 
			
		||||
    'system',
 | 
			
		||||
    'user',
 | 
			
		||||
    'views',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Views used by this test.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $testViews = ['test_block_content_revision_user'];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Map column names.
 | 
			
		||||
   *
 | 
			
		||||
   * @var array
 | 
			
		||||
   */
 | 
			
		||||
  public static $columnMap = [
 | 
			
		||||
    'id' => 'id',
 | 
			
		||||
    'revision_id' => 'revision_id',
 | 
			
		||||
    'revision_user' => 'revision_user',
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp($import_test_views = TRUE): void {
 | 
			
		||||
    parent::setUp($import_test_views);
 | 
			
		||||
 | 
			
		||||
    $this->installEntitySchema('block_content');
 | 
			
		||||
    $this->installEntitySchema('user');
 | 
			
		||||
 | 
			
		||||
    if ($import_test_views) {
 | 
			
		||||
      ViewTestData::createTestViews(get_class($this), ['block_content_test_views']);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Tests the block_content_revision_user relationship.
 | 
			
		||||
   */
 | 
			
		||||
  public function testRevisionUser(): void {
 | 
			
		||||
    $primary_author = $this->createUser();
 | 
			
		||||
    $secondary_author = $this->createUser();
 | 
			
		||||
 | 
			
		||||
    $block_content_type = BlockContentType::create([
 | 
			
		||||
      'id' => 'basic',
 | 
			
		||||
      'label' => 'basic block',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content_type->save();
 | 
			
		||||
 | 
			
		||||
    $block_content = BlockContent::create([
 | 
			
		||||
      'info' => 'Test block content',
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content->setRevisionUserId($primary_author->id());
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $view = Views::getView('test_block_content_revision_user');
 | 
			
		||||
    $this->executeView($view);
 | 
			
		||||
    $this->assertIdenticalResultset($view, [
 | 
			
		||||
      [
 | 
			
		||||
        'id' => 1,
 | 
			
		||||
        'revision_id' => 1,
 | 
			
		||||
        'revision_user' => $primary_author->id(),
 | 
			
		||||
      ],
 | 
			
		||||
    ], static::$columnMap);
 | 
			
		||||
 | 
			
		||||
    // Test results shows the revision author.
 | 
			
		||||
    $block_content->setRevisionUser($secondary_author);
 | 
			
		||||
    $block_content->setNewRevision();
 | 
			
		||||
    $block_content->save();
 | 
			
		||||
 | 
			
		||||
    $view = Views::getView('test_block_content_revision_user');
 | 
			
		||||
    $this->executeView($view);
 | 
			
		||||
    $this->assertIdenticalResultset($view, [
 | 
			
		||||
      [
 | 
			
		||||
        'id' => 1,
 | 
			
		||||
        'revision_id' => 2,
 | 
			
		||||
        'revision_user' => $secondary_author->id(),
 | 
			
		||||
      ],
 | 
			
		||||
    ], static::$columnMap);
 | 
			
		||||
 | 
			
		||||
    // Build a larger dataset to allow filtering.
 | 
			
		||||
    $block_content2_title = $this->randomString();
 | 
			
		||||
    $block_content2 = BlockContent::create([
 | 
			
		||||
      'info' => $block_content2_title,
 | 
			
		||||
      'type' => 'basic',
 | 
			
		||||
    ]);
 | 
			
		||||
    $block_content2->save();
 | 
			
		||||
    $block_content2->setRevisionUser($primary_author);
 | 
			
		||||
    $block_content2->setNewRevision();
 | 
			
		||||
    $block_content2->save();
 | 
			
		||||
 | 
			
		||||
    $view = Views::getView('test_block_content_revision_user');
 | 
			
		||||
    $this->executeView($view);
 | 
			
		||||
    $this->assertIdenticalResultset($view, [
 | 
			
		||||
      [
 | 
			
		||||
        'id' => 1,
 | 
			
		||||
        'revision_id' => 2,
 | 
			
		||||
        'revision_user' => $secondary_author->id(),
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        'id' => 2,
 | 
			
		||||
        'revision_id' => 4,
 | 
			
		||||
        'revision_user' => $primary_author->id(),
 | 
			
		||||
      ],
 | 
			
		||||
    ], static::$columnMap);
 | 
			
		||||
 | 
			
		||||
    // Test filter by revision_author.
 | 
			
		||||
    $view = Views::getView('test_block_content_revision_user');
 | 
			
		||||
    $view->initHandlers();
 | 
			
		||||
    $view->filter['revision_user']->value = [$secondary_author->id()];
 | 
			
		||||
    $this->executeView($view);
 | 
			
		||||
    $this->assertIdenticalResultset($view, [
 | 
			
		||||
      [
 | 
			
		||||
        'id' => 1,
 | 
			
		||||
        'revision_id' => 2,
 | 
			
		||||
        'revision_user' => $secondary_author->id(),
 | 
			
		||||
      ],
 | 
			
		||||
    ], static::$columnMap);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Drupal\Tests\block_content\Unit\Menu;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
 | 
			
		||||
use Drupal\Tests\Core\Menu\LocalTaskIntegrationTestBase;
 | 
			
		||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests existence of block_content local tasks.
 | 
			
		||||
 *
 | 
			
		||||
 * @group block_content
 | 
			
		||||
 */
 | 
			
		||||
class BlockContentLocalTasksTest extends LocalTaskIntegrationTestBase {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  protected function setUp(): void {
 | 
			
		||||
    $this->directoryList = [
 | 
			
		||||
      'system' => 'core/modules/system',
 | 
			
		||||
      'block_content' => 'core/modules/block_content',
 | 
			
		||||
    ];
 | 
			
		||||
    parent::setUp();
 | 
			
		||||
 | 
			
		||||
    $config_factory = $this->getConfigFactoryStub([
 | 
			
		||||
      'system.theme' => ['default' => 'test_c'],
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    $themes = [];
 | 
			
		||||
    $themes['test_a'] = (object) [
 | 
			
		||||
      'status' => 0,
 | 
			
		||||
    ];
 | 
			
		||||
    $themes['test_b'] = (object) [
 | 
			
		||||
      'status' => 1,
 | 
			
		||||
      'info' => [
 | 
			
		||||
        'name' => 'test_b',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    $themes['test_c'] = (object) [
 | 
			
		||||
      'status' => 1,
 | 
			
		||||
      'info' => [
 | 
			
		||||
        'name' => 'test_c',
 | 
			
		||||
      ],
 | 
			
		||||
    ];
 | 
			
		||||
    $theme_handler = $this->createMock('Drupal\Core\Extension\ThemeHandlerInterface');
 | 
			
		||||
    $theme_handler->expects($this->any())
 | 
			
		||||
      ->method('listInfo')
 | 
			
		||||
      ->willReturn($themes);
 | 
			
		||||
 | 
			
		||||
    // Add services required for block local tasks.
 | 
			
		||||
    $entity_type_manager = $this->createMock(EntityTypeManagerInterface::class);
 | 
			
		||||
    $entity_type_manager->expects($this->any())
 | 
			
		||||
      ->method('getDefinitions')
 | 
			
		||||
      ->willReturn([]);
 | 
			
		||||
 | 
			
		||||
    $container = new ContainerBuilder();
 | 
			
		||||
    $container->set('config.factory', $config_factory);
 | 
			
		||||
    $container->set('theme_handler', $theme_handler);
 | 
			
		||||
    $container->set('entity_type.manager', $entity_type_manager);
 | 
			
		||||
    \Drupal::setContainer($container);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Checks block_content listing local tasks.
 | 
			
		||||
   *
 | 
			
		||||
   * @dataProvider getBlockContentListingRoutes
 | 
			
		||||
   */
 | 
			
		||||
  public function testBlockContentListLocalTasks($route): void {
 | 
			
		||||
    $this->assertLocalTasks($route, [
 | 
			
		||||
      0 => [
 | 
			
		||||
        'system.admin_content',
 | 
			
		||||
        'entity.block_content.collection',
 | 
			
		||||
      ],
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Provides a list of routes to test.
 | 
			
		||||
   */
 | 
			
		||||
  public static function getBlockContentListingRoutes() {
 | 
			
		||||
    return [
 | 
			
		||||
      ['entity.block_content.collection', 'system.admin_content'],
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user