Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -0,0 +1,34 @@
/**
* @file
* Javascript behaviors for the Book module.
*/
(function($, Drupal) {
/**
* Adds summaries to the book outline form.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches summary behavior to book outline forms.
*/
Drupal.behaviors.bookDetailsSummaries = {
attach(context) {
$(context)
.find('.book-outline-form')
.drupalSetSummary(context => {
const $select = $(context).find('.book-title-select');
const val = $select.val();
if (val === '0') {
return Drupal.t('Not in book');
}
if (val === 'new') {
return Drupal.t('New book');
}
return Drupal.checkPlain($select.find(':selected').text());
});
},
};
})(jQuery, Drupal);

View file

@ -5,5 +5,5 @@ package: Core
version: VERSION
core: 8.x
dependencies:
- node
- drupal:node
configure: book.settings

View file

@ -1,22 +1,13 @@
/**
* @file
* Javascript behaviors for the Book module.
*/
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/
(function ($, Drupal) {
'use strict';
/**
* Adds summaries to the book outline form.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches summary behavior to book outline forms.
*/
Drupal.behaviors.bookDetailsSummaries = {
attach: function (context) {
attach: function attach(context) {
$(context).find('.book-outline-form').drupalSetSummary(function (context) {
var $select = $(context).find('.book-title-select');
var val = $select.val();
@ -24,14 +15,12 @@
if (val === '0') {
return Drupal.t('Not in book');
}
else if (val === 'new') {
if (val === 'new') {
return Drupal.t('New book');
}
else {
return Drupal.checkPlain($select.find(':selected').text());
}
return Drupal.checkPlain($select.find(':selected').text());
});
}
};
})(jQuery, Drupal);
})(jQuery, Drupal);

View file

@ -6,4 +6,3 @@ drupal.book:
- core/jquery
- core/drupal
- core/drupal.form

View file

@ -82,7 +82,8 @@ function book_entity_type_build(array &$entity_types) {
$entity_types['node']
->setFormClass('book_outline', 'Drupal\book\Form\BookOutlineForm')
->setLinkTemplate('book-outline-form', '/node/{node}/outline')
->setLinkTemplate('book-remove-form', '/node/{node}/outline/remove');
->setLinkTemplate('book-remove-form', '/node/{node}/outline/remove')
->addConstraint('BookOutline', []);
}
/**
@ -110,7 +111,7 @@ function book_node_links_alter(array &$links, NodeInterface $node, array &$conte
'type' => 'html',
'node' => $node->id(),
]),
'attributes' => ['title' => t('Show a printer-friendly version of this book page and its sub-pages.')]
'attributes' => ['title' => t('Show a printer-friendly version of this book page and its sub-pages.')],
];
}
}
@ -437,7 +438,7 @@ function template_preprocess_book_navigation(&$variables) {
}
if (!empty($build)) {
drupal_render($build);
\Drupal::service('renderer')->render($build);
}
$variables['has_links'] = FALSE;
@ -538,3 +539,16 @@ function book_node_type_update(NodeTypeInterface $type) {
$config->save();
}
}
/**
* Implements hook_migration_plugins_alter().
*/
function book_migration_plugins_alter(array &$migrations) {
// Book settings are migrated identically for Drupal 6 and Drupal 7. However,
// a d6_book_settings migration already existed before the consolidated
// book_settings migration existed, so to maintain backwards compatibility,
// ensure that d6_book_settings is an alias of book_settings.
if (isset($migrations['book_settings'])) {
$migrations['d6_book_settings'] = &$migrations['book_settings'];
}
}

View file

@ -33,6 +33,13 @@ content:
weight: 15
region: content
third_party_settings: { }
status:
type: boolean_checkbox
settings:
display_label: true
weight: 120
region: content
third_party_settings: { }
sticky:
type: boolean_checkbox
settings:

View file

@ -1,13 +1,16 @@
id: d6_book_settings
id: book_settings
label: Book configuration
migration_tags:
- Drupal 6
- Drupal 7
- Configuration
source:
plugin: variable
variables:
- book_child_type
- book_block_mode
- book_allowed_types
source_module: book
process:
child_type: book_child_type
'block/navigation/mode': book_block_mode

View file

@ -2,8 +2,9 @@ id: d6_book
label: Books
migration_tags:
- Drupal 6
- Content
source:
plugin: d6_book
plugin: book
process:
nid: nid
'book/bid': bid

View file

@ -0,0 +1,24 @@
id: d7_book
label: Books
migration_tags:
- Drupal 7
- Content
source:
plugin: book
process:
nid: nid
'book/bid': bid
'book/weight': weight
'book/pid':
-
plugin: skip_on_empty
method: process
source: plid
-
plugin: migration_lookup
migration: d7_book
destination:
plugin: book
migration_dependencies:
required:
- d7_node

View file

@ -275,6 +275,20 @@ class BookManager implements BookManagerInterface {
// handle it here if it did not.
$node->book['pid'] = $node->book['bid'];
}
// Prevent changes to the book outline if the node being saved is not the
// default revision.
$updated = FALSE;
if (!$new) {
$original = $this->loadBookLink($node->id(), FALSE);
if ($node->book['bid'] != $original['bid'] || $node->book['pid'] != $original['pid'] || $node->book['weight'] != $original['weight']) {
$updated = TRUE;
}
}
if (($new || $updated) && !$node->isDefaultRevision()) {
return FALSE;
}
return $this->saveBookLink($node->book, $new);
}

View file

@ -6,7 +6,6 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
/**
* Provides an interface defining a book manager.
*/
@ -247,7 +246,8 @@ interface BookManagerInterface {
* A data structure representing the tree as returned from buildBookOutlineData.
*
* @return array
* A structured array to be rendered by drupal_render().
* A structured array to be rendered by
* \Drupal\Core\Render\RendererInterface::render().
*
* @see \Drupal\Core\Menu\MenuLinkTree::build
*/

View file

@ -39,12 +39,14 @@ class BookOutline {
if ($book_link['pid'] == 0) {
return NULL;
}
// Assigning the array to $flat resets the array pointer for use with each().
$flat = $this->bookManager->bookTreeGetFlat($book_link);
reset($flat);
$curr = NULL;
do {
$prev = $curr;
list($key, $curr) = each($flat);
$key = key($flat);
$curr = current($flat);
next($flat);
} while ($key && $key != $book_link['nid']);
if ($key == $book_link['nid']) {
@ -78,10 +80,11 @@ class BookOutline {
* $book_link.
*/
public function nextLink(array $book_link) {
// Assigning the array to $flat resets the array pointer for use with each().
$flat = $this->bookManager->bookTreeGetFlat($book_link);
reset($flat);
do {
list($key,) = each($flat);
$key = key($flat);
next($flat);
} while ($key && $key != $book_link['nid']);
if ($key == $book_link['nid']) {

View file

@ -69,7 +69,7 @@ interface BookOutlineStorageInterface {
public function delete($nid);
/**
* Loads book's children using it's parent ID.
* Loads book's children using its parent ID.
*
* @param int $pid
* The book's parent ID.
@ -110,7 +110,6 @@ interface BookOutlineStorageInterface {
*/
public function insert($link, $parents);
/**
* Updates book reference for links that were moved between books.
*

View file

@ -154,7 +154,7 @@ class BookController extends ControllerBase {
// @todo Convert the custom export functionality to serializer.
if (!method_exists($this->bookExport, $method)) {
drupal_set_message(t('Unknown export format.'));
$this->messenger()->addStatus(t('Unknown export format.'));
throw new NotFoundHttpException();
}

View file

@ -15,6 +15,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a form for administering a single book's hierarchy.
*
* @internal
*/
class BookAdminEditForm extends FormBase {
@ -125,7 +127,7 @@ class BookAdminEditForm extends FormBase {
}
}
drupal_set_message($this->t('Updated book %title.', ['%title' => $form['#node']->label()]));
$this->messenger()->addStatus($this->t('Updated book %title.', ['%title' => $form['#node']->label()]));
}
/**
@ -220,7 +222,7 @@ class BookAdminEditForm extends FormBase {
}
$form[$id]['title'] = [
'#prefix' => !empty($indentation) ? drupal_render($indentation) : '',
'#prefix' => !empty($indentation) ? \Drupal::service('renderer')->render($indentation) : '',
'#type' => 'textfield',
'#default_value' => $data['link']['title'],
'#maxlength' => 255,

View file

@ -5,7 +5,7 @@ namespace Drupal\book\Form;
use Drupal\book\BookManagerInterface;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
@ -13,6 +13,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Displays the book outline form.
*
* @internal
*/
class BookOutlineForm extends ContentEntityForm {
@ -33,8 +35,8 @@ class BookOutlineForm extends ContentEntityForm {
/**
* Constructs a BookOutlineForm object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository.
* @param \Drupal\book\BookManagerInterface $book_manager
* The BookManager service.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
@ -42,8 +44,8 @@ class BookOutlineForm extends ContentEntityForm {
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
*/
public function __construct(EntityManagerInterface $entity_manager, BookManagerInterface $book_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
parent::__construct($entity_manager, $entity_type_bundle_info, $time);
public function __construct(EntityRepositoryInterface $entity_repository, BookManagerInterface $book_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
$this->bookManager = $book_manager;
}
@ -52,7 +54,7 @@ class BookOutlineForm extends ContentEntityForm {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager'),
$container->get('entity.repository'),
$container->get('book.manager'),
$container->get('entity_type.bundle.info'),
$container->get('datetime.time')
@ -111,7 +113,7 @@ class BookOutlineForm extends ContentEntityForm {
);
$book_link = $form_state->getValue('book');
if (!$book_link['bid']) {
drupal_set_message($this->t('No changes were made'));
$this->messenger()->addStatus($this->t('No changes were made'));
return;
}
@ -119,15 +121,15 @@ class BookOutlineForm extends ContentEntityForm {
if ($this->bookManager->updateOutline($this->entity)) {
if (isset($this->entity->book['parent_mismatch']) && $this->entity->book['parent_mismatch']) {
// This will usually only happen when JS is disabled.
drupal_set_message($this->t('The post has been added to the selected book. You may now position it relative to other pages.'));
$this->messenger()->addStatus($this->t('The post has been added to the selected book. You may now position it relative to other pages.'));
$form_state->setRedirectUrl($this->entity->urlInfo('book-outline-form'));
}
else {
drupal_set_message($this->t('The book outline has been updated.'));
$this->messenger()->addStatus($this->t('The book outline has been updated.'));
}
}
else {
drupal_set_message($this->t('There was an error adding the post to the book.'), 'error');
$this->messenger()->addError($this->t('There was an error adding the post to the book.'));
}
}

View file

@ -10,6 +10,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Remove form for book module.
*
* @internal
*/
class BookRemoveForm extends ConfirmFormBase {
@ -101,7 +103,7 @@ class BookRemoveForm extends ConfirmFormBase {
public function submitForm(array &$form, FormStateInterface $form_state) {
if ($this->bookManager->checkNodeIsRemovable($this->node)) {
$this->bookManager->deleteFromBook($this->node->id());
drupal_set_message($this->t('The post has been removed from the book.'));
$this->messenger()->addStatus($this->t('The post has been removed from the book.'));
}
$form_state->setRedirectUrl($this->getCancelUrl());
}

View file

@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface;
/**
* Configure book settings for this site.
*
* @internal
*/
class BookSettingsForm extends ConfigFormBase {

View file

@ -0,0 +1,19 @@
<?php
namespace Drupal\book\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Validation constraint for changing the book outline in pending revisions.
*
* @Constraint(
* id = "BookOutline",
* label = @Translation("Book outline.", context = "Validation"),
* )
*/
class BookOutlineConstraint extends Constraint {
public $message = 'You can only change the book outline for the <em>published</em> version of this content.';
}

View file

@ -0,0 +1,77 @@
<?php
namespace Drupal\book\Plugin\Validation\Constraint;
use Drupal\book\BookManagerInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Constraint validator for changing the book outline in pending revisions.
*/
class BookOutlineConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The book manager.
*
* @var \Drupal\book\BookManagerInterface
*/
protected $bookManager;
/**
* Creates a new BookOutlineConstraintValidator instance.
*
* @param \Drupal\book\BookManagerInterface $book_manager
* The book manager.
*/
public function __construct(BookManagerInterface $book_manager) {
$this->bookManager = $book_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('book.manager')
);
}
/**
* {@inheritdoc}
*/
public function validate($entity, Constraint $constraint) {
if (isset($entity) && !$entity->isNew() && !$entity->isDefaultRevision()) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $original */
$original = $this->bookManager->loadBookLink($entity->id(), FALSE) ?: [
'bid' => 0,
'weight' => 0,
];
if (empty($original['pid'])) {
$original['pid'] = -1;
}
if ($entity->book['bid'] != $original['bid']) {
$this->context->buildViolation($constraint->message)
->atPath('book.bid')
->setInvalidValue($entity)
->addViolation();
}
if ($entity->book['pid'] != $original['pid']) {
$this->context->buildViolation($constraint->message)
->atPath('book.pid')
->setInvalidValue($entity)
->addViolation();
}
if ($entity->book['weight'] != $original['weight']) {
$this->context->buildViolation($constraint->message)
->atPath('book.weight')
->setInvalidValue($entity)
->addViolation();
}
}
}
}

View file

@ -0,0 +1,63 @@
<?php
namespace Drupal\book\Plugin\migrate\source;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 6 and 7 book source.
*
* @MigrateSource(
* id = "book",
* source_module = "book",
* )
*/
class Book extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('book', 'b')->fields('b', ['nid', 'bid']);
$query->join('menu_links', 'ml', 'b.mlid = ml.mlid');
$ml_fields = ['mlid', 'plid', 'weight', 'has_children', 'depth'];
foreach (range(1, 9) as $i) {
$field = "p$i";
$ml_fields[] = $field;
$query->orderBy('ml.' . $field);
}
return $query->fields('ml', $ml_fields);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['mlid']['type'] = 'integer';
$ids['mlid']['alias'] = 'ml';
return $ids;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'nid' => $this->t('Node ID'),
'bid' => $this->t('Book ID'),
'mlid' => $this->t('Menu link ID'),
'plid' => $this->t('Parent link ID'),
'weight' => $this->t('Weight'),
'p1' => $this->t('The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the parent link mlid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.'),
'p2' => $this->t('The second mlid in the materialized path. See p1.'),
'p3' => $this->t('The third mlid in the materialized path. See p1.'),
'p4' => $this->t('The fourth mlid in the materialized path. See p1.'),
'p5' => $this->t('The fifth mlid in the materialized path. See p1.'),
'p6' => $this->t('The sixth mlid in the materialized path. See p1.'),
'p7' => $this->t('The seventh mlid in the materialized path. See p1.'),
'p8' => $this->t('The eighth mlid in the materialized path. See p1.'),
'p9' => $this->t('The ninth mlid in the materialized path. See p1.'),
];
}
}

View file

@ -2,62 +2,20 @@
namespace Drupal\book\Plugin\migrate\source\d6;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
use Drupal\book\Plugin\migrate\source\Book as BookGeneral;
@trigger_error('Book is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.x. Use \Drupal\book\Plugin\migrate\source\Book instead. See https://www.drupal.org/node/2947487 for more information.', E_USER_DEPRECATED);
/**
* Drupal 6 book source.
*
* @MigrateSource(
* id = "d6_book"
* id = "d6_book",
* source_module = "book"
* )
*
* @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.x. Use
* \Drupal\book\Plugin\migrate\source\Book instead. See
* https://www.drupal.org/node/2947487 for more information.
*/
class Book extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('book', 'b')->fields('b', ['nid', 'bid']);
$query->join('menu_links', 'ml', 'b.mlid = ml.mlid');
$ml_fields = ['mlid', 'plid', 'weight', 'has_children', 'depth'];
for ($i = 1; $i <= 9; $i++) {
$field = "p$i";
$ml_fields[] = $field;
$query->orderBy('ml.' . $field);
}
$query->fields('ml', $ml_fields);
return $query;
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['mlid']['type'] = 'integer';
$ids['mlid']['alias'] = 'ml';
return $ids;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'nid' => $this->t('Node ID'),
'bid' => $this->t('Book ID'),
'mlid' => $this->t('Menu link ID'),
'plid' => $this->t('Parent link ID'),
'weight' => $this->t('Weight'),
'p1' => $this->t('The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the parent link mlid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.'),
'p2' => $this->t('The second mlid in the materialized path. See p1.'),
'p3' => $this->t('The third mlid in the materialized path. See p1.'),
'p4' => $this->t('The fourth mlid in the materialized path. See p1.'),
'p5' => $this->t('The fifth mlid in the materialized path. See p1.'),
'p6' => $this->t('The sixth mlid in the materialized path. See p1.'),
'p7' => $this->t('The seventh mlid in the materialized path. See p1.'),
'p8' => $this->t('The eighth mlid in the materialized path. See p1.'),
'p9' => $this->t('The ninth mlid in the materialized path. See p1.'),
];
}
}
class Book extends BookGeneral {}

View file

@ -17,6 +17,6 @@
function book_test_page_attachments(array &$page) {
$page['#cache']['tags'][] = 'book_test.debug_book_navigation_cache_context';
if (\Drupal::state()->get('book_test.debug_book_navigation_cache_context', FALSE)) {
drupal_set_message(\Drupal::service('cache_contexts_manager')->convertTokensToKeys(['route.book_navigation'])->getKeys()[0]);
\Drupal::messenger()->addStatus(\Drupal::service('cache_contexts_manager')->convertTokensToKeys(['route.book_navigation'])->getKeys()[0]);
}
}

View file

@ -5,5 +5,5 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- book
- views
- drupal:book
- drupal:views

View file

@ -0,0 +1,139 @@
<?php
namespace Drupal\Tests\book\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Tests Book and Content Moderation integration.
*
* @group book
*/
class BookContentModerationTest extends BrowserTestBase {
use BookTestTrait;
use ContentModerationTestTrait;
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['book', 'block', 'book_test', 'content_moderation'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('system_breadcrumb_block');
$this->drupalPlaceBlock('page_title_block');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'book');
$workflow->save();
// We need a user with additional content moderation permissions.
$this->bookAuthor = $this->drupalCreateUser(['create new books', 'create book content', 'edit own book content', 'add content to books', 'access printer-friendly version', 'view any unpublished content', 'use editorial transition create_new_draft', 'use editorial transition publish']);
}
/**
* Tests that book drafts can not modify the book outline.
*/
public function testBookWithPendingRevisions() {
// Create two books.
$book_1_nodes = $this->createBook(['moderation_state[0][state]' => 'published']);
$book_1 = $this->book;
$this->createBook(['moderation_state[0][state]' => 'published']);
$book_2 = $this->book;
$this->drupalLogin($this->bookAuthor);
// Check that book pages display along with the correct outlines.
$this->book = $book_1;
$this->checkBookNode($book_1, [$book_1_nodes[0], $book_1_nodes[3], $book_1_nodes[4]], FALSE, FALSE, $book_1_nodes[0], []);
$this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
// Create a new book page without actually attaching it to a book and create
// a draft.
$edit = [
'title[0][value]' => $this->randomString(),
'moderation_state[0][state]' => 'published',
];
$this->drupalPostForm('node/add/book', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertTrue($node);
$edit = [
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
// Create a book draft with no changes, then publish it.
$edit = [
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
$edit = [
'moderation_state[0][state]' => 'published',
];
$this->drupalPostForm('node/' . $book_1->id() . '/edit', $edit, t('Save'));
// Try to move Node 2 to a different parent.
$edit = [
'book[pid]' => $book_1_nodes[3]->id(),
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextContains('You can only change the book outline for the published version of this content.');
// Check that the book outline did not change.
$this->book = $book_1;
$this->checkBookNode($book_1, [$book_1_nodes[0], $book_1_nodes[3], $book_1_nodes[4]], FALSE, FALSE, $book_1_nodes[0], []);
$this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
// Try to move Node 2 to a different book.
$edit = [
'book[bid]' => $book_2->id(),
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextContains('You can only change the book outline for the published version of this content.');
// Check that the book outline did not change.
$this->book = $book_1;
$this->checkBookNode($book_1, [$book_1_nodes[0], $book_1_nodes[3], $book_1_nodes[4]], FALSE, FALSE, $book_1_nodes[0], []);
$this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
// Try to change the weight of Node 2.
$edit = [
'book[weight]' => 2,
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextContains('You can only change the book outline for the published version of this content.');
// Check that the book outline did not change.
$this->book = $book_1;
$this->checkBookNode($book_1, [$book_1_nodes[0], $book_1_nodes[3], $book_1_nodes[4]], FALSE, FALSE, $book_1_nodes[0], []);
$this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
// Save a new draft revision for the node without any changes and check that
// the error message is not displayed.
$edit = [
'moderation_state[0][state]' => 'draft',
];
$this->drupalPostForm('node/' . $book_1_nodes[1]->id() . '/edit', $edit, t('Save'));
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
}
}

View file

@ -2,9 +2,7 @@
namespace Drupal\Tests\book\Functional;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\RoleInterface;
@ -15,6 +13,8 @@ use Drupal\user\RoleInterface;
*/
class BookTest extends BrowserTestBase {
use BookTestTrait;
/**
* Modules to install.
*
@ -22,20 +22,6 @@ class BookTest extends BrowserTestBase {
*/
public static $modules = ['book', 'block', 'node_access_test', 'book_test'];
/**
* A book node.
*
* @var \Drupal\node\NodeInterface
*/
protected $book;
/**
* A user with permission to create and edit books.
*
* @var object
*/
protected $bookAuthor;
/**
* A user with permission to view a book and access printer-friendly version.
*
@ -75,39 +61,6 @@ class BookTest extends BrowserTestBase {
$this->adminUser = $this->drupalCreateUser(['create new books', 'create book content', 'edit any book content', 'delete any book content', 'add content to books', 'administer blocks', 'administer permissions', 'administer book outlines', 'node test view', 'administer content types', 'administer site configuration']);
}
/**
* Creates a new book with a page hierarchy.
*
* @return \Drupal\node\NodeInterface[]
*/
public function createBook() {
// Create new book.
$this->drupalLogin($this->bookAuthor);
$this->book = $this->createBookNode('new');
$book = $this->book;
/*
* Add page hierarchy to book.
* Book
* |- Node 0
* |- Node 1
* |- Node 2
* |- Node 3
* |- Node 4
*/
$nodes = [];
$nodes[] = $this->createBookNode($book->id()); // Node 0.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid']); // Node 1.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid']); // Node 2.
$nodes[] = $this->createBookNode($book->id()); // Node 3.
$nodes[] = $this->createBookNode($book->id()); // Node 4.
$this->drupalLogout();
return $nodes;
}
/**
* Tests the book navigation cache context.
*
@ -199,7 +152,8 @@ class BookTest extends BrowserTestBase {
* |- Node 5
* |- Node 4
*/
$nodes[] = $this->createBookNode($book->id(), $nodes[3]->book['nid']); // Node 5.
// Node 5.
$nodes[] = $this->createBookNode($book->id(), $nodes[3]->book['nid']);
$this->drupalLogout();
$this->drupalLogin($this->webUser);
// Verify the new outline - make sure we don't get stale cached data.
@ -223,153 +177,12 @@ class BookTest extends BrowserTestBase {
$this->checkBookNode($other_book, [$node], FALSE, FALSE, $node, []);
$this->checkBookNode($node, NULL, $other_book, $other_book, FALSE, [$other_book]);
// Test that we can save a book programatically.
// Test that we can save a book programmatically.
$this->drupalLogin($this->bookAuthor);
$book = $this->createBookNode('new');
$book->save();
}
/**
* Checks the outline of sub-pages; previous, up, and next.
*
* Also checks the printer friendly version of the outline.
*
* @param \Drupal\Core\Entity\EntityInterface $node
* Node to check.
* @param $nodes
* Nodes that should be in outline.
* @param $previous
* (optional) Previous link node. Defaults to FALSE.
* @param $up
* (optional) Up link node. Defaults to FALSE.
* @param $next
* (optional) Next link node. Defaults to FALSE.
* @param array $breadcrumb
* The nodes that should be displayed in the breadcrumb.
*/
public function checkBookNode(EntityInterface $node, $nodes, $previous = FALSE, $up = FALSE, $next = FALSE, array $breadcrumb) {
// $number does not use drupal_static as it should not be reset
// since it uniquely identifies each call to checkBookNode().
static $number = 0;
$this->drupalGet('node/' . $node->id());
// Check outline structure.
if ($nodes !== NULL) {
$this->assertPattern($this->generateOutlinePattern($nodes), format_string('Node @number outline confirmed.', ['@number' => $number]));
}
else {
$this->pass(format_string('Node %number does not have outline.', ['%number' => $number]));
}
// Check previous, up, and next links.
if ($previous) {
/** @var \Drupal\Core\Url $url */
$url = $previous->urlInfo();
$url->setOptions(['attributes' => ['rel' => ['prev'], 'title' => t('Go to previous page')]]);
$text = SafeMarkup::format('<b></b> @label', ['@label' => $previous->label()]);
$this->assertRaw(\Drupal::l($text, $url), 'Previous page link found.');
}
if ($up) {
/** @var \Drupal\Core\Url $url */
$url = $up->urlInfo();
$url->setOptions(['attributes' => ['title' => t('Go to parent page')]]);
$this->assertRaw(\Drupal::l('Up', $url), 'Up page link found.');
}
if ($next) {
/** @var \Drupal\Core\Url $url */
$url = $next->urlInfo();
$url->setOptions(['attributes' => ['rel' => ['next'], 'title' => t('Go to next page')]]);
$text = SafeMarkup::format('@label <b></b>', ['@label' => $next->label()]);
$this->assertRaw(\Drupal::l($text, $url), 'Next page link found.');
}
// Compute the expected breadcrumb.
$expected_breadcrumb = [];
$expected_breadcrumb[] = \Drupal::url('<front>');
foreach ($breadcrumb as $a_node) {
$expected_breadcrumb[] = $a_node->url();
}
// Fetch links in the current breadcrumb.
$links = $this->xpath('//nav[@class="breadcrumb"]/ol/li/a');
$got_breadcrumb = [];
foreach ($links as $link) {
$got_breadcrumb[] = $link->getAttribute('href');
}
// Compare expected and got breadcrumbs.
$this->assertIdentical($expected_breadcrumb, $got_breadcrumb, 'The breadcrumb is correctly displayed on the page.');
// Check printer friendly version.
$this->drupalGet('book/export/html/' . $node->id());
$this->assertText($node->label(), 'Printer friendly title found.');
$this->assertRaw($node->body->processed, 'Printer friendly body found.');
$number++;
}
/**
* Creates a regular expression to check for the sub-nodes in the outline.
*
* @param array $nodes
* An array of nodes to check in outline.
*
* @return string
* A regular expression that locates sub-nodes of the outline.
*/
public function generateOutlinePattern($nodes) {
$outline = '';
foreach ($nodes as $node) {
$outline .= '(node\/' . $node->id() . ')(.*?)(' . $node->label() . ')(.*?)';
}
return '/<nav id="book-navigation-' . $this->book->id() . '"(.*?)<ul(.*?)' . $outline . '<\/ul>/s';
}
/**
* Creates a book node.
*
* @param int|string $book_nid
* A book node ID or set to 'new' to create a new book.
* @param int|null $parent
* (optional) Parent book reference ID. Defaults to NULL.
*
* @return \Drupal\node\NodeInterface
* The created node.
*/
public function createBookNode($book_nid, $parent = NULL) {
// $number does not use drupal_static as it should not be reset
// since it uniquely identifies each call to createBookNode().
static $number = 0; // Used to ensure that when sorted nodes stay in same order.
$edit = [];
$edit['title[0][value]'] = str_pad($number, 2, '0', STR_PAD_LEFT) . ' - SimpleTest test node ' . $this->randomMachineName(10);
$edit['body[0][value]'] = 'SimpleTest test body ' . $this->randomMachineName(32) . ' ' . $this->randomMachineName(32);
$edit['book[bid]'] = $book_nid;
if ($parent !== NULL) {
$this->drupalPostForm('node/add/book', $edit, t('Change book (update list of parents)'));
$edit['book[pid]'] = $parent;
$this->drupalPostForm(NULL, $edit, t('Save'));
// Make sure the parent was flagged as having children.
$parent_node = \Drupal::entityManager()->getStorage('node')->loadUnchanged($parent);
$this->assertFalse(empty($parent_node->book['has_children']), 'Parent node is marked as having children');
}
else {
$this->drupalPostForm('node/add/book', $edit, t('Save'));
}
// Check to make sure the book node was created.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertNotNull(($node === FALSE ? NULL : $node), 'Book node found in database.');
$number++;
return $node;
}
/**
* Tests book export ("printer-friendly version") functionality.
*/
@ -469,7 +282,7 @@ class BookTest extends BrowserTestBase {
$nodes[$child] = $this->createBookNode($book->id(), $nodes[$parent]->id());
}
$this->drupalGet($nodes[0]->toUrl('edit-form'));
// Snice Node 0 has children 2 levels deep, nodes 10 and 11 should not
// Since Node 0 has children 2 levels deep, nodes 10 and 11 should not
// appear in the selector.
$this->assertNoOption('edit-book-pid', $nodes[10]->id());
$this->assertNoOption('edit-book-pid', $nodes[11]->id());
@ -741,8 +554,8 @@ class BookTest extends BrowserTestBase {
$this->drupalPlaceBlock('book_navigation', ['block_mode' => 'book pages']);
// Unpublish book node.
$edit = [];
$this->drupalPostForm('node/' . $this->book->id() . '/edit', $edit, t('Save and unpublish'));
$edit = ['status[value]' => FALSE];
$this->drupalPostForm('node/' . $this->book->id() . '/edit', $edit, t('Save'));
// Test node page.
$this->drupalGet('node/' . $this->book->id());

View file

@ -0,0 +1,215 @@
<?php
namespace Drupal\Tests\book\Functional;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Entity\EntityInterface;
/**
* Provides common functionality for Book test classes.
*/
trait BookTestTrait {
/**
* A book node.
*
* @var \Drupal\node\NodeInterface
*/
protected $book;
/**
* A user with permission to create and edit books.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $bookAuthor;
/**
* Creates a new book with a page hierarchy.
*
* @param array $edit
* (optional) Field data in an associative array. Changes the current input
* fields (where possible) to the values indicated. Defaults to an empty
* array.
*
* @return \Drupal\node\NodeInterface[]
*/
public function createBook($edit = []) {
// Create new book.
$this->drupalLogin($this->bookAuthor);
$this->book = $this->createBookNode('new', NULL, $edit);
$book = $this->book;
/*
* Add page hierarchy to book.
* Book
* |- Node 0
* |- Node 1
* |- Node 2
* |- Node 3
* |- Node 4
*/
$nodes = [];
// Node 0.
$nodes[] = $this->createBookNode($book->id(), NULL, $edit);
// Node 1.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $edit);
// Node 2.
$nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['nid'], $edit);
// Node 3.
$nodes[] = $this->createBookNode($book->id(), NULL, $edit);
// Node 4.
$nodes[] = $this->createBookNode($book->id(), NULL, $edit);
$this->drupalLogout();
return $nodes;
}
/**
* Checks the outline of sub-pages; previous, up, and next.
*
* Also checks the printer friendly version of the outline.
*
* @param \Drupal\Core\Entity\EntityInterface $node
* Node to check.
* @param $nodes
* Nodes that should be in outline.
* @param $previous
* Previous link node.
* @param $up
* Up link node.
* @param $next
* Next link node.
* @param array $breadcrumb
* The nodes that should be displayed in the breadcrumb.
*/
public function checkBookNode(EntityInterface $node, $nodes, $previous, $up, $next, array $breadcrumb) {
// $number does not use drupal_static as it should not be reset
// since it uniquely identifies each call to checkBookNode().
static $number = 0;
$this->drupalGet('node/' . $node->id());
// Check outline structure.
if ($nodes !== NULL) {
$this->assertPattern($this->generateOutlinePattern($nodes), format_string('Node @number outline confirmed.', ['@number' => $number]));
}
else {
$this->pass(format_string('Node %number does not have outline.', ['%number' => $number]));
}
// Check previous, up, and next links.
if ($previous) {
/** @var \Drupal\Core\Url $url */
$url = $previous->urlInfo();
$url->setOptions(['attributes' => ['rel' => ['prev'], 'title' => t('Go to previous page')]]);
$text = new FormattableMarkup('<b></b> @label', ['@label' => $previous->label()]);
$this->assertRaw(\Drupal::l($text, $url), 'Previous page link found.');
}
if ($up) {
/** @var \Drupal\Core\Url $url */
$url = $up->urlInfo();
$url->setOptions(['attributes' => ['title' => t('Go to parent page')]]);
$this->assertRaw(\Drupal::l('Up', $url), 'Up page link found.');
}
if ($next) {
/** @var \Drupal\Core\Url $url */
$url = $next->urlInfo();
$url->setOptions(['attributes' => ['rel' => ['next'], 'title' => t('Go to next page')]]);
$text = new FormattableMarkup('@label <b></b>', ['@label' => $next->label()]);
$this->assertRaw(\Drupal::l($text, $url), 'Next page link found.');
}
// Compute the expected breadcrumb.
$expected_breadcrumb = [];
$expected_breadcrumb[] = \Drupal::url('<front>');
foreach ($breadcrumb as $a_node) {
$expected_breadcrumb[] = $a_node->url();
}
// Fetch links in the current breadcrumb.
$links = $this->xpath('//nav[@class="breadcrumb"]/ol/li/a');
$got_breadcrumb = [];
foreach ($links as $link) {
$got_breadcrumb[] = $link->getAttribute('href');
}
// Compare expected and got breadcrumbs.
$this->assertIdentical($expected_breadcrumb, $got_breadcrumb, 'The breadcrumb is correctly displayed on the page.');
// Check printer friendly version.
$this->drupalGet('book/export/html/' . $node->id());
$this->assertText($node->label(), 'Printer friendly title found.');
$this->assertRaw($node->body->processed, 'Printer friendly body found.');
$number++;
}
/**
* Creates a regular expression to check for the sub-nodes in the outline.
*
* @param array $nodes
* An array of nodes to check in outline.
*
* @return string
* A regular expression that locates sub-nodes of the outline.
*/
public function generateOutlinePattern($nodes) {
$outline = '';
foreach ($nodes as $node) {
$outline .= '(node\/' . $node->id() . ')(.*?)(' . $node->label() . ')(.*?)';
}
return '/<nav id="book-navigation-' . $this->book->id() . '"(.*?)<ul(.*?)' . $outline . '<\/ul>/s';
}
/**
* Creates a book node.
*
* @param int|string $book_nid
* A book node ID or set to 'new' to create a new book.
* @param int|null $parent
* (optional) Parent book reference ID. Defaults to NULL.
* @param array $edit
* (optional) Field data in an associative array. Changes the current input
* fields (where possible) to the values indicated. Defaults to an empty
* array.
*
* @return \Drupal\node\NodeInterface
* The created node.
*/
public function createBookNode($book_nid, $parent = NULL, $edit = []) {
// $number does not use drupal_static as it should not be reset
// since it uniquely identifies each call to createBookNode().
// Used to ensure that when sorted nodes stay in same order.
static $number = 0;
$edit['title[0][value]'] = str_pad($number, 2, '0', STR_PAD_LEFT) . ' - SimpleTest test node ' . $this->randomMachineName(10);
$edit['body[0][value]'] = 'SimpleTest test body ' . $this->randomMachineName(32) . ' ' . $this->randomMachineName(32);
$edit['book[bid]'] = $book_nid;
if ($parent !== NULL) {
$this->drupalPostForm('node/add/book', $edit, t('Change book (update list of parents)'));
$edit['book[pid]'] = $parent;
$this->drupalPostForm(NULL, $edit, t('Save'));
// Make sure the parent was flagged as having children.
$parent_node = \Drupal::entityManager()->getStorage('node')->loadUnchanged($parent);
$this->assertFalse(empty($parent_node->book['has_children']), 'Parent node is marked as having children');
}
else {
$this->drupalPostForm('node/add/book', $edit, t('Save'));
}
// Check to make sure the book node was created.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertNotNull(($node === FALSE ? NULL : $node), 'Book node found in database.');
$number++;
return $node;
}
}

View file

@ -1,8 +1,8 @@
<?php
namespace Drupal\book\Tests\Views;
namespace Drupal\Tests\book\Functional\Views;
use Drupal\views\Tests\ViewTestBase;
use Drupal\Tests\views\Functional\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
/**
@ -45,8 +45,8 @@ class BookRelationshipTest extends ViewTestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
// Create users.
$this->bookAuthor = $this->drupalCreateUser(

View file

@ -4,7 +4,7 @@ namespace Drupal\Tests\book\FunctionalJavascript;
use Behat\Mink\Exception\ExpectationException;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\node\Entity\Node;
/**
@ -12,7 +12,7 @@ use Drupal\node\Entity\Node;
*
* @group book
*/
class BookJavascriptTest extends JavascriptTestBase {
class BookJavascriptTest extends WebDriverTestBase {
/**
* {@inheritdoc}

View file

@ -0,0 +1,100 @@
<?php
namespace Drupal\Tests\book\Kernel;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests that the Book module handles pending revisions correctly.
*
* @group book
*/
class BookPendingRevisionTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field', 'filter', 'text', 'node', 'book'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installSchema('book', ['book']);
$this->installSchema('node', ['node_access']);
$this->installConfig(['node', 'book', 'field']);
}
/**
* Tests pending revision handling for books.
*/
public function testBookWithPendingRevisions() {
$content_type = NodeType::create([
'type' => $this->randomMachineName(),
'name' => $this->randomString(),
]);
$content_type->save();
$book_config = $this->config('book.settings');
$allowed_types = $book_config->get('allowed_types');
$allowed_types[] = $content_type->id();
$book_config->set('allowed_types', $allowed_types)->save();
// Create two top-level books a child.
$book_1 = Node::create(['title' => $this->randomString(), 'type' => $content_type->id()]);
$book_1->book['bid'] = 'new';
$book_1->save();
$book_1_child = Node::create(['title' => $this->randomString(), 'type' => $content_type->id()]);
$book_1_child->book['bid'] = $book_1->id();
$book_1_child->book['pid'] = $book_1->id();
$book_1_child->save();
$book_2 = Node::create(['title' => $this->randomString(), 'type' => $content_type->id()]);
$book_2->book['bid'] = 'new';
$book_2->save();
$child = Node::create(['title' => $this->randomString(), 'type' => $content_type->id()]);
$child->book['bid'] = $book_1->id();
$child->book['pid'] = $book_1->id();
$child->save();
// Try to move the child to a different book while saving it as a pending
// revision.
/** @var \Drupal\book\BookManagerInterface $book_manager */
$book_manager = $this->container->get('book.manager');
// Check that the API doesn't allow us to change the book outline for
// pending revisions.
$child->book['bid'] = $book_2->id();
$child->setNewRevision(TRUE);
$child->isDefaultRevision(FALSE);
$this->assertFalse($book_manager->updateOutline($child), 'A pending revision can not change the book outline.');
// Check that the API doesn't allow us to change the book parent for
// pending revisions.
$child = \Drupal::entityTypeManager()->getStorage('node')->loadUnchanged($child->id());
$child->book['pid'] = $book_1_child->id();
$child->setNewRevision(TRUE);
$child->isDefaultRevision(FALSE);
$this->assertFalse($book_manager->updateOutline($child), 'A pending revision can not change the book outline.');
// Check that the API doesn't allow us to change the book weight for
// pending revisions.
$child = \Drupal::entityTypeManager()->getStorage('node')->loadUnchanged($child->id());
$child->book['weight'] = 2;
$child->setNewRevision(TRUE);
$child->isDefaultRevision(FALSE);
$this->assertFalse($book_manager->updateOutline($child), 'A pending revision can not change the book outline.');
}
}

View file

@ -76,7 +76,7 @@ class BookUninstallTest extends KernelTestBase {
$book_node->delete();
// No nodes exist therefore the book module is not required.
$module_data = _system_rebuild_module_data();
$module_data = \Drupal::service('extension.list.module')->reset()->getList();
$this->assertFalse(isset($module_data['book']->info['required']), 'The book module is not required.');
$node = Node::create(['title' => $this->randomString(), 'type' => $content_type->id()]);

View file

@ -20,17 +20,29 @@ class MigrateBookConfigsTest extends MigrateDrupal6TestBase {
public static $modules = ['book'];
/**
* {@inheritdoc}
* Data provider for testBookSettings().
*
* @return array
* The data for each test scenario.
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('d6_book_settings');
public function providerBookSettings() {
return [
// d6_book_settings was renamed to book_settings, but use the old alias to
// prove that it works.
// @see book_migration_plugins_alter()
['d6_book_settings'],
['book_settings'],
];
}
/**
* Tests migration of book variables to book.settings.yml.
*
* @dataProvider providerBookSettings
*/
public function testBookSettings() {
public function testBookSettings($migration_id) {
$this->executeMigration($migration_id);
$config = $this->config('book.settings');
$this->assertIdentical('book', $config->get('child_type'));
$this->assertSame('book pages', $config->get('block.navigation.mode'));

View file

@ -0,0 +1,41 @@
<?php
namespace Drupal\Tests\book\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\Tests\SchemaCheckTestTrait;
/**
* Tests the migration of Book settings.
*
* @group migrate_drupal_7
*/
class MigrateBookConfigsTest extends MigrateDrupal7TestBase {
use SchemaCheckTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['book', 'node'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('book_settings');
}
/**
* Tests migration of book variables to book.settings.yml.
*/
public function testBookSettings() {
$config = $this->config('book.settings');
$this->assertSame('book', $config->get('child_type'));
$this->assertSame('all pages', $config->get('block.navigation.mode'));
$this->assertSame(['book'], $config->get('allowed_types'));
$this->assertConfigSchema(\Drupal::service('config.typed'), 'book.settings', $config->get());
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace Drupal\Tests\book\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\node\Entity\Node;
/**
* Tests migration of book structures from Drupal 7.
*
* @group migrate_drupal_7
*/
class MigrateBookTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'book',
'menu_ui',
'node',
'taxonomy',
'text',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('node');
$this->installEntitySchema('taxonomy_term');
$this->installConfig(['node']);
$this->installSchema('book', ['book']);
$this->installSchema('node', ['node_access']);
$this->executeMigrations([
'd7_user_role',
'd7_user',
'd7_node_type',
'd7_node',
'd7_book',
]);
}
/**
* Tests the Drupal 7 book structure to Drupal 8 migration.
*/
public function testBook() {
$nodes = Node::loadMultiple([1, 2, 4, 6]);
$this->assertSame('8', $nodes[1]->book['bid']);
$this->assertSame('6', $nodes[1]->book['pid']);
$this->assertSame('4', $nodes[2]->book['bid']);
$this->assertSame('6', $nodes[2]->book['pid']);
$this->assertSame('4', $nodes[4]->book['bid']);
$this->assertSame('0', $nodes[4]->book['pid']);
$this->assertSame('4', $nodes[6]->book['bid']);
$this->assertSame('4', $nodes[6]->book['pid']);
$tree = \Drupal::service('book.manager')->bookTreeAllData(4);
$this->assertSame('4', $tree['49990 is - The thing about Firefly 4']['link']['nid']);
$this->assertSame('6', $tree['49990 is - The thing about Firefly 4']['below']['50000 Comments are closed :-( 6']['link']['nid']);
$this->assertSame('2', $tree['49990 is - The thing about Firefly 4']['below']['50000 Comments are closed :-( 6']['below']['50000 The thing about Deep Space 9 2']['link']['nid']);
$this->assertSame([], $tree['49990 is - The thing about Firefly 4']['below']['50000 Comments are closed :-( 6']['below']['50000 The thing about Deep Space 9 2']['below']);
}
}

View file

@ -1,19 +1,21 @@
<?php
namespace Drupal\Tests\book\Kernel\Plugin\migrate\source\d6;
namespace Drupal\Tests\book\Kernel\Plugin\migrate\source;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
use Drupal\book\Plugin\migrate\source\d6\Book as D6Book;
/**
* @covers \Drupal\book\Plugin\migrate\source\d6\Book
* @covers \Drupal\book\Plugin\migrate\source\Book
* @group book
* @group legacy
*/
class BookTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['book', 'migrate_drupal'];
public static $modules = ['book', 'migrate_drupal', 'node'];
/**
* {@inheritdoc}
@ -81,4 +83,18 @@ class BookTest extends MigrateSqlSourceTestBase {
return $tests;
}
/**
* @expectedDeprecation Book is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.x. Use \Drupal\book\Plugin\migrate\source\Book instead. See https://www.drupal.org/node/2947487 for more information.
*/
public function testDeprecatedPlugin() {
new D6Book(
[],
'd6_book',
[],
$this->prophesize('Drupal\migrate\Plugin\MigrationInterface')->reveal(),
$this->prophesize('Drupal\Core\State\StateInterface')->reveal(),
$this->prophesize('Drupal\Core\Entity\EntityManagerInterface')->reveal()
);
}
}