diff --git a/core/UPGRADE.txt b/core/UPGRADE.txt index 420f6ad..f035b6c 100644 --- a/core/UPGRADE.txt +++ b/core/UPGRADE.txt @@ -5,7 +5,7 @@ This document describes how to: * Update your Drupal site from one minor 8.x version to another minor 8.x version; for example, from 8.8 to 8.9, or from 8.6 to 8.10. - * Migrate your Drupal site to version 8.x. + * Upgrade your Drupal site's major version from 7.x to 8.x. First steps and definitions: @@ -121,10 +121,118 @@ following the instructions in the INTRODUCTION section at the top of this file: Disable the "Put site into maintenance mode" checkbox and save the configuration. -MAJOR VERSION MIGRATION ------------------------ -Upgrading from a prior major version of Drupal to Drupal 8.x is not possible. -The process now requires a migration to a Drupal 8.x site, utilizing the Migrate -module in Drupal core. +MAJOR VERSION UPGRADE +--------------------- +To upgrade from a previous major version of Drupal to Drupal 8.x, after +following the instructions in the INTRODUCTION section at the top of this file: + +1. Check on the Drupal 8 status of your contributed and custom modules and + themes. See http://drupal.org/node/948216 for information on upgrading + contributed modules and themes. See http://drupal.org/node/895314 for a list + of modules that have been moved into core for Drupal 8, and instructions on + how to update them. See http://drupal.org/update/modules for information on + how to update your custom modules, and http://drupal.org/update/theme for + custom themes. + + You may decide at this point that you cannot upgrade your site because + needed modules or themes are not ready for Drupal 8 + +2. Update to the latest available version of Drupal 7.x (if your current version + is Drupal 6.x, you have to upgrade to 7.x first). If you need to update, + download Drupal 7.x and follow the instructions in its UPGRADE.txt. This + document only applies for upgrades from 7.x to 8.x. + +3. In addition to updating to the latest available version of Drupal 7.x core, + you must also upgrade all of your contributed modules for Drupal to their + latest Drupal 7.x versions. + +4. Log in as user ID 1 (the site maintenance user). + +5. Go to Administer > Site configuration > Site maintenance. Select + "Off-line" and save the configuration. + +6. Go to Administer > Site building > Themes. Enable "Bartik" and select it as + the default theme. + +7. Go to Administer > Site building > Modules. Disable all modules that are not + listed under "Core - required" or "Core - optional". It is possible that some + modules cannot be disabled because others depend on them. Repeat this step + until all non-core modules are disabled. + + If you know that you will not re-enable some modules for Drupal 8.x and you + no longer need their data, then you can uninstall them under the Uninstall + tab after disabling them. + +8. On the command line or in your FTP client, remove the file + + sites/default/default.settings.php + +9. Remove all old core files and directories, except for the 'sites' directory + and any custom files you added elsewhere. + + If you made modifications to files like .htaccess or robots.txt, you will + need to re-apply them from your backup, after the new files are in place. + +10. If you uninstalled any modules, remove them from the /modules and other + sites/*/modules directories. Leave other modules in place, even though they + are incompatible with Drupal 8.x. + +11. Download the latest Drupal 8.x release from http://drupal.org to a + directory outside of your web root. Extract the archive and copy the files + into your Drupal directory. + + On a typical Unix/Linux command line, use the following commands to download + and extract: + + wget http://drupal.org/files/projects/drupal-x.y.tar.gz + tar -zxvf drupal-x.y.tar.gz + + This creates a new directory drupal-x.y/ containing all Drupal files and + directories. Copy the files into your Drupal installation directory: + + cp -R drupal-x.y/* drupal-x.y/.htaccess /path/to/your/installation + + If you do not have command line access to your server, download the archive + from http://drupal.org using your web browser, extract it, and then use an + FTP client to upload the files to your web root. + +12. Re-apply any modifications to files such as .htaccess or robots.txt. + +13. Make your settings.php file writeable, so that the update process can + convert it to the format of Drupal 8.x. settings.php is usually located in + + sites/default/settings.php + +14. Run update.php by visiting http://www.example.com/core/update.php (replace + www.example.com with your domain name). This will update the core database + tables. + + If you are unable to access update.php do the following: + + - Open settings.php with a text editor. + + - Find the line that says: + $settings['update_free_access'] = FALSE; + + - Change it into: + $settings['update_free_access'] = TRUE; + + - Once the upgrade is done, $settings['update_free_access'] must be + reverted to FALSE. + +15. Backup your database after the core upgrade has run. + +16. Replace and update your non-core modules and themes, following the + procedures at http://drupal.org/node/948216 + +17. Go to Administration > Reports > Status report. Verify that everything is + working as expected. + +18. Ensure that $settings['update_free_access'] is FALSE in settings.php. + +19. Go to Administration > Configuration > Development > Maintenance mode. + Disable the "Put site into maintenance mode" checkbox and save the + configuration. -Note that migration support in Drupal 8 is currently only partially implemented. +To get started with Drupal 8 administration, visit +http://drupal.org/getting-started/7/admin diff --git a/core/core.libraries.yml b/core/core.libraries.yml index d2c35b9..e405d95 100644 --- a/core/core.libraries.yml +++ b/core/core.libraries.yml @@ -280,7 +280,7 @@ html5shiv: remote: https://github.com/aFarkas/html5shiv version: 3.6.2 js: - assets/vendor/html5shiv/html5.js: { every_page: true, weight: -22, browsers: { IE: 'lte IE 8', '!IE': false } } + assets/vendor/html5shiv/html5.js: { weight: -22, browsers: { IE: 'lte IE 8', '!IE': false } } jquery: remote: https://github.com/jquery/jquery diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 7962015..5372dc7 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -184,6 +184,13 @@ define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']); /** + * Flag for drupal_set_title(); text has already been sanitized. + * + * @todo Move to the Title class. + */ +const PASS_THROUGH = -1; + +/** * Regular expression to match PHP function names. * * @see http://php.net/manual/language.functions.php @@ -1324,6 +1331,46 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) { } /** + * Gets the title of the current page. + * + * The title is displayed on the page and in the title bar. + * + * @return + * The current page's title. + */ +function drupal_get_title() { + return drupal_set_title() ?: ''; +} + +/** + * Sets the title of the current page. + * + * The title is displayed on the page and in the title bar. + * + * @param $title + * Optional string value to assign to the page title; or if set to NULL + * (default), leaves the current title unchanged. + * @param $output + * Optional flag - normally should be left as Title::CHECK_PLAIN. Only set to + * PASS_THROUGH if you have already removed any possibly dangerous code + * from $title using a function like + * \Drupal\Component\Utility\String::checkPlain() or filter_xss(). With this + * flag the string will be passed through unchanged. + * + * @return + * The updated title of the current page. + */ +function drupal_set_title($title = NULL, $output = Title::CHECK_PLAIN) { + $stored_title = &drupal_static(__FUNCTION__); + + if (isset($title)) { + $stored_title = ($output == PASS_THROUGH) ? $title : String::checkPlain($title); + } + + return $stored_title; +} + +/** * Generates a default anonymous $user object. * * @return \Drupal\Core\Session\AccountInterface diff --git a/core/includes/common.inc b/core/includes/common.inc index d18c0c1..ecdce53 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -2457,7 +2457,7 @@ function drupal_pre_render_scripts($elements) { * FALSE if there were any missing library dependencies; TRUE if all library * dependencies were met. * - * @see _drupal_add_library() + * @see drupal_add_library() * @see _drupal_add_js() * @see _drupal_add_css() * @see drupal_render() @@ -2473,7 +2473,7 @@ function drupal_process_attached($elements, $dependency_check = FALSE) { // Add the libraries first. $success = TRUE; foreach ($elements['#attached']['library'] as $library) { - if (_drupal_add_library($library) === FALSE) { + if (drupal_add_library($library) === FALSE) { $success = FALSE; // Exit if the dependency is missing. if ($dependency_check) { @@ -2672,7 +2672,7 @@ function drupal_process_states(&$elements) { * @see drupal_get_library() * @see hook_library_info_alter() */ -function _drupal_add_library($library_name, $every_page = NULL) { +function drupal_add_library($library_name, $every_page = NULL) { $added = &drupal_static(__FUNCTION__, array()); list($extension, $name) = explode('/', $library_name, 2); @@ -2731,7 +2731,7 @@ function _drupal_add_library($library_name, $every_page = NULL) { * or FALSE if it does not exist. If no $name was passed, an associative array * of libraries registered by the module is returned (which may be empty). * - * @see _drupal_add_library() + * @see drupal_add_library() * @see hook_library_info_alter() * * @todo The purpose of drupal_get_*() is completely different to other page @@ -3894,12 +3894,6 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) { drupal_process_states($elements); } - // Add additional libraries, CSS, JavaScript and other custom - // attached data associated with this element. - if (!empty($elements['#attached'])) { - drupal_process_attached($elements); - } - // Get the children of the element, sorted by weight. $children = Element::children($elements, TRUE); @@ -3945,6 +3939,12 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) { $elements['#children'] = $elements['#markup'] . $elements['#children']; } + // Add additional libraries, CSS, JavaScript an other custom + // attached data associated with this element. + if (!empty($elements['#attached'])) { + drupal_process_attached($elements); + } + // Let the theme functions in #theme_wrappers add markup around the rendered // children. // #states and #attached have to be processed before #theme_wrappers, because diff --git a/core/includes/form.inc b/core/includes/form.inc index f4a7718..f56a364 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1600,7 +1600,7 @@ function form_process_container($element, &$form_state) { function theme_tableselect($variables) { $element = $variables['element']; $table = array( - '#type' => 'table', + '#theme' => 'table', ); $rows = array(); $header = $element['#header']; diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 61d9fee..44ff142 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1690,7 +1690,7 @@ function install_get_localization_release($version = \Drupal::VERSION) { } } - // All releases may fall back to the previous major release (e.g., 8.1 falls + // All releases may a fallback to the previous major release (e.g., 8.1 falls // back to 7.0, 8.x-dev falls back to 7.0). This will probably only be used // for early dev releases or languages with an inactive translation team. $alternatives[] = $info['major'] - 1 . '.0'; diff --git a/core/includes/tablesort.inc b/core/includes/tablesort.inc index cd5c0c1..5b1440c 100644 --- a/core/includes/tablesort.inc +++ b/core/includes/tablesort.inc @@ -9,7 +9,7 @@ * @file * Functions to aid in the creation of sortable tables. * - * All tables created when rendering a '#type' => 'table' have the option of + * All tables created when rendering a '#theme' => 'table' have the option of * having column headers that the user can click on to sort the table by that * column. */ @@ -33,7 +33,7 @@ function tablesort_init($header) { * @param $cell * The cell to format. * @param $header - * An array of column headers in the format described in '#type' => 'table'. + * An array of column headers in the format described in '#theme' => 'table'. * @param $ts * The current table sort context as returned from tablesort_init(). * @@ -77,7 +77,7 @@ function tablesort_header($cell, $header, $ts) { * @param $cell * The cell to format. * @param $header - * An array of column headers in the format described in '#type' => 'table'. + * An array of column headers in the format described in '#theme' => 'table'. * @param $ts * The current table sort context as returned from tablesort_init(). * @param $i @@ -113,7 +113,7 @@ function tablesort_get_query_parameters() { * Determines the current sort criterion. * * @param $headers - * An array of column headers in the format described in '#type' => 'table'. + * An array of column headers in the format described in '#theme' => 'table'. * * @return * An associative array describing the criterion, containing the keys: @@ -150,7 +150,7 @@ function tablesort_get_order($headers) { * Determines the current sort direction. * * @param $headers - * An array of column headers in the format described in '#type' => 'table'. + * An array of column headers in the format described in '#theme' => 'table'. * * @return * The current sort direction ("asc" or "desc"). diff --git a/core/includes/theme.inc b/core/includes/theme.inc index bbeb9cb..a58b59a 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -340,23 +340,87 @@ function list_themes($refresh = FALSE) { } /** - * Generates themed output (internal use only). - * - * _theme() is an internal function. Do not call this function directly as it - * will prevent the following items from working correctly: - * - Render caching. - * - JavaScript and CSS asset attachment. - * - Pre / post render hooks. - * - Defaults provided by hook_element_info(), including attached assets. - * Instead, build a render array with a #theme key, and either return the - * array (where possible) or call drupal_render() to convert it to HTML. - * - * All requests for themed output must go through this function, which is - * invoked as part of the @link theme_render drupal_render() process @endlink. - * The appropriate theme function is indicated by the #theme property - * of a renderable array. _theme() examines the request and routes it to the - * appropriate @link themeable theme function or template @endlink, by checking - * the theme registry. + * Generates themed output. + * + * All requests for themed output must go through this function (however, + * calling the _theme() function directly is very strongly discouraged - see + * next paragraph). It examines the request and routes it to the appropriate + * @link themeable theme function or template @endlink, by checking the theme + * registry. + * + * Avoid calling this function directly. It is preferable to replace direct + * calls to the _theme() function with calls to drupal_render() by passing a + * render array with a #theme key to drupal_render(), which in turn calls + * _theme(). + * + * @section sec_theme_hooks Theme Hooks + * Most commonly, the first argument to this function is the name of the theme + * hook. For instance, to theme a taxonomy term, the theme hook name is + * 'taxonomy_term'. Modules register theme hooks within a hook_theme() + * implementation and provide a default implementation via a function named + * theme_HOOK() (e.g., theme_taxonomy_term()) or via a template file named + * according to the value of the 'template' key registered with the theme hook + * (see hook_theme() for details). Default templates are implemented with the + * Twig rendering engine and are named the same as the theme hook, with + * underscores changed to hyphens, so for the 'taxonomy_term' theme hook, the + * default template is 'taxonomy-term.html.twig'. + * + * @subsection sub_overriding_theme_hooks Overriding Theme Hooks + * Themes may also register new theme hooks within a hook_theme() + * implementation, but it is more common for themes to override default + * implementations provided by modules than to register entirely new theme + * hooks. Themes can override a default implementation by implementing a + * function named THEME_HOOK() (for example, the 'bartik' theme overrides the + * default implementation of the 'menu_tree' theme hook by implementing a + * bartik_menu_tree() function), or by adding a template file within its folder + * structure that follows the template naming structure used by the theme's + * rendering engine (for example, since the Bartik theme uses the Twig rendering + * engine, it overrides the default implementation of the 'page' theme hook by + * containing a 'page.html.twig' file within its folder structure). + * + * @subsection sub_preprocess_templates Preprocessing for Template Files + * If the implementation is a template file, several functions are called before + * the template file is invoked to modify the $variables array. These make up + * the "preprocessing" phase, and are executed (if they exist), in the following + * order (note that in the following list, HOOK indicates the theme hook name, + * MODULE indicates a module name, THEME indicates a theme name, and ENGINE + * indicates a theme engine name): + * - template_preprocess(&$variables, $hook): Creates a default set of variables + * for all theme hooks with template implementations. + * - template_preprocess_HOOK(&$variables): Should be implemented by the module + * that registers the theme hook, to set up default variables. + * - MODULE_preprocess(&$variables, $hook): hook_preprocess() is invoked on all + * implementing modules. + * - MODULE_preprocess_HOOK(&$variables): hook_preprocess_HOOK() is invoked on + * all implementing modules, so that modules that didn't define the theme hook + * can alter the variables. + * - ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to + * set necessary variables for all theme hooks with template implementations. + * - ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set + * necessary variables for the particular theme hook. + * - THEME_preprocess(&$variables, $hook): Allows the theme to set necessary + * variables for all theme hooks with template implementations. + * - THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary + * variables specific to the particular theme hook. + * + * @subsection sub_preprocess_theme_funcs Preprocessing for Theme Functions + * If the implementation is a function, only the theme-hook-specific preprocess + * functions (the ones ending in _HOOK) are called from the list above. This is + * because theme hooks with function implementations need to be fast, and + * calling the non-theme-hook-specific preprocess functions for them would incur + * a noticeable performance penalty. + * + * @subsection sub_alternate_suggestions Suggesting Alternate Hooks + * Alternate hooks can be suggested by implementing the hook-specific + * hook_theme_suggestions_HOOK_alter() or the generic + * hook_theme_suggestions_alter(). These alter hooks are used to manipulate an + * array of suggested alternate theme hooks to use, in reverse order of + * priority. _theme() will use the highest priority implementation that exists. + * If none exists, _theme() will use the implementation for the theme hook it + * was called with. These suggestions are similar to and are used for similar + * reasons as calling _theme() with an array as the $hook parameter (see below). + * The difference is whether the suggestions are determined by the code that + * calls _theme() or by altering the suggestions via the suggestion alter hooks. * * @param $hook * The name of the theme hook to call. If the name contains a @@ -864,17 +928,17 @@ function theme_get_setting($setting_name, $theme = NULL) { } foreach ($theme_keys as $theme_key) { if (!empty($themes[$theme_key]->info['settings'])) { - $cache[$theme]->merge($themes[$theme_key]->info['settings']); + $cache[$theme]->mergeData($themes[$theme_key]->info['settings']); } } } // Get the global settings from configuration. - $cache[$theme]->merge(\Drupal::config('system.theme.global')->get()); + $cache[$theme]->mergeData(\Drupal::config('system.theme.global')->get()); if ($theme) { // Get the saved theme-specific settings from the configuration system. - $cache[$theme]->merge(\Drupal::config($theme . '.settings')->get()); + $cache[$theme]->mergeData(\Drupal::config($theme . '.settings')->get()); // If the theme does not support a particular feature, override the global // setting and set the value to NULL. @@ -1352,24 +1416,6 @@ function drupal_pre_render_table(array $element) { // Take over $element['#id'] as HTML ID attribute, if not already set. element_set_attributes($element, array('id')); - - // Add sticky headers, if applicable. - if (count($element['#header']) && $element['#sticky']) { - $element['#attached']['library'][] = 'core/drupal.tableheader'; - // Add 'sticky-enabled' class to the table to identify it for JS. - // This is needed to target tables constructed by this function. - $element['#attributes']['class'][] = 'sticky-enabled'; - } - // If the table has headers and it should react responsively to columns hidden - // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM - // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors. - if (count($element['#header']) && $element['#responsive']) { - $element['#attached']['library'][] = 'core/drupal.tableresponsive'; - // Add 'responsive-enabled' class to the table to identify it for JS. - // This is needed to target tables constructed by this function. - $element['#attributes']['class'][] = 'responsive-enabled'; - } - // If the custom #tabledrag is set and there is a HTML ID, add the table's // HTML ID to the options and attach the behavior. if (!empty($element['#tabledrag']) && isset($element['#attributes']['id'])) { @@ -1477,6 +1523,23 @@ function theme_table($variables) { $responsive = $variables['responsive']; $empty = $variables['empty']; + // Add sticky headers, if applicable. + if (count($header) && $sticky) { + drupal_add_library('core/drupal.tableheader'); + // Add 'sticky-enabled' class to the table to identify it for JS. + // This is needed to target tables constructed by this function. + $attributes['class'][] = 'sticky-enabled'; + } + // If the table has headers and it should react responsively to columns hidden + // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM + // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors. + if (count($header) && $responsive) { + drupal_add_library('core/drupal.tableresponsive'); + // Add 'responsive-enabled' class to the table to identify it for JS. + // This is needed to target tables constructed by this function. + $attributes['class'][] = 'responsive-enabled'; + } + $output = '\n"; if (isset($caption)) { @@ -1905,28 +1968,6 @@ function _template_preprocess_default_variables() { } /** - * #pre_render callback for the html element type. - * - * @param array $element - * A structured array containing the html element type build properties. - * - * @see system_element_info() - */ -function drupal_pre_render_html(array $element) { - // Add favicon. - if (theme_get_setting('features.favicon')) { - $favicon = theme_get_setting('favicon.url'); - $type = theme_get_setting('favicon.mimetype'); - $element['#attached']['drupal_add_html_head_link'][][] = array( - 'rel' => 'shortcut icon', - 'href' => UrlHelper::stripDangerousProtocols($favicon), - 'type' => $type, - ); - } - - return $element; -} -/** * Prepares variables for HTML document templates. * * Default template: html.html.twig. @@ -1975,6 +2016,18 @@ function template_preprocess_html(&$variables) { $variables['html_attributes']['lang'] = $language_interface->id; $variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr'; + // Add favicon. + if (theme_get_setting('features.favicon')) { + $favicon = theme_get_setting('favicon.url'); + $type = theme_get_setting('favicon.mimetype'); + $build['#attached']['drupal_add_html_head_link'][][] = array( + 'rel' => 'shortcut icon', + 'href' => UrlHelper::stripDangerousProtocols($favicon), + 'type' => $type, + ); + drupal_render($build); + } + $site_config = \Drupal::config('system.site'); // Construct page title. if ($page->hasTitle()) { @@ -1983,6 +2036,12 @@ function template_preprocess_html(&$variables) { 'name' => String::checkPlain($site_config->get('name')), ); } + elseif (drupal_get_title()) { + $head_title = array( + 'title' => strip_tags(drupal_get_title()), + 'name' => String::checkPlain($site_config->get('name')), + ); + } // @todo Remove once views is not bypassing the view subscriber anymore. // @see http://drupal.org/node/2068471 elseif (drupal_is_front_page()) { @@ -2029,6 +2088,8 @@ function template_preprocess_html(&$variables) { drupal_add_html_head($element, $name); } + drupal_add_library('core/html5shiv', TRUE); + $variables['page_top'][] = array('#markup' => $page->getBodyTop()); $variables['page_bottom'][] = array('#markup' => $page->getBodyBottom()); @@ -2063,7 +2124,6 @@ function template_preprocess_page(&$variables) { // Move some variables to the top level for themer convenience and template cleanliness. $variables['show_messages'] = $variables['page']['#show_messages']; - $variables['title'] = $variables['page']['#title']; foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) { if (!isset($variables['page'][$region_key])) { @@ -2093,6 +2153,13 @@ function template_preprocess_page(&$variables) { $variables['site_slogan'] = (theme_get_setting('features.slogan') ? filter_xss_admin($site_config->get('slogan')) : ''); $variables['tabs'] = menu_local_tabs(); + if (isset($variables['page']['#title'])) { + $variables['title'] = $variables['page']['#title']; + } + else { + $variables['title'] = new RenderWrapper('drupal_get_title'); + } + // Pass the main menu and secondary menu to the template as render arrays. if (!empty($variables['main_menu'])) { $variables['main_menu'] = array( @@ -2277,6 +2344,12 @@ function template_preprocess_maintenance_page(&$variables) { 'name' => String::checkPlain($site_config->get('name')), ); } + elseif (drupal_get_title()) { + $head_title = array( + 'title' => strip_tags(drupal_get_title()), + 'name' => String::checkPlain($site_config->get('name')), + ); + } else { $head_title = array('name' => String::checkPlain($site_name)); if ($site_slogan) { @@ -2337,6 +2410,9 @@ function template_preprocess_maintenance_page(&$variables) { if (isset($variables['page']['#title'])) { $variables['title'] = $variables['page']['#title']; } + if (!isset($variables['title'])) { + $variables['title'] = drupal_get_title(); + } } /** diff --git a/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php b/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php index f298d88..595d64e 100644 --- a/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php +++ b/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php @@ -14,7 +14,7 @@ /** * Subscribes to the kernel request event to add the Ajax media type. * - * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event + * @param \Symfont\Component\HttpKernel\Event\GetResponseEvent $event * The event to process. */ class AjaxSubscriber implements EventSubscriberInterface { diff --git a/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php b/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php index 4b42bf7..07d823b 100644 --- a/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php +++ b/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php @@ -124,7 +124,7 @@ public function setDialogTitle($title) { */ public function render() { // Add the library for handling the dialog in the response. - $this->drupalAttachLibrary('core/drupal.dialog.ajax'); + drupal_add_library('core/drupal.dialog.ajax'); // For consistency ensure the modal option is set to TRUE or FALSE. $this->dialogOptions['modal'] = isset($this->dialogOptions['modal']) && $this->dialogOptions['modal']; @@ -136,19 +136,4 @@ public function render() { 'dialogOptions' => $this->dialogOptions, ); } - - /** - * Wraps drupal_render. - * - * @param string $name - * The name of the library. - * - * @todo Remove once drupal_render is converted to autoloadable code. - * @see https://drupal.org/node/2171071 - */ - protected function drupalAttachLibrary($name) { - $attached['#attached']['library'][] = $name; - drupal_render($attached); - } - } diff --git a/core/lib/Drupal/Core/Annotation/Translation.php b/core/lib/Drupal/Core/Annotation/Translation.php index 5726878..ebb2655 100644 --- a/core/lib/Drupal/Core/Annotation/Translation.php +++ b/core/lib/Drupal/Core/Annotation/Translation.php @@ -24,11 +24,6 @@ * Remove spaces after @ in your actual plugin - these are put into this sample * code so that it is not recognized as annotation. * - * To provide replacement values for placeholders, use the "arguments" array: - * @code - * title = @ Translation("Bundle !title", arguments = {"!title" = "Foo"}), - * @endcode - * * It is also possible to provide a context with the text, similar to t(): * @code * title = @ Translation("Bundle", context = "Validation"), @@ -60,35 +55,20 @@ class Translation extends AnnotationBase { protected $translation; /** - * The translation manager. - * - * @var \Drupal\Core\StringTranslation\TranslationInterface - */ - protected $translationManager; - - /** - * Constructs a new class instance. + * Constructs a Translation object. * * Parses values passed into this class through the t() function in Drupal and * handles an optional context for the string. - * - * @param array $values - * Possible array keys: - * - value (required): the string that is to be translated. - * - arguments (optional): an array with placeholder replacements, keyed by - * placeholder. - * - context (optional): a string that describes the context of "value"; */ - public function __construct(array $values) { + public function __construct($values) { $string = $values['value']; - $arguments = isset($values['arguments']) ? $values['arguments'] : array(); $options = array(); if (!empty($values['context'])) { $options = array( 'context' => $values['context'], ); } - $this->translation = $this->getTranslationManager()->translate($string, $arguments, $options); + $this->translation = t($string, array(), $options); } /** @@ -98,18 +78,4 @@ public function get() { return $this->translation; } - /** - * Returns the translation manager. - * - * @return \Drupal\Core\StringTranslation\TranslationInterface - * The translation manager. - */ - protected function getTranslationManager() { - if (!$this->translationManager) { - $this->translationManager = \Drupal::translation(); - } - - return $this->translationManager; - } - } diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index cafc026..e000200 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -9,7 +9,9 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; +use Drupal\Core\Config\ConfigNameException; use Drupal\Core\Config\Schema\SchemaIncompleteException; +use Drupal\Core\DependencyInjection\DependencySerialization; use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\TypedData\Type\FloatInterface; use Drupal\Core\TypedData\Type\IntegerInterface; @@ -19,7 +21,20 @@ /** * Defines the default configuration object. */ -class Config extends StorableConfigBase { +class Config extends DependencySerialization { + + /** + * The maximum length of a configuration object name. + * + * Many filesystems (including HFS, NTFS, and ext4) have a maximum file name + * length of 255 characters. To ensure that no configuration objects + * incompatible with this limitation are created, we enforce a maximum name + * length of 250 characters (leaving 5 characters for the file extension). + * + * @see http://en.wikipedia.org/wiki/Comparison_of_file_systems + */ + const MAX_NAME_LENGTH = 250; + /** * An event dispatcher instance to use for configuration events. * @@ -30,11 +45,39 @@ class Config extends StorableConfigBase { /** * The language object used to override configuration data. * - * @var \Drupal\Core\Language\Language + * @var Drupal\Core\Language\Language */ protected $language; /** + * The name of the configuration object. + * + * @var string + */ + protected $name; + + /** + * Whether the configuration object is new or has been saved to the storage. + * + * @var bool + */ + protected $isNew = TRUE; + + /** + * The data of the configuration object. + * + * @var array + */ + protected $data = array(); + + /** + * The original data of the configuration object. + * + * @var array + */ + protected $originalData = array(); + + /** * The current runtime data. * * The configuration data from storage merged with language, module and @@ -59,11 +102,25 @@ class Config extends StorableConfigBase { protected $moduleOverrides; /** - * The current settings overrides. + * The storage used to load and save this configuration object. * - * @var array + * @var \Drupal\Core\Config\StorageInterface + */ + protected $storage; + + /** + * The config schema wrapper object for this configuration object. + * + * @var \Drupal\Core\Config\Schema\Element */ - protected $settingsOverrides; + protected $schemaWrapper; + + /** + * The typed config manager. + * + * @var \Drupal\Core\Config\TypedConfigManager + */ + protected $typedConfigManager; /** * Constructs a configuration object. @@ -89,19 +146,111 @@ public function __construct($name, StorageInterface $storage, EventDispatcherInt } /** - * {@inheritdoc} + * Initializes a configuration object with pre-loaded data. + * + * @param array $data + * Array of loaded data for this configuration object. + * + * @return \Drupal\Core\Config\Config + * The configuration object. */ public function initWithData(array $data) { - parent::initWithData($data); $this->settingsOverrides = array(); $this->languageOverrides = array(); $this->moduleOverrides = array(); - $this->setData($data); + $this->isNew = FALSE; + $this->replaceData($data); + $this->originalData = $this->data; return $this; } /** - * {@inheritdoc} + * Returns the name of this configuration object. + * + * @return string + * The name of the configuration object. + */ + public function getName() { + return $this->name; + } + + /** + * Sets the name of this configuration object. + * + * @param string $name + * The name of the configuration object. + * + * @return \Drupal\Core\Config\Config + * The configuration object. + */ + public function setName($name) { + $this->name = $name; + return $this; + } + + /** + * Validates the configuration object name. + * + * @param string $name + * The name of the configuration object. + * + * @throws \Drupal\Core\Config\ConfigNameException + * + * @see Config::MAX_NAME_LENGTH + */ + public static function validateName($name) { + // The name must be namespaced by owner. + if (strpos($name, '.') === FALSE) { + throw new ConfigNameException(format_string('Missing namespace in Config object name @name.', array( + '@name' => $name, + ))); + } + // The name must be shorter than Config::MAX_NAME_LENGTH characters. + if (strlen($name) > self::MAX_NAME_LENGTH) { + throw new ConfigNameException(format_string('Config object name @name exceeds maximum allowed length of @length characters.', array( + '@name' => $name, + '@length' => self::MAX_NAME_LENGTH, + ))); + } + + // The name must not contain any of the following characters: + // : ? * < > " ' / \ + if (preg_match('/[:?*<>"\'\/\\\\]/', $name)) { + throw new ConfigNameException(format_string('Invalid character in Config object name @name.', array( + '@name' => $name, + ))); + } + } + + /** + * Returns whether this configuration object is new. + * + * @return bool + * TRUE if this configuration object does not exist in storage. + */ + public function isNew() { + return $this->isNew; + } + + /** + * Gets data from this configuration object. + * + * @param string $key + * A string that maps to a key within the configuration data. + * For instance in the following configuration array: + * @code + * array( + * 'foo' => array( + * 'bar' => 'baz', + * ), + * ); + * @endcode + * A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo' + * would return array('bar' => 'baz'). + * If no key is specified, then the entire data array is returned. + * + * @return mixed + * The data that was requested. */ public function get($key = '') { if (!isset($this->overriddenData)) { @@ -123,9 +272,33 @@ public function get($key = '') { } /** - * {@inheritdoc} + * Replaces the data of this configuration object. + * + * @param array $data + * The new configuration data. + * + * @return \Drupal\Core\Config\Config + * The configuration object. */ public function setData(array $data) { + $this->replaceData($data); + return $this; + } + + /** + * Replaces the data of this configuration object. + * + * This function is separate from setData() to avoid load() state tracking. + * A load() would destroy the replaced data (for example on import). Do not + * call set() when inside load(). + * + * @param array $data + * The new configuration data. + * + * @return \Drupal\Core\Config\Config + * The configuration object. + */ + protected function replaceData(array $data) { $this->data = $data; $this->resetOverriddenData(); return $this; @@ -218,25 +391,56 @@ protected function resetOverriddenData() { } /** - * {@inheritdoc} + * Sets a value in this configuration object. + * + * @param string $key + * Identifier to store value in configuration. + * @param mixed $value + * Value to associate with identifier. + * + * @return \Drupal\Core\Config\Config + * The configuration object. */ public function set($key, $value) { - parent::set($key, $value); + // The dot/period is a reserved character; it may appear between keys, but + // not within keys. + $parts = explode('.', $key); + if (count($parts) == 1) { + $this->data[$key] = $value; + } + else { + NestedArray::setValue($this->data, $parts, $value); + } $this->resetOverriddenData(); return $this; } /** - * {@inheritdoc} + * Unsets a value in this configuration object. + * + * @param string $key + * Name of the key whose value should be unset. + * + * @return \Drupal\Core\Config\Config + * The configuration object. */ public function clear($key) { - parent::clear($key); + $parts = explode('.', $key); + if (count($parts) == 1) { + unset($this->data[$key]); + } + else { + NestedArray::unsetValue($this->data, $parts); + } $this->resetOverriddenData(); return $this; } /** - * {@inheritdoc} + * Saves the configuration object. + * + * @return \Drupal\Core\Config\Config + * The configuration object. */ public function save() { // Validate the configuration object name before saving. @@ -297,7 +501,7 @@ public function getStorage() { */ public function merge(array $data_to_merge) { // Preserve integer keys so that configuration keys are not changed. - $this->setData(NestedArray::mergeDeepArray(array($this->data, $data_to_merge), TRUE)); + $this->replaceData(NestedArray::mergeDeepArray(array($this->data, $data_to_merge), TRUE)); return $this; } @@ -447,3 +651,4 @@ public function getOriginal($key = '', $apply_overrides = TRUE) { } } } + diff --git a/core/lib/Drupal/Core/Config/ConfigBase.php b/core/lib/Drupal/Core/Config/ConfigBase.php deleted file mode 100644 index 7d12d51..0000000 --- a/core/lib/Drupal/Core/Config/ConfigBase.php +++ /dev/null @@ -1,209 +0,0 @@ -name; - } - - /** - * Sets the name of this configuration object. - * - * @param string $name - * The name of the configuration object. - * - * @return $this - * The configuration object. - */ - public function setName($name) { - $this->name = $name; - return $this; - } - - /** - * Validates the configuration object name. - * - * @param string $name - * The name of the configuration object. - * - * @throws \Drupal\Core\Config\ConfigNameException - * - * @see Config::MAX_NAME_LENGTH - */ - public static function validateName($name) { - // The name must be namespaced by owner. - if (strpos($name, '.') === FALSE) { - throw new ConfigNameException(String::format('Missing namespace in Config object name @name.', array( - '@name' => $name, - ))); - } - // The name must be shorter than Config::MAX_NAME_LENGTH characters. - if (strlen($name) > self::MAX_NAME_LENGTH) { - throw new ConfigNameException(String::format('Config object name @name exceeds maximum allowed length of @length characters.', array( - '@name' => $name, - '@length' => self::MAX_NAME_LENGTH, - ))); - } - - // The name must not contain any of the following characters: - // : ? * < > " ' / \ - if (preg_match('/[:?*<>"\'\/\\\\]/', $name)) { - throw new ConfigNameException(String::format('Invalid character in Config object name @name.', array( - '@name' => $name, - ))); - } - } - - /** - * Gets data from this configuration object. - * - * @param string $key - * A string that maps to a key within the configuration data. - * For instance in the following configuration array: - * @code - * array( - * 'foo' => array( - * 'bar' => 'baz', - * ), - * ); - * @endcode - * A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo' - * would return array('bar' => 'baz'). - * If no key is specified, then the entire data array is returned. - * - * @return mixed - * The data that was requested. - */ - public function get($key = '') { - if (empty($key)) { - return $this->data; - } - else { - $parts = explode('.', $key); - if (count($parts) == 1) { - return isset($this->data[$key]) ? $this->data[$key] : NULL; - } - else { - $value = NestedArray::getValue($this->data, $parts, $key_exists); - return $key_exists ? $value : NULL; - } - } - } - - /** - * Replaces the data of this configuration object. - * - * @param array $data - * The new configuration data. - * - * @return $this - * The configuration object. - */ - public function setData(array $data) { - $this->data = $data; - return $this; - } - - /** - * Sets a value in this configuration object. - * - * @param string $key - * Identifier to store value in configuration. - * @param mixed $value - * Value to associate with identifier. - * - * @return $this - * The configuration object. - */ - public function set($key, $value) { - // The dot/period is a reserved character; it may appear between keys, but - // not within keys. - $parts = explode('.', $key); - if (count($parts) == 1) { - $this->data[$key] = $value; - } - else { - NestedArray::setValue($this->data, $parts, $value); - } - return $this; - } - - /** - * Unsets a value in this configuration object. - * - * @param string $key - * Name of the key whose value should be unset. - * - * @return $this - * The configuration object. - */ - public function clear($key) { - $parts = explode('.', $key); - if (count($parts) == 1) { - unset($this->data[$key]); - } - else { - NestedArray::unsetValue($this->data, $parts); - } - return $this; - } - - /** - * Merges data into a configuration object. - * - * @param array $data_to_merge - * An array containing data to merge. - * - * @return $this - * The configuration object. - */ - public function merge(array $data_to_merge) { - return $this->setData(NestedArray::mergeDeepArray(array($this->data, $data_to_merge), TRUE)); - } -} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index 5033244..18e0260 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -7,10 +7,9 @@ namespace Drupal\Core\Config\Entity; -use Drupal\Component\Utility\String; use Drupal\Core\Entity\Entity; -use Drupal\Core\Config\ConfigDuplicateUUIDException; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Config\ConfigDuplicateUUIDException; /** * Defines a base configuration entity class. @@ -126,8 +125,6 @@ public function set($property_name, $value) { } $this->{$property_name} = $value; - - return $this; } /** @@ -164,8 +161,6 @@ public function status() { */ public function setSyncing($syncing) { $this->isSyncing = $syncing; - - return $this; } /** @@ -189,7 +184,7 @@ public function createDuplicate() { /** * Helper callback for uasort() to sort configuration entities by weight and label. */ - public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { + public static function sort($a, $b) { $a_weight = isset($a->weight) ? $a->weight : 0; $b_weight = isset($b->weight) ? $b->weight : 0; if ($a_weight == $b_weight) { @@ -236,14 +231,14 @@ public function preSave(EntityStorageControllerInterface $storage_controller) { ->execute(); $matched_entity = reset($matching_entities); if (!empty($matched_entity) && ($matched_entity != $this->id())) { - throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this UUID is already used for %matched', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%matched' => $matched_entity))); + throw new ConfigDuplicateUUIDException(format_string('Attempt to save a configuration entity %id with UUID %uuid when this UUID is already used for %matched', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%matched' => $matched_entity))); } if (!$this->isNew()) { $original = $storage_controller->loadUnchanged($this->id()); // Ensure that the UUID cannot be changed for an existing entity. if ($original && ($original->uuid() != $this->uuid())) { - throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this entity already exists with UUID %original_uuid', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%original_uuid' => $original->uuid()))); + throw new ConfigDuplicateUUIDException(format_string('Attempt to save a configuration entity %id with UUID %uuid when this entity already exists with UUID %original_uuid', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%original_uuid' => $original->uuid()))); } } } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 1f1c715..5aa737d 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -28,21 +28,23 @@ public function getOriginalId(); * @param string $id * The new ID to set as original ID. * - * @return $this + * @return self */ public function setOriginalId($id); /** * Enables the configuration entity. * - * @return $this + * @return \Drupal\Core\Config\Entity\ConfigEntityInterface + * The configuration entity. */ public function enable(); /** * Disables the configuration entity. * - * @return $this + * @return \Drupal\Core\Config\Entity\ConfigEntityInterface + * The configuration entity. */ public function disable(); @@ -52,7 +54,8 @@ public function disable(); * @param bool $status * The status of the configuration entity. * - * @return $this + * @return \Drupal\Core\Config\Entity\ConfigEntityInterface + * The class instance that this method is called on. */ public function setStatus($status); @@ -61,8 +64,6 @@ public function setStatus($status); * * @param bool $status * The status of the sync flag. - * - * @return $this */ public function setSyncing($status); @@ -108,8 +109,6 @@ public function get($property_name); * The name of the property that should be set. * @param mixed $value * The value the property should be set to. - * - * @return $this */ public function set($property_name, $value); diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index 8a26ec0..a70ad36 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -66,6 +66,13 @@ class ConfigStorageController extends EntityStorageControllerBase implements Con protected $configStorage; /** + * The entity query factory. + * + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $entityQueryFactory; + + /** * Constructs a ConfigStorageController object. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type @@ -74,10 +81,12 @@ class ConfigStorageController extends EntityStorageControllerBase implements Con * The config factory service. * @param \Drupal\Core\Config\StorageInterface $config_storage * The config storage service. + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query_factory + * The entity query factory. * @param \Drupal\Component\Uuid\UuidInterface $uuid_service * The UUID service. */ - public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service) { + public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service) { parent::__construct($entity_type); $this->idKey = $this->entityType->getKey('id'); @@ -85,6 +94,7 @@ public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInter $this->configFactory = $config_factory; $this->configStorage = $config_storage; + $this->entityQueryFactory = $entity_query_factory; $this->uuidService = $uuid_service; } @@ -96,6 +106,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $entity_type, $container->get('config.factory'), $container->get('config.storage'), + $container->get('entity.query'), $container->get('uuid') ); } @@ -164,6 +175,13 @@ public function deleteRevision($revision_id) { /** * {@inheritdoc} */ + public function getQuery($conjunction = 'AND') { + return $this->entityQueryFactory->get($this->entityTypeId, $conjunction); + } + + /** + * {@inheritdoc} + */ public function getConfigPrefix() { return $this->entityType->getConfigPrefix() . '.'; } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageControllerInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageControllerInterface.php index 4ffe876..114fa33 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageControllerInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageControllerInterface.php @@ -31,6 +31,20 @@ public function importCreate($name, Config $new_config, Config $old_config); /** + * Returns an entity query instance. + * + * @param string $conjunction + * - AND: all of the conditions on the query need to match. + * - OR: at least one of the conditions on the query need to match. + * + * @return \Drupal\Core\Entity\Query\QueryInterface + * The query instance. + * + * @see \Drupal\Core\Entity\EntityStorageControllerInterface::getQueryServicename() + */ + public function getQuery($conjunction = 'AND'); + + /** * Updates configuration upon synchronizing configuration changes. * * This callback is invoked when configuration is synchronized between storages diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php deleted file mode 100644 index 8b05f95..0000000 --- a/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ /dev/null @@ -1,185 +0,0 @@ -isNew = FALSE; - $this->setData($data); - $this->originalData = $this->data; - return $this; - } - - /** - * Returns whether this configuration object is new. - * - * @return bool - * TRUE if this configuration object does not exist in storage. - */ - public function isNew() { - return $this->isNew; - } - - /** - * Retrieves the storage used to load and save this configuration object. - * - * @return \Drupal\Core\Config\StorageInterface - * The configuration storage object. - */ - public function getStorage() { - return $this->storage; - } - - /** - * Gets the schema wrapper for the whole configuration object. - * - * The schema wrapper is dependent on the configuration name and the whole - * data structure, so if the name or the data changes in any way, the wrapper - * should be reset. - * - * @return \Drupal\Core\Config\Schema\Element - */ - protected function getSchemaWrapper() { - if (!isset($this->schemaWrapper)) { - $definition = $this->typedConfigManager->getDefinition($this->name); - $this->schemaWrapper = $this->typedConfigManager->create($definition, $this->data); - } - return $this->schemaWrapper; - } - - /** - * Casts the value to correct data type using the configuration schema. - * - * @param string $key - * A string that maps to a key within the configuration data. - * @param string $value - * Value to associate with the key. - * - * @return mixed - * The value cast to the type indicated in the schema. - * - * @throws \Drupal\Core\Config\UnsupportedDataTypeConfigException - * Exception on unsupported/undefined data type deducted. - */ - protected function castValue($key, $value) { - if ($value === NULL) { - $value = NULL; - } - elseif (is_scalar($value)) { - try { - $element = $this->getSchemaWrapper()->get($key); - if ($element instanceof PrimitiveInterface) { - // Special handling for integers and floats since the configuration - // system is primarily concerned with saving values from the Form API - // we have to special case the meaning of an empty string for numeric - // types. In PHP this would be casted to a 0 but for the purposes of - // configuration we need to treat this as a NULL. - if ($value === '' && ($element instanceof IntegerInterface || $element instanceof FloatInterface)) { - $value = NULL; - } - else { - $value = $element->getCastedValue(); - } - } - else { - // Config only supports primitive data types. If the config schema - // does define a type $element will be an instance of - // \Drupal\Core\Config\Schema\Property. Convert it to string since it - // is the safest possible type. - $value = $element->getString(); - } - } - catch (SchemaIncompleteException $e) { - // @todo throw an exception due to an incomplete schema. - // Fix as part of https://drupal.org/node/2183983. - } - } - else { - // Throw exception on any non-scalar or non-array value. - if (!is_array($value)) { - throw new UnsupportedDataTypeConfigException(String::format('Invalid data type for config element @name:@key', array( - '@name' => $this->getName(), - '@key' => $key, - ))); - } - // Recurse into any nested keys. - foreach ($value as $nested_value_key => $nested_value) { - $value[$nested_value_key] = $this->castValue($key . '.' . $nested_value_key, $nested_value); - } - } - return $value; - } - -} diff --git a/core/lib/Drupal/Core/Controller/DialogController.php b/core/lib/Drupal/Core/Controller/DialogController.php index e86b9bd..5fda730 100644 --- a/core/lib/Drupal/Core/Controller/DialogController.php +++ b/core/lib/Drupal/Core/Controller/DialogController.php @@ -93,7 +93,14 @@ public function dialog(Request $request, $_content, $modal = FALSE) { } $content = drupal_render($page_content); - $title = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)); + + // @todo Remove use of drupal_get_title() when + // http://drupal.org/node/1871596 is in. + if (!$title = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT))) { + // @todo Remove use of drupal_get_title() when + // http://drupal.org/node/1871596 is in. + $title = drupal_get_title(); + } $response = new AjaxResponse(); // Fetch any modal options passed in from data-dialog-options. if (!($options = $request->request->get('dialogOptions'))) { diff --git a/core/lib/Drupal/Core/Controller/HtmlControllerBase.php b/core/lib/Drupal/Core/Controller/HtmlControllerBase.php index 9cc7651..0204bc0 100644 --- a/core/lib/Drupal/Core/Controller/HtmlControllerBase.php +++ b/core/lib/Drupal/Core/Controller/HtmlControllerBase.php @@ -80,7 +80,7 @@ protected function createHtmlFragment($page_content, Request $request) { $fragment->setTitle($page_content['#title'], Title::FILTER_XSS_ADMIN); } else if ($route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) { - $fragment->setTitle($this->titleResolver->getTitle($request, $route), Title::PASS_THROUGH); + $fragment->setTitle($this->titleResolver->getTitle($request, $route), PASS_THROUGH); } return $fragment; diff --git a/core/lib/Drupal/Core/Database/Query/Query.php b/core/lib/Drupal/Core/Database/Query/Query.php index 790ed5c..ad1f75e 100644 --- a/core/lib/Drupal/Core/Database/Query/Query.php +++ b/core/lib/Drupal/Core/Database/Query/Query.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\Core\Database\Query\Query. + * Definition of Drupal\Core\Database\Query\Query */ namespace Drupal\Core\Database\Query; @@ -106,9 +106,6 @@ public function __clone() { /** * Runs the query against the database. - * - * @return \Drupal\Core\Database\StatementInterface|null - * A prepared statement, or NULL if the query is not valid. */ abstract protected function execute(); @@ -118,7 +115,7 @@ public function __clone() { * The toString operation is how we compile a query object to a prepared * statement. * - * @return string + * @return * A prepared statement query string for this object. */ abstract public function __toString(); @@ -134,7 +131,7 @@ public function uniqueIdentifier() { * Gets the next placeholder value for this query object. * * @return int - * The next placeholder value. + * Next placeholder value. */ public function nextPlaceholder() { return $this->nextPlaceholder++; @@ -154,7 +151,8 @@ public function nextPlaceholder() { * @param $comment * The comment string to be inserted into the query. * - * @return $this + * @return \Drupal\Core\Database\Query\Query + * The called object. */ public function comment($comment) { $this->comments[] = $comment; @@ -173,7 +171,7 @@ public function comment($comment) { * $comments =& $query->getComments(); * @endcode * - * @return array + * @return * A reference to the comments array structure. */ public function &getComments() { diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php index 54a3555..2498ed0 100644 --- a/core/lib/Drupal/Core/Database/Query/Select.php +++ b/core/lib/Drupal/Core/Database/Query/Select.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\Core\Database\Query\Select. + * Definition of Drupal\Core\Database\Query\Select */ namespace Drupal\Core\Database\Query; @@ -121,18 +121,6 @@ class Select extends Query implements SelectInterface { */ protected $forUpdate = FALSE; - /** - * Constructs a Select object. - * - * @param string $table - * The name of the table that is being queried. - * @param string $alias - * The alias for the table. - * @param \Drupal\Core\Database\Connection $connection - * Database connection object. - * @param array $options - * Array of query options. - */ public function __construct($table, $alias = NULL, Connection $connection, $options = array()) { $options['return'] = Database::RETURN_STATEMENT; parent::__construct($connection, $options); @@ -142,68 +130,45 @@ public function __construct($table, $alias = NULL, Connection $connection, $opti $this->addJoin(NULL, $table, $alias); } - /** - * {@inheritdoc} - */ + /* Implementations of Drupal\Core\Database\Query\AlterableInterface. */ + public function addTag($tag) { $this->alterTags[$tag] = 1; return $this; } - /** - * {@inheritdoc} - */ public function hasTag($tag) { return isset($this->alterTags[$tag]); } - /** - * {@inheritdoc} - */ public function hasAllTags() { return !(boolean)array_diff(func_get_args(), array_keys($this->alterTags)); } - /** - * {@inheritdoc} - */ public function hasAnyTag() { return (boolean)array_intersect(func_get_args(), array_keys($this->alterTags)); } - /** - * {@inheritdoc} - */ public function addMetaData($key, $object) { $this->alterMetaData[$key] = $object; return $this; } - /** - * {@inheritdoc} - */ public function getMetaData($key) { return isset($this->alterMetaData[$key]) ? $this->alterMetaData[$key] : NULL; } - /** - * {@inheritdoc} - */ + /* Implementations of Drupal\Core\Database\Query\ConditionInterface for the WHERE clause. */ + public function condition($field, $value = NULL, $operator = NULL) { $this->where->condition($field, $value, $operator); return $this; } - /** - * {@inheritdoc} - */ public function &conditions() { return $this->where->conditions(); } - /** - * {@inheritdoc} - */ public function arguments() { if (!$this->compiled()) { return NULL; @@ -236,49 +201,31 @@ public function arguments() { return $args; } - /** - * {@inheritdoc} - */ public function where($snippet, $args = array()) { $this->where->where($snippet, $args); return $this; } - /** - * {@inheritdoc} - */ public function isNull($field) { $this->where->isNull($field); return $this; } - /** - * {@inheritdoc} - */ public function isNotNull($field) { $this->where->isNotNull($field); return $this; } - /** - * {@inheritdoc} - */ public function exists(SelectInterface $select) { $this->where->exists($select); return $this; } - /** - * {@inheritdoc} - */ public function notExists(SelectInterface $select) { $this->where->notExists($select); return $this; } - /** - * {@inheritdoc} - */ public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) { $this->where->compile($connection, $queryPlaceholder); $this->having->compile($connection, $queryPlaceholder); @@ -296,9 +243,6 @@ public function compile(Connection $connection, PlaceholderInterface $queryPlace } } - /** - * {@inheritdoc} - */ public function compiled() { if (!$this->where->compiled() || !$this->having->compiled()) { return FALSE; @@ -322,68 +266,32 @@ public function compiled() { return TRUE; } - /** - * {@inheritdoc} - */ + /* Implementations of Drupal\Core\Database\Query\ConditionInterface for the HAVING clause. */ + public function havingCondition($field, $value = NULL, $operator = NULL) { $this->having->condition($field, $value, $operator); return $this; } - /** - * Gets a list of all conditions in the HAVING clause. - * - * This method returns by reference. That allows alter hooks to access the - * data structure directly and manipulate it before it gets compiled. - * - * @return array - * An array of conditions. - * - * @see \Drupal\Core\Database\Query\ConditionInterface::conditions() - */ public function &havingConditions() { return $this->having->conditions(); } - /** - * Gets a list of all values to insert into the HAVING clause. - * - * @return array - * An associative array of placeholders and values. - */ public function havingArguments() { return $this->having->arguments(); } - /** - * Adds an arbitrary HAVING clause to the query. - * - * @param $snippet - * A portion of a HAVING clause as a prepared statement. It must use named - * placeholders, not ? placeholders. - * @param $args - * (optional) An associative array of arguments. - * - * @return $this - */ public function having($snippet, $args = array()) { $this->having->where($snippet, $args); return $this; } - /** - * Compiles the HAVING clause for later retrieval. - * - * @param $connection - * The database connection for which to compile the clause. - */ public function havingCompile(Connection $connection) { - $this->having->compile($connection, $this); + return $this->having->compile($connection, $this); } - /** - * {@inheritdoc} - */ + /* Implementations of Drupal\Core\Database\Query\ExtendableInterface. */ + public function extend($extender_name) { $override_class = $extender_name . '_' . $this->connection->driver(); if (class_exists($override_class)) { @@ -392,61 +300,26 @@ public function extend($extender_name) { return new $extender_name($this, $this->connection); } - /** - * Sets a condition in the HAVING clause that the specified field be NULL. - * - * @param $field - * The name of the field to check. - * - * @return $this - */ public function havingIsNull($field) { $this->having->isNull($field); return $this; } - /** - * Sets a condition in the HAVING clause that the specified field be NOT NULL. - * - * @param $field - * The name of the field to check. - * - * @return $this - */ public function havingIsNotNull($field) { $this->having->isNotNull($field); return $this; } - /** - * Sets a HAVING condition that the specified subquery returns values. - * - * @param \Drupal\Core\Database\Query\SelectInterface $select - * The subquery that must contain results. - * - * @return $this - */ public function havingExists(SelectInterface $select) { $this->having->exists($select); return $this; } - /** - * Sets a HAVING condition that the specified subquery returns no values. - * - * @param \Drupal\Core\Database\Query\SelectInterface $select - * The subquery that must contain results. - * - * @return $this - */ public function havingNotExists(SelectInterface $select) { $this->having->notExists($select); return $this; } - /** - * {@inheritdoc} - */ public function forUpdate($set = TRUE) { if (isset($set)) { $this->forUpdate = $set; @@ -454,51 +327,32 @@ public function forUpdate($set = TRUE) { return $this; } - /** - * {@inheritdoc} - */ + /* Alter accessors to expose the query data to alter hooks. */ + public function &getFields() { return $this->fields; } - /** - * {@inheritdoc} - */ public function &getExpressions() { return $this->expressions; } - /** - * {@inheritdoc} - */ public function &getOrderBy() { return $this->order; } - /** - * {@inheritdoc} - */ public function &getGroupBy() { return $this->group; } - /** - * {@inheritdoc} - */ public function &getTables() { return $this->tables; } - /** - * {@inheritdoc} - */ public function &getUnion() { return $this->union; } - /** - * {@inheritdoc} - */ public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) { if (!isset($queryPlaceholder)) { $queryPlaceholder = $this; @@ -508,14 +362,17 @@ public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) { } /** - * {@inheritdoc} + * Indicates if preExecute() has already been called on that object. */ public function isPrepared() { return $this->prepared; } /** - * {@inheritdoc} + * Generic preparation and validation for a SELECT query. + * + * @return + * TRUE if the validation was successful, FALSE if not. */ public function preExecute(SelectInterface $query = NULL) { // If no query object is passed in, use $this. @@ -553,9 +410,6 @@ public function preExecute(SelectInterface $query = NULL) { return $this->prepared; } - /** - * {@inheritdoc} - */ public function execute() { // If validation fails, simply return NULL. // Note that validation routines in preExecute() may throw exceptions instead. @@ -567,17 +421,11 @@ public function execute() { return $this->connection->query((string) $this, $args, $this->queryOptions); } - /** - * {@inheritdoc} - */ public function distinct($distinct = TRUE) { $this->distinct = $distinct; return $this; } - /** - * {@inheritdoc} - */ public function addField($table_alias, $field, $alias = NULL) { // If no alias is specified, first try the field name itself. if (empty($alias)) { @@ -606,10 +454,8 @@ public function addField($table_alias, $field, $alias = NULL) { return $alias; } - /** - * {@inheritdoc} - */ public function fields($table_alias, array $fields = array()) { + if ($fields) { foreach ($fields as $field) { // We don't care what alias was assigned. @@ -624,9 +470,6 @@ public function fields($table_alias, array $fields = array()) { return $this; } - /** - * {@inheritdoc} - */ public function addExpression($expression, $alias = NULL, $arguments = array()) { if (empty($alias)) { $alias = 'expression'; @@ -648,38 +491,24 @@ public function addExpression($expression, $alias = NULL, $arguments = array()) return $alias; } - /** - * {@inheritdoc} - */ public function join($table, $alias = NULL, $condition = NULL, $arguments = array()) { return $this->addJoin('INNER', $table, $alias, $condition, $arguments); } - /** - * {@inheritdoc} - */ public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) { return $this->addJoin('INNER', $table, $alias, $condition, $arguments); } - /** - * {@inheritdoc} - */ public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) { return $this->addJoin('LEFT OUTER', $table, $alias, $condition, $arguments); } - /** - * {@inheritdoc} - */ public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) { return $this->addJoin('RIGHT OUTER', $table, $alias, $condition, $arguments); } - /** - * {@inheritdoc} - */ public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) { + if (empty($alias)) { if ($table instanceof SelectInterface) { $alias = 'subquery'; @@ -711,9 +540,6 @@ public function addJoin($type, $table, $alias = NULL, $condition = NULL, $argume return $alias; } - /** - * {@inheritdoc} - */ public function orderBy($field, $direction = 'ASC') { // Only allow ASC and DESC, default to ASC. $direction = strtoupper($direction) == 'DESC' ? 'DESC' : 'ASC'; @@ -721,26 +547,17 @@ public function orderBy($field, $direction = 'ASC') { return $this; } - /** - * {@inheritdoc} - */ public function orderRandom() { $alias = $this->addExpression('RAND()', 'random_field'); $this->orderBy($alias); return $this; } - /** - * {@inheritdoc} - */ public function range($start = NULL, $length = NULL) { $this->range = func_num_args() ? array('start' => $start, 'length' => $length) : array(); return $this; } - /** - * {@inheritdoc} - */ public function union(SelectInterface $query, $type = '') { // Handle UNION aliasing. switch ($type) { @@ -763,16 +580,13 @@ public function union(SelectInterface $query, $type = '') { return $this; } - /** - * {@inheritdoc} - */ public function groupBy($field) { $this->group[$field] = $field; return $this; } /** - * {@inheritdoc} + * Implements SelectInterface::countQuery(). */ public function countQuery() { $count = $this->prepareCountQuery(); @@ -846,9 +660,6 @@ protected function prepareCountQuery() { return $count; } - /** - * {@inheritdoc} - */ public function __toString() { // For convenience, we compile the query ourselves if the caller forgot // to do it. This allows constructs like "(string) $query" to work. When @@ -968,9 +779,6 @@ public function __toString() { return $query; } - /** - * {@inheritdoc} - */ public function __clone() { // On cloning, also clone the dependent objects. However, we do not // want to clone the database connection object as that would duplicate the diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index ba016cb..82e5241 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -129,19 +129,12 @@ protected $isDefaultRevision = TRUE; /** - * The typed data manager. - * - * @var \Drupal\Core\TypedData\TypedDataManager - */ - protected $typedDataManager; - - /** * Overrides Entity::__construct(). */ public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) { $this->entityTypeId = $entity_type; $this->bundle = $bundle ? $bundle : $this->entityTypeId; - $this->languages = $this->languageList(Language::STATE_ALL); + $this->languages = language_list(Language::STATE_ALL); foreach ($values as $key => $value) { // If the key matches an existing property set the value to the property @@ -169,26 +162,6 @@ public function __construct(array $values, $entity_type, $bundle = FALSE, $trans } /** - * Wraps $this->languageList(). - */ - protected function languageList($flags = Language::STATE_CONFIGURABLE) { - return language_list($flags); - } - - /** - * Returns the typed data manager. - * - * @return \Drupal\Core\TypedData\TypedDataManager - */ - protected function typedDataManager() { - if (!$this->typedDataManager) { - $this->typedDataManager = \Drupal::typedDataManager(); - } - - return $this->typedDataManager; - } - - /** * {@inheritdoc} */ public function setNewRevision($value = TRUE) { @@ -224,7 +197,8 @@ public function getRevisionId() { * {@inheritdoc} */ public function isTranslatable() { - $bundles = $this->entityManager()->getBundleInfo($this->entityTypeId); + // @todo Inject the entity manager and retrieve bundle info from it. + $bundles = entity_get_bundles($this->entityTypeId); return !empty($bundles[$this->bundle()]['translatable']); } @@ -265,14 +239,15 @@ public function setValue($value, $notify = TRUE) { * {@inheritdoc} */ public function getString() { - return (string) $this->label(); + return $this->label(); } /** * {@inheritdoc} */ public function validate() { - return $this->typedDataManager()->getValidator()->validate($this); + // @todo: Add the typed data manager as proper dependency. + return \Drupal::typedDataManager()->getValidator()->validate($this); } /** @@ -358,7 +333,10 @@ public function __sleep() { $this->fieldDefinitions = NULL; $this->clearTranslationCache(); - return parent::__sleep(); + // Don't serialize the url generator. + $this->urlGenerator = NULL; + + return array_keys(get_object_vars($this)); } @@ -366,7 +344,6 @@ public function __sleep() { * Magic __wakeup() implementation. */ public function __wakeup() { - parent::__wakeup(); $this->init(); } @@ -416,7 +393,7 @@ public function get($property_name) { protected function getTranslatedField($name, $langcode) { if ($this->translations[$this->activeLangcode]['status'] == static::TRANSLATION_REMOVED) { $message = 'The entity object refers to a removed translation (@langcode) and cannot be manipulated.'; - throw new \InvalidArgumentException(String::format($message, array('@langcode' => $this->activeLangcode))); + throw new \InvalidArgumentException(format_string($message, array('@langcode' => $this->activeLangcode))); } // Populate $this->fields to speed-up further look-ups and to keep track of // fields objects, possibly holding changes to field values. @@ -549,13 +526,13 @@ public function isEmpty() { /** * {@inheritdoc} */ - public function access($operation, AccountInterface $account = NULL) { + public function access($operation = 'view', AccountInterface $account = NULL) { if ($operation == 'create') { - return $this->entityManager() + return \Drupal::entityManager() ->getAccessController($this->entityTypeId) ->createAccess($this->bundle(), $account); } - return $this->entityManager() + return \Drupal::entityManager() ->getAccessController($this->entityTypeId) ->access($this, $operation, $this->activeLangcode, $account); } @@ -567,7 +544,7 @@ public function language() { $language = NULL; if ($this->activeLangcode != Language::LANGCODE_DEFAULT) { if (!isset($this->languages[$this->activeLangcode])) { - $this->languages += $this->languageList(Language::STATE_ALL); + $this->languages += language_list(Language::STATE_ALL); } $language = $this->languages[$this->activeLangcode]; } @@ -617,7 +594,7 @@ public function onChange($name) { if ($name == 'langcode') { $this->setDefaultLangcode(); if (isset($this->translations[$this->defaultLangcode])) { - $message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode)); + $message = format_string('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode)); throw new \InvalidArgumentException($message); } $this->updateFieldLangcodes($this->defaultLangcode); @@ -666,7 +643,7 @@ public function getTranslation($langcode) { if (empty($translation)) { $message = 'Invalid translation language (@langcode) specified.'; - throw new \InvalidArgumentException(String::format($message, array('@langcode' => $langcode))); + throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode))); } return $translation; @@ -731,14 +708,14 @@ public function hasTranslation($langcode) { public function addTranslation($langcode, array $values = array()) { if (!isset($this->languages[$langcode]) || $this->hasTranslation($langcode)) { $message = 'Invalid translation language (@langcode) specified.'; - throw new \InvalidArgumentException(String::format($message, array('@langcode' => $langcode))); + throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode))); } // Instantiate a new empty entity so default values will be populated in the // specified language. $entity_type = $this->getEntityType(); $default_values = array($entity_type->getKey('bundle') => $this->bundle, 'langcode' => $langcode); - $entity = $this->entityManager() + $entity = \Drupal::entityManager() ->getStorageController($this->getEntityTypeId()) ->create($default_values); @@ -776,7 +753,7 @@ public function removeTranslation($langcode) { } else { $message = 'The specified translation (@langcode) cannot be removed.'; - throw new \InvalidArgumentException(String::format($message, array('@langcode' => $langcode))); + throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode))); } } @@ -918,7 +895,7 @@ public function __unset($name) { public function createDuplicate() { if ($this->translations[$this->activeLangcode]['status'] == static::TRANSLATION_REMOVED) { $message = 'The entity object refers to a removed translation (@langcode) and cannot be manipulated.'; - throw new \InvalidArgumentException(String::format($message, array('@langcode' => $this->activeLangcode))); + throw new \InvalidArgumentException(format_string($message, array('@langcode' => $this->activeLangcode))); } $duplicate = clone $this; @@ -927,7 +904,8 @@ public function createDuplicate() { // Check if the entity type supports UUIDs and generate a new one if so. if ($entity_type->hasKey('uuid')) { - $duplicate->{$entity_type->getKey('uuid')}->value = $this->uuidGenerator()->generate(); + // @todo Inject the UUID service into the Entity class once possible. + $duplicate->{$entity_type->getKey('uuid')}->value = \Drupal::service('uuid')->generate(); } // Check whether the entity type supports revisions and initialize it if so. @@ -975,8 +953,9 @@ public function __clone() { public function label() { $label = NULL; $entity_type = $this->getEntityType(); - if (($label_callback = $entity_type->getLabelCallback()) && is_callable($label_callback)) { - $label = call_user_func($label_callback, $this); + // @todo Convert to is_callable() and call_user_func(). + if (($label_callback = $entity_type->getLabelCallback()) && function_exists($label_callback)) { + $label = $label_callback($this); } elseif (($label_key = $entity_type->getKey('label')) && isset($this->{$label_key})) { $label = $this->{$label_key}->value; diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 8fd3a62..5d70510 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -7,14 +7,13 @@ namespace Drupal\Core\Entity; -use Drupal\Core\DependencyInjection\DependencySerialization; use Drupal\Core\Language\Language; use Drupal\Core\Session\AccountInterface; /** * Defines a base entity class. */ -abstract class Entity extends DependencySerialization implements EntityInterface { +abstract class Entity implements EntityInterface { /** * The language code of the entity's default language. @@ -24,20 +23,6 @@ public $langcode = Language::LANGCODE_NOT_SPECIFIED; /** - * The entity manager. - * - * @var \Drupal\Core\Entity\EntityManagerInterface - */ - protected $entityManager; - - /** - * The UUID generator. - * - * @var \Drupal\Component\Uuid\UuidInterface - */ - protected $uuidGenerator; - - /** * The entity type. * * @var string @@ -76,39 +61,6 @@ public function __construct(array $values, $entity_type) { } /** - * Wraps language_load(). - */ - protected function languageLoad($langcode) { - return language_load($langcode); - } - - /** - * Returns the entity manager. - * - * @return \Drupal\Core\Entity\EntityManagerInterface - */ - protected function entityManager() { - if (!$this->entityManager) { - $this->entityManager = \Drupal::entityManager(); - } - - return $this->entityManager; - } - - /** - * Returns the UUID generator. - * - * @return \Drupal\Component\Uuid\UuidInterface - */ - protected function uuidGenerator() { - if (!$this->uuidGenerator) { - $this->uuidGenerator = \Drupal::service('uuid'); - } - - return $this->uuidGenerator; - } - - /** * {@inheritdoc} */ public function id() { @@ -134,8 +86,6 @@ public function isNew() { */ public function enforceIsNew($value = TRUE) { $this->enforceIsNew = $value; - - return $this; } /** @@ -158,8 +108,9 @@ public function bundle() { public function label() { $label = NULL; $entity_type = $this->getEntityType(); - if (($label_callback = $entity_type->getLabelCallback()) && is_callable($label_callback)) { - $label = call_user_func($label_callback, $this); + // @todo Convert to is_callable() and call_user_func(). + if (($label_callback = $entity_type->getLabelCallback()) && function_exists($label_callback)) { + $label = $label_callback($this); } elseif (($label_key = $entity_type->getKey('label')) && isset($this->{$label_key})) { $label = $this->{$label_key}; @@ -187,7 +138,7 @@ public function urlInfo($rel = 'canonical') { $bundle = $this->bundle(); // A bundle-specific callback takes precedence over the generic one for // the entity type. - $bundles = $this->entityManager()->getBundleInfo($this->getEntityTypeId()); + $bundles = \Drupal::entityManager()->getBundleInfo($this->getEntityTypeId()); if (isset($bundles[$bundle]['uri_callback'])) { $uri_callback = $bundles[$bundle]['uri_callback']; } @@ -197,8 +148,9 @@ public function urlInfo($rel = 'canonical') { // Invoke the callback to get the URI. If there is no callback, use the // default URI format. - if (isset($uri_callback) && is_callable($uri_callback)) { - $uri = call_user_func($uri_callback, $this); + // @todo Convert to is_callable() and call_user_func(). + if (isset($uri_callback) && function_exists($uri_callback)) { + $uri = $uri_callback($this); } else { return array(); @@ -295,13 +247,13 @@ public function uriRelationships() { /** * {@inheritdoc} */ - public function access($operation, AccountInterface $account = NULL) { + public function access($operation = 'view', AccountInterface $account = NULL) { if ($operation == 'create') { - return $this->entityManager() + return \Drupal::entityManager() ->getAccessController($this->entityTypeId) ->createAccess($this->bundle(), $account); } - return $this->entityManager() + return \Drupal::entityManager() ->getAccessController($this->entityTypeId) ->access($this, $operation, Language::LANGCODE_DEFAULT, $account); } @@ -310,7 +262,7 @@ public function access($operation, AccountInterface $account = NULL) { * {@inheritdoc} */ public function language() { - $language = $this->languageLoad($this->langcode); + $language = language_load($this->langcode); if (!$language) { // Make sure we return a proper language object. $language = new Language(array('id' => Language::LANGCODE_NOT_SPECIFIED)); @@ -322,7 +274,7 @@ public function language() { * {@inheritdoc} */ public function save() { - return $this->entityManager()->getStorageController($this->entityTypeId)->save($this); + return \Drupal::entityManager()->getStorageController($this->entityTypeId)->save($this); } /** @@ -330,7 +282,7 @@ public function save() { */ public function delete() { if (!$this->isNew()) { - $this->entityManager()->getStorageController($this->entityTypeId)->delete(array($this->id() => $this)); + \Drupal::entityManager()->getStorageController($this->entityTypeId)->delete(array($this->id() => $this)); } } @@ -344,7 +296,8 @@ public function createDuplicate() { // Check if the entity type supports UUIDs and generate a new one if so. if ($entity_type->hasKey('uuid')) { - $duplicate->{$entity_type->getKey('uuid')} = $this->uuidGenerator()->generate(); + // @todo Inject the UUID service into the Entity class once possible. + $duplicate->{$entity_type->getKey('uuid')} = \Drupal::service('uuid')->generate(); } return $duplicate; } @@ -353,7 +306,7 @@ public function createDuplicate() { * {@inheritdoc} */ public function getEntityType() { - return $this->entityManager()->getDefinition($this->getEntityTypeId()); + return \Drupal::entityManager()->getDefinition($this->getEntityTypeId()); } /** @@ -391,7 +344,6 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr * {@inheritdoc} */ public static function postDelete(EntityStorageControllerInterface $storage_controller, array $entities) { - /** @var self[] $entities */ foreach ($entities as $entity) { $entity->onSaveOrDelete(); } @@ -423,8 +375,8 @@ protected function onSaveOrDelete() { } foreach ($referenced_entities as $entity_type => $entities) { - if ($this->entityManager()->hasController($entity_type, 'view_builder')) { - $this->entityManager()->getViewBuilder($entity_type)->resetCache($entities); + if (\Drupal::entityManager()->hasController($entity_type, 'view_builder')) { + \Drupal::entityManager()->getViewBuilder($entity_type)->resetCache($entities); } } } @@ -442,4 +394,14 @@ protected function urlGenerator() { return $this->urlGenerator; } + /** + * {@inheritdoc} + */ + public function __sleep() { + // Don't serialize the url generator. + $this->urlGenerator = NULL; + + return array_keys(get_object_vars($this)); + } + } diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 769a85e..057727b 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -65,8 +65,6 @@ public function isNew(); * (optional) Whether the entity should be forced to be new. Defaults to * TRUE. * - * @return self - * * @see \Drupal\Core\Entity\EntityInterface::isNew() */ public function enforceIsNew($value = TRUE); diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php index c6585be..0703f50 100644 --- a/core/lib/Drupal/Core/Entity/EntityListController.php +++ b/core/lib/Drupal/Core/Entity/EntityListController.php @@ -171,7 +171,7 @@ public function buildOperations(EntityInterface $entity) { */ public function render() { $build = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $this->buildHeader(), '#title' => $this->getTitle(), '#rows' => array(), diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index c7c111c..5bfd687 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -370,7 +370,7 @@ public function getFieldDefinitions($entity_type_id, $bundle) { } else { // Rebuild the definitions and put it into the cache. - $bundle_field_definitions = $this->buildBundleFieldDefinitions($entity_type_id, $bundle, $base_field_definitions); + $bundle_field_definitions = $this->buildBuildFieldDefinitions($entity_type_id, $bundle, $base_field_definitions); $this->cache->set($cid, $bundle_field_definitions, Cache::PERMANENT, array('entity_types' => TRUE, 'entity_field_info' => TRUE)); } // Field definitions consist of the bundle specific overrides and the @@ -397,7 +397,7 @@ public function getFieldDefinitions($entity_type_id, $bundle) { * An array of bundle field definitions, keyed by field name. Does * not include base fields. */ - protected function buildBundleFieldDefinitions($entity_type_id, $bundle, array $base_field_definitions) { + protected function buildBuildFieldDefinitions($entity_type_id, $bundle, array $base_field_definitions) { $entity_type = $this->getDefinition($entity_type_id); $class = $entity_type->getClass(); diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php index 7c39f19..5416935 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php @@ -8,7 +8,6 @@ namespace Drupal\Core\Entity; use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Extension\ModuleHandlerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * A base entity storage controller class. @@ -195,17 +194,10 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value */ public function loadByProperties(array $values = array()) { // Build a query to fetch the entity IDs. - $entity_query = $this->getQuery(); + $entity_query = \Drupal::entityQuery($this->entityTypeId); $this->buildPropertyQuery($entity_query, $values); $result = $entity_query->execute(); return $result ? $this->loadMultiple($result) : array(); } - /** - * {@inheritdoc} - */ - public function getQuery($conjunction = 'AND') { - return \Drupal::entityQuery($this->getEntityTypeId(), $conjunction); - } - } diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php index 2658aa2..3da5abc 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php @@ -155,21 +155,6 @@ public function save(EntityInterface $entity); public function getQueryServicename(); /** - * Returns an entity query instance. - * - * @param string $conjunction - * (optional) The logical operator for the query, either: - * - AND: all of the conditions on the query need to match. - * - OR: at least one of the conditions on the query need to match. - * - * @return \Drupal\Core\Entity\Query\QueryInterface - * The query instance. - * - * @see \Drupal\Core\Entity\EntityStorageControllerInterface::getQueryServicename() - */ - public function getQuery($conjunction = 'AND'); - - /** * Returns the entity type ID. * * @return string diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index 1231689..69431a5 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -553,15 +553,6 @@ public function processForm($form_id, &$form, &$form_state) { if (isset($form['#token']) && $form['#token'] === FALSE) { unset($form['#token']); } - // Form values for programmed form submissions typically do not include a - // value for the submit button. But without a triggering element, a - // potentially existing #limit_validation_errors property on the primary - // submit button is not taken account. Therefore, check whether there is - // exactly one submit button in the form, and if so, automatically use it - // as triggering_element. - if ($form_state['programmed'] && !isset($form_state['triggering_element']) && count($form_state['buttons']) == 1) { - $form_state['triggering_element'] = reset($form_state['buttons']); - } $this->validateForm($form_id, $form, $form_state); // drupal_html_id() maintains a cache of element IDs it has seen, so it diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php index 6e0c509..64aed01 100644 --- a/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php +++ b/core/lib/Drupal/Core/Page/DefaultHtmlFragmentRenderer.php @@ -74,6 +74,14 @@ public function render(HtmlFragment $fragment, $status_code = 200) { * The modified page object. */ public function preparePage(HtmlPage $page, &$page_array) { + // @todo Remove this one drupal_get_title() has been eliminated. + if (!$page->hasTitle()) { + $title = drupal_get_title(); + // drupal_set_title() already ensured security, so not letting the + // title pass through would cause double escaping. + $page->setTitle($title, PASS_THROUGH); + } + $page_array['#page'] = $page; // HTML element attributes. diff --git a/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php b/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php index 821d42d..63e0d9c 100644 --- a/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php +++ b/core/lib/Drupal/Core/Page/DefaultHtmlPageRenderer.php @@ -17,7 +17,7 @@ class DefaultHtmlPageRenderer implements HtmlPageRendererInterface { */ public function render(HtmlPage $page) { $render = array( - '#type' => 'html', + '#theme' => 'html', '#page_object' => $page, ); return drupal_render($render); diff --git a/core/lib/Drupal/Core/Page/HtmlFragment.php b/core/lib/Drupal/Core/Page/HtmlFragment.php index cf1ca4d..cc5cac5 100644 --- a/core/lib/Drupal/Core/Page/HtmlFragment.php +++ b/core/lib/Drupal/Core/Page/HtmlFragment.php @@ -103,8 +103,8 @@ public function getContent() { * Value to assign to the page title. * @param int $output * (optional) normally should be left as Title::CHECK_PLAIN. Only set to - * Title::PASS_THROUGH if you have already removed any possibly dangerous - * code from $title using a function like + * PASS_THROUGH if you have already removed any possibly dangerous code + * from $title using a function like * \Drupal\Component\Utility\String::checkPlain() or * \Drupal\Component\Utility\Xss::filterAdmin(). With this flag the string * will be passed through unchanged. diff --git a/core/lib/Drupal/Core/Theme/ThemeSettings.php b/core/lib/Drupal/Core/Theme/ThemeSettings.php index 6749f01..d20b843 100644 --- a/core/lib/Drupal/Core/Theme/ThemeSettings.php +++ b/core/lib/Drupal/Core/Theme/ThemeSettings.php @@ -7,12 +7,12 @@ namespace Drupal\Core\Theme; -use Drupal\Core\Config\ConfigBase; +use Drupal\Component\Utility\NestedArray; /** * Defines the default theme settings object. */ -class ThemeSettings extends ConfigBase { +class ThemeSettings { /** * The theme of the theme settings object. @@ -22,13 +22,21 @@ class ThemeSettings extends ConfigBase { protected $theme; /** + * The data of the theme settings object. + * + * @var array + */ + protected $data; + + /** * Constructs a theme settings object. * - * @param string $theme + * @param string $name * The name of the theme settings object being constructed. */ public function __construct($theme) { $this->theme = $theme; + $this->data = array(); } /** @@ -40,4 +48,113 @@ public function __construct($theme) { public function getTheme() { return $this->theme; } + + /** + * Gets data from this theme settings object. + * + * @param string $key + * A string that maps to a key within the theme settings data. + * For instance in the following theme settings array: + * @code + * array( + * 'foo' => array( + * 'bar' => 'baz', + * ), + * ); + * @endcode + * A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo' + * would return array('bar' => 'baz'). + * If no key is specified, then the entire data array is returned. + * + * + * @return mixed + * The data that was requested. + */ + public function get($key = '') { + if (empty($key)) { + return $this->data; + } + else { + $parts = explode('.', $key); + if (count($parts) == 1) { + return isset($this->data[$key]) ? $this->data[$key] : NULL; + } + else { + $value = NestedArray::getValue($this->data, $parts, $key_exists); + return $key_exists ? $value : NULL; + } + } + } + + /** + * Replaces the data of this theme settings object. + * + * @param array $data + * The new theme settings data. + * + * @return \Drupal\Core\Theme\ThemeSettings + * The theme settings object. + */ + public function setData(array $data) { + $this->data = $data; + return $this; + } + + /** + * Sets value in this theme settings object. + * + * @param string $key + * Identifier to store value in theme settings. + * @param string $value + * Value to associate with identifier. + * + * @return \Drupal\Core\Theme\ThemeSettings + * The theme settings object. + */ + public function set($key, $value) { + // The dot/period is a reserved character; it may appear between keys, but + // not within keys. + $parts = explode('.', $key); + if (count($parts) == 1) { + $this->data[$key] = $value; + } + else { + NestedArray::setValue($this->data, $parts, $value); + } + return $this; + } + + /** + * Unsets value in this theme settings object. + * + * @param string $key + * Name of the key whose value should be unset. + * + * @return \Drupal\Core\Theme\ThemeSettings + * The theme settings object. + */ + public function clear($key) { + $parts = explode('.', $key); + if (count($parts) == 1) { + unset($this->data[$key]); + } + else { + NestedArray::unsetValue($this->data, $parts); + } + return $this; + } + + /** + * Merges the data into this theme settings object. + * + * @param array $data + * Theme settings data to merge. + * + * @return \Drupal\Core\Theme\ThemeSettings + * The theme settings object. + */ + public function mergeData ($data) { + $this->data = NestedArray::mergeDeep($this->data, $data); + return $this; + } } diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php index 581e79c..452b602 100644 --- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php @@ -63,7 +63,7 @@ public function set($property_name, $value, $notify = TRUE); * @param bool $include_computed * If set to TRUE, computed properties are included. Defaults to FALSE. * - * @return \Drupal\Core\TypedData\TypedDataInterface[] + * @return array * An array of property objects implementing the TypedDataInterface, keyed * by property name. */ diff --git a/core/lib/Drupal/Core/Utility/Title.php b/core/lib/Drupal/Core/Utility/Title.php index 40a3a91..b6380b6 100644 --- a/core/lib/Drupal/Core/Utility/Title.php +++ b/core/lib/Drupal/Core/Utility/Title.php @@ -22,9 +22,4 @@ class Title { */ const FILTER_XSS_ADMIN = 1; - /** - * For controller titles, text has already been sanitized. - */ - const PASS_THROUGH = -1; - } diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php b/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php index 5e89acf..f7313cc 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Controller/AggregatorController.php @@ -174,7 +174,7 @@ public function adminOverview() { } $build['feeds'] = array( '#prefix' => '

' . $this->t('Feed overview') . '

', - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => $this->t('No feeds available. Add feed.', array('@link' => $this->urlGenerator()->generateFromPath('admin/config/services/aggregator/add/feed'))), diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Form/OpmlFeedAdd.php b/core/modules/aggregator/lib/Drupal/aggregator/Form/OpmlFeedAdd.php index 1ba376b..c1eda08 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Form/OpmlFeedAdd.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Form/OpmlFeedAdd.php @@ -9,6 +9,7 @@ use Drupal\aggregator\FeedStorageControllerInterface; use Drupal\Component\Utility\UrlHelper; +use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Form\FormBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Guzzle\Http\Exception\RequestException; @@ -21,6 +22,13 @@ class OpmlFeedAdd extends FormBase { /** + * The entity query factory object. + * + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $queryFactory; + + /** * The feed storage. * * @var \Drupal\aggregator\FeedStorageControllerInterface @@ -37,12 +45,15 @@ class OpmlFeedAdd extends FormBase { /** * Constructs a database object. * + * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory + * The entity query object. * @param \Drupal\aggregator\FeedStorageControllerInterface $feed_storage * The feed storage. * @param \Guzzle\Http\ClientInterface $http_client * The Guzzle HTTP client. */ - public function __construct(FeedStorageControllerInterface $feed_storage, ClientInterface $http_client) { + public function __construct(QueryFactory $query_factory, FeedStorageControllerInterface $feed_storage, ClientInterface $http_client) { + $this->queryFactory = $query_factory; $this->feedStorageController = $feed_storage; $this->httpClient = $http_client; } @@ -52,6 +63,7 @@ public function __construct(FeedStorageControllerInterface $feed_storage, Client */ public static function create(ContainerInterface $container) { return new static( + $container->get('entity.query'), $container->get('entity.manager')->getStorageController('aggregator_feed'), $container->get('http_default_client') ); @@ -152,7 +164,7 @@ public function submitForm(array &$form, array &$form_state) { } // Check for duplicate titles or URLs. - $query = $this->feedStorageController->getQuery(); + $query = $this->queryFactory->get('aggregator_feed'); $condition = $query->orConditionGroup() ->condition('title', $feed['title']) ->condition('url', $feed['url']); diff --git a/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php b/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php index bfaeb7a..29ca186 100644 --- a/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php +++ b/core/modules/ban/lib/Drupal/ban/Form/BanAdmin.php @@ -90,7 +90,7 @@ public function buildForm(array $form, array &$form_state, $default_ip = '') { ); $form['ban_ip_banning_table'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => $this->t('No blocked IP addresses available.'), diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 6f341ad..1bca18b 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -199,7 +199,7 @@ function _block_get_renderable_region($list = array()) { $settings = $block->get('settings'); if ($not_cacheable || in_array($settings['cache'], array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM))) { // Non-cached blocks get built immediately. - if ($block->access('view')) { + if ($block->access()) { $build[$key] = entity_view($block, 'block'); } } @@ -378,7 +378,7 @@ function block_load($entity_id) { function _block_get_renderable_block($element) { $block = $element['#block']; // Don't bother to build blocks that aren't accessible. - if ($element['#access'] = $block->access('view')) { + if ($element['#access'] = $block->access()) { $element += entity_view($block, 'block'); } return $element; diff --git a/core/modules/block/lib/Drupal/block/BlockFormController.php b/core/modules/block/lib/Drupal/block/BlockFormController.php index 4ce4c81..08bf090 100644 --- a/core/modules/block/lib/Drupal/block/BlockFormController.php +++ b/core/modules/block/lib/Drupal/block/BlockFormController.php @@ -11,6 +11,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityFormController; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\language\ConfigurableLanguageManagerInterface; @@ -36,6 +37,13 @@ class BlockFormController extends EntityFormController { protected $storageController; /** + * The entity query factory. + * + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $entityQueryFactory; + + /** * The language manager. * * @var \Drupal\Core\Language\LanguageManagerInterface @@ -54,13 +62,16 @@ class BlockFormController extends EntityFormController { * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query_factory + * The entity query factory. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory. */ - public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) { + public function __construct(EntityManagerInterface $entity_manager, QueryFactory $entity_query_factory, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) { $this->storageController = $entity_manager->getStorageController('block'); + $this->entityQueryFactory = $entity_query_factory; $this->languageManager = $language_manager; $this->configFactory = $config_factory; } @@ -71,6 +82,7 @@ public function __construct(EntityManagerInterface $entity_manager, LanguageMana public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), + $container->get('entity.query'), $container->get('language_manager'), $container->get('config.factory') ); @@ -361,7 +373,7 @@ public function getUniqueMachineName(BlockInterface $block) { $suggestion = $block->getPlugin()->getMachineNameSuggestion(); // Get all the blocks which starts with the suggested machine name. - $query = $this->storageController->getQuery(); + $query = $this->entityQueryFactory->get('block'); $query->condition('id', $suggestion, 'CONTAINS'); $block_ids = $query->execute(); diff --git a/core/modules/block/lib/Drupal/block/Entity/Block.php b/core/modules/block/lib/Drupal/block/Entity/Block.php index e44d028..cb49cac 100644 --- a/core/modules/block/lib/Drupal/block/Entity/Block.php +++ b/core/modules/block/lib/Drupal/block/Entity/Block.php @@ -10,7 +10,6 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\block\BlockPluginBag; use Drupal\block\BlockInterface; -use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Config\Entity\EntityWithPluginBagInterface; /** @@ -149,7 +148,7 @@ public function getExportProperties() { /** * Sorts active blocks by weight; sorts inactive blocks by name. */ - public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { + public static function sort($a, $b) { // Separate enabled from disabled. $status = $b->get('status') - $a->get('status'); if ($status) { diff --git a/core/modules/block/tests/Drupal/block/Tests/BlockFormControllerTest.php b/core/modules/block/tests/Drupal/block/Tests/BlockFormControllerTest.php index aa54731..5d9f692 100644 --- a/core/modules/block/tests/Drupal/block/Tests/BlockFormControllerTest.php +++ b/core/modules/block/tests/Drupal/block/Tests/BlockFormControllerTest.php @@ -31,6 +31,7 @@ public static function getInfo() { * @see \Drupal\block\BlockFormController::getUniqueMachineName() */ public function testGetUniqueMachineName() { + $block_storage = $this->getMock('Drupal\Core\Config\Entity\ConfigStorageControllerInterface'); $blocks = array(); $blocks['test'] = $this->getBlockMockWithMachineName('test'); @@ -38,7 +39,9 @@ public function testGetUniqueMachineName() { $blocks['other_test_1'] = $this->getBlockMockWithMachineName('other_test'); $blocks['other_test_2'] = $this->getBlockMockWithMachineName('other_test'); - $query = $this->getMock('Drupal\Core\Entity\Query\QueryInterface'); + $query = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryInterface') + ->disableOriginalConstructor() + ->getMock(); $query->expects($this->exactly(5)) ->method('condition') ->will($this->returnValue($query)); @@ -47,9 +50,12 @@ public function testGetUniqueMachineName() { ->method('execute') ->will($this->returnValue(array('test', 'other_test', 'other_test_1', 'other_test_2'))); - $block_storage = $this->getMock('Drupal\Core\Config\Entity\ConfigStorageControllerInterface'); - $block_storage->expects($this->exactly(5)) - ->method('getQuery') + $query_factory = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryFactory') + ->disableOriginalConstructor() + ->getMock(); + $query_factory->expects($this->exactly(5)) + ->method('get') + ->with('block', 'AND') ->will($this->returnValue($query)); $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); @@ -62,7 +68,7 @@ public function testGetUniqueMachineName() { $config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface'); - $block_form_controller = new BlockFormController($entity_manager, $language_manager, $config_factory); + $block_form_controller = new BlockFormController($entity_manager, $query_factory, $language_manager, $config_factory); // Ensure that the block with just one other instance gets the next available // name suggestion. diff --git a/core/modules/book/lib/Drupal/book/Controller/BookController.php b/core/modules/book/lib/Drupal/book/Controller/BookController.php index dec592c..49a4947 100644 --- a/core/modules/book/lib/Drupal/book/Controller/BookController.php +++ b/core/modules/book/lib/Drupal/book/Controller/BookController.php @@ -89,7 +89,7 @@ public function adminOverview() { $rows[] = $row; } return array( - '#type' => 'table', + '#theme' => 'table', '#header' => $headers, '#rows' => $rows, '#empty' => t('No books available.'), diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 9af0246..abc63b4 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -950,25 +950,17 @@ function comment_entity_insert(EntityInterface $entity) { * Implements hook_entity_predelete(). */ function comment_entity_predelete(EntityInterface $entity) { - // Entities can have non-numeric IDs, but {comment} and - // {comment_entity_statistics} tables have integer columns for entity ID, and - // PostgreSQL throws exceptions if you attempt query conditions with - // mismatched types. So, we need to verify that the ID is numeric (even for an - // entity type that has an integer ID, $entity->id() might be a string - // containing a number), and then cast it to an integer when querying. - if ($entity->getEntityType()->isFieldable() && is_numeric($entity->id())) { - $cids = db_select('comment', 'c') - ->fields('c', array('cid')) - ->condition('entity_id', (int) $entity->id()) - ->condition('entity_type', $entity->getEntityTypeId()) - ->execute() - ->fetchCol(); - entity_delete_multiple('comment', $cids); - db_delete('comment_entity_statistics') - ->condition('entity_id', (int) $entity->id()) - ->condition('entity_type', $entity->getEntityTypeId()) - ->execute(); - } + $cids = db_select('comment', 'c') + ->fields('c', array('cid')) + ->condition('entity_id', $entity->id()) + ->condition('entity_type', $entity->getEntityTypeId()) + ->execute() + ->fetchCol(); + entity_delete_multiple('comment', $cids); + db_delete('comment_entity_statistics') + ->condition('entity_id', $entity->id()) + ->condition('entity_type', $entity->getEntityTypeId()) + ->execute(); } /** diff --git a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php index b0c7cbe..f46a606 100644 --- a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php +++ b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php @@ -174,7 +174,7 @@ public function overviewBundles() { } $build['overview'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => $this->t('No comment forms available.'), diff --git a/core/modules/comment/lib/Drupal/comment/Form/CommentAdminOverview.php b/core/modules/comment/lib/Drupal/comment/Form/CommentAdminOverview.php index e2ce52a..5fed1db 100644 --- a/core/modules/comment/lib/Drupal/comment/Form/CommentAdminOverview.php +++ b/core/modules/comment/lib/Drupal/comment/Form/CommentAdminOverview.php @@ -13,6 +13,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Datetime\Date; use Drupal\Core\Entity\EntityManager; +use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -37,6 +38,13 @@ class CommentAdminOverview extends FormBase { protected $commentStorage; /** + * The entity query service. + * + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $entityQuery; + + /** * Date service object. * * @var \Drupal\Core\Datetime\Date @@ -57,14 +65,17 @@ class CommentAdminOverview extends FormBase { * The entity manager service. * @param \Drupal\comment\CommentStorageControllerInterface $comment_storage * The comment storage. + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query + * The entity query service. * @param \Drupal\Core\Datetime\Date $date * The date service. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. */ - public function __construct(EntityManager $entity_manager, CommentStorageControllerInterface $comment_storage, Date $date, ModuleHandlerInterface $module_handler) { + public function __construct(EntityManager $entity_manager, CommentStorageControllerInterface $comment_storage, QueryFactory $entity_query, Date $date, ModuleHandlerInterface $module_handler) { $this->entityManager = $entity_manager; $this->commentStorage = $comment_storage; + $this->entityQuery = $entity_query; $this->date = $date; $this->moduleHandler = $module_handler; } @@ -76,6 +87,7 @@ public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), $container->get('entity.manager')->getStorageController('comment'), + $container->get('entity.query'), $container->get('date'), $container->get('module_handler') ); @@ -155,7 +167,7 @@ public function buildForm(array $form, array &$form_state, $type = 'new') { ), 'operations' => $this->t('Operations'), ); - $cids = $this->commentStorage->getQuery() + $cids = $this->entityQuery->get('comment') ->condition('status', $status) ->tableSort($header) ->pager(50) diff --git a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php index 18f6287..ee5cd4a 100644 --- a/core/modules/config/lib/Drupal/config/Controller/ConfigController.php +++ b/core/modules/config/lib/Drupal/config/Controller/ConfigController.php @@ -115,7 +115,7 @@ public function diff($config_file) { $build['#attached']['css'][] = drupal_get_path('module', 'system') . '/css/system.diff.css'; $build['diff'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => array( array('data' => t('Old'), 'colspan' => '2'), array('data' => t('New'), 'colspan' => '2'), diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSync.php b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php index c600001..22ac55f 100644 --- a/core/modules/config/lib/Drupal/config/Form/ConfigSync.php +++ b/core/modules/config/lib/Drupal/config/Form/ConfigSync.php @@ -136,7 +136,7 @@ public function buildForm(array $form, array &$form_state) { $storage_comparer = new StorageComparer($this->sourceStorage, $this->targetStorage); if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) { $form['no_changes'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => array('Name', 'Operations'), '#rows' => array(), '#empty' => $this->t('There are no configuration changes.'), @@ -182,7 +182,7 @@ public function buildForm(array $form, array &$form_state) { break; } $form[$config_change_type]['list'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => array('Name', 'Operations'), ); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php index 7ec5e86..55ded74 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php @@ -97,4 +97,14 @@ public function testStorageControllerMethods() { } } + /** + * Tests getOriginalId() and setOriginalId(). + */ + protected function testGetOriginalId() { + $entity = $this->storage->create(array()); + $id = $this->randomName(); + $this->assertIdentical(spl_object_hash($entity->setOriginalId($id)), spl_object_hash($entity)); + $this->assertIdentical($entity->getOriginalId(), $id); + } + } diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php index 8074ab3..029a7ac 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php @@ -9,7 +9,6 @@ use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\config_test\ConfigTestInterface; -use Drupal\Core\Config\Entity\ConfigEntityInterface; /** * Defines the ConfigTest configuration entity. @@ -94,7 +93,7 @@ public function getExportProperties() { /** * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::sort(). */ - public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { + public static function sort($a, $b) { \Drupal::state()->set('config_entity_sort', TRUE); return parent::sort($a, $b); } diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php index 14f9724..8b7f63f 100644 --- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php +++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationMapperList.php @@ -53,7 +53,7 @@ public static function create(ContainerInterface $container) { */ public function render() { $build = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $this->buildHeader(), '#rows' => array(), ); diff --git a/core/modules/content_translation/content_translation.pages.inc b/core/modules/content_translation/content_translation.pages.inc index ac36ff7..bed50a0 100644 --- a/core/modules/content_translation/content_translation.pages.inc +++ b/core/modules/content_translation/content_translation.pages.inc @@ -136,7 +136,7 @@ function content_translation_overview(EntityInterface $entity) { $build['#entity'] = $entity; $build['content_translation_overview'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php index 76b4cb9..94ff1ae 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php +++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php @@ -323,7 +323,7 @@ function testDefaultValue() { // Check if default_date has been stored successfully. $config_entity = $this->container->get('config.factory')->get('field.instance.node.date_content.' . $field->name)->get(); - $this->assertEqual($config_entity['default_value'][0]['default_date'], 'now', 'Default value has been stored successfully'); + $this->assertEqual($config_entity['default_value'][0]['default_date'], 'now', 'Default value has been stored succesfully'); // Clean field_info cache in order to avoid stale cache values. field_info_cache_clear(); @@ -345,7 +345,7 @@ function testDefaultValue() { // Check if default_date has been stored successfully. $config_entity = $this->container->get('config.factory')->get('field.instance.node.date_content.' . $field->name)->get(); - $this->assertTrue(empty($config_entity['default_value']), 'Empty default value has been stored successfully'); + $this->assertTrue(empty($config_entity['default_value']), 'Empty default value has been stored succesfully'); // Clean field_info cache in order to avoid stale cache values. field_info_cache_clear(); diff --git a/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php b/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php index d891bfe..9728f35 100644 --- a/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php +++ b/core/modules/dblog/lib/Drupal/dblog/Controller/DbLogController.php @@ -205,7 +205,7 @@ public function overview() { } $build['dblog_table'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#attributes' => array('id' => 'admin-dblog', 'class' => array('admin-dblog')), @@ -280,7 +280,7 @@ public function eventDetails($event_id) { ), ); $build['dblog_table'] = array( - '#type' => 'table', + '#theme' => 'table', '#rows' => $rows, '#attributes' => array('class' => array('dblog-event')), ); @@ -379,7 +379,7 @@ public function topLogMessages($type) { } $build['dblog_top_table'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => $this->t('No log messages available.'), diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php index d07030a..6705f03 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php @@ -8,7 +8,6 @@ namespace Drupal\entity; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Core\Config\Entity\ConfigEntityInterface; /** * Base class for config entity types that hold settings for form and view modes. @@ -61,9 +60,7 @@ /** * {@inheritdoc} */ - public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { - /** @var \Drupal\entity\EntityDisplayModeInterface $a */ - /** @var \Drupal\entity\EntityDisplayModeInterface $b */ + public static function sort($a, $b) { // Sort by the type of entity the view mode is used for. $a_type = $a->getTargetType(); $b_type = $b->getTargetType(); diff --git a/core/modules/field/lib/Drupal/field/FieldConfigStorageController.php b/core/modules/field/lib/Drupal/field/FieldConfigStorageController.php index 7fb0866..f6d8759 100644 --- a/core/modules/field/lib/Drupal/field/FieldConfigStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldConfigStorageController.php @@ -54,6 +54,8 @@ class FieldConfigStorageController extends ConfigStorageController { * The config factory service. * @param \Drupal\Core\Config\StorageInterface $config_storage * The config storage service. + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query_factory + * The entity query factory. * @param \Drupal\Component\Uuid\UuidInterface $uuid_service * The UUID service. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager @@ -63,8 +65,8 @@ class FieldConfigStorageController extends ConfigStorageController { * @param \Drupal\Core\KeyValueStore\StateInterface $state * The state key value store. */ - public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state) { - parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service); + public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, ModuleHandler $module_handler, StateInterface $state) { + parent::__construct($entity_type, $config_factory, $config_storage, $entity_query_factory, $uuid_service); $this->entityManager = $entity_manager; $this->moduleHandler = $module_handler; $this->state = $state; @@ -78,6 +80,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $entity_type, $container->get('config.factory'), $container->get('config.storage'), + $container->get('entity.query'), $container->get('uuid'), $container->get('entity.manager'), $container->get('module_handler'), diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceConfigStorageController.php b/core/modules/field/lib/Drupal/field/FieldInstanceConfigStorageController.php index d18fbf3..1251b5e 100644 --- a/core/modules/field/lib/Drupal/field/FieldInstanceConfigStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldInstanceConfigStorageController.php @@ -52,6 +52,8 @@ class FieldInstanceConfigStorageController extends ConfigStorageController { * The config factory service. * @param \Drupal\Core\Config\StorageInterface $config_storage * The config storage service. + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query_factory + * The entity query factory. * @param \Drupal\Component\Uuid\UuidInterface $uuid_service * The UUID service. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager @@ -59,8 +61,8 @@ class FieldInstanceConfigStorageController extends ConfigStorageController { * @param \Drupal\Core\KeyValueStore\StateInterface $state * The state key value store. */ - public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, StateInterface $state) { - parent::__construct($entity_type, $config_factory, $config_storage, $uuid_service); + public function __construct(EntityTypeInterface $entity_type, ConfigFactoryInterface $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service, EntityManagerInterface $entity_manager, StateInterface $state) { + parent::__construct($entity_type, $config_factory, $config_storage, $entity_query_factory, $uuid_service); $this->entityManager = $entity_manager; $this->state = $state; } @@ -73,6 +75,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI $entity_type, $container->get('config.factory'), $container->get('config.storage'), + $container->get('entity.query'), $container->get('uuid'), $container->get('entity.manager'), $container->get('state') diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index a08593a..4279bb3 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -237,7 +237,7 @@ function field_ui_view_mode_delete(EntityViewModeInterface $view_mode) { */ function theme_field_ui_table($variables) { $elements = $variables['elements']; - $table = array('#type' => 'table'); + $table = array('#theme' => 'table'); // Add table headers and attributes. foreach (array('#header', '#attributes') as $key) { diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc index a3c7140..ee80560 100644 --- a/core/modules/file/file.field.inc +++ b/core/modules/file/file.field.inc @@ -271,7 +271,7 @@ function theme_file_formatter_table($variables) { } $build = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php index f94037a..dcb931c 100644 --- a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php +++ b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterHtml.php @@ -152,7 +152,7 @@ public function tips($long = FALSE) { } } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); @@ -177,7 +177,7 @@ public function tips($long = FALSE) { ); } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc index 1f43cf8..a883bc2 100644 --- a/core/modules/image/image.admin.inc +++ b/core/modules/image/image.admin.inc @@ -192,7 +192,7 @@ function theme_image_anchor($variables) { } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => array(), '#rows' => $rows, '#attributes' => array('class' => array('image-anchor')), diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index b506136..8fefe3d 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -140,7 +140,7 @@ function theme_language_negotiation_configure_browser_form_table($variables) { ); $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#attributes' => array('id' => 'lang-neg-browser'), @@ -292,7 +292,7 @@ function template_preprocess_language_content_settings_table(&$variables) { '#title' => $element['#title'], '#header' => $header, '#rows' => $rows, - '#type' => 'table', + '#theme' => 'table', ); } diff --git a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php index e9aff29..93d37ea 100644 --- a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php +++ b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\link\Plugin\Field\FieldType\LinkItem. + * Contains \Drupal\email\Plugin\Field\FieldType\LinkItem. */ namespace Drupal\link\Plugin\Field\FieldType; diff --git a/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php b/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php index fb41d01..423aebe 100644 --- a/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php +++ b/core/modules/locale/lib/Drupal/locale/Form/TranslateEditForm.php @@ -34,6 +34,10 @@ public function buildForm(array $form, array &$form_state) { $langname = isset($langcode) ? $languages[$langcode]->name : "- None -"; + $path = drupal_get_path('module', 'locale'); + $form['#attached']['css'] = array( + $path . '/css/locale.admin.css', + ); $form['#attached']['library'][] = 'locale/drupal.locale.admin'; $form['langcode'] = array( diff --git a/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php b/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php index 213935a..2fd6ad6 100644 --- a/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php +++ b/core/modules/locale/lib/Drupal/locale/Form/TranslateFilterForm.php @@ -26,7 +26,9 @@ public function buildForm(array $form, array &$form_state) { $filters = $this->translateFilters(); $filter_values = $this->translateFilterValues(); - $form['#attached']['library'][] = 'locale/drupal.locale.admin'; + $form['#attached']['css'] = array( + drupal_get_path('module', 'locale') . '/css/locale.admin.css', + ); $form['filters'] = array( '#type' => 'details', diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php index c0ceb05..d77fdc2 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php @@ -121,9 +121,9 @@ function testExportTranslation() { * Test exportation of translation template file. */ function testExportTranslationTemplateFile() { - // Load an admin page with JavaScript so _drupal_add_library() fires at - // least once and _locale_parse_js_file() gets to run at least once so that - // the locales_source table gets populated with something. + // Load an admin page with JavaScript so drupal_add_library() fires at least + // once and _locale_parse_js_file() gets to run at least once so that the + // locales_source table gets populated with something. $this->drupalGet('admin/config/regional/language'); // Get the translation template file. $this->drupalPostForm('admin/config/regional/translate/export', array(), t('Export')); diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php index 1bf1373..30e0c8d 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php @@ -36,8 +36,7 @@ public static function getInfo() { * @see locale_library_info_alter() */ public function testLibraryInfoAlter() { - $attached['#attached']['library'][] = 'core/jquery.ui.datepicker'; - drupal_render($attached); + drupal_add_library('core/jquery.ui.datepicker'); $scripts = drupal_get_js(); $this->assertTrue(strpos($scripts, 'locale.datepicker.js'), 'locale.datepicker.js added to scripts.'); } diff --git a/core/modules/locale/locale.libraries.yml b/core/modules/locale/locale.libraries.yml index 69efb02..230f182 100644 --- a/core/modules/locale/locale.libraries.yml +++ b/core/modules/locale/locale.libraries.yml @@ -2,9 +2,6 @@ drupal.locale.admin: version: VERSION js: locale.admin.js: {} - css: - component: - css/locale.admin.css: {} dependencies: - core/jquery - core/drupal diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc index 7ab9ce0..73125fd 100644 --- a/core/modules/locale/locale.pages.inc +++ b/core/modules/locale/locale.pages.inc @@ -162,6 +162,7 @@ function locale_translation_status_form($form, &$form_state) { ); $form['#attached']['library'][] = 'locale/drupal.locale.admin'; + $form['#attached']['css'] = array(drupal_get_path('module', 'locale') . '/css/locale.admin.css'); $form['actions'] = array('#type' => 'actions'); if ($languages_update) { @@ -297,7 +298,7 @@ function theme_locale_translate_edit_form_strings($variables) { ); } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No strings available.'), diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index 51a7241..ee9d0b8 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -166,7 +166,7 @@ public function updateParentalStatus(EntityInterface $entity, $exclude = FALSE) // If plid == 0, there is nothing to update. if ($entity->plid) { // Check if at least one visible child exists in the table. - $query = $this->getQuery(); + $query = \Drupal::entityQuery($this->entityTypeId); $query ->condition('menu_name', $entity->menu_name) ->condition('hidden', 0) @@ -259,7 +259,7 @@ public function moveChildren(EntityInterface $entity) { * {@inheritdoc} */ public function countMenuLinks($menu_name) { - $query = $this->getQuery(); + $query = \Drupal::entityQuery($this->entityTypeId); $query ->condition('menu_name', $menu_name) ->count(); @@ -275,7 +275,7 @@ public function getParentFromHierarchy(EntityInterface $entity) { $parent = FALSE; $parent_path = substr($parent_path, 0, strrpos($parent_path, '/')); - $query = $this->getQuery(); + $query = \Drupal::entityQuery($this->entityTypeId); $query ->condition('mlid', $entity->id(), '<>') ->condition('module', 'system') diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index d562e51..24fa5b9 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -114,7 +114,7 @@ public function form(array $form, array &$form_state) { 'class' => array('node-form-revision-information'), ), '#attached' => array( - 'library' => array('node/drupal.node'), + 'js' => array(drupal_get_path('module', 'node') . '/node.js'), ), '#weight' => 20, '#optional' => TRUE, @@ -152,8 +152,8 @@ public function form(array $form, array &$form_state) { 'class' => array('node-form-author'), ), '#attached' => array( - 'library' => array('node/drupal.node'), 'js' => array( + drupal_get_path('module', 'node') . '/node.js', array( 'type' => 'setting', 'data' => array('anonymous' => $user_config->get('anonymous')), @@ -194,7 +194,7 @@ public function form(array $form, array &$form_state) { 'class' => array('node-form-options'), ), '#attached' => array( - 'library' => array('node/drupal.node'), + 'js' => array(drupal_get_path('module', 'node') . '/node.js'), ), '#weight' => 95, '#optional' => TRUE, diff --git a/core/modules/node/node.module b/core/modules/node/node.module index c97851e..74dc548 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -898,7 +898,7 @@ function theme_node_search_admin($variables) { $rows[] = $row; } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc index fe5b0c1..99f4024 100644 --- a/core/modules/node/node.pages.inc +++ b/core/modules/node/node.pages.inc @@ -175,7 +175,7 @@ function node_revision_overview($node) { } $build['node_revisions_table'] = array( - '#type' => 'table', + '#theme' => 'table', '#rows' => $rows, '#header' => $header, '#attached' => array ( diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml index 4efc395..84b9a57 100644 --- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_row_plugin.yml @@ -42,14 +42,14 @@ display: display_plugin: default display_title: Master id: default - position: 0 + position: { } page_1: display_options: path: test-node-row-plugin display_plugin: page display_title: Page id: page_1 - position: 0 + position: { } label: test_node_row_plugin langcode: en module: views diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc index d22fe66..a2b2072 100644 --- a/core/modules/path/path.admin.inc +++ b/core/modules/path/path.admin.inc @@ -89,7 +89,7 @@ function path_admin_overview($keys = NULL) { } $build['path_table'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No URL aliases available. Add URL alias.', array('@link' => url('admin/config/search/path/add'))), diff --git a/core/modules/search/lib/Drupal/search/Entity/SearchPage.php b/core/modules/search/lib/Drupal/search/Entity/SearchPage.php index 947c878..36444e0 100644 --- a/core/modules/search/lib/Drupal/search/Entity/SearchPage.php +++ b/core/modules/search/lib/Drupal/search/Entity/SearchPage.php @@ -8,7 +8,6 @@ namespace Drupal\search\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Config\Entity\EntityWithPluginBagInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Component\Plugin\ConfigurablePluginInterface; @@ -214,7 +213,7 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont /** * {@inheritdoc} */ - public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { + public static function sort($a, $b) { /** @var $a \Drupal\search\SearchPageInterface */ /** @var $b \Drupal\search\SearchPageInterface */ $a_status = (int) $a->status(); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php index d3f6a4c..bfc9b8c 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/Form/SimpletestResultsForm.php @@ -172,7 +172,7 @@ public function buildForm(array $form, array &$form_state, $test_id = NULL) { $form['result']['summary']['#' . $assertion->status]++; } $form['result']['results'][$group]['table'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, ); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 30a6280..0814697 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -237,6 +237,7 @@ function drupalGetNodeByTitle($title, $reset = FALSE) { * @endcode * - title: Random string. * - comment: CommentItemInterface::OPEN. + * - changed: REQUEST_TIME. * - promote: NODE_NOT_PROMOTED. * - log: Empty string. * - status: NODE_PUBLISHED. @@ -255,6 +256,7 @@ protected function drupalCreateNode(array $settings = array()) { $settings += array( 'body' => array(array()), 'title' => $this->randomName(8), + 'changed' => REQUEST_TIME, 'promote' => NODE_NOT_PROMOTED, 'revision' => 1, 'log' => '', diff --git a/core/modules/system/core.api.php b/core/modules/system/core.api.php deleted file mode 100644 index 5d131ce..0000000 --- a/core/modules/system/core.api.php +++ /dev/null @@ -1,324 +0,0 @@ -getType(); $b_type = $b->getType(); if ($a_type != $b_type) { diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php b/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php index ac94508..caae9f7 100644 --- a/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php +++ b/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php @@ -14,6 +14,7 @@ use Drupal\Core\Language\Language; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Entity\EntityFormController; /** @@ -29,6 +30,13 @@ protected $patternType; /** + * The entity query factory. + * + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $queryFactory; + + /** * The date service. * * @var \Drupal\Core\Datetime\Date @@ -45,15 +53,18 @@ /** * Constructs a new date format form. * + * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory + * The entity query factory. * @param \Drupal\Core\Datetime\Date $date_service * The date service. * @param \Drupal\Core\Config\Entity\ConfigStorageControllerInterface $date_format_storage * The date format storage controller. */ - public function __construct(Date $date_service, ConfigStorageControllerInterface $date_format_storage) { + public function __construct(QueryFactory $query_factory, Date $date_service, ConfigStorageControllerInterface $date_format_storage) { $date = new DrupalDateTime(); $this->patternType = $date->canUseIntl() ? DrupalDateTime::INTL : DrupalDateTime::PHP; + $this->queryFactory = $query_factory; $this->dateService = $date_service; $this->dateFormatStorage = $date_format_storage; } @@ -63,6 +74,7 @@ public function __construct(Date $date_service, ConfigStorageControllerInterface */ public static function create(ContainerInterface $container) { return new static( + $container->get('entity.query'), $container->get('date'), $container->get('entity.manager')->getStorageController('date_format') ); @@ -82,8 +94,8 @@ public static function create(ContainerInterface $container) { * TRUE if this format already exists, FALSE otherwise. */ public function exists($entity_id, array $element, array $form_state) { - return (bool) $this->dateFormatStorage - ->getQuery() + return (bool) $this->queryFactory + ->get($this->entity->getEntityTypeId()) ->condition('id', $element['#field_prefix'] . $entity_id) ->execute(); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php index 4c282d8..bdb0910 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php @@ -47,8 +47,9 @@ function setUp() { $config->set('js.preprocess', 0); $config->save(); - // Reset _drupal_add_js() statics before each test. + // Reset _drupal_add_js() and drupal_add_library() statics before each test. drupal_static_reset('_drupal_add_js'); + drupal_static_reset('drupal_add_library'); } function tearDown() { @@ -70,9 +71,7 @@ function testDefault() { * Tests adding a JavaScript file. */ function testAddFile() { - $attached['#attached']['js']['core/misc/collapse.js'] = array(); - drupal_render($attached); - $javascript = _drupal_add_js(); + $javascript = _drupal_add_js('core/misc/collapse.js'); $this->assertTrue(array_key_exists('core/misc/collapse.js', $javascript), 'JavaScript files are correctly added.'); } @@ -81,8 +80,7 @@ function testAddFile() { */ function testAddSetting() { // Add a file in order to test default settings. - $attached['#attached']['library'][] = 'core/drupalSettings'; - drupal_render($attached); + drupal_add_library('core/drupalSettings'); $javascript = _drupal_add_js(); $last_settings = reset($javascript['settings']['data']); $this->assertTrue(array_key_exists('currentPath', $last_settings['path']), 'The current path JavaScript setting is set correctly.'); @@ -97,9 +95,8 @@ function testAddSetting() { * Tests adding an external JavaScript File. */ function testAddExternal() { - $attached['#attached']['js']['http://example.com/script.js'] = array('type' => 'external'); - drupal_render($attached); - $javascript = _drupal_add_js(); + $path = 'http://example.com/script.js'; + $javascript = _drupal_add_js($path, 'external'); $this->assertTrue(array_key_exists('http://example.com/script.js', $javascript), 'Added an external JavaScript file.'); } @@ -109,18 +106,12 @@ function testAddExternal() { function testAttributes() { $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0'; - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['http://example.com/script.js'] = array( - 'type' => 'external', - 'attributes' => array('defer' => 'defer'), - ); - $attached['#attached']['js']['core/misc/collapse.js'] = array( - 'attributes' => array('defer' => 'defer'), - ); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer'))); + _drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer'))); $javascript = drupal_get_js(); - $expected_1 = ''; + $expected_1 = ''; $expected_2 = ''; $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute.'); @@ -136,18 +127,12 @@ function testAggregatedAttributes() { $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0'; - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['http://example.com/script.js'] = array( - 'type' => 'external', - 'attributes' => array('defer' => 'defer'), - ); - $attached['#attached']['js']['core/misc/collapse.js'] = array( - 'attributes' => array('defer' => 'defer'), - ); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer'))); + _drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer'))); $javascript = drupal_get_js(); - $expected_1 = ''; + $expected_1 = ''; $expected_2 = ''; $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute with aggregation enabled.'); @@ -158,9 +143,7 @@ function testAggregatedAttributes() { * Tests drupal_get_js() for JavaScript settings. */ function testHeaderSetting() { - $attached = array(); - $attached['#attached']['library'][] = 'core/drupalSettings'; - drupal_render($attached); + drupal_add_library('core/drupalSettings'); $javascript = drupal_get_js('header'); $this->assertTrue(strpos($javascript, 'basePath') > 0, 'Rendered JavaScript header returns basePath setting.'); @@ -169,57 +152,25 @@ function testHeaderSetting() { $this->assertTrue(strpos($javascript, 'currentPath') > 0, 'Rendered JavaScript header returns currentPath setting.'); // Only the second of these two entries should appear in drupalSettings. - $attached = array(); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTest' => 'commonTestShouldNotAppear'), - ); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTest' => 'commonTestShouldAppear'), - ); + _drupal_add_js(array('commonTest' => 'commonTestShouldNotAppear'), 'setting'); + _drupal_add_js(array('commonTest' => 'commonTestShouldAppear'), 'setting'); // Only the second of these entries should appear in drupalSettings. - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralOldValue')), - ); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralNewValue')), - ); + _drupal_add_js(array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralOldValue')), 'setting'); + _drupal_add_js(array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralNewValue')), 'setting'); // Only the second of these two entries should appear in drupalSettings. - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralOldValue')), - ); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralNewValue')), - ); + _drupal_add_js(array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralOldValue')), 'setting'); + _drupal_add_js(array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralNewValue')), 'setting'); // Real world test case: multiple elements in a render array are adding the // same (or nearly the same) JavaScript settings. When merged, they should // contain all settings and not duplicate some settings. $settings_one = array('moduleName' => array('ui' => array('button A', 'button B'), 'magical flag' => 3.14159265359)); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestRealWorldIdentical' => $settings_one), - ); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestRealWorldIdentical' => $settings_one), - ); + _drupal_add_js(array('commonTestRealWorldIdentical' => $settings_one), 'setting'); + _drupal_add_js(array('commonTestRealWorldIdentical' => $settings_one), 'setting'); $settings_two = array('moduleName' => array('ui' => array('button A', 'button B'), 'magical flag' => 3.14159265359, 'thingiesOnPage' => array('id1' => array()))); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestRealWorldAlmostIdentical' => $settings_two), - ); + _drupal_add_js(array('commonTestRealWorldAlmostIdentical' => $settings_two), 'setting'); $settings_two = array('moduleName' => array('ui' => array('button C', 'button D'), 'magical flag' => 3.14, 'thingiesOnPage' => array('id2' => array()))); - $attached['#attached']['js'][] = array( - 'type' => 'setting', - 'data' => array('commonTestRealWorldAlmostIdentical' => $settings_two), - ); + _drupal_add_js(array('commonTestRealWorldAlmostIdentical' => $settings_two), 'setting'); - drupal_render($attached); $javascript = drupal_get_js('header'); // Test whether _drupal_add_js can be used to override a previous setting. @@ -254,9 +205,8 @@ function testHeaderSetting() { * Tests to see if resetting the JavaScript empties the cache. */ function testReset() { - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/collapse.js'] = array(); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('core/misc/collapse.js'); drupal_static_reset('_drupal_add_js'); $this->assertEqual(array(), _drupal_add_js(), 'Resetting the JavaScript correctly empties the cache.'); } @@ -265,15 +215,9 @@ function testReset() { * Tests adding inline scripts. */ function testAddInline() { + drupal_add_library('core/jquery'); $inline = 'jQuery(function () { });'; - $attached['#attached']['library'][] = 'core/jquery'; - $attached['#attached']['js'][] = array( - 'type' => 'inline', - 'data' => $inline, - 'attributes' => array('defer' => 'defer'), - ); - drupal_render($attached); - $javascript = _drupal_add_js(); + $javascript = _drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer')); $this->assertTrue(array_key_exists('core/assets/vendor/jquery/jquery.js', $javascript), 'jQuery is added when inline scripts are added.'); $data = end($javascript); $this->assertEqual($inline, $data['data'], 'Inline JavaScript is correctly added to the footer.'); @@ -283,14 +227,9 @@ function testAddInline() { * Tests rendering an external JavaScript file. */ function testRenderExternal() { + drupal_add_library('core/drupal'); $external = 'http://example.com/example.js'; - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js'][] = array( - 'type' => 'external', - 'data' => $external, - ); - drupal_render($attached); - + _drupal_add_js($external, 'external'); $javascript = drupal_get_js(); // Local files have a base_path() prefix, external files should not. $this->assertTrue(strpos($javascript, 'src="' . $external) > 0, 'Rendering an external JavaScript file.'); @@ -300,16 +239,9 @@ function testRenderExternal() { * Tests drupal_get_js() with a footer scope. */ function testFooterHTML() { + drupal_add_library('core/drupal'); $inline = 'jQuery(function () { });'; - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js'][] = array( - 'type' => 'inline', - 'data' => $inline, - 'scope' => 'footer', - 'attributes' => array('defer' => 'defer'), - ); - drupal_render($attached); - + _drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer')); $javascript = drupal_get_js('footer'); $this->assertTrue(strpos($javascript, $inline) > 0, 'Rendered JavaScript footer returns the inline code.'); } @@ -318,10 +250,8 @@ function testFooterHTML() { * Tests _drupal_add_js() sets preproccess to FALSE when cache is also FALSE. */ function testNoCache() { - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/collapse.js'] = array('cache' => FALSE); - drupal_render($attached); - $javascript = _drupal_add_js(); + drupal_add_library('core/drupal'); + $javascript = _drupal_add_js('core/misc/collapse.js', array('cache' => FALSE)); $this->assertFalse($javascript['core/misc/collapse.js']['preprocess'], 'Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.'); } @@ -329,10 +259,8 @@ function testNoCache() { * Tests adding a JavaScript file with a different group. */ function testDifferentGroup() { - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/collapse.js'] = array('group' => JS_THEME); - drupal_render($attached); - $javascript = _drupal_add_js(); + drupal_add_library('core/drupal'); + $javascript = _drupal_add_js('core/misc/collapse.js', array('group' => JS_THEME)); $this->assertEqual($javascript['core/misc/collapse.js']['group'], JS_THEME, 'Adding a JavaScript file with a different group caches the given group.'); } @@ -340,9 +268,7 @@ function testDifferentGroup() { * Tests adding a JavaScript file with a different weight. */ function testDifferentWeight() { - $attached['#attached']['js']['core/misc/collapse.js'] = array('weight' => 2); - drupal_render($attached); - $javascript = _drupal_add_js(); + $javascript = _drupal_add_js('core/misc/collapse.js', array('weight' => 2)); $this->assertEqual($javascript['core/misc/collapse.js']['weight'], 2, 'Adding a JavaScript file with a different weight caches the given weight.'); } @@ -354,16 +280,9 @@ function testDifferentWeight() { function testBrowserConditionalComments() { $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0'; - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/collapse.js'] = array( - 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE), - ); - $attached['#attached']['js'][] = array( - 'type' => 'inline', - 'data' => 'jQuery(function () { });', - 'browsers' => array('IE' => FALSE), - ); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('core/misc/collapse.js', array('browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE))); + _drupal_add_js('jQuery(function () { });', array('type' => 'inline', 'browsers' => array('IE' => FALSE))); $javascript = drupal_get_js(); $expected_1 = ""; @@ -377,10 +296,9 @@ function testBrowserConditionalComments() { * Tests JavaScript versioning. */ function testVersionQueryString() { - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/collapse.js'] = array('version' => 'foo'); - $attached['#attached']['js']['core/misc/ajax.js'] = array('version' => 'bar'); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('core/misc/collapse.js', array('version' => 'foo')); + _drupal_add_js('core/misc/ajax.js', array('version' => 'bar')); $javascript = drupal_get_js(); $this->assertTrue(strpos($javascript, 'core/misc/collapse.js?v=foo') > 0 && strpos($javascript, 'core/misc/ajax.js?v=bar') > 0 , 'JavaScript version identifiers correctly appended to URLs'); } @@ -395,13 +313,11 @@ function testAggregation() { // ahead of ones without. The order of JavaScript execution must be the // same regardless of whether aggregation is enabled, so ensure this // expected order, first with aggregation off. - $attached = array(); - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/ajax.js'] = array(); - $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE); - $attached['#attached']['js']['core/misc/autocomplete.js'] = array(); - $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('core/misc/ajax.js'); + _drupal_add_js('core/misc/collapse.js', array('every_page' => TRUE)); + _drupal_add_js('core/misc/autocomplete.js'); + _drupal_add_js('core/misc/batch.js', array('every_page' => TRUE)); $javascript = drupal_get_js(); $expected = implode("\n", array( '', @@ -417,13 +333,11 @@ function testAggregation() { $config = \Drupal::config('system.performance'); $config->set('js.preprocess', 1); $config->save(); - $attached = array(); - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/ajax.js'] = array(); - $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE); - $attached['#attached']['js']['core/misc/autocomplete.js'] = array(); - $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('core/misc/ajax.js'); + _drupal_add_js('core/misc/collapse.js', array('every_page' => TRUE)); + _drupal_add_js('core/misc/autocomplete.js'); + _drupal_add_js('core/misc/batch.js', array('every_page' => TRUE)); $js_items = _drupal_add_js(); $javascript = drupal_get_js(); $expected = implode("\n", array( @@ -442,11 +356,9 @@ function testAggregationOrder() { drupal_static_reset('_drupal_add_js'); // Add two JavaScript files to the current request and build the cache. - $attached = array(); - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['core/misc/ajax.js'] = array(); - $attached['#attached']['js']['core/misc/autocomplete.js'] = array(); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('core/misc/ajax.js'); + _drupal_add_js('core/misc/autocomplete.js'); $js_items = _drupal_add_js(); $scripts_html = array( @@ -465,12 +377,10 @@ function testAggregationOrder() { // Reset variables and add a file in a different scope first. \Drupal::state()->delete('system.js_cache_files'); drupal_static_reset('_drupal_add_js'); - $attached = array(); - $attached['#attached']['library'][] = 'core/drupal'; - $attached['#attached']['js']['some/custom/javascript_file.js'] = array('scope' => 'footer'); - $attached['#attached']['js']['core/misc/ajax.js'] = array(); - $attached['#attached']['js']['core/misc/autocomplete.js'] = array(); - drupal_render($attached); + drupal_add_library('core/drupal'); + _drupal_add_js('some/custom/javascript_file.js', array('scope' => 'footer')); + _drupal_add_js('core/misc/ajax.js'); + _drupal_add_js('core/misc/autocomplete.js'); // Rebuild the cache. $js_items = _drupal_add_js(); @@ -493,50 +403,17 @@ function testAggregationOrder() { * Tests JavaScript ordering. */ function testRenderOrder() { - $shared_options = array( - 'type' => 'inline', - 'scope' => 'footer', - ); // Add a bunch of JavaScript in strange ordering. - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight 5 #1");})(jQuery);', - 'weight' => 5, - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight 0 #1");})(jQuery);', - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight 0 #2");})(jQuery);', - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight -8 #1");})(jQuery);', - 'weight' => -8, - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight -8 #2");})(jQuery);', - 'weight' => -8, - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight -8 #3");})(jQuery);', - 'weight' => -8, - ); - $attached['#attached']['js']['http://example.com/example.js?Weight -5 #1'] = array( - 'type' => 'external', - 'scope' => 'footer', - 'weight' => -5, - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight -8 #4");})(jQuery);', - 'weight' => -8, - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight 5 #2");})(jQuery);', - 'weight' => 5, - ); - $attached['#attached']['js'][] = $shared_options + array( - 'data' => '(function($){alert("Weight 0 #3");})(jQuery);', - ); - drupal_render($attached); + _drupal_add_js('(function($){alert("Weight 5 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5)); + _drupal_add_js('(function($){alert("Weight 0 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer')); + _drupal_add_js('(function($){alert("Weight 0 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer')); + _drupal_add_js('(function($){alert("Weight -8 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8)); + _drupal_add_js('(function($){alert("Weight -8 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8)); + _drupal_add_js('(function($){alert("Weight -8 #3");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8)); + _drupal_add_js('http://example.com/example.js?Weight -5 #1', array('type' => 'external', 'scope' => 'footer', 'weight' => -5)); + _drupal_add_js('(function($){alert("Weight -8 #4");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8)); + _drupal_add_js('(function($){alert("Weight 5 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5)); + _drupal_add_js('(function($){alert("Weight 0 #3");})(jQuery);', array('type' => 'inline', 'scope' => 'footer')); // Construct the expected result from the regex. $expected = array( @@ -571,13 +448,8 @@ function testRenderDifferentWeight() { // JavaScript files are sorted first by group, then by the 'every_page' // flag, then by weight (see drupal_sort_css_js()), so to test the effect of // weight, we need the other two options to be the same. - $attached['#attached']['library'][] = 'core/jquery'; - $attached['#attached']['js']['core/misc/collapse.js'] = array( - 'group' => JS_LIBRARY, - 'every_page' => TRUE, - 'weight' => -21, - ); - drupal_render($attached); + drupal_add_library('core/jquery'); + _drupal_add_js('core/misc/collapse.js', array('group' => JS_LIBRARY, 'every_page' => TRUE, 'weight' => -21)); $javascript = drupal_get_js(); $this->assertTrue(strpos($javascript, 'core/misc/collapse.js') < strpos($javascript, 'core/assets/vendor/jquery/jquery.js'), 'Rendering a JavaScript file above jQuery.'); } @@ -589,9 +461,8 @@ function testRenderDifferentWeight() { */ function testAlter() { // Add both tableselect.js and simpletest.js, with a larger weight on SimpleTest. - $attached['#attached']['js']['core/misc/tableselect.js'] = array(); - $attached['#attached']['js'][drupal_get_path('module', 'simpletest') . '/simpletest.js'] = array('weight' => 9999); - drupal_render($attached); + _drupal_add_js('core/misc/tableselect.js'); + _drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => 9999)); // Render the JavaScript, testing if simpletest.js was altered to be before // tableselect.js. See simpletest_js_alter() to see where this alteration @@ -604,9 +475,8 @@ function testAlter() { * Adds a library to the page and tests for both its JavaScript and its CSS. */ function testLibraryRender() { - $attached = array(); - $attached['#attached']['library'][] = 'core/jquery.farbtastic'; - drupal_render($attached); + $result = drupal_add_library('core/jquery.farbtastic'); + $this->assertTrue($result !== FALSE, 'Library was added without errors.'); $scripts = drupal_get_js(); $styles = drupal_get_css(); $this->assertTrue(strpos($scripts, 'core/assets/vendor/farbtastic/farbtastic.js'), 'JavaScript of library was added to the page.'); @@ -624,8 +494,7 @@ function testLibraryAlter() { $this->assertEqual($library['version'], '0.0', 'Registered libraries were altered.'); // common_test_library_info_alter() also added a dependency on jQuery Form. - $attached['#attached']['library'][] = 'core/jquery.farbtastic'; - drupal_render($attached); + drupal_add_library('core/jquery.farbtastic'); $scripts = drupal_get_js(); $this->assertTrue(strpos($scripts, 'core/assets/vendor/jquery-form/jquery.form.js'), 'Altered library dependencies are added to the page.'); } @@ -648,8 +517,8 @@ function testLibraryUnknown() { $this->assertFalse($result, 'Unknown library returned FALSE.'); drupal_static_reset('drupal_get_library'); - $attached['#attached']['library'][] = 'unknown/unknown'; - drupal_render($attached); + $result = drupal_add_library('unknown/unknown'); + $this->assertFalse($result, 'Unknown library returned FALSE.'); $scripts = drupal_get_js(); $this->assertTrue(strpos($scripts, 'unknown') === FALSE, 'Unknown library was not added to the page.'); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php index 001b807..daf2e77 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php @@ -161,6 +161,21 @@ function testMaintenancePage() { $html_attributes['dir'] = $language_interface->direction ? 'rtl' : 'ltr'; $site_config = \Drupal::config('system.site'); + $site_name = $site_config->get('name'); + $site_slogan = $site_config->get('slogan'); + if ($title = drupal_get_title()) { + $head_title = array( + 'title' => strip_tags($title), + 'name' => String::checkPlain($site_config->get('name')), + ); + } + else { + $head_title = array('name' => String::checkPlain($site_name)); + if ($site_slogan) { + $head_title['slogan'] = strip_tags(Xss::filterAdmin($site_slogan)); + } + } + $head_title = implode(' | ', $head_title); // Add favicon. $favicon = theme_get_setting('favicon.url'); @@ -214,14 +229,14 @@ function testMaintenancePage() { $placeholders = array( '!html_attributes' => $html_attributes->__toString(), '!head' => drupal_get_html_head(), - '!head_title' => $site_config->get('name'), + '!head_title' => $head_title, '!styles' => drupal_get_css($css), '!scripts' => drupal_get_js(), '!attributes.class' => 'maintenance-page in-maintenance no-sidebars', '!front_page' => url(), '!logo' => theme_get_setting('logo.url'), '!site_name' => $site_config->get('name'), - '!title' => '', + '!title' => $title ? '

' . $title . '

' : '', '!content' => 'foo', ); @@ -229,7 +244,6 @@ function testMaintenancePage() { drupal_static_reset(); // Test basic string for maintenance page content. - // No page title is set, so it should default to the site name. $elements = array( array( 'name' => "#theme 'maintenance_page' with content of foo", @@ -248,11 +262,6 @@ function testMaintenancePage() { drupal_static_reset(); $elements[0]['name'] = "#theme 'maintenance_page' with content as a render array"; $elements[0]['value']['#content'] = array('#markup' => 'foo'); - // Testing with a page title, which should be combined with the site name. - $title = t('A non-empty title'); - $elements[0]['value']['#page']['#title'] = $title; - $elements[0]['placeholders']['!title'] = '

' . $title . '

'; - $elements[0]['placeholders']['!head_title'] = strip_tags($title) . ' | ' . String::checkPlain($site_config->get('name')); $this->assertElements($elements); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php new file mode 100644 index 0000000..097c7bc --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php @@ -0,0 +1,55 @@ + 'Entity label', + 'description' => 'Tests entity labels.', + 'group' => 'Entity API', + ); + } + + /** + * Tests label key and label callback of an entity. + */ + function testEntityLabel() { + $entity_types = array( + 'entity_test_no_label', + 'entity_test_label', + 'entity_test_label_callback', + ); + + $values = array( + 'name' => $this->randomName(), + ); + foreach ($entity_types as $entity_type) { + $entity = entity_create($entity_type, $values); + $label = $entity->label(); + + switch ($entity_type) { + case 'entity_test_no_label': + $this->assertFalse($label, 'Entity with no label property or callback returned FALSE.'); + break; + + case 'entity_test_label': + $this->assertEqual($label, $entity->name->value, 'Entity with label key returned correct label.'); + break; + + case 'entity_test_label_callback': + $this->assertEqual($label, 'label callback ' . $entity->name->value, 'Entity with label callback returned correct label.'); + break; + } + } + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/TriggeringElementProgrammedUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/TriggeringElementProgrammedUnitTest.php deleted file mode 100644 index 72e57ec..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/Form/TriggeringElementProgrammedUnitTest.php +++ /dev/null @@ -1,97 +0,0 @@ - 'Form triggering element programmed determination', - 'description' => 'Tests detection of triggering_element for programmed form submissions.', - 'group' => 'Form API', - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'triggering_element_programmed_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, array &$form_state) { - $form['one'] = array( - '#type' => 'textfield', - '#title' => 'One', - '#required' => TRUE, - ); - $form['two'] = array( - '#type' => 'textfield', - '#title' => 'Two', - '#required' => TRUE, - ); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => 'Save', - '#limit_validation_errors' => array( - array($form_state['input']['section']), - ), - // Required for #limit_validation_errors. - '#submit' => array(array($this, 'submitForm')), - ); - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, array &$form_state) { - // Verify that the only submit button was recognized as triggering_element. - $this->assertEqual($form['actions']['submit']['#array_parents'], $form_state['triggering_element']['#array_parents']); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, array &$form_state) { - } - - /** - * Tests that #limit_validation_errors of the only submit button takes effect. - */ - function testLimitValidationErrors() { - // Programmatically submit the form. - $form_state['values'] = array(); - $form_state['values']['section'] = 'one'; - $form_builder = $this->container->get('form_builder'); - $form_builder->submitForm($this, $form_state); - - // Verify that only the specified section was validated. - $errors = $form_builder->getErrors($form_state); - $this->assertTrue(isset($errors['one']), "Section 'one' was validated."); - $this->assertFalse(isset($errors['two']), "Section 'two' was not validated."); - - // Verify that there are only values for the specified section. - $this->assertTrue(isset($form_state['values']['one']), "Values for section 'one' found."); - $this->assertFalse(isset($form_state['values']['two']), "Values for section 'two' not found."); - } - -} diff --git a/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php b/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php index fdc511a..33f2f47 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/PageTitleTest.php @@ -28,7 +28,7 @@ class PageTitleTest extends WebTestBase { public static function getInfo() { return array( 'name' => 'Page titles', - 'description' => 'Tests correct escaping of page title, site name and slogan.', + 'description' => 'Tests correct handling or conversion by drupal_set_title() and drupal_get_title() and checks the correct escaping of site name and slogan.', 'group' => 'System' ); } @@ -43,13 +43,32 @@ function setUp() { $this->content_user = $this->drupalCreateUser(array('create page content', 'access content', 'administer themes', 'administer site configuration')); $this->drupalLogin($this->content_user); + $this->saved_title = drupal_get_title(); } /** - * Tests the handling of HTML in node titles. + * Reset page title. + */ + function tearDown() { + // Restore the page title. + drupal_set_title($this->saved_title, PASS_THROUGH); + + parent::tearDown(); + } + + /** + * Tests the handling of HTML by drupal_set_title() and drupal_get_title() */ function testTitleTags() { $title = "string with HTML"; + // drupal_set_title's $filter is Title::CHECK_PLAIN by default, so the title should be + // returned with check_plain(). + drupal_set_title($title, Title::CHECK_PLAIN); + $this->assertTrue(strpos(drupal_get_title(), '') === FALSE, 'Tags in title converted to entities when $output is Title::CHECK_PLAIN.'); + // drupal_set_title's $filter is passed as PASS_THROUGH, so the title should be + // returned with HTML. + drupal_set_title($title, PASS_THROUGH); + $this->assertTrue(strpos(drupal_get_title(), '') !== FALSE, 'Tags in title are not converted to entities when $output is PASS_THROUGH.'); // Generate node content. $edit = array( 'title[0][value]' => '!SimpleTest! ' . $title . $this->randomName(20), @@ -63,7 +82,6 @@ function testTitleTags() { $this->drupalGet("node/" . $node->id()); $this->assertText(check_plain($edit['title[0][value]']), 'Check to make sure tags in the node title are converted.'); } - /** * Test if the title of the site is XSS proof. */ @@ -95,10 +113,9 @@ function testTitleXSS() { $this->drupalGet(''); // Test the title. - $this->assertNoRaw($title, 'Check for the lack of the unfiltered version of the title.'); - // Add to make sure we're checking the title tag, rather than the - // first 'heading' on the page. - $this->assertRaw($title_filtered . '', 'Check for the filtered version of the title in a tag.'); + $this->assertNoRaw($title, 'Check for the unfiltered version of the title.'); + // Adding so we do not test the escaped version from drupal_set_title(). + $this->assertRaw($title_filtered . '', 'Check for the filtered version of the title.'); // Test the slogan. $this->assertNoRaw($slogan, 'Check for the unfiltered version of the slogan.'); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index 75f1c60..5064e61e 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -83,6 +83,44 @@ function _system_is_incompatible(&$incompatible, $files, Extension $file) { } /** + * Returns HTML for an administrative block for display. + * + * @param $variables + * An associative array containing: + * - block: An array containing information about the block: + * - show: A Boolean whether to output the block. Defaults to FALSE. + * - title: The block's title. + * - content: (optional) Formatted content for the block. + * - description: (optional) Description of the block. Only output if + * 'content' is not set. + * + * @ingroup themeable + */ +function theme_admin_block($variables) { + $block = $variables['block']; + $output = ''; + + // Don't display the block if it has no content to display. + if (empty($block['show'])) { + return $output; + } + + $output .= '
'; + if (!empty($block['title'])) { + $output .= '

' . $block['title'] . '

'; + } + if (!empty($block['content'])) { + $output .= '
' . render($block['content']) . '
'; + } + else { + $output .= '
' . $block['description'] . '
'; + } + $output .= '
'; + + return $output; +} + +/** * Prepares variables for administrative content block templates. * * Default template: admin-block-content.html.twig. @@ -116,9 +154,7 @@ function template_preprocess_admin_block_content(&$variables) { } /** - * Prepares variables for administrative index page templates. - * - * Default template: admin-page.html.twig. + * Returns HTML for an administrative page. * * @param $variables * An associative array containing: @@ -129,24 +165,40 @@ function template_preprocess_admin_block_content(&$variables) { * * @ingroup themeable */ -function template_preprocess_admin_page(&$variables) { - $variables['system_compact_link'] = array( - '#theme' => 'system_compact_link', - ); - $variables['containers'] = array(); +function theme_admin_page($variables) { + $blocks = $variables['blocks']; + $stripe = 0; - foreach ($variables['blocks'] as $block) { - if (!empty($block['content']['#content'])) { + $container = array(); + + foreach ($blocks as $block) { + $admin_block = array( + '#theme' => 'admin_block', + '#block' => $block, + ); + if ($block_output = drupal_render($admin_block)) { if (empty($block['position'])) { - // Perform automatic striping. + // perform automatic striping. $block['position'] = ++$stripe % 2 ? 'left' : 'right'; } - $variables['containers'][$block['position']]['blocks'][] = array( - '#theme' => 'admin_block', - '#block' => $block, - ); + if (!isset($container[$block['position']])) { + $container[$block['position']] = ''; + } + $container[$block['position']] .= $block_output; } } + + $system_compact_link = array('#theme' => 'system_compact_link'); + $output = '
'; + $output .= drupal_render($system_compact_link); + + foreach ($container as $id => $data) { + $output .= '
'; + $output .= $data; + $output .= '
'; + } + $output .= '
'; + return $output; } /** @@ -179,6 +231,7 @@ function theme_system_admin_index($variables) { $block['title'] = $module; $block['content'] = drupal_render($admin_block_content); $block['description'] = t($description); + $block['show'] = TRUE; $admin_block = array( '#theme' => 'admin_block', @@ -342,7 +395,7 @@ function theme_system_modules_details($variables) { } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $form['#header'], '#rows' => $rows, ); @@ -406,7 +459,7 @@ function theme_system_modules_uninstall($variables) { } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No modules are available to uninstall.'), diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 8ae6c7c..2df7c2e 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -360,7 +360,7 @@ function hook_library_info_alter(&$libraries, $module) { * @param string $name * The name of the library. * - * @see _drupal_add_library() + * @see drupal_add_library() */ function hook_library_alter(array &$library, $name) { if ($name == 'core/jquery.ui.datepicker') { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index ca908a2..721bcf8 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -196,12 +196,10 @@ function system_theme() { 'admin_page' => array( 'variables' => array('blocks' => NULL), 'file' => 'system.admin.inc', - 'template' => 'admin-page', ), 'admin_block' => array( 'variables' => array('block' => NULL), 'file' => 'system.admin.inc', - 'template' => 'admin-block', ), 'admin_block_content' => array( 'variables' => array('content' => NULL), @@ -278,14 +276,6 @@ function system_hook_info() { */ function system_element_info() { // Top level elements. - $types['html'] = array( - '#theme' => 'html', - '#pre_render' => array('drupal_pre_render_html'), - // HTML5 Shiv - '#attached' => array( - 'library' => array('core/html5shiv'), - ), - ); $types['form'] = array( '#method' => 'post', '#action' => request_uri(), @@ -294,7 +284,6 @@ function system_element_info() { $types['page'] = array( '#show_messages' => TRUE, '#theme' => 'page', - '#title' => '', ); // By default, we don't want Ajax commands being rendered in the context of an // HTML page, so we don't provide defaults for #theme or #theme_wrappers. @@ -622,8 +611,6 @@ function system_element_info() { '#input' => TRUE, '#tree' => TRUE, '#tableselect' => FALSE, - '#sticky' => FALSE, - '#responsive' => TRUE, '#multiple' => TRUE, '#js_select' => TRUE, '#value_callback' => 'form_type_table_value', @@ -1231,8 +1218,8 @@ function system_user_timezone(&$form, &$form_state) { ); if (!$account->getTimezone() && $account->id() == $user->id() && empty($form_state['input']['timezone'])) { $form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Confirm the selection and click save.'); - $form['timezone']['#attached']['library'][] = 'core/drupal.timezone'; $form['timezone']['timezone']['#attributes'] = array('class' => array('timezone-detect')); + drupal_add_library('core/drupal.timezone'); } } diff --git a/core/modules/system/templates/admin-block.html.twig b/core/modules/system/templates/admin-block.html.twig deleted file mode 100644 index 20aa000..0000000 --- a/core/modules/system/templates/admin-block.html.twig +++ /dev/null @@ -1,26 +0,0 @@ -{# -/** - * @file - * Default theme implementation for an administrative block. - * - * Available variables: - * - block: An array of information about the block, including: - * - show: A flag indicating if the block should be displayed. - * - title: The block title. - * - content: (optional) The content of the block. - * - description: (optional) A description of the block. - * (Description should only be output if content is not available). - * - * @ingroup themeable - */ -#} -
- {% if block.title %} -

{{ block.title }}

- {% endif %} - {% if block.content %} -
{{ block.content }}
- {% elseif block.description %} -
{{ block.description }}
- {% endif %} -
diff --git a/core/modules/system/templates/admin-page.html.twig b/core/modules/system/templates/admin-page.html.twig deleted file mode 100644 index 73cae67..0000000 --- a/core/modules/system/templates/admin-page.html.twig +++ /dev/null @@ -1,26 +0,0 @@ -{# -/** - * @file - * Default theme implementation for an administrative page. - * - * Available variables: - * - system_compact_link: Themed link to toggle compact view. - * - containers: An list of administrative blocks keyed by position: left or - * right. Contains: - * - blocks: A list of blocks within a container. - * - * @see template_preprocess_admin_page() - * - * @ingroup themeable - */ -#} -
- {{ system_compact_link }} - {% for position, container in containers %} -
- {% for block in container.blocks %} - {{ block }} - {% endfor %} -
- {% endfor %} -
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index d7a08fc..bfc73b5 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -318,6 +318,19 @@ function entity_test_entity_test_insert($entity) { } /** + * Entity label callback. + * + * @param $entity + * The entity object. + * + * @return + * The label of the entity prefixed with "label callback". + */ +function entity_test_label_callback($entity) { + return 'label callback ' . $entity->name->value; +} + +/** * Implements hook_entity_field_access(). * * @see \Drupal\system\Tests\Entity\FieldAccessTest::testFieldAccess() diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php index c86b161..931707b 100644 --- a/core/modules/system/theme.api.php +++ b/core/modules/system/theme.api.php @@ -9,104 +9,74 @@ * layer. Each theme can take control over most of Drupal's output, and * has complete control over the CSS. * - * The theme layer is utilized by specifying theme implementations in a - * renderable array. The names of the keys in a renderable array - * determine how the information in the array is converted to themed output. - * - * To invoke a theme implementation on a renderable array, define a key named - * '#theme' and assign it a string value that is the name of a theme hook. Any - * variables that the theme hook requires may be supplied as additional keys -- - * prepended with a '#' character -- in the renderable array. + * Inside Drupal, the theme layer is utilized by the use of the _theme() + * function, which is passed the name of a component (the theme hook) + * and an array of variables. For example, + * _theme('table', array('header' => $header, 'rows' => $rows)); + * Additionally, the _theme() function can take an array of theme + * hooks, which can be used to provide 'fallback' implementations to + * allow for more specific control of output. For example, the function: + * _theme(array('table__foo', 'table'), $variables) would look to see if + * 'table__foo' is registered anywhere; if it is not, it would 'fall back' + * to the generic 'table' implementation. This can be used to attach specific + * theme functions to named objects, allowing the themer more control over + * specific types of output. + * + * Calling the _theme() function directly is highly discouraged. Building a + * renderable array is preferred. For example, rather than calling + * _theme('table', array()) in-place, one can assemble a renderable array as + * follows: * * @code - * $item_list = array( - * '#theme' => 'item_list', - * '#items' => $links, - * '#title' => t('Next steps'), + * $table = array( + * '#type' => 'table', + * '#header' => '', + * '#rows' => array(), * ); - * - * return $item_list; * @endcode * - * Do not call _theme() directly; instead, build and return a renderable array. - * If necessary, the array may be rendered to a string in-place - * by calling drupal_render(). + * Note that a table is defined as a type as well as a theme function. Building + * it as a type is preferred. The $table array can simply be passed along as + * a renderable array in a page build process. If necessary, the array may be + * rendered to a string by calling drupal_render(). * * @code - * $output = drupal_render($item_list); + * $output = drupal_render($table); * @endcode * - * @section sec_theme_hooks Theme Hooks - * Modules register theme hooks within a hook_theme()implementation and provide - * a default implementation via a function named theme_HOOK(). For instance, to - * theme a taxonomy term, the theme hook name is 'taxonomy_term'. If theming is - * handled via a function then the corresponding function name is - * theme_taxonomy_term(). If theming is handled via a template then the file - * should be named according to the value of the 'template' key registered with - * the theme hook (see hook_theme() for details). Default templates are - * implemented with the Twig rendering engine and are named the same as the - * theme hook, with underscores changed to hyphens, so for the 'taxonomy_term' - * theme hook, the default template is 'taxonomy-term.html.twig'. - * - * @subsection sub_overriding_theme_hooks Overriding Theme Hooks - * Themes may register new theme hooks within a hook_theme() - * implementation, but it is more common for themes to override default - * implementations provided by modules than to register entirely new theme - * hooks. Themes can override a default implementation by implementing a - * function named THEME_HOOK() (for example, the 'bartik' theme overrides the - * default implementation of the 'menu_tree' theme hook by implementing a - * bartik_menu_tree() function), or by adding a template file within its folder - * structure that follows the template naming structure used by the theme's - * rendering engine. For example, since the Bartik theme uses the Twig rendering - * engine, it overrides the default implementation of the 'page' theme hook by - * containing a 'page.html.twig' file within its folder structure. - * - * @subsection sub_preprocess_templates Preprocessing for Template Files - * If the implementation is a template file, several functions are called before - * the template file is invoked to modify the $variables array. These make up - * the "preprocessing" phase, and are executed (if they exist), in the following - * order (note that in the following list, HOOK indicates the theme hook name, - * MODULE indicates a module name, THEME indicates a theme name, and ENGINE - * indicates a theme engine name): - * - template_preprocess(&$variables, $hook): Creates a default set of variables - * for all theme hooks with template implementations. - * - template_preprocess_HOOK(&$variables): Should be implemented by the module - * that registers the theme hook, to set up default variables. - * - MODULE_preprocess(&$variables, $hook): hook_preprocess() is invoked on all - * implementing modules. - * - MODULE_preprocess_HOOK(&$variables): hook_preprocess_HOOK() is invoked on - * all implementing modules, so that modules that didn't define the theme hook - * can alter the variables. - * - ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to - * set necessary variables for all theme hooks with template implementations. - * - ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set - * necessary variables for the particular theme hook. - * - THEME_preprocess(&$variables, $hook): Allows the theme to set necessary - * variables for all theme hooks with template implementations. - * - THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary - * variables specific to the particular theme hook. - * - * @subsection sub_preprocess_theme_funcs Preprocessing for Theme Functions - * If the theming implementation is a function, only the theme-hook-specific - * preprocess functions (the ones ending in _HOOK) are called from the list - * above. This is because theme hooks with function implementations need to be - * fast, and calling the non-theme-hook-specific preprocess functions for them - * would incur a noticeable performance penalty. - * - * @subsection sub_alternate_suggestions Suggesting Alternate Hooks - * Alternate hooks can be suggested by implementing the hook-specific - * hook_theme_suggestions_HOOK_alter() or the generic - * hook_theme_suggestions_alter(). These alter hooks are used to manipulate an - * array of suggested alternate theme hooks to use, in reverse order of - * priority. _theme() will use the highest priority implementation that exists. - * If none exists, _theme() will use the implementation for the theme hook it - * was called with. These suggestions are similar to and are used for similar - * reasons as assigning an array of theme hooks to the #theme property of a - * renderable array. The difference is whether the suggestions are determined - * when _theme() is called or through altering the suggestions via the - * suggestion alter hooks. - * - * @see drupal_render() + * As of Drupal 6, every theme hook is required to be registered by the + * module that owns it, so that Drupal can tell what to do with it and + * to make it simple for themes to identify and override the behavior + * for these calls. + * + * The theme hooks are registered via hook_theme(), which returns an + * array of arrays with information about the hook. It describes the + * arguments the function or template will need, and provides + * defaults for the template in case they are not filled in. If the default + * implementation is a function, by convention it is named theme_HOOK(). + * + * Each module should provide a default implementation for theme_hooks that + * it registers. This implementation may be either a function or a template; + * if it is a function it must be specified via hook_theme(). By convention, + * default implementations of theme hooks are named theme_HOOK. Default + * template implementations are stored in the module directory. + * + * Drupal's default template renderer is Twig. Drupal's theme engines can + * provide alternate template engines, such as XTemplate, Smarty and PHPTal. + * + * In order to create theme-specific implementations of these hooks, themes can + * implement their own version of theme hooks, either as functions or templates. + * These implementations will be used instead of the default implementation. If + * using a pure .theme without an engine, the .theme is required to implement + * its own version of hook_theme() to tell Drupal what it is implementing; + * themes utilizing an engine will have their well-named theming functions + * automatically registered for them. While this can vary based upon the theme + * engine, the standard is that theme functions should be named THEMENAME_HOOK. + * For example, for Drupal's default theme (Bartik) to implement the 'table' + * hook, the theme function should be called bartik_table(). + * + * The theme system is described and defined in theme.inc. + * * @see _theme() * @see hook_theme() * @see hooks diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php index b624351..7246970 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php @@ -20,12 +20,7 @@ class VocabularyFormController extends EntityFormController { */ public function form(array $form, array &$form_state) { $vocabulary = $this->entity; - if ($vocabulary->isNew()) { - $form['#title'] = $this->t('Add vocabulary'); - } - else { - $form['#title'] = $this->t('Edit vocabulary'); - } + $form['#title'] = $this->t('Edit vocabulary'); $form['name'] = array( '#type' => 'textfield', diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml index 5fd37bc..2dc1c2b 100644 --- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml +++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_groupwise_term.yml @@ -65,7 +65,7 @@ display: display_plugin: default display_title: Master id: default - position: 0 + position: { } label: test_groupwise langcode: und module: views diff --git a/core/modules/toolbar/js/escapeAdmin.js b/core/modules/toolbar/js/escapeAdmin.js index 554d6a7..5467420 100644 --- a/core/modules/toolbar/js/escapeAdmin.js +++ b/core/modules/toolbar/js/escapeAdmin.js @@ -16,7 +16,7 @@ // there is not need to save the current path because the page is loaded within // an existing "workflow". if (!pathInfo.currentPathIsAdmin && !/destination=/.test(windowLocation.search)) { - sessionStorage.setItem('escapeAdminPath', windowLocation); + sessionStorage.setItem('escapeAdminPath', windowLocation.pathname.substring(pathInfo.basePath.length) + windowLocation.search); } /** @@ -30,7 +30,7 @@ var $toolbarEscape = $('[data-toolbar-escape-admin]').once('escapeAdmin'); if ($toolbarEscape.length) { if (pathInfo.currentPathIsAdmin && escapeAdminPath !== null) { - $toolbarEscape.attr('href', escapeAdminPath); + $toolbarEscape.attr('href', Drupal.url(escapeAdminPath)); $toolbarEscape.closest('.toolbar-tab').removeClass('hidden'); } } diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc index 8922672..e94c163 100644 --- a/core/modules/tracker/tracker.pages.inc +++ b/core/modules/tracker/tracker.pages.inc @@ -139,7 +139,7 @@ function tracker_page($account = NULL) { $page['tracker'] = array( '#rows' => $rows, '#header' => array(t('Type'), t('Title'), t('Author'), t('Replies'), t('Last updated')), - '#type' => 'table', + '#theme' => 'table', '#empty' => t('No content available.'), ); $page['pager'] = array( diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc index f5c1d8a..c93b63b 100644 --- a/core/modules/update/update.manager.inc +++ b/core/modules/update/update.manager.inc @@ -267,7 +267,7 @@ function update_manager_update_form($form, $form_state = array(), $context) { $prefix = '

' . t('Manual updates required') . '

'; $prefix .= '

' . t('Updates of Drupal core are not supported at this time.') . '

'; $form['manual_updates'] = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $headers, '#rows' => $projects['manual'], '#prefix' => $prefix, diff --git a/core/modules/update/update.report.inc b/core/modules/update/update.report.inc index bf3a6d2..bb87e61 100644 --- a/core/modules/update/update.report.inc +++ b/core/modules/update/update.report.inc @@ -283,7 +283,7 @@ function theme_update_report($variables) { ksort($rows[$type_name]); $output .= "\n

" . $type_label . "

\n"; $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows[$type_name], '#attributes' => array( diff --git a/core/modules/user/config/views.view.user_admin_people.yml b/core/modules/user/config/views.view.user_admin_people.yml index 849697a..86f49be 100644 --- a/core/modules/user/config/views.view.user_admin_people.yml +++ b/core/modules/user/config/views.view.user_admin_people.yml @@ -561,7 +561,6 @@ display: empty_zero: false hide_alter_empty: true text: Translate - optional: true plugin_id: content_translation_link provider: content_translation dropbutton: diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml index 4dc494a..b0a6665 100644 --- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_groupwise_user.yml @@ -77,7 +77,7 @@ display: display_plugin: default display_title: Master id: default - position: 0 + position: { } label: test_groupwise_user langcode: und module: views diff --git a/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php b/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php index cd38199..8df3017 100644 --- a/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php +++ b/core/modules/views/lib/Drupal/views/Controller/ViewAjaxController.php @@ -131,7 +131,7 @@ public function ajaxView(Request $request) { $view->dom_id = $dom_id; $preview = $view->preview($display_id, $args); - $response->addCommand(new ReplaceCommand(".view-dom-id-$dom_id", $this->drupalRender($preview))); + $response->addCommand(new ReplaceCommand(".view-dom-id-$dom_id", drupal_render($preview))); return $response; } else { @@ -143,20 +143,4 @@ public function ajaxView(Request $request) { } } - /** - * Wraps drupal_render. - * - * @param array $elements - * The structured array describing the data to be rendered. - * - * @return string - * The rendered HTML. - * - * @todo Remove once drupal_render is converted to autoloadable code. - * @see https://drupal.org/node/2171071 - */ - protected function drupalRender(array $elements) { - return drupal_render($elements); - } - } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php index bbc26ec..66f3495 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/Title.php @@ -7,8 +7,6 @@ namespace Drupal\views\Plugin\views\area; -use \Drupal\Core\Utility\Title as UtilityTitle; - /** * Views area title override handler. * @@ -53,7 +51,7 @@ public function preRender(array $results) { // If a title is provided, process it. if (!empty($this->options['title'])) { $value = $this->globalTokenReplace($this->options['title']); - $this->view->setTitle($this->sanitizeValue($value, 'xss_admin'), UtilityTitle::PASS_THROUGH); + $this->view->setTitle($this->sanitizeValue($value, 'xss_admin'), PASS_THROUGH); } } diff --git a/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php b/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php index da1245b..8cc5d10 100644 --- a/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php +++ b/core/modules/views/tests/Drupal/views/Tests/Controller/ViewAjaxControllerTest.php @@ -58,7 +58,7 @@ protected function setUp() { ->disableOriginalConstructor() ->getMock(); - $this->viewAjaxController = new TestViewAjaxController($this->viewStorage, $this->executableFactory); + $this->viewAjaxController = new ViewAjaxController($this->viewStorage, $this->executableFactory); } /** @@ -280,18 +280,6 @@ protected function assertViewResultCommand(ViewAjaxResponse $response, $position } -/** - * Overrides ViewAjaxController::drupalRender to protect the parent method. - */ -class TestViewAjaxController extends ViewAjaxController { - - // @todo Remove once drupal_render is converted to autoloadable code. - protected function drupalRender(array $elements) { - return isset($elements['#markup']) ? $elements['#markup'] : ''; - } - -} - } namespace { @@ -302,4 +290,11 @@ function &drupal_static($key) { } } + // @todo Remove once drupal_render is converted to autoloadable code. + if (!function_exists('drupal_render')) { + function drupal_render($array) { + return isset($array['#markup']) ? $array['#markup'] : ''; + } + } + } diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php index f2d2a1e..faacf8a 100644 --- a/core/modules/views/views.api.php +++ b/core/modules/views/views.api.php @@ -576,9 +576,9 @@ function hook_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { * * @param array $rows * An associative array with two keys: - * - query: An array of rows suitable for '#type' => 'table', containing + * - query: An array of rows suitable for '#theme' => 'table', containing * information about the query and the display title and path. - * - statistics: An array of rows suitable for '#type' => 'table', + * - statistics: An array of rows suitable for '#theme' => 'table', * containing performance statistics. * @param \Drupal\views\ViewExecutable $view * The view object. diff --git a/core/modules/views/views.module b/core/modules/views/views.module index 922a8d9..a4311e8 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -9,7 +9,6 @@ * incoming page and block requests. */ -use Drupal\Component\Utility\String; use Drupal\Core\Cache\Cache; use Drupal\Core\Database\Query\AlterableInterface; use Drupal\Core\Language\Language; @@ -58,37 +57,6 @@ function views_element_info() { } /** - * Implements hook_views_pre_render(). - */ -function views_views_pre_render($view) { - // If using AJAX, send identifying data about this view. - if ($view->ajaxEnabled() && empty($view->is_attachment) && empty($view->live_preview)) { - $settings = array( - 'views' => array( - 'ajax_path' => url('views/ajax'), - 'ajaxViews' => array( - 'views_dom_id:' . $view->dom_id => array( - 'view_name' => $view->storage->id(), - 'view_display_id' => $view->current_display, - 'view_args' => String::checkPlain(implode('/', $view->args)), - 'view_path' => String::checkPlain(current_path()), - 'view_base_path' => $view->getPath(), - 'view_dom_id' => $view->dom_id, - // To fit multiple views on a page, the programmer may have - // overridden the display's pager_element. - 'pager_element' => isset($view->pager) ? $view->pager->getPagerId() : 0, - ), - ), - ), - ); - $view->element['#attached']['js'][] = array('type' => 'setting', 'data' => $settings); - $view->element['#attached']['library'][] = 'views/views.ajax'; - } - - return $view; -} - -/** * View element pre render callback. */ function views_pre_render_view_element($element) { @@ -364,8 +332,7 @@ function views_preprocess_page(&$variables) { unset($class[$key]); $attributes['class'] = $class; $attributes['data-views-page-contextual-id'] = $variables['title_suffix']['contextual_links']['#id']; - $attached['#attached']['library'][] = 'views/views.contextual-links'; - drupal_render($attached); + drupal_add_library('views/views.contextual-links'); } } } diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc index eaf3d86..1acadb7 100644 --- a/core/modules/views/views.theme.inc +++ b/core/modules/views/views.theme.inc @@ -106,6 +106,30 @@ function template_preprocess_views_view(&$variables) { $variables['attributes']['class'][] = 'view-dom-id-' . $variables['dom_id']; } + // If using AJAX, send identifying data about this view. + if ($view->ajaxEnabled() && empty($view->is_attachment) && empty($view->live_preview)) { + $settings = array( + 'views' => array( + 'ajax_path' => url('views/ajax'), + 'ajaxViews' => array( + 'views_dom_id:' . $variables['dom_id'] => array( + 'view_name' => $view->storage->id(), + 'view_display_id' => $view->current_display, + 'view_args' => String::checkPlain(implode('/', $view->args)), + 'view_path' => String::checkPlain(current_path()), + 'view_base_path' => $view->getPath(), + 'view_dom_id' => $variables['dom_id'], + // To fit multiple views on a page, the programmer may have + // overridden the display's pager_element. + 'pager_element' => isset($view->pager) ? $view->pager->getPagerId() : 0, + ), + ), + ), + ); + $view->element['#attached']['js'][] = array('type' => 'setting', 'data' => $settings); + $view->element['#attached']['library'][] = 'views/views.ajax'; + } + // If form fields were found in the view, reformat the view output as a form. if ($view->hasFormElements()) { // Copy the rows so as not to modify them by reference when rendering. diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php b/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php index 018d4d9..df9aff3 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Controller/ViewsUIController.php @@ -98,7 +98,7 @@ public function reportFields() { // Sort rows by field name. ksort($rows); $output = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No fields have been used in views yet.'), @@ -126,7 +126,7 @@ public function reportPlugins() { // Sort rows by field name. ksort($rows); return array( - '#type' => 'table', + '#theme' => 'table', '#header' => array(t('Type'), t('Name'), t('Provided by'), t('Used in')), '#rows' => $rows, '#empty' => t('There are no enabled views.'), diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayTest.php index 5590138..f355412 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayTest.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/DisplayTest.php @@ -47,6 +47,7 @@ public function testReorderDisplay() { 'block[create]' => TRUE ); $view = $this->randomView($view); + $path_prefix = 'admin/structure/views/view/' . $view['id'] .'/edit'; $this->clickLink(t('Reorder displays')); $this->assertTrue($this->xpath('//tr[@id="display-row-default"]'), 'Make sure the default display appears on the reorder listing'); diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/ViewsUITourTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/ViewsUITourTest.php index 5808cde..899e08a 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/ViewsUITourTest.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/ViewsUITourTest.php @@ -52,6 +52,7 @@ public function testViewsUiTourTips() { $view['id'] = strtolower($this->randomName(16)); $view['page[create]'] = 1; $view['page[path]'] = $this->randomName(16); + $view_path = $view['page[path]']; $this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit')); $this->assertTourTips(); } diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php index 1facb3c..ec64320 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php @@ -196,7 +196,7 @@ public function render() { $list[$status]['#type'] = 'container'; $list[$status]['#attributes'] = array('class' => array('views-list-section', $status)); $list[$status]['table'] = array( - '#type' => 'table', + '#theme' => 'table', '#attributes' => array( 'class' => array('views-listing-table'), ), diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php index f959d0d..1ea7ee2 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -712,7 +712,7 @@ public function renderPreview($display_id, $args = array()) { // Assemble the preview, the query info, and the query statistics in the // requested order. $table = array( - '#type' => 'table', + '#theme' => 'table', '#prefix' => '
', '#suffix' => '
', ); diff --git a/core/modules/views_ui/views_ui.theme.inc b/core/modules/views_ui/views_ui.theme.inc index b224dca..87ca306 100644 --- a/core/modules/views_ui/views_ui.theme.inc +++ b/core/modules/views_ui/views_ui.theme.inc @@ -195,7 +195,7 @@ function theme_views_ui_build_group_filter_form($variables) { $rows[] = array('data' => $data, 'id' => 'views-row-' . $group_id, 'class' => array('draggable')); } $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#attributes' => array( @@ -297,7 +297,7 @@ function theme_views_ui_rearrange_filter_form(&$variables) { if (!empty($ungroupable_rows)) { $header = array(t('Ungroupable filters'), t('Weight'), array('class' => array('views-hide-label'), 'data' => t('Group')), array('class' => array('views-hide-label'), 'data' => t('Remove'))); $table = array( - '#type' => 'table', + '#theme' => 'table', '#header' => $header, '#rows' => $ungroupable_rows, '#attributes' => array( @@ -317,7 +317,7 @@ function theme_views_ui_rearrange_filter_form(&$variables) { // Set up tabledrag so that the weights are changed when rows are dragged. $table = array( - '#type' => 'table', + '#theme' => 'table', '#rows' => $rows, '#attributes' => array( 'id' => 'views-rearrange-filters', diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 5594dd5..363c69b 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -71,7 +71,7 @@ exit; } -$test_list = simpletest_script_get_test_list(); +$test_list = array_fill(0, 20, 'Drupal\toolbar\Tests\ToolbarAdminMenuTest'); // Try to allocate unlimited time to run the tests. drupal_set_time_limit(0); diff --git a/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php b/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php index 0384148..188c042 100644 --- a/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php +++ b/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php @@ -5,7 +5,7 @@ * Contains \Drupal\Tests\Core\Ajax\AjaxCommandsTest. */ -namespace Drupal\Tests\Core\Ajax; +namespace Drupal\Tests\Core\Ajax { use Drupal\Tests\UnitTestCase; use Drupal\Core\Ajax\AddCssCommand; @@ -308,7 +308,7 @@ public function testSettingsCommand() { * Tests that OpenDialogCommand objects can be constructed and rendered. */ public function testOpenDialogCommand() { - $command = new TestOpenDialogCommand('#some-dialog', 'Title', '

Text!

', array( + $command = new OpenDialogCommand('#some-dialog', 'Title', '

Text!

', array( 'url' => FALSE, 'width' => 500, )); @@ -332,7 +332,7 @@ public function testOpenDialogCommand() { * Tests that OpenModalDialogCommand objects can be constructed and rendered. */ public function testOpenModalDialogCommand() { - $command = new TestOpenModalDialogCommand('Title', '

Text!

', array( + $command = new OpenModalDialogCommand('Title', '

Text!

', array( 'url' => 'example', 'width' => 500, )); @@ -425,26 +425,12 @@ public function testRedirectCommand() { } -/** - * Wraps OpenModalDialogCommand::drupalAttachLibrary(). - * - * {@inheritdoc} - */ -class TestOpenModalDialogCommand extends OpenModalDialogCommand { - - protected function drupalAttachLibrary($name) { - } - } -/** - * Wraps OpenDialogCommand::drupalAttachLibrary(). - * - * {@inheritdoc} - */ -class TestOpenDialogCommand extends OpenDialogCommand { - - protected function drupalAttachLibrary($name) { +namespace { + if (!function_exists('drupal_add_library')) { + function drupal_add_library() { + return TRUE; + } } - } diff --git a/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php b/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php deleted file mode 100644 index 258279e..0000000 --- a/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php +++ /dev/null @@ -1,97 +0,0 @@ - '', - 'name' => '\Drupal\Core\Annotation\Translation unit test', - 'group' => 'System', - ); - } - - /** - * {@inheritdoc} - */ - public function setUp() { - $this->translationManager = $this->getStringTranslationStub(); - } - - /** - * @covers \Drupal\Core\Annotation\Translation::get() - * - * @dataProvider providerTestGet - */ - public function testGet(array $values, $expected) { - $container = new ContainerBuilder(); - $container->set('string_translation', $this->translationManager); - \Drupal::setContainer($container); - - $arguments = isset($values['arguments']) ? $values['arguments'] : array(); - $options = isset($values['context']) ? array( - 'context' => $values['context'], - ) : array(); - $this->translationManager->expects($this->once()) - ->method('translate') - ->with($values['value'], $arguments, $options); - - $annotation = new Translation($values); - - $this->assertSame($expected, $annotation->get()); - } - - /** - * Provides data to self::testGet(). - */ - public function providerTestGet() { - $data = array(); - $data[] = array( - array( - 'value' => 'Foo', - ), - 'Foo' - ); - $random = $this->randomName(); - $random_html_entity = '&' . $random; - $data[] = array( - array( - 'value' => 'Foo !bar @baz %qux', - 'arguments' => array( - '!bar' => $random, - '@baz' => $random_html_entity, - '%qux' => $random_html_entity, - ), - 'context' => $this->randomName(), - ), - 'Foo ' . $random . ' &' . $random . ' &' . $random . '', - ); - - return $data; - } - -} diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php deleted file mode 100644 index d7271d9..0000000 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ /dev/null @@ -1,233 +0,0 @@ - '', - 'name' => '\Drupal\Core\Config\Entity\ConfigEntityBase unit test', - 'group' => 'Entity', - ); - } - - /** - * {@inheritdoc} - */ - public function setUp() { - $values = array(); - $this->entityType = $this->randomName(); - - $this->entityInfo = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); - - $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); - $this->entityManager->expects($this->any()) - ->method('getDefinition') - ->with($this->entityType) - ->will($this->returnValue($this->entityInfo)); - - $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); - - $container = new ContainerBuilder(); - $container->set('entity.manager', $this->entityManager); - $container->set('uuid', $this->uuid); - \Drupal::setContainer($container); - - $this->entity = $this->getMockBuilder('\Drupal\Core\Config\Entity\ConfigEntityBase') - ->setConstructorArgs(array($values, $this->entityType)) - ->setMethods(array('languageLoad')) - ->getMock(); - $this->entity->expects($this->any()) - ->method('languageLoad') - ->will($this->returnValue(NULL)); - } - - /** - * @covers ::setOriginalId - * @covers ::getOriginalId - */ - public function testGetOriginalId() { - $id = $this->randomName(); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->setOriginalId($id))); - $this->assertSame($id, $this->entity->getOriginalId()); - } - - /** - * @covers ::isNew - */ - public function testIsNew() { - $this->assertFalse($this->entity->isNew()); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->enforceIsNew())); - $this->assertTrue($this->entity->isNew()); - $this->entity->enforceIsNew(FALSE); - $this->assertFalse($this->entity->isNew()); - } - - /** - * @covers ::set - * @covers ::get - */ - public function testGet() { - $name = $this->randomName(); - $value = $this->randomName(); - $this->assertNull($this->entity->get($name)); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->set($name, $value))); - $this->assertSame($value, $this->entity->get($name)); - } - - /** - * @covers ::setStatus - * @covers ::status - */ - public function testSetStatus() { - $this->assertTrue($this->entity->status()); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->setStatus(FALSE))); - $this->assertFalse($this->entity->status()); - $this->entity->setStatus(TRUE); - $this->assertTrue($this->entity->status()); - } - - /** - * @covers ::enable - * @depends testSetStatus - */ - public function testEnable() { - $this->entity->setStatus(FALSE); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->enable())); - $this->assertTrue($this->entity->status()); - } - - /** - * @covers ::disable - * @depends testSetStatus - */ - public function testDisable() { - $this->entity->setStatus(TRUE); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->disable())); - $this->assertFalse($this->entity->status()); - } - - /** - * @covers ::setSyncing - * @covers ::isSyncing - */ - public function testIsSyncing() { - $this->assertFalse($this->entity->isSyncing()); - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->setSyncing(TRUE))); - $this->assertTrue($this->entity->isSyncing()); - $this->entity->setSyncing(FALSE); - $this->assertFalse($this->entity->isSyncing()); - } - - /** - * @covers ::createDuplicate - */ - public function testCreateDuplicate() { - $this->entityInfo->expects($this->once()) - ->method('getKey') - ->with('id') - ->will($this->returnValue('id')); - - $this->entity->setOriginalId('foo'); - /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $duplicate */ - $duplicate = $this->entity->createDuplicate(); - $this->assertInstanceOf('\Drupal\Core\Entity\Entity', $duplicate); - $this->assertNotSame(spl_object_hash($this->entity), spl_object_hash($duplicate)); - $this->assertNull($duplicate->id()); - $this->assertNull($duplicate->getOriginalId()); - $this->assertNull($duplicate->uuid()); - } - - /** - * @covers ::sort - */ - public function testSort() { - $this->entityManager->expects($this->any()) - ->method('getDefinition') - ->with($this->entityType) - ->will($this->returnValue(array( - 'entity_keys' => array( - 'label' => 'label', - ), - ))); - $entity_a = $this->entity; - $entity_a->label = 'foo'; - $entity_b = clone $this->entity; - $entity_b->label = 'bar'; - $list = array($entity_a, $entity_b); - // Suppress errors because of https://bugs.php.net/bug.php?id=50688. - @usort($list, '\Drupal\Core\Config\Entity\ConfigEntityBase::sort'); - $this->assertSame(spl_object_hash($entity_b), spl_object_hash($list[0])); - $entity_a->weight = 0; - $entity_b->weight = 1; - // Suppress errors because of https://bugs.php.net/bug.php?id=50688. - @usort($list, array($entity_a, 'sort')); - $this->assertSame(spl_object_hash($entity_a), spl_object_hash($list[0])); - } - - /** - * @covers ::getExportProperties - */ - public function testGetExportProperties() { - $properties = $this->entity->getExportProperties(); - $this->assertInternalType('array', $properties); - $class_info = new \ReflectionClass($this->entity); - foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { - $name = $property->getName(); - $this->assertArrayHasKey($name, $properties); - $this->assertSame($this->entity->get($name), $properties[$name]); - } - } -} diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php deleted file mode 100644 index 789306b..0000000 --- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php +++ /dev/null @@ -1,326 +0,0 @@ - '', - 'name' => '\Drupal\Core\Entity\ContentEntityBase unit test', - 'group' => 'Entity', - ); - } - - /** - * {@inheritdoc} - */ - public function setUp() { - $values = array(); - $this->entityType = $this->randomName(); - $this->bundle = $this->randomName(); - - $this->entityInfo = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); - - $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); - $this->entityManager->expects($this->any()) - ->method('getDefinition') - ->with($this->entityType) - ->will($this->returnValue($this->entityInfo)); - $this->entityManager->expects($this->any()) - ->method('getFieldDefinitions') - ->with($this->entityType, $this->bundle) - ->will($this->returnValue(array( - 'id' => array( - 'type' => 'integer_field', - ), - ))); - - $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); - - $this->typedDataManager = $this->getMockBuilder('\Drupal\Core\TypedData\TypedDataManager') - ->disableOriginalConstructor() - ->getMock(); - - $container = new ContainerBuilder(); - $container->set('entity.manager', $this->entityManager); - $container->set('uuid', $this->uuid); - $container->set('typed_data_manager', $this->typedDataManager); - \Drupal::setContainer($container); - - $this->entity = $this->getMockBuilder('\Drupal\Core\Entity\ContentEntityBase') - ->setConstructorArgs(array($values, $this->entityType, $this->bundle)) - ->setMethods(array('languageList', 'languageLoad')) - ->getMockForAbstractClass(); - $this->entity->expects($this->any()) - ->method('languageList') - ->will($this->returnValue(array())); - $this->entity->expects($this->any()) - ->method('languageLoad') - ->will($this->returnValue(NULL)); - } - - /** - * @covers ::isNewRevision - * @covers ::setNewRevision - */ - public function testIsNewRevision() { - $this->entityInfo->expects($this->at(0)) - ->method('hasKey') - ->with('revision') - ->will($this->returnValue(FALSE)); - $this->entityInfo->expects($this->at(1)) - ->method('hasKey') - ->with('revision') - ->will($this->returnValue(TRUE)); - - $this->assertFalse($this->entity->isNewRevision()); - $this->assertTrue($this->entity->isNewRevision()); - $this->entity->setNewRevision(TRUE); - $this->assertTRUE($this->entity->isNewRevision()); - } - - /** - * @covers ::isDefaultRevision - */ - public function testIsDefaultRevision() { - // The default value is TRUE. - $this->assertTrue($this->entity->isDefaultRevision()); - // We override the value, but it does not affect this call. - $this->assertTrue($this->entity->isDefaultRevision(FALSE)); - // The last call changed the return value for this call. - $this->assertFalse($this->entity->isDefaultRevision()); - } - - /** - * @covers ::getRevisionId - */ - public function testGetRevisionId() { - $this->assertNull($this->entity->getRevisionId()); - } - - /** - * @covers ::isTranslatable - */ - public function testIsTranslatable() { - $this->entityManager->expects($this->at(0)) - ->method('getBundleInfo') - ->with($this->entityType) - ->will($this->returnValue(array( - $this->bundle => array( - 'translatable' => TRUE, - ), - ))); - $this->assertTrue($this->entity->isTranslatable()); - $this->assertFalse($this->entity->isTranslatable()); - } - - /** - * @covers ::preSaveRevision - */ - public function testPreSaveRevision() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $record = new \stdClass(); - $this->entity->preSaveRevision($storage, $record); - } - - /** - * @covers ::getString - */ - public function testGetString() { - $label = $this->randomName(); - /** @var \Drupal\Core\Entity\ContentEntityBase|\PHPUnit_Framework_MockObject_MockObject $entity */ - $entity = $this->getMockBuilder('\Drupal\Core\Entity\ContentEntityBase') - ->setMethods(array('label')) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $entity->expects($this->once()) - ->method('label') - ->will($this->returnValue($label)); - - $this->assertSame($label, $entity->getString()); - } - - /** - * @covers ::validate - */ - public function testValidate() { - $validator = $this->getMock('\Symfony\Component\Validator\ValidatorInterface'); - /** @var \Symfony\Component\Validator\ConstraintViolationList|\PHPUnit_Framework_MockObject_MockObject $empty_violation_list */ - $empty_violation_list = $this->getMockBuilder('\Symfony\Component\Validator\ConstraintViolationList') - ->setMethods(NULL) - ->getMock(); - $non_empty_violation_list = clone $empty_violation_list; - $violation = $this->getMock('\Symfony\Component\Validator\ConstraintViolationInterface'); - $non_empty_violation_list->add($violation); - $validator->expects($this->at(0)) - ->method('validate') - ->with($this->entity) - ->will($this->returnValue($empty_violation_list)); - $validator->expects($this->at(1)) - ->method('validate') - ->with($this->entity) - ->will($this->returnValue($non_empty_violation_list)); - $this->typedDataManager->expects($this->exactly(2)) - ->method('getValidator') - ->will($this->returnValue($validator)); - $this->assertSame(0, count($this->entity->validate())); - $this->assertSame(1, count($this->entity->validate())); - } - - /** - * @covers ::getConstraints - */ - public function testGetConstraints() { - $this->assertInternalType('array', $this->entity->getConstraints()); - } - - /** - * @covers ::getName - */ - public function testGetName() { - $this->assertNull($this->entity->getName()); - } - - /** - * @covers ::getRoot - */ - public function testGetRoot() { - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->getRoot())); - } - - /** - * @covers ::getPropertyPath - */ - public function testGetPropertyPath() { - $this->assertSame('', $this->entity->getPropertyPath()); - } - - /** - * @covers ::getParent - */ - public function testGetParent() { - $this->assertNull($this->entity->getParent()); - } - - /** - * @covers ::setContext - */ - public function testSetContext() { - $name = $this->randomName(); - $parent = $this->getMock('\Drupal\Core\TypedData\TypedDataInterface'); - $this->entity->setContext($name, $parent); - } - - /** - * @covers ::bundle - */ - public function testBundle() { - $this->assertSame($this->bundle, $this->entity->bundle()); - } - - /** - * @covers ::access - */ - public function testAccess() { - $access = $this->getMock('\Drupal\Core\Entity\EntityAccessControllerInterface'); - $operation = $this->randomName(); - $access->expects($this->at(0)) - ->method('access') - ->with($this->entity, $operation) - ->will($this->returnValue(TRUE)); - $access->expects($this->at(1)) - ->method('createAccess') - ->will($this->returnValue(TRUE)); - $this->entityManager->expects($this->exactly(2)) - ->method('getAccessController') - ->will($this->returnValue($access)); - $this->assertTrue($this->entity->access($operation)); - $this->assertTrue($this->entity->access('create')); - } - - /** - * @covers ::label - */ - public function testLabel() { - // Make a mock with one method that we use as the entity's uri_callback. We - // check that it is called, and that the entity's label is the callback's - // return value. - $callback_label = $this->randomName(); - $callback_container = $this->getMock(get_class()); - $callback_container->expects($this->once()) - ->method(__FUNCTION__) - ->will($this->returnValue($callback_label)); - $this->entityInfo->expects($this->once()) - ->method('getLabelCallback') - ->will($this->returnValue(array($callback_container, __FUNCTION__))); - - $this->assertSame($callback_label, $this->entity->label()); - } -} diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php deleted file mode 100644 index a467a90..0000000 --- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php +++ /dev/null @@ -1,332 +0,0 @@ - '', - 'name' => '\Drupal\Core\Entity\Entity unit test', - 'group' => 'Entity', - ); - } - - /** - * {@inheritdoc} - */ - public function setUp() { - $values = array(); - $this->entityTypeId = $this->randomName(); - - $this->entityInfo = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); - - $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); - $this->entityManager->expects($this->any()) - ->method('getDefinition') - ->with($this->entityTypeId) - ->will($this->returnValue($this->entityInfo)); - - $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); - - $container = new ContainerBuilder(); - $container->set('entity.manager', $this->entityManager); - $container->set('uuid', $this->uuid); - \Drupal::setContainer($container); - - $this->entity = $this->getMockBuilder('\Drupal\Core\Entity\Entity') - ->setConstructorArgs(array($values, $this->entityTypeId)) - ->setMethods(array('languageLoad')) - ->getMock(); - $this->entity->expects($this->any()) - ->method('languageLoad') - ->will($this->returnValue(NULL)); - } - - /** - * @covers ::id - */ - public function testId() { - // @todo How to test this? - $this->assertNull($this->entity->id()); - } - - /** - * @covers ::uuid - */ - public function testUuid() { - // @todo How to test this? - $this->assertNull($this->entity->uuid()); - } - - /** - * @covers ::isNew - */ - public function testIsNew() { - // @todo How to test this? - $this->assertInternalType('bool', $this->entity->isNew()); - } - - /** - * @covers ::enforceIsNew - */ - public function testEnforceIsNew() { - $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->enforceIsNew())); - } - - /** - * @covers ::getEntityType - */ - public function testGetEntityType() { - $this->assertInstanceOf('\Drupal\Core\Entity\EntityTypeInterface', $this->entity->getEntityType()); - } - - /** - * @covers ::bundle - */ - public function testBundle() { - $this->assertSame($this->entityTypeId, $this->entity->bundle()); - } - - /** - * @covers ::label - */ - public function testLabel() { - // Make a mock with one method that we use as the entity's uri_callback. We - // check that it is called, and that the entity's label is the callback's - // return value. - $callback_label = $this->randomName(); - $property_label = $this->randomName(); - $callback_container = $this->getMock(get_class()); - $callback_container->expects($this->once()) - ->method(__FUNCTION__) - ->will($this->returnValue($callback_label)); - $this->entityInfo->expects($this->at(0)) - ->method('getLabelCallback') - ->will($this->returnValue(array($callback_container, __FUNCTION__))); - $this->entityInfo->expects($this->at(1)) - ->method('getLabelCallback') - ->will($this->returnValue(NULL)); - $this->entityInfo->expects($this->at(2)) - ->method('getKey') - ->with('label') - ->will($this->returnValue('label')); - - // Set a dummy property on the entity under test to test that the label can - // be returned form a property if there is no callback. - $this->entityManager->expects($this->at(1)) - ->method('getDefinition') - ->with($this->entityTypeId) - ->will($this->returnValue(array( - 'entity_keys' => array( - 'label' => 'label', - ), - ))); - $this->entity->label = $property_label; - - $this->assertSame($callback_label, $this->entity->label()); - $this->assertSame($property_label, $this->entity->label()); - } - - /** - * @covers ::access - */ - public function testAccess() { - $access = $this->getMock('\Drupal\Core\Entity\EntityAccessControllerInterface'); - $operation = $this->randomName(); - $access->expects($this->at(0)) - ->method('access') - ->with($this->entity, $operation) - ->will($this->returnValue(TRUE)); - $access->expects($this->at(1)) - ->method('createAccess') - ->will($this->returnValue(TRUE)); - $this->entityManager->expects($this->exactly(2)) - ->method('getAccessController') - ->will($this->returnValue($access)); - $this->assertTrue($this->entity->access($operation)); - $this->assertTrue($this->entity->access('create')); - } - - /** - * @covers ::language - */ - public function testLanguage() { - $this->assertInstanceOf('\Drupal\Core\Language\Language', $this->entity->language()); - } - - /** - * @covers ::save - */ - public function testSave() { - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $storage->expects($this->once()) - ->method('save') - ->with($this->entity); - $this->entityManager->expects($this->once()) - ->method('getStorageController') - ->with($this->entityTypeId) - ->will($this->returnValue($storage)); - $this->entity->save(); - } - - /** - * @covers ::delete - */ - public function testDelete() { - $this->entity->id = $this->randomName(); - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - // Testing the argument of the delete() method consumes too much memory. - $storage->expects($this->once()) - ->method('delete'); - $this->entityManager->expects($this->once()) - ->method('getStorageController') - ->with($this->entityTypeId) - ->will($this->returnValue($storage)); - $this->entity->delete(); - } - - /** - * @covers ::getEntityTypeId - */ - public function testGetEntityTypeId() { - $this->assertSame($this->entityTypeId, $this->entity->getEntityTypeId()); - } - - /** - * @covers ::preSave - */ - public function testPreSave() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $this->entity->preSave($storage); - } - - /** - * @covers ::postSave - */ - public function testPostSave() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $this->entity->postSave($storage); - } - - /** - * @covers ::preCreate - */ - public function testPreCreate() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $values = array(); - $this->entity->preCreate($storage, $values); - } - - /** - * @covers ::postCreate - */ - public function testPostCreate() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $this->entity->postCreate($storage); - } - - /** - * @covers ::preDelete - */ - public function testPreDelete() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $this->entity->preDelete($storage, array($this->entity)); - } - - /** - * @covers ::postDelete - */ - public function testPostDelete() { - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - - $entity = $this->getMockBuilder('\Drupal\Core\Entity\Entity') - ->setMethods(array('onSaveOrDelete')) - ->disableOriginalConstructor() - ->getMock(); - $entity->expects($this->once()) - ->method('onSaveOrDelete'); - - $this->entity->postDelete($storage, array($entity)); - } - - /** - * @covers ::postLoad - */ - public function testPostLoad() { - // This method is internal, so check for errors on calling it only. - $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); - $entities = array($this->entity); - $this->entity->postLoad($storage, $entities); - } - - /** - * @covers ::referencedEntities - */ - public function testReferencedEntities() { - $this->assertSame(array(), $this->entity->referencedEntities()); - } -} diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index f64dca0..b862f12 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -190,7 +190,7 @@ public function getStringTranslationStub() { $translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface'); $translation->expects($this->any()) ->method('translate') - ->will($this->returnCallback('Drupal\Component\Utility\String::format')); + ->will($this->returnCallback(function ($string, array $args = array()) { return strtr($string, $args); })); return $translation; } diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css index e8d1fd9..e362985 100644 --- a/core/themes/seven/style.css +++ b/core/themes/seven/style.css @@ -64,12 +64,6 @@ ul.menu li.expanded { .skip-link:active { outline: 0; } -.skip-link.visually-hidden.focusable:active, -.skip-link.visually-hidden.focusable:focus, -.skip-link.visually-hidden.focusable:hover -{ - position: absolute !important; -} /** * Branding.