diff --git a/core/modules/block_content/config/schema/block_content.views.schema.yml b/core/modules/block_content/config/schema/block_content.views.schema.yml new file mode 100644 index 0000000..11101b7 --- /dev/null +++ b/core/modules/block_content/config/schema/block_content.views.schema.yml @@ -0,0 +1,81 @@ +# Schema for the views plugins of the Block Content module. + +views.field.block_content: + type: views_field + label: 'Block Content' + mapping: + link_to_block_content: + type: boolean + label: 'Link this field to the original piece of block content' + +views.field.block_content_link: + type: views_field + label: 'Block Content link' + mapping: + text: + type: label + label: 'Text to display' + +views.field.block_content_link_delete: + type: views_field + label: 'Block Content delete link' + mapping: + text: + type: label + label: 'Text to display' + +views.field.block_content_link_edit: + type: views_field + label: 'Block Content edit link' + mapping: + text: + type: label + label: 'Text to display' + +views.field.block_content_path: + type: views_field + label: 'Block Content path' + mapping: + absolute: + type: boolean + label: 'Use absolute link (begins with "http://")' + +#views.field.block_content_revision: +# type: views.field.node +# label: 'Block Content revision' +# mapping: +# link_to_block_content_revision: +# type: boolean +# label: 'Link this field to its block content revision' + +#views.field.block_content_revision_link: +# type: views_field +# label: 'Link to a block_content revision' +# mapping: +# text: +# type: label +# label: 'Text to display' + +#views.field.block_content_revision_link_delete: +# type: views_field +# label: 'Link to delete a block_content revision' +# mapping: +# text: +# type: label +# label: 'Text to display' + +#views.field.block_content_revision_link_revert: +# type: views_field +# label: 'Link to revert a block_content to a revision' +# mapping: +# text: +# type: label +# label: 'Text to display' + +views.field.block_content_type: + type: views.field.block_content + label: 'Block content type' + mapping: + machine_name: + type: string + label: 'Output machine name' diff --git a/core/modules/block_content/src/BlockContentViewsData.php b/core/modules/block_content/src/BlockContentViewsData.php new file mode 100644 index 0000000..d30277f --- /dev/null +++ b/core/modules/block_content/src/BlockContentViewsData.php @@ -0,0 +1,222 @@ +moduleExists('content_translation')) { + $data['block_content']['translation_link'] = array( + 'title' => t('Translation link'), + 'help' => t('Provide a link to the translations overview for custom blocks.'), + 'field' => array( + 'id' => 'content_translation_link', + ), + ); + } + + $data['block_content']['view_link'] = array( + 'field' => array( + 'title' => t('Link to block content'), + 'help' => t('Provide a simple link to the block content.'), + 'id' => 'block_content_link', + ), + ); + + $data['block_content']['edit_link'] = array( + 'field' => array( + 'title' => t('Link to edit block content'), + 'help' => t('Provide a simple link to edit the block content.'), + 'id' => 'block_content_edit_link', + ), + ); + + $data['block_content']['delete_link'] = array( + 'field' => array( + 'title' => t('Link to delete block content'), + 'help' => t('Provide a simple link to delete the block content.'), + 'id' => 'block_content_delete_link', + ), + ); + + $data['block_content']['path'] = array( + 'field' => array( + 'title' => t('Path'), + 'help' => t('The aliased path to this block content.'), + 'id' => 'block_content_path', + ), + ); + + // @todo Fix this when we support block content bulk form. + // $data['block_content']['block_content_bulk_form'] = array( + // 'title' => t('Block Content operations bulk form'), + // 'help' => t('Add a form element that lets you run operations on multiple block contents.'), + // 'field' => array( + // 'id' => 'block_content_bulk_form', + // ), + // ); + + // Bogus fields for aliasing purposes. + + // @todo Add similar support to any date field + // @see https://drupal.org/node/2337507 + $data['block_content_field_data']['changed_fulldate'] = array( + 'title' => t('Updated date'), + 'help' => t('Date in the form of CCYYMMDD.'), + 'argument' => array( + 'field' => 'changed', + 'id' => 'date_fulldate', + ), + ); + + $data['block_content_field_data']['changed_year_month'] = array( + 'title' => t('Updated year + month'), + 'help' => t('Date in the form of YYYYMM.'), + 'argument' => array( + 'field' => 'changed', + 'id' => 'date_year_month', + ), + ); + + $data['block_content_field_data']['changed_year'] = array( + 'title' => t('Updated year'), + 'help' => t('Date in the form of YYYY.'), + 'argument' => array( + 'field' => 'changed', + 'id' => 'date_year', + ), + ); + + $data['block_content_field_data']['changed_month'] = array( + 'title' => t('Updated month'), + 'help' => t('Date in the form of MM (01 - 12).'), + 'argument' => array( + 'field' => 'changed', + 'id' => 'date_month', + ), + ); + + $data['block_content_field_data']['changed_day'] = array( + 'title' => t('Updated day'), + 'help' => t('Date in the form of DD (01 - 31).'), + 'argument' => array( + 'field' => 'changed', + 'id' => 'date_day', + ), + ); + + $data['block_content_field_data']['changed_week'] = array( + 'title' => t('Updated week'), + 'help' => t('Date in the form of WW (01 - 53).'), + 'argument' => array( + 'field' => 'changed', + 'id' => 'date_week', + ), + ); + + $data['block_content_revision']['table']['wizard_id'] = 'block_content_revision'; + + // Advertise this table as a possible base table. + $data['block_content_revision']['table']['base']['help'] = t('Block Content revision is a history of changes to block content.'); + $data['block_content_revision']['table']['base']['defaults']['title'] = 'info'; + + // @todo the ID field needs different behaviour on revision/non-revision + // tables. It would be neat if this could be encoded in the base field + // definition. + $data['block_content_revision']['id']['relationship']['id'] = 'standard'; + $data['block_content_revision']['id']['relationship']['base'] = 'block_content'; + $data['block_content_revision']['id']['relationship']['base field'] = 'id'; + $data['block_content_revision']['id']['relationship']['title'] = t('Block Content'); + $data['block_content_revision']['id']['relationship']['label'] = t('Get the actual block content from a block content revision.'); + + $data['block_content_revision']['revision_id']['relationship']['id'] = 'standard'; + $data['block_content_revision']['revision_id']['relationship']['base'] = 'block_content'; + $data['block_content_revision']['revision_id']['relationship']['base field'] = 'revision_id'; + $data['block_content_revision']['revision_id']['relationship']['title'] = t('Block Content'); + $data['block_content_revision']['revision_id']['relationship']['label'] = t('Get the actual block content from a block content revision.'); + + // @todo Figure out do we need this or not. + // $data['block_content_revision']['langcode']['field']['id'] = 'block_content_language'; + + $data['block_content_revision']['revision_log']['field']['id'] = 'xss'; + + $data['block_content_field_revision']['table']['wizard_id'] = 'block_content_field_revision'; + $data['block_content_field_revision']['table']['group'] = t('Custom Block revision'); + + $data['block_content_field_revision']['table']['join']['block_content_revision']['left_field'] = 'revision_id'; + $data['block_content_field_revision']['table']['join']['block_content_revision']['field'] = 'revision_id'; + $data['block_content_field_revision']['table']['join']['block_content_revision']['type'] = 'INNER'; + + $data['block_content_field_revision']['table']['join']['block_content']['left_field'] = 'revision_id'; + $data['block_content_field_revision']['table']['join']['block_content']['field'] = 'revision_id'; + + // @todo Fix this when we support block content revision links. + // $data['block_content_field_revision']['info']['field']['id'] = 'block_content_revision'; + + // @todo Figure out do we need this or not. + // $data['block_content_field_revision']['langcode']['field']['id'] = 'block_content_language'; + + // @todo Fix this when we support block content revision links. + // $data['block_content_revision']['link_to_revision'] = array( + // 'field' => array( + // 'title' => t('Link to revision'), + // 'help' => t('Provide a simple link to the revision.'), + // 'id' => 'block_content_revision_link', + // 'click sortable' => FALSE, + // ), + // ); + + // @todo Fix this when we support block content revision links. + // $data['block_content_revision']['revert_revision'] = array( + // 'field' => array( + // 'title' => t('Link to revert revision'), + // 'help' => t('Provide a simple link to revert to the revision.'), + // 'id' => 'block_content_revision_link_revert', + // 'click sortable' => FALSE, + // ), + // ); + + // @todo Fix this when we support block content revision links. + // $data['block_content_revision']['delete_revision'] = array( + // 'field' => array( + // 'title' => t('Link to delete revision'), + // 'help' => t('Provide a simple link to delete the content revision.'), + // 'id' => 'block_content_revision_link_delete', + // 'click sortable' => FALSE, + // ), + // ); + + return $data; + + } + +} diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php index 4908d95..5829a0b 100644 --- a/core/modules/block_content/src/Entity/BlockContent.php +++ b/core/modules/block_content/src/Entity/BlockContent.php @@ -26,6 +26,7 @@ * "access" = "Drupal\block_content\BlockContentAccessControlHandler", * "list_builder" = "Drupal\block_content\BlockContentListBuilder", * "view_builder" = "Drupal\block_content\BlockContentViewBuilder", + * "views_data" = "Drupal\block_content\BlockContentViewsData", * "form" = { * "add" = "Drupal\block_content\BlockContentForm", * "edit" = "Drupal\block_content\BlockContentForm", diff --git a/core/modules/block_content/src/Plugin/views/field/BlockContent.php b/core/modules/block_content/src/Plugin/views/field/BlockContent.php new file mode 100644 index 0000000..e575cfd --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/field/BlockContent.php @@ -0,0 +1,158 @@ +languageManager = $language_manager; + $this->entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('language_manager'), + $container->get('entity.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { + parent::init($view, $display, $options); + + // Don't add the additional fields to groupby + if (!empty($this->options['link_to_block_content'])) { + $this->additional_fields['id'] = array('table' => 'block_content', 'field' => 'id'); + } + } + + /** + * {@inheritdoc} + */ + protected function defineOptions() { + $options = parent::defineOptions(); + $options['link_to_block_content'] = array('default' => isset($this->definition['link_to_block_content default']) ? $this->definition['link_to_block_content default'] : FALSE); + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + $form['link_to_block_content'] = array( + '#title' => $this->t('Link this field to the original piece of block content'), + '#description' => $this->t("Enable to override this field's links."), + '#type' => 'checkbox', + '#default_value' => !empty($this->options['link_to_block_content']), + ); + + parent::buildOptionsForm($form, $form_state); + } + + /** + * Prepares link to the block_content. + * + * @param string $data + * The XSS safe string for the link text. + * @param \Drupal\views\ResultRow $values + * The values retrieved from a single row of a view's query result. + * + * @return string + * Returns a string for the link text. + */ + protected function renderLink($data, ResultRow $values) { + if (!empty($this->options['link_to_block_content']) && !empty($this->additional_fields['id'])) { + if ($data !== NULL && $data !== '') { + $id = $this->getValue($values, 'id'); + $block_content = $this->entityManager->getStorage('block_content')->load($id); + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = $block_content->url(); + if (isset($this->aliases['langcode'])) { + $languages = $this->languageManager->getLanguages(); + $langcode = $this->getValue($values, 'langcode'); + if (isset($languages[$langcode])) { + $this->options['alter']['language'] = $languages[$langcode]; + } + else { + unset($this->options['alter']['language']); + } + } + } + else { + $this->options['alter']['make_link'] = FALSE; + } + } + return $data; + } + + /** + * {@inheritdoc} + */ + public function render(ResultRow $values) { + $value = $this->getValue($values); + return $this->renderLink($this->sanitizeValue($value), $values); + } + +} diff --git a/core/modules/block_content/src/Plugin/views/field/Link.php b/core/modules/block_content/src/Plugin/views/field/Link.php new file mode 100644 index 0000000..c5fc646 --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/field/Link.php @@ -0,0 +1,94 @@ + ''); + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + $form['text'] = array( + '#type' => 'textfield', + '#title' => $this->t('Text to display'), + '#default_value' => $this->options['text'], + ); + parent::buildOptionsForm($form, $form_state); + + // The path is set by renderLink function so don't allow to set it. + $form['alter']['path'] = array('#access' => FALSE); + $form['alter']['external'] = array('#access' => FALSE); + } + + /** + * {@inheritdoc} + */ + public function query() { + $this->addAdditionalFields(); + } + + /** + * {@inheritdoc} + */ + public function render(ResultRow $values) { + if ($entity = $this->getEntity($values)) { + return $this->renderLink($entity, $values); + } + } + + /** + * Prepares the link to the block_content. + * + * @param \Drupal\Core\Entity\EntityInterface $block_content + * The block_content entity this field belongs to. + * @param ResultRow $values + * The values retrieved from the view's result set. + * + * @return string + * Returns a string for the link text. + */ + protected function renderLink($block_content, ResultRow $values) { + // Ensure user has access to view this block_content. + if (!$block_content->access('view')) { + return; + } + + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = $block_content->url(); + $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('View'); + return $text; + } + +} diff --git a/core/modules/block_content/src/Plugin/views/field/LinkDelete.php b/core/modules/block_content/src/Plugin/views/field/LinkDelete.php new file mode 100644 index 0000000..5d8a79f --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/field/LinkDelete.php @@ -0,0 +1,38 @@ +access('delete')) { + return; + } + + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = $block_content->url('delete-form'); + $this->options['alter']['query'] = drupal_get_destination(); + + $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Delete'); + return $text; + } + +} diff --git a/core/modules/block_content/src/Plugin/views/field/LinkEdit.php b/core/modules/block_content/src/Plugin/views/field/LinkEdit.php new file mode 100644 index 0000000..1ab8e16 --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/field/LinkEdit.php @@ -0,0 +1,46 @@ +access('update')) { + return; + } + + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = $block_content->url('edit-form'); + $this->options['alter']['query'] = drupal_get_destination(); + + $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit'); + return $text; + } + +} diff --git a/core/modules/block_content/src/Plugin/views/field/Path.php b/core/modules/block_content/src/Plugin/views/field/Path.php new file mode 100644 index 0000000..78116b8 --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/field/Path.php @@ -0,0 +1,113 @@ +urlGenerator = $url_generator; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('url_generator') + ); + } + + /** + * {@inheritdoc} + */ + public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { + parent::init($view, $display, $options); + + $this->additional_fields['id'] = 'id'; + } + + /** + * {@inheritdoc} + */ + protected function defineOptions() { + $options = parent::defineOptions(); + $options['absolute'] = array('default' => FALSE); + + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + parent::buildOptionsForm($form, $form_state); + $form['absolute'] = array( + '#type' => 'checkbox', + '#title' => $this->t('Use absolute link (begins with "http://")'), + '#default_value' => $this->options['absolute'], + '#description' => $this->t('Enable this option to output an absolute link. Required if you want to use the path as a link destination (as in "output this field as a link" above).'), + '#fieldset' => 'alter', + ); + } + + /** + * {@inheritdoc} + */ + public function query() { + $this->ensureMyTable(); + $this->addAdditionalFields(); + } + + /** + * {@inheritdoc} + */ + public function render(ResultRow $values) { + $id = $this->getValue($values, 'id'); + return $this->urlGenerator->generateFromRoute('entity.block_content.canonical', ['block_content' => $id], ['absolute' => $this->options['absolute']]); + } + +} diff --git a/core/modules/block_content/src/Plugin/views/field/Type.php b/core/modules/block_content/src/Plugin/views/field/Type.php new file mode 100644 index 0000000..dd69a7d --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/field/Type.php @@ -0,0 +1,65 @@ + FALSE); + + return $options; + } + + /** + * {@inheritdoc} + */ + public function buildOptionsForm(&$form, FormStateInterface $form_state) { + parent::buildOptionsForm($form, $form_state); + + $form['machine_name'] = array( + '#title' => $this->t('Output machine name'), + '#description' => $this->t('Display field as the block content type machine name.'), + '#type' => 'checkbox', + '#default_value' => !empty($this->options['machine_name']), + ); + } + + /** + * Renders block content type as human readable name, unless using machine_name option. + */ + function renderName($data, $values) { + if ($this->options['machine_name'] != 1 && $data !== NULL && $data !== '') { + $type = $this->entityManager->getStorage('block_content_type')->load($data); + return $type ? $this->t($this->sanitizeValue($type->label())) : ''; + } + return $this->sanitizeValue($data); + } + + /** + * {@inheritdoc} + */ + public function render(ResultRow $values) { + $value = $this->getValue($values); + return $this->renderLink($this->renderName($value, $values), $values); + } + +} diff --git a/core/modules/block_content/src/Plugin/views/wizard/BlockContent.php b/core/modules/block_content/src/Plugin/views/wizard/BlockContent.php new file mode 100644 index 0000000..d5ab851 --- /dev/null +++ b/core/modules/block_content/src/Plugin/views/wizard/BlockContent.php @@ -0,0 +1,67 @@ +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->translatable = TRUE; + $field_storage->save(); + + // Set up block_content infos. + $this->block_content_infos = array( + 'en' => 'Food in Paris', + 'es' => 'Comida en Paris', + 'fr' => 'Nouriture en Paris', + ); + + // Create block_content with translations. + $block_content = $this->createBlockContent(array('info' => $this->block_content_infos['en'], 'langcode' => 'en', 'type' => 'basic', 'body' => array(array('value' => $this->block_content_infos['en'])))); + foreach (array('es', 'fr') as $langcode) { + $translation = $block_content->addTranslation($langcode, array('info' => $this->block_content_infos[$langcode])); + $translation->body->value = $this->block_content_infos[$langcode]; + } + $block_content->save(); + } + + /** + * Tests body and info filters. + */ + public function testFilters() { + // Test the info filter page, which filters for info contains 'Comida'. + // Should show just the Spanish translation, once. + $this->assertPageCounts('test-info-filter', array('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', array('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', array('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', array('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. + */ + protected function assertPageCounts($path, $counts, $message) { + // Get the text of the page. + $this->drupalGet($path); + $text = $this->getTextContent(); + + foreach ($counts as $langcode => $count) { + $this->assertEqual(substr_count($text, $this->block_content_infos[$langcode]), $count, 'Translation ' . $langcode . ' has count ' . $count . ' with ' . $message); + } + } +} diff --git a/core/modules/block_content/src/Tests/Views/BlockContentIntegrationTest.php b/core/modules/block_content/src/Tests/Views/BlockContentIntegrationTest.php new file mode 100644 index 0000000..64b02db --- /dev/null +++ b/core/modules/block_content/src/Tests/Views/BlockContentIntegrationTest.php @@ -0,0 +1,72 @@ +createBlockContentType(); + $types[] = $type; + + for ($j = 0; $j < 5; $j++) { + // Ensure the right order of the block_contents. + $block_content = $this->createBlockContent(array('type' => $type->id(), 'changed' => REQUEST_TIME - ($i * 5 + $j))); + $block_contents[$type->id()][$block_content->id()] = $block_content; + $all_ids[] = $block_content->id(); + } + } + + $this->drupalGet('test-block_content-view'); + $this->assertResponse(404); + + $this->drupalGet('test-block_content-view/all'); + $this->assertResponse(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. + */ + protected function assertIds(array $expected_ids = array()) { + $result = $this->xpath('//span[@class="field-content"]'); + $ids = array(); + foreach ($result as $element) { + $ids[] = (int) $element; + } + $this->assertEqual($ids, $expected_ids); + } + +} diff --git a/core/modules/block_content/src/Tests/Views/BlockContentRevisionWizardTest.php b/core/modules/block_content/src/Tests/Views/BlockContentRevisionWizardTest.php new file mode 100644 index 0000000..52fb62b --- /dev/null +++ b/core/modules/block_content/src/Tests/Views/BlockContentRevisionWizardTest.php @@ -0,0 +1,80 @@ + 'basic', + 'label' => 'Basic', + 'revision' => TRUE, + )); + // Create two block_contents with two revision. + $block_content_storage = \Drupal::entityManager()->getStorage('block_content'); + /** @var \Drupal\block_content\BlockContentInterface $block_content */ + $block_content = $block_content_storage->create(array('info' => $this->randomMachineName(), 'type' => 'basic')); + $block_content->save(); + + $block_content = $block_content->createDuplicate(); + $block_content->setNewRevision(); + $block_content->setInfo($this->randomMachineName()); + $block_content->save(); + + $block_content = $block_content_storage->create(array('info' => $this->randomMachineName(), 'type' => 'basic')); + $block_content->save(); + + $block_content = $block_content->createDuplicate(); + $block_content->setNewRevision(); + $block_content->setInfo($this->randomMachineName()); + $block_content->save(); + + $view = array(); + $view['label'] = $this->randomMachineName(16); + $view['id'] = strtolower($this->randomMachineName(16)); + $view['description'] = $this->randomMachineName(16); + $view['page[create]'] = FALSE; + $view['show[wizard_key]'] = 'block_content_revision'; + $this->drupalPostAjaxForm('admin/structure/views/add', $view, 'show[wizard_key]'); + $view['show[sort]'] = 'block_content_field_revision-changed:DESC'; + $this->drupalPostForm(NULL, $view, t('Save and edit')); + + $view_storage_controller = \Drupal::entityManager()->getStorage('view'); + /** @var \Drupal\views\Entity\View $view */ + $view = $view_storage_controller->load($view['id']); + + $this->assertEqual($view->get('base_table'), 'block_content_revision'); + + $executable = Views::executableFactory()->get($view); + $this->executeView($executable); + + $this->assertIdenticalResultset($executable, array(array('revision_id' => 1), array('revision_id' => 2), array('revision_id' => 3), array('revision_id' => 4)), + array('block_content_revision_id' => 'revision_id')); + } + +} diff --git a/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php b/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php new file mode 100644 index 0000000..83dc590 --- /dev/null +++ b/core/modules/block_content/src/Tests/Views/BlockContentTestBase.php @@ -0,0 +1,111 @@ +createBlockContentType(array('id' => 'basic')); + + $this->adminUser = $this->drupalCreateUser($this->permissions); + + if ($import_test_views) { + ViewTestData::createTestViews(get_class($this), array('block_content_test_views')); + } + } + + /** + * Creates a custom block. + * + * @param array $settings + * (optional) An associative array of settings for the block_content, as + * used in entity_create(). + * + * @return \Drupal\block_content\Entity\BlockContent + * Created custom block. + */ + protected function createBlockContent(array $settings = array()) { + $status = 0; + $settings += array( + 'info' => $this->randomMachineName(), + 'type' => 'basic', + 'langcode' => 'en', + ); + if ($block_content = entity_create('block_content', $settings)) { + $status = $block_content->save(); + } + $this->assertEqual($status, SAVED_NEW, String::format('Created block content %info.', array('%info' => $block_content->label()))); + return $block_content; + } + + /** + * Creates a custom block type (bundle). + * + * @param array $values + * An array of settings to change from the defaults. + * + * @return \Drupal\block_content\Entity\BlockContentType + * Created custom block type. + */ + protected function createBlockContentType(array $values = array()) { + // Find a non-existent random type name. + if (!isset($values['id'])) { + do { + $id = strtolower($this->randomMachineName(8)); + } while (BlockContentType::load($id)); + } + else { + $id = $values['id']; + } + $values += array( + 'id' => $id, + 'label' => $id, + 'revision' => FALSE + ); + $bundle = entity_create('block_content_type', $values); + $status = $bundle->save(); + block_content_add_body_field($bundle->id()); + + $this->assertEqual($status, SAVED_NEW, String::format('Created block content type %bundle.', array('%bundle' => $bundle->id()))); + return $bundle; + } + +} diff --git a/core/modules/block_content/src/Tests/Views/BlockContentWizardTest.php b/core/modules/block_content/src/Tests/Views/BlockContentWizardTest.php new file mode 100644 index 0000000..8e15525 --- /dev/null +++ b/core/modules/block_content/src/Tests/Views/BlockContentWizardTest.php @@ -0,0 +1,78 @@ + 'basic', + 'label' => 'Basic', + 'revision' => FALSE, + )); + // Create two block_contents with two revision. + $block_content_storage = \Drupal::entityManager()->getStorage('block_content'); + /** @var \Drupal\block_content\BlockContentInterface $block_content */ + $block_content = $block_content_storage->create(array('info' => $this->randomMachineName(), 'type' => 'basic')); + $block_content->save(); + + $block_content = $block_content->createDuplicate(); + $block_content->setInfo($this->randomMachineName()); + $block_content->save(); + + $block_content = $block_content_storage->create(array('info' => $this->randomMachineName(), 'type' => 'basic')); + $block_content->save(); + + $block_content = $block_content->createDuplicate(); + $block_content->setInfo($this->randomMachineName()); + $block_content->save(); + + $view = array(); + $view['label'] = $this->randomMachineName(16); + $view['id'] = strtolower($this->randomMachineName(16)); + $view['description'] = $this->randomMachineName(16); + $view['page[create]'] = FALSE; + $view['show[wizard_key]'] = 'block_content'; + $this->drupalPostAjaxForm('admin/structure/views/add', $view, 'show[wizard_key]'); + $view['show[sort]'] = 'block_content_field_data-changed:DESC'; + $this->drupalPostForm(NULL, $view, t('Save and edit')); + + $view_storage_controller = \Drupal::entityManager()->getStorage('view'); + /** @var \Drupal\views\Entity\View $view */ + $view = $view_storage_controller->load($view['id']); + + $this->assertEqual($view->get('base_table'), 'block_content'); + + $executable = Views::executableFactory()->get($view); + $this->executeView($executable); + + $this->assertIdenticalResultset($executable, array(array('id' => 1), array('id' => 2), array('id' => 3), array('id' => 4)), + array('id' => 'id')); + } + +} diff --git a/core/modules/block_content/src/Tests/Views/FieldTypeTest.php b/core/modules/block_content/src/Tests/Views/FieldTypeTest.php new file mode 100644 index 0000000..301fa45 --- /dev/null +++ b/core/modules/block_content/src/Tests/Views/FieldTypeTest.php @@ -0,0 +1,42 @@ +createBlockContent(); + $expected_result[] = array( + 'id' => $block_content->id(), + 'block_content_field_data_type' => $block_content->bundle(), + ); + $column_map = array( + 'id' => 'id', + 'block_content_field_data_type' => 'block_content_field_data_type', + ); + + $view = Views::getView('test_field_type'); + $this->executeView($view); + $this->assertIdenticalResultset($view, $expected_result, $column_map, 'The correct block_content type was displayed.'); + } + +} diff --git a/core/modules/block_content/src/Tests/Views/RevisionRelationshipsTest.php b/core/modules/block_content/src/Tests/Views/RevisionRelationshipsTest.php new file mode 100644 index 0000000..a7ecabe --- /dev/null +++ b/core/modules/block_content/src/Tests/Views/RevisionRelationshipsTest.php @@ -0,0 +1,96 @@ + 'basic', + 'label' => 'basic', + 'revision' => TRUE, + )); + ViewTestData::createTestViews(get_class($this), array('block_content_test_views')); + } + + /** + * Create a block_content with revision and rest result count for both views. + */ + public function testBlockContentRevisionRelationship() { + $block_content = BlockContent::create(array( + '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 = array( + 'revision_id' => 'revision_id', + 'block_content_revision_id' => 'block_content_revision_id', + 'block_content_block_content_revision_id' => 'block_content_block_content_revision_id', + ); + + // Here should be two rows. + $view_id = Views::getView('test_block_content_revision_id'); + $this->executeView($view_id, array($block_content->id())); + $resultset_id = array( + array( + 'revision_id' => '1', + 'block_content_revision_id' => '1', + 'block_content_block_content_revision_id' => '1', + ), + array( + 'revision_id' => '2', + 'block_content_revision_id' => '1', + 'block_content_block_content_revision_id' => '1', + ), + ); + $this->assertIdenticalResultset($view_id, $resultset_id, $column_map); + + // There should be only one row with active revision 2. + $view_revision_id = Views::getView('test_block_content_revision_revision_id'); + $this->executeView($view_revision_id, array($block_content->id())); + $resultset_revision_id = array( + array( + 'revision_id' => '2', + 'block_content_revision_id' => '1', + 'block_content_block_content_revision_id' => '1', + ), + ); + $this->assertIdenticalResultset($view_revision_id, $resultset_revision_id, $column_map); + } + +} diff --git a/core/modules/block_content/tests/modules/block_content_test_views/block_content_test_views.info.yml b/core/modules/block_content/tests/modules/block_content_test_views/block_content_test_views.info.yml new file mode 100644 index 0000000..43b58c1 --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_test_views/block_content_test_views.info.yml @@ -0,0 +1,9 @@ +name: 'Block Content test views' +type: module +description: 'Provides default views for views block_content tests.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - block_content + - views diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml new file mode 100644 index 0000000..c872156 --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_id.yml @@ -0,0 +1,60 @@ +langcode: und +status: true +dependencies: + module: + - block_content +id: test_block_content_revision_id +label: null +module: views +description: '' +tag: '' +base_table: block_content_revision +base_field: revision_id +core: '8' +display: + default: + display_options: + relationships: + id: + id: id + table: block_content_revision + field: id + required: true + plugin_id: standard + fields: + revision_id: + id: revision_id + table: block_content_revision + field: revision_id + plugin_id: numeric + entity_type: block_content + entity_field: revision_id + id_1: + id: id_1 + table: block_content_revision + field: id + plugin_id: standard + entity_type: block_content + entity_field: id + id: + id: id + table: block_content + field: id + relationship: id + plugin_id: block_content + entity_type: block_content + entity_field: id + arguments: + id: + id: id + table: block_content_revision + field: id + plugin_id: numeric + entity_type: block_content + entity_field: id + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_plugin: default + display_title: Master + id: default + position: 0 diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml new file mode 100644 index 0000000..7d35c4c --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_revision_revision_id.yml @@ -0,0 +1,63 @@ +langcode: und +status: true +dependencies: + module: + - block_content +id: test_block_content_revision_revision_id +label: null +module: views +description: '' +tag: '' +base_table: block_content_revision +base_field: revision_id +core: '8' +display: + default: + display_options: + relationships: + revision_id: + id: revision_id + table: block_content_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_revision + field: revision_id + plugin_id: standard + entity_type: block_content + entity_field: revision_id + id_1: + id: id_1 + table: block_content_revision + field: id + plugin_id: standard + entity_type: block_content + entity_field: id + id: + id: id + table: block_content + field: id + relationship: revision_id + plugin_id: block_content + entity_type: block_content + entity_field: id + arguments: + id: + id: id + table: block_content_revision + field: id + plugin_id: block_content_id + entity_type: block_content + entity_field: id + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_extenders: { } + display_plugin: default + display_title: Master + id: default + position: 0 diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml new file mode 100644 index 0000000..8f2d45f --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_block_content_view.yml @@ -0,0 +1,198 @@ +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 +base_field: id +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: null + display_options: + access: + type: none + options: { } + cache: + type: none + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: false + 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: 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: '' + 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 + link_to_block_content: false + plugin_id: block_content + entity_type: block_content + entity_field: id + 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_block_content_view + header: { } + footer: { } + empty: { } + relationships: { } + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_extenders: { } + arguments: + type: + id: type + table: block_content + 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: '' + default_argument_skip_url: false + 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 + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_extenders: { } diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml new file mode 100644 index 0000000..899d5ab --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_filters.yml @@ -0,0 +1,347 @@ +langcode: en +status: true +dependencies: + module: + - block_content +id: test_field_filters +label: 'Test field filters' +module: views +description: '' +tag: '' +base_table: block_content +base_field: id +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: none + options: { } + cache: + type: none + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: false + 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 + link_to_block_content: true + 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 + entity_field: title + plugin_id: block_content + 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: { } + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + rendering_language: translation_language_renderer + display_extenders: { } + page_bf: + display_plugin: page + id: page_bf + display_title: 'Body filter page' + position: 1 + display_options: + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + 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: + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + 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: + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + 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: + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + path: test-info-paris + display_description: '' + title: 'Test info filter' + defaults: + title: false + display_extenders: { } diff --git a/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml new file mode 100644 index 0000000..674cf7f --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_test_views/test_views/views.view.test_field_type.yml @@ -0,0 +1,30 @@ +langcode: und +status: true +dependencies: + module: + - block_content +id: test_field_type +label: '' +module: views +description: '' +tag: '' +base_table: block_content +base_field: id +core: '8' +display: + default: + display_options: + fields: + type: + field: type + id: type + table: block_content_field_data + plugin_id: block_content_type + entity_type: block_content + entity_field: type + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_plugin: default + display_title: Master + id: default + position: 0