diff --git a/core/modules/book/book.admin.inc b/core/modules/book/book.admin.inc index 611537b..07ba878 100644 --- a/core/modules/book/book.admin.inc +++ b/core/modules/book/book.admin.inc @@ -79,11 +79,10 @@ function book_admin_edit_submit($form, &$form_state) { // Update the title if changed. if ($row['title']['#default_value'] != $values['title']) { $node = node_load($values['nid']); - $langcode = Language::LANGCODE_NOT_SPECIFIED; $node->title = $values['title']; - $node->book['link_title'] = $values['title']; + $node->book->link_title = $values['title']; $node->setNewRevision(); - $node->log = t('Title changed from %original to %current.', array('%original' => $node->title, '%current' => $values['title'])); + $node->log = t('Title changed from %original to %current.', array('%original' => $node->label(), '%current' => $values['title'])); $node->save(); watchdog('content', 'book: updated %title.', array('%title' => $node->label()), WATCHDOG_NOTICE, l(t('view'), 'node/' . $node->id())); diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 23dd8d7..ecf0db0 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -113,6 +113,21 @@ function book_permission() { } /** + * Implements hook_entity_field_info(). + */ +function book_entity_field_info($entity_type) { + if ($entity_type === 'node') { + $info['definitions']['book'] = array( + 'type' => 'book_field', + 'label' => t('The book data'), + 'computed' => TRUE, + 'list' => TRUE, + ); + return $info; + } +} + +/** * Adds relevant book links to the node's links. * * @param \Drupal\Core\Entity\EntityInterface $node @@ -123,14 +138,14 @@ function book_permission() { function book_node_view_link(NodeInterface $node, $view_mode) { $links = array(); - if (isset($node->book['depth'])) { + if (isset($node->book->depth)) { if ($view_mode == 'full' && node_is_page($node)) { $child_type = config('book.settings')->get('child_type'); - if ((user_access('add content to books') || user_access('administer book outlines')) && node_access('create', $child_type) && $node->isPublished() && $node->book['depth'] < MENU_MAX_DEPTH) { + if ((user_access('add content to books') || user_access('administer book outlines')) && node_access('create', $child_type) && $node->isPublished() && $node->book->depth < MENU_MAX_DEPTH) { $links['book_add_child'] = array( 'title' => t('Add child page'), 'href' => 'node/add/' . $child_type, - 'query' => array('parent' => $node->book['mlid']), + 'query' => array('parent' => $node->book->mlid), ); } @@ -265,7 +280,7 @@ function _book_outline_remove_access(EntityInterface $node) { * The node to remove from the outline. */ function _book_node_is_removable(EntityInterface $node) { - return (!empty($node->book['bid']) && (($node->book['bid'] != $node->id()) || !$node->book['has_children'])); + return (!empty($node->book->bid) && (($node->book->bid != $node->id()) || !$node->book->has_children)); } /** @@ -307,7 +322,7 @@ function book_form_node_form_alter(&$form, &$form_state, $form_id) { $node = $form_state['controller']->getEntity(); $access = user_access('administer book outlines'); if (!$access) { - if (user_access('add content to books') && ((!empty($node->book['mlid']) && !$node->isNew()) || book_type_is_allowed($node->bundle()))) { + if (user_access('add content to books') && ((!empty($node->book->mlid) && !$node->isNew()) || book_type_is_allowed($node->bundle()))) { // Already in the book hierarchy, or this node type is allowed. $access = TRUE; } @@ -373,25 +388,25 @@ function _book_parent_select($book_link) { '#suffix' => '', ); - if ($book_link['nid'] === $book_link['bid']) { + if ($book_link->nid === $book_link->bid) { // This is a book - at the top level. - if ($book_link['original_bid'] === $book_link['bid']) { + if ($book_link->original_bid === $book_link->bid) { $form['#prefix'] .= '' . t('This is the top-level page in this book.') . ''; } else { $form['#prefix'] .= '' . t('This will be the top-level page in this book.') . ''; } } - elseif (!$book_link['bid']) { + elseif (!$book_link->bid) { $form['#prefix'] .= '' . t('No book selected.') . ''; } else { $form = array( '#type' => 'select', '#title' => t('Parent item'), - '#default_value' => $book_link['plid'], + '#default_value' => $book_link->plid, '#description' => t('The parent page in the book. The maximum depth for a book and all child pages is !maxdepth. Some pages in the selected book may not be available as parents if selecting them would exceed this limit.', array('!maxdepth' => MENU_MAX_DEPTH)), - '#options' => book_toc($book_link['bid'], $book_link['parent_depth_limit'], array($book_link['mlid'])), + '#options' => book_toc($book_link->bid, $book_link->parent_depth_limit, array($book_link->mlid)), '#attributes' => array('class' => array('book-title-select')), '#prefix' => '
', '#suffix' => '
', @@ -431,7 +446,7 @@ function _book_add_form_elements(&$form, &$form_state, EntityInterface $node) { foreach (array('menu_name', 'mlid', 'nid', 'router_path', 'has_children', 'options', 'module', 'original_bid', 'parent_depth_limit') as $key) { $form['book'][$key] = array( '#type' => 'value', - '#value' => $node->book[$key], + '#value' => $node->book->$key, ); } @@ -441,15 +456,15 @@ function _book_add_form_elements(&$form, &$form_state, EntityInterface $node) { $form['book']['weight'] = array( '#type' => 'weight', '#title' => t('Weight'), - '#default_value' => $node->book['weight'], - '#delta' => max(15, abs($node->book['weight'])), + '#default_value' => $node->book->weight, + '#delta' => max(15, abs($node->book->weight)), '#weight' => 5, '#description' => t('Pages at a given level are ordered first by weight and then by title.'), ); $options = array(); $nid = !$node->isNew() ? $node->id() : 'new'; - if ($node->id() && ($nid == $node->book['original_bid']) && ($node->book['parent_depth_limit'] == 0)) { + if ($node->id() && ($nid == $node->book->original_bid) && ($node->book->parent_depth_limit == 0)) { // This is the top level node in a maximum depth book and thus cannot be moved. $options[$node->id()] = $node->label(); } @@ -459,11 +474,11 @@ function _book_add_form_elements(&$form, &$form_state, EntityInterface $node) { } } - if (user_access('create new books') && ($nid == 'new' || ($nid != $node->book['original_bid']))) { + if (user_access('create new books') && ($nid == 'new' || ($nid != $node->book->original_bid))) { // The node can become a new book, if it is not one already. $options = array($nid => t('- Create a new book -')) + $options; } - if (!$node->book['mlid']) { + if (!$node->book->mlid) { // The node is not currently in the hierarchy. $options = array(0 => t('- None -')) + $options; } @@ -472,7 +487,7 @@ function _book_add_form_elements(&$form, &$form_state, EntityInterface $node) { $form['book']['bid'] = array( '#type' => 'select', '#title' => t('Book'), - '#default_value' => $node->book['bid'], + '#default_value' => $node->book->bid, '#options' => $options, '#access' => (bool) $options, '#description' => t('Your page will be a part of the selected book.'), @@ -514,50 +529,52 @@ function book_form_update($form, $form_state) { * TRUE if the menu link was saved; FALSE otherwise. */ function _book_update_outline(EntityInterface $node) { - if (empty($node->book['bid'])) { + if (empty($node->book->bid)) { return FALSE; } - $new = empty($node->book['mlid']); + $new = empty($node->book->mlid); - $node->book['link_path'] = 'node/' . $node->id(); - $node->book['link_title'] = $node->label(); - $node->book['parent_mismatch'] = FALSE; // The normal case. + $node->book->link_path = 'node/' . $node->id(); + $node->book->link_title = $node->label(); + $node->book->parent_mismatch = FALSE; // The normal case. - if ($node->book['bid'] == $node->id()) { - $node->book['plid'] = 0; - $node->book['menu_name'] = book_menu_name($node->id()); + if ($node->book->bid == $node->id()) { + $node->book->plid = 0; + $node->book->menu_name = book_menu_name($node->id()); } else { // Check in case the parent is not is this book; the book takes precedence. - if (!empty($node->book['plid'])) { + if (!empty($node->book->plid)) { $parent = db_query("SELECT * FROM {book} WHERE mlid = :mlid", array( - ':mlid' => $node->book['plid'], + ':mlid' => $node->book->plid, ))->fetchAssoc(); } - if (empty($node->book['plid']) || !$parent || $parent['bid'] != $node->book['bid']) { - $node->book['plid'] = db_query("SELECT mlid FROM {book} WHERE nid = :nid", array( - ':nid' => $node->book['bid'], + if (empty($node->book->plid) || !$parent || $parent['bid'] != $node->book->bid) { + $node->book->plid = db_query("SELECT mlid FROM {book} WHERE nid = :nid", array( + ':nid' => $node->book->bid, ))->fetchField(); - $node->book['parent_mismatch'] = TRUE; // Likely when JS is disabled. + $node->book->parent_mismatch = TRUE; // Likely when JS is disabled. } } - $node->book = entity_create('menu_link', $node->book); - if ($node->book->save()) { + $link = entity_create('menu_link', $node->book->getValue()); + debug($link); + if ($link->save()) { + debug($link); if ($new) { // Insert new. db_insert('book') ->fields(array( 'nid' => $node->id(), - 'mlid' => $node->book['mlid'], - 'bid' => $node->book['bid'], + 'mlid' => $link->mlid, + 'bid' => $node->book->bid, )) ->execute(); // Reset the cache of stored books. drupal_static_reset('book_get_books'); } else { - if ($node->book['bid'] != db_query("SELECT bid FROM {book} WHERE nid = :nid", array( + if ($node->book->bid != db_query("SELECT bid FROM {book} WHERE nid = :nid", array( ':nid' => $node->id(), ))->fetchField()) { // Update the bid for this page and all children. @@ -583,14 +600,14 @@ function _book_update_outline(EntityInterface $node) { function book_update_bid($book_link) { $query = db_select('menu_links'); $query->addField('menu_links', 'mlid'); - for ($i = 1; $i <= MENU_MAX_DEPTH && $book_link["p$i"]; $i++) { - $query->condition("p$i", $book_link["p$i"]); + for ($i = 1; $i <= MENU_MAX_DEPTH && $book_link->{"p$i"}; $i++) { + $query->condition("p$i", $book_link->{"p$i"}); } $mlids = $query->execute()->fetchCol(); if ($mlids) { db_update('book') - ->fields(array('bid' => $book_link['bid'])) + ->fields(array('bid' => $book_link->bid)) ->condition('mlid', $mlids, 'IN') ->execute(); } @@ -612,14 +629,14 @@ function book_update_bid($book_link) { function book_get_flat_menu($book_link) { $flat = &drupal_static(__FUNCTION__, array()); - if (!isset($flat[$book_link['mlid']])) { + if (!isset($flat[$book_link->mlid])) { // Call menu_tree_all_data() to take advantage of the menu system's caching. - $tree = menu_tree_all_data($book_link['menu_name'], $book_link, $book_link['depth'] + 1); - $flat[$book_link['mlid']] = array(); - _book_flatten_menu($tree, $flat[$book_link['mlid']]); + $tree = menu_tree_all_data($book_link->menu_name, $book_link, $book_link->depth + 1); + $flat[$book_link->mlid] = array(); + _book_flatten_menu($tree, $flat[$book_link->mlid]); } - return $flat[$book_link['mlid']]; + return $flat[$book_link->mlid]; } /** @@ -655,7 +672,7 @@ function _book_flatten_menu($tree, &$flat) { */ function book_prev($book_link) { // If the parent is zero, we are at the start of a book. - if ($book_link['plid'] == 0) { + if ($book_link->plid == 0) { return NULL; } $flat = book_get_flat_menu($book_link); @@ -664,11 +681,11 @@ function book_prev($book_link) { do { $prev = $curr; list($key, $curr) = each($flat); - } while ($key && $key != $book_link['mlid']); + } while ($key && $key != $book_link->mlid); - if ($key == $book_link['mlid']) { + if ($key == $book_link->mlid) { // The previous page in the book may be a child of the previous visible link. - if ($prev['depth'] == $book_link['depth'] && $prev['has_children']) { + if ($prev->depth == $book_link->depth && $prev->has_children) { // The subtree will have only one link at the top level - get its data. $tree = book_menu_subtree_data($prev); $data = array_shift($tree); @@ -701,9 +718,9 @@ function book_next($book_link) { do { list($key, $curr) = each($flat); } - while ($key && $key != $book_link['mlid']); + while ($key && $key != $book_link->mlid); - if ($key == $book_link['mlid']) { + if ($key == $book_link->mlid) { return current($flat); } } @@ -722,14 +739,14 @@ function book_children($book_link) { $children = array(); - if ($book_link['has_children']) { + if ($book_link->has_children) { // Walk through the array until we find the current page. do { $link = array_shift($flat); } - while ($link && ($link['mlid'] != $book_link['mlid'])); + while ($link && ($link['mlid'] != $book_link->mlid)); // Continue though the array and collect the links whose parent is this page. - while (($link = array_shift($flat)) && $link['plid'] == $book_link['mlid']) { + while (($link = array_shift($flat)) && $link['plid'] == $book_link->mlid) { $data['link'] = $link; $data['below'] = ''; $children[] = $data; @@ -762,10 +779,11 @@ function book_menu_name($bid) { function book_node_load($nodes, $types) { $result = db_query("SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid IN (:nids)", array(':nids' => array_keys($nodes)), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $record) { + debug($record); $nodes[$record['nid']]->book = $record; - $nodes[$record['nid']]->book['href'] = $record['link_path']; - $nodes[$record['nid']]->book['title'] = $record['link_title']; - $nodes[$record['nid']]->book['options'] = unserialize($record['options']); + $nodes[$record['nid']]->book->href = $record['link_path']; + $nodes[$record['nid']]->book->title = $record['link_title']; + $nodes[$record['nid']]->book->options = unserialize($record['options']); } } @@ -774,7 +792,7 @@ function book_node_load($nodes, $types) { */ function book_node_view(EntityInterface $node, EntityDisplay $display, $view_mode) { if ($view_mode == 'full') { - if (!empty($node->book['bid']) && empty($node->in_preview)) { + if (!empty($node->book->bid) && empty($node->in_preview)) { $book_navigation = array( '#theme' => 'book_navigation', '#book_link' => $node->book); $node->content['book_navigation'] = array( '#markup' => drupal_render($book_navigation), @@ -800,9 +818,9 @@ function book_node_view(EntityInterface $node, EntityDisplay $display, $view_mod * viewing a book page. */ function book_page_alter(&$page) { - if (($node = menu_get_object()) && !empty($node->book['bid'])) { + if (($node = menu_get_object()) && !empty($node->book->bid)) { $active_menus = menu_get_active_menu_names(); - $active_menus[] = $node->book['menu_name']; + $active_menus[] = $node->book->menu_name; menu_set_active_menu_names($active_menus); } } @@ -812,12 +830,12 @@ function book_page_alter(&$page) { */ function book_node_presave(EntityInterface $node) { // Always save a revision for non-administrators. - if (!empty($node->book['bid']) && !user_access('administer nodes')) { + if (!empty($node->book->bid) && !user_access('administer nodes')) { $node->setNewRevision(); } // Make sure a new node gets a new menu link. if ($node->isNew()) { - $node->book['mlid'] = NULL; + $node->book->mlid = NULL; } } @@ -825,13 +843,13 @@ function book_node_presave(EntityInterface $node) { * Implements hook_node_insert(). */ function book_node_insert(EntityInterface $node) { - if (!empty($node->book['bid'])) { - if ($node->book['bid'] == 'new') { + if (!empty($node->book->bid)) { + if ($node->book->bid == 'new') { // New nodes that are their own book. - $node->book['bid'] = $node->id(); + $node->book->bid = $node->id(); } - $node->book['nid'] = $node->id(); - $node->book['menu_name'] = book_menu_name($node->book['bid']); + $node->book->nid = $node->id(); + $node->book->menu_name = book_menu_name($node->book->bid); _book_update_outline($node); } } @@ -840,13 +858,13 @@ function book_node_insert(EntityInterface $node) { * Implements hook_node_update(). */ function book_node_update(EntityInterface $node) { - if (!empty($node->book['bid'])) { - if ($node->book['bid'] == 'new') { + if (!empty($node->book->bid)) { + if ($node->book->bid == 'new') { // New nodes that are their own book. - $node->book['bid'] = $node->id(); + $node->book->bid = $node->id(); } - $node->book['nid'] = $node->id(); - $node->book['menu_name'] = book_menu_name($node->book['bid']); + $node->book->nid = $node->id(); + $node->book->menu_name = book_menu_name($node->book->bid); _book_update_outline($node); } } @@ -855,21 +873,21 @@ function book_node_update(EntityInterface $node) { * Implements hook_node_predelete(). */ function book_node_predelete(EntityInterface $node) { - if (!empty($node->book['bid'])) { - if ($node->id() == $node->book['bid']) { + if (!empty($node->book->bid)) { + if ($node->id() == $node->book->bid) { // Handle deletion of a top-level post. $result = db_query("SELECT b.nid FROM {menu_links} ml INNER JOIN {book} b on b.mlid = ml.mlid WHERE ml.plid = :plid", array( - ':plid' => $node->book['mlid'] + ':plid' => $node->book->mlid )); foreach ($result as $child) { $child_node = node_load($child->id()); - $child_node->book['bid'] = $child_node->id(); + $child_node->book->bid = $child_node->id(); _book_update_outline($child_node); } } - menu_link_delete($node->book['mlid']); + menu_link_delete($node->book->mlid); db_delete('book') - ->condition('mlid', $node->book['mlid']) + ->condition('mlid', $node->book->mlid) ->execute(); drupal_static_reset('book_get_books'); } @@ -889,22 +907,22 @@ function book_node_prepare_form(NodeInterface $node, $form_display, $operation, $parent = book_link_load($query->get('parent')); if ($parent && $parent['access']) { - $node->book['bid'] = $parent['bid']; - $node->book['plid'] = $parent['mlid']; - $node->book['menu_name'] = $parent['menu_name']; + $node->book->bid = $parent['bid']; + $node->book->plid = $parent['mlid']; + $node->book->menu_name = $parent['menu_name']; } } // Set defaults. $node->book += _book_link_defaults(!$node->isNew() ? $node->id() : 'new'); } else { - if (isset($node->book['bid']) && !isset($node->book['original_bid'])) { - $node->book['original_bid'] = $node->book['bid']; + if (isset($node->book->bid) && !isset($node->book->original_bid)) { + $node->book->original_bid = $node->book->bid; } } // Find the depth limit for the parent select. - if (isset($node->book['bid']) && !isset($node->book['parent_depth_limit'])) { - $node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book); + if (isset($node->book->bid) && !isset($node->book->parent_depth_limit)) { + $node->book->parent_depth_limit = _book_parent_depth_limit($node->book); } } @@ -918,7 +936,7 @@ function book_node_prepare_form(NodeInterface $node, $form_display, $operation, * The depth limit for items in the parent select. */ function _book_parent_depth_limit($book_link) { - return MENU_MAX_DEPTH - 1 - (($book_link['mlid'] && $book_link['has_children']) ? entity_get_controller('menu_link')->findChildrenRelativeDepth($book_link) : 0); + return MENU_MAX_DEPTH - 1 - (($book_link->mlid && $book_link->has_children) ? entity_get_controller('menu_link')->findChildrenRelativeDepth($book_link) : 0); } /** @@ -931,7 +949,7 @@ function _book_parent_depth_limit($book_link) { function book_form_node_delete_confirm_alter(&$form, $form_state) { $node = node_load($form['nid']['#value']); - if (isset($node->book) && $node->book['has_children']) { + if (isset($node->book) && $node->book->has_children) { $form['book_warning'] = array( '#markup' => '

' . t('%title is part of a book outline, and has associated child pages. If you proceed with deletion, the child pages will be relocated automatically.', array('%title' => $node->label())) . '

', '#weight' => -10, @@ -998,13 +1016,13 @@ function template_preprocess_book_navigation(&$variables) { $book_link = $variables['book_link']; // Provide extra variables for themers. Not needed by default. - $variables['book_id'] = $book_link['bid']; - $variables['book_title'] = check_plain($book_link['link_title']); - $variables['book_url'] = 'node/' . $book_link['bid']; - $variables['current_depth'] = $book_link['depth']; + $variables['book_id'] = $book_link->bid; + $variables['book_title'] = check_plain($book_link->link_title); + $variables['book_url'] = 'node/' . $book_link->bid; + $variables['current_depth'] = $book_link->depth; $variables['tree'] = ''; - if ($book_link['mlid']) { + if ($book_link->mlid) { $variables['tree'] = book_children($book_link); if ($prev = book_prev($book_link)) { @@ -1014,7 +1032,7 @@ function template_preprocess_book_navigation(&$variables) { $variables['prev_title'] = check_plain($prev['title']); } - if ($book_link['plid'] && $parent = book_link_load($book_link['plid'])) { + if ($book_link->plid && $parent = book_link_load($book_link->plid)) { $parent_href = url($parent['link_path']); drupal_add_html_head_link(array('rel' => 'up', 'href' => $parent_href)); $variables['parent_url'] = $parent_href; @@ -1099,7 +1117,9 @@ function _book_toc_recurse($tree, $indent, &$toc, $exclude, $depth_limit) { * book page. */ function book_toc($bid, $depth_limit, $exclude = array()) { + debug(array_keys(entity_load_multiple('menu'))); $tree = menu_tree_all_data(book_menu_name($bid)); + debug($tree); $toc = array(); _book_toc_recurse($tree, '', $toc, $exclude, $depth_limit); @@ -1208,7 +1228,7 @@ function book_node_export(EntityInterface $node, $children = '') { * to an empty string. */ function template_preprocess_book_node_export_html(&$variables) { - $variables['depth'] = $variables['node']->book['depth']; + $variables['depth'] = $variables['node']->book->depth; $variables['title'] = check_plain($variables['node']->label()); $variables['content'] = $variables['node']->rendered; } @@ -1290,7 +1310,7 @@ function book_menu_subtree_data($link) { $tree = &drupal_static(__FUNCTION__, array()); // Generate a cache ID (cid) specific for this $menu_name and $link. - $cid = 'links:' . $link['menu_name'] . ':subtree-cid:' . $link['mlid']; + $cid = 'links:' . $link->menu_name . ':subtree-cid:' . $link->mlid; if (!isset($tree[$cid])) { $cache = cache('menu')->get($cid); @@ -1313,22 +1333,24 @@ function book_menu_subtree_data($link) { $query->fields('b'); $query->fields('m', array('load_functions', 'to_arg_functions', 'access_callback', 'access_arguments', 'page_callback', 'page_arguments', 'title', 'title_callback', 'title_arguments', 'type')); $query->fields('ml'); - $query->condition('menu_name', $link['menu_name']); - for ($i = 1; $i <= MENU_MAX_DEPTH && $link["p$i"]; ++$i) { - $query->condition("p$i", $link["p$i"]); + $query->condition('menu_name', $link->menu_name); + for ($i = 1; $i <= MENU_MAX_DEPTH && $link->{"p$i"}; ++$i) { + $query->condition("p$i", $link->{"p$i"}); } for ($i = 1; $i <= MENU_MAX_DEPTH; ++$i) { $query->orderBy("p$i"); } $links = array(); + debug((string)$query); + debug($query->getArguments()); foreach ($query->execute() as $item) { $links[] = $item; } - $data['tree'] = menu_tree_data($links, array(), $link['depth']); + $data['tree'] = menu_tree_data($links, array(), $link->depth); $data['node_links'] = array(); menu_tree_collect_node_links($data['tree'], $data['node_links']); // Compute the real cid for book subtree data. - $tree_cid = 'links:' . $item['menu_name'] . ':subtree-data:' . hash('sha256', serialize($data)); + $tree_cid = 'links:' . $item->menu_name . ':subtree-data:' . hash('sha256', serialize($data)); // Cache the data, if it is not already in the cache. if (!cache('menu')->get($tree_cid)) { diff --git a/core/modules/book/book.pages.inc b/core/modules/book/book.pages.inc index 4cd7e25..7b087f6 100644 --- a/core/modules/book/book.pages.inc +++ b/core/modules/book/book.pages.inc @@ -72,7 +72,7 @@ function book_export_html(EntityInterface $node) { if (isset($node->book)) { $tree = book_menu_subtree_data($node->book); $contents = book_export_traverse($tree, 'book_node_export'); - $book_exported_html = array('#theme' => 'book_export_html', '#title' => $node->label(), '#contents' => $contents, '#depth' => $node->book['depth']); + $book_exported_html = array('#theme' => 'book_export_html', '#title' => $node->label(), '#contents' => $contents, '#depth' => $node->book->depth); return drupal_render($book_exported_html); } else { @@ -118,12 +118,12 @@ function book_outline_form($form, &$form_state, EntityInterface $node) { $node->book = _book_link_defaults($node->id()); } else { - $node->book['original_bid'] = $node->book['bid']; + $node->book->original_bid = $node->book->bid; } // Find the depth limit for the parent select. - if (!isset($node->book['parent_depth_limit'])) { - $node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book); + if (!isset($node->book->parent_depth_limit)) { + $node->book->parent_depth_limit = _book_parent_depth_limit($node->book); } $form['#node'] = $node; $form['#id'] = 'book-outline'; @@ -131,7 +131,7 @@ function book_outline_form($form, &$form_state, EntityInterface $node) { $form['update'] = array( '#type' => 'submit', - '#value' => $node->book['original_bid'] ? t('Update book outline') : t('Add to book outline'), + '#value' => $node->book->original_bid ? t('Update book outline') : t('Add to book outline'), '#weight' => 15, ); @@ -175,7 +175,7 @@ function book_outline_form_submit($form, &$form_state) { $book_link['menu_name'] = book_menu_name($book_link['bid']); $node->book = $book_link; if (_book_update_outline($node)) { - if ($node->book['parent_mismatch']) { + if ($node->book->parent_mismatch) { // This will usually only happen when JS is disabled. drupal_set_message(t('The post has been added to the selected book. You may now position it relative to other pages.')); $form_state['redirect'] = "node/" . $node->id() . "/outline"; @@ -203,7 +203,7 @@ function book_remove_form($form, &$form_state, EntityInterface $node) { $form['#node'] = $node; $title = array('%title' => $node->label()); - if ($node->book['has_children']) { + if ($node->book->has_children) { $description = t('%title has associated child pages, which will be relocated automatically to maintain their connection to the book. To recreate the hierarchy (as it was before removing this page), %title may be added again using the Outline tab, and each of its former child pages will need to be relocated manually.', $title); } else { @@ -219,7 +219,7 @@ function book_remove_form($form, &$form_state, EntityInterface $node) { function book_remove_form_submit($form, &$form_state) { $node = $form['#node']; if (_book_node_is_removable($node)) { - menu_link_delete($node->book['mlid']); + menu_link_delete($node->book->mlid); db_delete('book') ->condition('nid', $node->id()) ->execute(); diff --git a/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php b/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php index 8cacc04..fe7fd35 100644 --- a/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php +++ b/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php @@ -64,7 +64,7 @@ public function blockSubmit($form, &$form_state) { public function build() { $current_bid = 0; if ($node = menu_get_object()) { - $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid']; + $current_bid = $node->book->bid; } if ($this->configuration['block_mode'] == 'all pages') { $book_menus = array(); @@ -73,7 +73,7 @@ public function build() { if ($book['bid'] == $current_bid) { // If the current page is a node associated with a book, the menu // needs to be retrieved. - $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book)); + $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book->menu_name, $node->book)); } else { // Since we know we will only display a link to the top node, there @@ -97,7 +97,7 @@ public function build() { // Only display this block when the user is browsing a book. $select = db_select('node', 'n') ->fields('n', array('nid')) - ->condition('n.nid', $node->book['bid']) + ->condition('n.nid', $node->book->bid) ->addTag('node_access'); $nid = $select->execute()->fetchField(); // Only show the block if the user has view access for the top-level node. diff --git a/core/modules/book/lib/Drupal/book/Plugin/DataType/BookItem.php b/core/modules/book/lib/Drupal/book/Plugin/DataType/BookItem.php new file mode 100644 index 0000000..c54822b --- /dev/null +++ b/core/modules/book/lib/Drupal/book/Plugin/DataType/BookItem.php @@ -0,0 +1,60 @@ + 'integer', + 'label' => t('Book id'), + ); + static::$propertyDefinitions['menu_name'] = array( + 'type' => 'string', + 'label' => t('Menu name'), + ); + static::$propertyDefinitions['link_path'] = array( + 'type' => 'string', + 'label' => t('Link path'), + ); + static::$propertyDefinitions['link_title'] = array( + 'type' => 'string', + 'label' => t('Link title'), + ); + } + return static::$propertyDefinitions; + } + +} diff --git a/core/modules/book/lib/Drupal/book/Tests/BookTest.php b/core/modules/book/lib/Drupal/book/Tests/BookTest.php index a72b92c..8caaa7c 100644 --- a/core/modules/book/lib/Drupal/book/Tests/BookTest.php +++ b/core/modules/book/lib/Drupal/book/Tests/BookTest.php @@ -80,6 +80,8 @@ function createBook() { $this->book = $this->createBookNode('new'); $book = $this->book; + debug($book->id()); + debug($book->getPropertyValues()); /* * Add page hierarchy to book. @@ -92,8 +94,11 @@ function createBook() { */ $nodes = array(); $nodes[] = $this->createBookNode($book->id()); // Node 0. - $nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['mlid']); // Node 1. - $nodes[] = $this->createBookNode($book->id(), $nodes[0]->book['mlid']); // Node 2. + debug(1); + $nodes[] = $this->createBookNode($book->id(), $nodes[0]->book->mlid); // Node 1. + debug(2); + $nodes[] = $this->createBookNode($book->id(), $nodes[0]->book->mlid); // Node 2. + debug($nodes[0]->book->getValue()); $nodes[] = $this->createBookNode($book->id()); // Node 3. $nodes[] = $this->createBookNode($book->id()); // Node 4. @@ -494,7 +499,7 @@ public function testBookOrdering() { $this->drupalLogin($this->admin_user); $node1 = $this->createBookNode($book->id()); $node2 = $this->createBookNode($book->id()); - $plid = $node1->book['mlid']; + $plid = $node1->book->mlid; // Head to admin screen and attempt to re-order. $this->drupalGet('admin/structure/book/' . $book->id()); diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index a8ffc3d..d9e2d2f 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -278,17 +278,18 @@ function forum_node_validate(EntityInterface $node, $form) { if (_forum_node_check_node_type($node)) { $langcode = $form['taxonomy_forums']['#language']; // vocabulary is selected, not a "container" term. - if (!empty($node->taxonomy_forums[$langcode])) { + if (!$node->taxonomy_forums->isEmpty()) { // Extract the node's proper topic ID. $containers = config('forum.settings')->get('containers'); - foreach ($node->taxonomy_forums[$langcode] as $delta => $item) { + foreach ($node->taxonomy_forums as $delta => $item) { // If no term was selected (e.g. when no terms exist yet), remove the // item. - if (empty($item['target_id'])) { - unset($node->taxonomy_forums[$langcode][$delta]); + if (empty($item->target_id)) { + // @todo: Does this work? + unset($node->taxonomy_forums[$delta]); continue; } - $term = entity_load('taxonomy_term', $item['target_id']); + $term = $item->entity; if (!$term) { form_set_error('taxonomy_forums', t('Select a forum.')); continue; @@ -311,19 +312,18 @@ function forum_node_validate(EntityInterface $node, $form) { * Assigns the forum taxonomy when adding a topic from within a forum. */ function forum_node_presave(EntityInterface $node) { + if (_forum_node_check_node_type($node)) { // Make sure all fields are set properly: $node->icon = !empty($node->icon) ? $node->icon : ''; - reset($node->taxonomy_forums); - $langcode = key($node->taxonomy_forums); - if (!empty($node->taxonomy_forums[$langcode])) { - $node->forum_tid = $node->taxonomy_forums[$langcode][0]['target_id']; + if (!$node->taxonomy_forums->isEmpty()) { + $node->forum_tid = $node->taxonomy_forums->target_id; // Only do a shadow copy check if this is not a new node. if (!$node->isNew()) { $old_tid = db_query_range("SELECT f.tid FROM {forum} f INNER JOIN {node} n ON f.vid = n.vid WHERE n.nid = :nid ORDER BY f.vid DESC", 0, 1, array(':nid' => $node->id()))->fetchField(); if ($old_tid && isset($node->forum_tid) && ($node->forum_tid != $old_tid) && !empty($node->shadow)) { // A shadow copy needs to be created. Retain new term and add old term. - $node->taxonomy_forums[$langcode][] = array('target_id' => $old_tid); + $node->taxonomy_forums[count($node->taxonomy_forums)] = array('target_id' => $old_tid); } } } @@ -501,6 +501,7 @@ function forum_comment_delete($comment) { * Implements hook_field_storage_pre_insert(). */ function forum_field_storage_pre_insert(EntityInterface $entity, &$skip_fields) { + $entity = $entity->getNGEntity(); if ($entity->entityType() == 'node' && $entity->isPublished() && _forum_node_check_node_type($entity)) { $query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp')); foreach ($entity->getTranslationLanguages() as $langcode => $language) { @@ -525,6 +526,7 @@ function forum_field_storage_pre_insert(EntityInterface $entity, &$skip_fields) function forum_field_storage_pre_update(EntityInterface $entity, &$skip_fields) { $first_call = &drupal_static(__FUNCTION__, array()); + $entity = $entity->getNGEntity(); if ($entity->entityType() == 'node' && _forum_node_check_node_type($entity)) { // If the node is published, update the forum index. @@ -1139,7 +1141,7 @@ function template_preprocess_forum_topic_list(&$variables) { $variables['topics'][$id]->new_text = ''; $variables['topics'][$id]->new_url = ''; if ($topic->new_replies) { - $variables['topics'][$id]->new_text = format_plural($topic->new_replies, '1 new post in topic %title', '@count new posts in topic %title', array('%title' => $variables['topics'][$id]->title)); + $variables['topics'][$id]->new_text = format_plural($topic->new_replies, '1 new post in topic %title', '@count new posts in topic %title', array('%title' => $variables['topics'][$id]->label())); $variables['topics'][$id]->new_url = url('node/' . $topic->id(), array('query' => comment_new_page_count($topic->comment_count, $topic->new_replies, $topic), 'fragment' => 'new')); } diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 93a13d1..2281a6f 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -191,7 +191,7 @@ public function form(array $form, array &$form_state) { '#title' => t('Authored by'), '#maxlength' => 60, '#autocomplete_path' => 'user/autocomplete', - '#default_value' => !empty($node->name) ? $node->name : '', + '#default_value' => $node->getAuthorId()? $node->getAuthor()->getUsername() : '', '#weight' => -1, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => $user_config->get('anonymous'))), ); @@ -332,11 +332,11 @@ public function validate(array $form, array &$form_state) { } // Validate the "authored by" field. - if (!empty($node->name) && !($account = user_load_by_name($node->name))) { + if (!empty($form_state['values']['name']) && !($account = user_load_by_name($form_state['values']['name']))) { // The use of empty() is mandatory in the context of usernames // as the empty string denotes the anonymous user. In case we // are dealing with an anonymous user we set the user ID to 0. - form_set_error('name', t('The username %name does not exist.', array('%name' => $node->name))); + form_set_error('name', t('The username %name does not exist.', array('%name' => $form_state['values']['name']))); } // Validate the "authored on" field. @@ -440,13 +440,11 @@ public function buildEntity(array $form, array &$form_state) { $entity = parent::buildEntity($form, $form_state); // A user might assign the node author by entering a user name in the node // form, which we then need to translate to a user ID. - if (!empty($form_state['values']['name'])) { - if ($account = user_load_by_name($form_state['values']['name'])) { - $entity->setAuthorId($account->id()); - } - else { - $entity->setAuthorId(0); - } + if (!empty($form_state['values']['name']) && $account = user_load_by_name($form_state['values']['name'])) { + $entity->setAuthorId($account->id()); + } + else { + $entity->setAuthorId(0); } if (!empty($form_state['values']['date']) && $form_state['values']['date'] instanceOf DrupalDateTime) { diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php b/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php index 640f00b..1fe68ef 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php +++ b/core/modules/node/lib/Drupal/node/Plugin/views/row/Rss.php @@ -121,7 +121,7 @@ public function render($row) { ), array( 'key' => 'dc:creator', - 'value' => $node->name, + 'value' => $node->getAuthor()->getUsername(), ), array( 'key' => 'guid', diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php index dac3575..6861c52 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php @@ -69,7 +69,7 @@ protected function getNewEntityValues($langcode) { * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::getFormSubmitAction(). */ protected function getFormSubmitAction(EntityInterface $entity) { - if ($entity->status) { + if ($entity->isPublished()) { return t('Save and unpublish'); } return t('Save and keep unpublished'); diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc index 458c93b..fb166c1 100644 --- a/core/modules/node/node.pages.inc +++ b/core/modules/node/node.pages.inc @@ -110,21 +110,6 @@ function node_add($node_type) { */ function node_preview(NodeInterface $node) { if (node_access('create', $node) || node_access('update', $node)) { - // Load the user's name when needed. - if (isset($node->name)) { - // The use of isset() is mandatory in the context of user IDs, because - // user ID 0 denotes the anonymous user. - if ($user = user_load_by_name($node->name)) { - $node->setAuthorId($user->id()); - } - else { - $node->setAuthorId(0); // anonymous user - } - } - elseif ($node->getAuthorId()) { - $user = $node->getAuthor(); - $node->name = $user->getUsername(); - } $node->changed = REQUEST_TIME; diff --git a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module index 1baa48e..fb217f2 100644 --- a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module +++ b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module @@ -29,10 +29,11 @@ function node_access_test_language_node_access_records(EntityInterface $node) { // Create grants for each translation of the node. foreach ($node->getTranslationLanguages() as $langcode => $language) { // If the translation is not marked as private, grant access. + $translation = $node->getTranslation($langcode); $grants[] = array( 'realm' => 'node_access_language_test', 'gid' => 7888, - 'grant_view' => empty($node->field_private[$langcode][0]['value']) ? 1 : 0, + 'grant_view' => empty($translation->field_private->value) ? 1 : 0, 'grant_update' => 0, 'grant_delete' => 0, 'priority' => 0, diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php index c580338..c73fd67 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php @@ -89,7 +89,7 @@ public function setUp() { 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock', 'context' => array( 'user' => array('class' => 'Drupal\user\UserInterface'), - 'node' => array('class' => 'Drupal\Core\Entity\EntityBCDecorator'), + 'node' => array('class' => 'Drupal\node\NodeInterface'), ), ), ); diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php index c2340f4..e22f5e3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php @@ -6,7 +6,9 @@ */ namespace Drupal\system\Tests\Upgrade; -use Drupal\Core\Language\Language; + +use Drupal\Core\Entity\DatabaseStorageController; +use Drupal\field\Plugin\Core\Entity\Field; /** * Tests upgrade of system variables. @@ -209,16 +211,10 @@ function testFieldUpgradeToConfig() { // The deleted field uuid and deleted instance field_uuid must match. $this->assertEqual($deleted_field['uuid'], $deleted_instance['field_uuid']); - // Check that pre-existing deleted field values are read correctly. - $entity = _field_create_entity_from_ids((object) array( - 'entity_type' => 'node', - 'bundle' => 'article', - 'entity_id' => 2, - 'revision_id' => 2, - )); - field_attach_load('node', array(2 => $entity), FIELD_LOAD_CURRENT, array('instance' => entity_create('field_instance', $deleted_instance))); - $deleted_value = $entity->get('test_deleted_field'); - $this->assertEqual($deleted_value->value, 'Some deleted value'); + // Check that pre-existing deleted field table is renamed correctly. + $field_entity = new Field($deleted_field); + $table_name = _field_sql_storage_tablename($deleted_field); + $this->assertEqual("field_deleted_data_" . substr(hash('sha256', $deleted_field['uuid']), 0, 10), $table_name); // Check that creation of a new node works as expected. $value = $this->randomName(); diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php index a897160..386841b 100644 --- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php @@ -91,7 +91,7 @@ public function __construct() { 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock', 'context' => array( 'user' => array('class' => 'Drupal\user\UserInterface'), - 'node' => array('class' => 'Drupal\Core\Entity\EntityBCDecorator'), + 'node' => array('class' => 'Drupal\node\NodeInterface'), ), )); diff --git a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php index 498bd33..c021e61 100644 --- a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php +++ b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php @@ -112,7 +112,7 @@ function testContentTranslation() { $edit["body[$langcode][0][value]"] = $this->randomName(); $this->drupalPost('node/add/page', $edit, t('Save'), array('query' => array('translation' => $node->id(), 'language' => 'es'))); $duplicate = $this->drupalGetNodeByTitle($edit["title"]); - $this->assertEqual($duplicate->tnid, 0, 'The node does not have a tnid.'); + $this->assertEqual($duplicate->tnid->value, 0, 'The node does not have a tnid.'); // Update original and mark translation as outdated. $node_body = $this->randomName(); @@ -171,7 +171,7 @@ function testLanguageSwitchLinks() { // Unpublish the Spanish translation to check that the related language // switch link is not shown. $this->drupalLogin($this->admin_user); - $this->drupalPost("node/$translation_es->nid/edit", array(), t('Save and unpublish')); + $this->drupalPost('node/' . $translation_es->id() . '/edit', array(), t('Save and unpublish')); $this->drupalLogin($this->translator); $this->assertLanguageSwitchLinks($node, $translation_es, FALSE); @@ -181,7 +181,7 @@ function testLanguageSwitchLinks() { $edit = array('language_interface[enabled][language-url]' => FALSE); $this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings')); $this->resetCaches(); - $this->drupalPost("node/$translation_es->nid/edit", array(), t('Save and publish')); + $this->drupalPost('node/' . $translation_es->id() . '/edit', array(), t('Save and publish')); $this->drupalLogin($this->translator); $this->assertLanguageSwitchLinks($node, $translation_es, TRUE, 'node'); } @@ -396,7 +396,7 @@ function createTranslation(EntityInterface $node, $title, $body, $langcode) { // Check to make sure that translation was successful. $translation = $this->drupalGetNodeByTitle($title); $this->assertTrue($translation, 'Node found in database.'); - $this->assertTrue($translation->tnid == $node->id(), 'Translation set id correctly stored.'); + $this->assertTrue($translation->tnid->value == $node->id(), 'Translation set id correctly stored.'); return $translation; } @@ -449,10 +449,9 @@ function assertLanguageSwitchLinks(NodeInterface $node, $translation, $find = TR } $result = TRUE; - $languages = language_list(); - $page_language = $languages[$node->language()->id]; - $translation_language = $languages[$translation->langcode]; - $url = url("node/$translation->nid", array('language' => $translation_language)); + $page_language = $node->language(); + $translation_language = $translation->language(); + $url = url('node/' . $translation->id(), array('language' => $translation_language)); $this->drupalGet('node/' . $node->id(), array('language' => $page_language)); diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module index 7f65448..e237ad2 100644 --- a/core/modules/translation/translation.module +++ b/core/modules/translation/translation.module @@ -331,8 +331,8 @@ function translation_node_prepare_form(NodeInterface $node, $form_display, $oper } // Ensure we don't have an existing translation in this language. - if (!empty($source_node->tnid)) { - $translations = translation_node_get_translations($source_node->tnid); + if (!empty($source_node->tnid->value)) { + $translations = translation_node_get_translations($source_node->tnid->value); if (isset($translations[$langcode])) { drupal_set_message(t('A translation of %title in %language already exists, a new %type will be created instead of a translation.', array('%title' => $source_node->label(), '%language' => $language_list[$langcode]->name, '%type' => $node->bundle())), 'error'); return; @@ -462,7 +462,7 @@ function translation_remove_from_set(NodeInterface $node) { // If the node being removed was the source of the translation set, // we pick a new source - preferably one that is up to date. if ($node->tnid->value == $node->id()) { - $new_tnid = db_query('SELECT nid FROM {node} WHERE tnid = :tnid ORDER BY translate ASC, nid ASC', array(':tnid' => $node->tnid))->fetchField(); + $new_tnid = db_query('SELECT nid FROM {node} WHERE tnid = :tnid ORDER BY translate ASC, nid ASC', array(':tnid' => $node->tnid->value))->fetchField(); db_update('node') ->fields(array('tnid' => $new_tnid)) ->condition('tnid', $node->tnid->value)