diff --git a/core/core.services.yml b/core/core.services.yml index a54bb4a..856c198 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -198,16 +198,12 @@ services: arguments: ['@router.route_provider'] calls: - [setFinalMatcher, ['@router.matcher.final_matcher']] - url_generator: + router.generator: class: Drupal\Core\Routing\UrlGenerator - arguments: ['@router.route_provider', '@path_processor_manager', '@config.factory', '@settings'] - calls: - - [setRequest, ['@?request']] - tags: - - { name: persist } + arguments: ['@router.route_provider', '@path.alias_manager.cached'] router.dynamic: class: Symfony\Cmf\Component\Routing\DynamicRouter - arguments: ['@router.request_context', '@router.matcher', '@url_generator'] + arguments: ['@router.request_context', '@router.matcher', '@router.generator'] legacy_generator: class: Drupal\Core\Routing\NullGenerator legacy_url_matcher: @@ -394,13 +390,11 @@ services: class: Drupal\Core\PathProcessor\PathProcessorFront tags: - { name: path_processor_inbound, priority: 200 } - - { name: path_processor_outbound, priority: 200 } arguments: ['@config.factory'] path_processor_alias: class: Drupal\Core\PathProcessor\PathProcessorAlias tags: - { name: path_processor_inbound, priority: 100 } - - { name: path_processor_outbound, priority: 300 } arguments: ['@path.alias_manager'] transliteration: class: Drupal\Core\Transliteration\PHPTransliteration diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 43c06c9..74d0cb2 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -17,12 +17,10 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\RuntimeException as DependencyInjectionRuntimeException; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Drupal\Core\Language\Language; use Drupal\Core\Lock\DatabaseLockBackend; use Drupal\Core\Lock\LockBackendInterface; use Drupal\user\Plugin\Core\Entity\User; -use Drupal\Core\Entity\EntityBCDecorator; /** * @file @@ -1070,8 +1068,6 @@ function drupal_load($type, $name) { * reason phrase, e.g. "404 Not Found". * @param $append * Whether to append the value to an existing header or to replace it. - * - * @deprecated Header handling is being shifted to a Symfony response object. */ function drupal_add_http_header($name, $value, $append = FALSE) { // The headers as name/value pairs. @@ -1091,6 +1087,7 @@ function drupal_add_http_header($name, $value, $append = FALSE) { else { $headers[$name_lower] = $value; } + drupal_send_headers(array($name => $headers[$name_lower]), TRUE); } /** @@ -1103,8 +1100,6 @@ function drupal_add_http_header($name, $value, $append = FALSE) { * @return * A string containing the header value, or FALSE if the header has been set, * or NULL if the header has not been set. - * - * @deprecated Header handling is being shifted to a Symfony response object. */ function drupal_get_http_header($name = NULL) { $headers = &drupal_static('drupal_http_headers', array()); @@ -1121,9 +1116,7 @@ function drupal_get_http_header($name = NULL) { * Sets the preferred name for the HTTP header. * * Header names are case-insensitive, but for maximum compatibility they should - * follow "common form" (see RFC 2616, section 4.2). - * - * @deprecated Header handling is being shifted to a Symfony response object. + * follow "common form" (see RFC 2617, section 4.2). */ function _drupal_set_preferred_header_name($name = NULL) { static $header_names = array(); @@ -1145,8 +1138,6 @@ function _drupal_set_preferred_header_name($name = NULL) { * @param bool $only_default * (optional) If TRUE and headers have already been sent, send only the * specified headers. - * - * @deprecated Header handling is being shifted to a Symfony response object. */ function drupal_send_headers($default_headers = array(), $only_default = FALSE) { $headers_sent = &drupal_static(__FUNCTION__, FALSE); @@ -1201,8 +1192,6 @@ function drupal_send_headers($default_headers = array(), $only_default = FALSE) * identical. * * @see drupal_page_set_cache() - * - * @deprecated Header handling is being shifted to a Symfony response object. */ function drupal_page_header() { $headers_sent = &drupal_static(__FUNCTION__, FALSE); @@ -1231,24 +1220,26 @@ function drupal_page_header() { * and the conditions match those currently in the cache, a 304 Not Modified * response is sent. */ -function drupal_serve_page_from_cache(stdClass $cache, Response $response, Request $request) { +function drupal_serve_page_from_cache(stdClass $cache) { $config = config('system.performance'); - // First half: we must determine if we should be returning a 304. - // Negotiate whether to use compression. $page_compression = $config->get('response.gzip') && extension_loaded('zlib'); - $return_compressed = $page_compression && $request->server->has('HTTP_ACCEPT_ENCODING') && strpos($request->server->get('HTTP_ACCEPT_ENCODING'), 'gzip') !== FALSE; + $return_compressed = $page_compression && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE; // Get headers. Keys are lower-case. $boot_headers = drupal_get_http_header(); + // Headers generated in this function, that may be replaced or unset using + // drupal_add_http_headers(). Keys are mixed-case. + $default_headers = array(); + foreach ($cache->data['headers'] as $name => $value) { // In the case of a 304 response, certain headers must be sent, and the // remaining may not (see RFC 2616, section 10.3.5). $name_lower = strtolower($name); if (in_array($name_lower, array('content-location', 'expires', 'cache-control', 'vary')) && !isset($boot_headers[$name_lower])) { - $response->headers->set($name, $value); + drupal_add_http_header($name, $value); unset($cache->data['headers'][$name]); } } @@ -1257,40 +1248,39 @@ function drupal_serve_page_from_cache(stdClass $cache, Response $response, Reque // to that one particular client due to Vary: Cookie. Thus, do not set // max-age > 0, allowing the page to be cached by external proxies, when a // session cookie is present unless the Vary header has been replaced. - $max_age = !$request->cookies->has(session_name()) || isset($boot_headers['vary']) ? $config->get('cache.page.max_age') : 0; - $response->headers->set('Cache-Control', 'public, max-age=' . $max_age); + $max_age = !isset($_COOKIE[session_name()]) || isset($boot_headers['vary']) ? $config->get('cache.page.max_age') : 0; + $default_headers['Cache-Control'] = 'public, max-age=' . $max_age; // Entity tag should change if the output changes. - $response->setEtag($cache->created); + $etag = '"' . $cache->created . '-' . intval($return_compressed) . '"'; + header('Etag: ' . $etag); // See if the client has provided the required HTTP headers. - $if_modified_since = $request->server->has('HTTP_IF_MODIFIED_SINCE') ? strtotime($request->server->get('HTTP_IF_MODIFIED_SINCE')) : FALSE; - $if_none_match = $request->server->has('HTTP_IF_NONE_MATCH') ? stripslashes($request->server->get('HTTP_IF_NONE_MATCH')) : FALSE; + $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE; + $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE; if ($if_modified_since && $if_none_match - && $if_none_match == $response->headers->get('etag') // etag must match + && $if_none_match == $etag // etag must match && $if_modified_since == $cache->created) { // if-modified-since must match - $response->setStatusCode(304); + header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified'); + drupal_send_headers($default_headers); return; } - // Second half: we're not returning a 304, so put in other headers. - // Send the remaining headers. foreach ($cache->data['headers'] as $name => $value) { - $response->headers->set($name, $value); drupal_add_http_header($name, $value); } - $response->setLastModified(\DateTime::createFromFormat('U', $cache->created)); + $default_headers['Last-Modified'] = gmdate(DATE_RFC1123, $cache->created); // HTTP/1.0 proxies does not support the Vary header, so prevent any caching // by sending an Expires date in the past. HTTP/1.1 clients ignores the // Expires header if a Cache-Control: max-age= directive is specified (see RFC // 2616, section 14.9.3). - if (!$response->getExpires()) { - $response->setExpires(\DateTime::createFromFormat('j-M-Y H:i:s T', '19-Nov-1978 05:00:00 GMT')); - } + $default_headers['Expires'] = 'Sun, 19 Nov 1978 05:00:00 GMT'; + + drupal_send_headers($default_headers); // Allow HTTP proxies to cache pages for anonymous users without a session // cookie. The Vary header is used to indicates the set of request-header @@ -1298,17 +1288,17 @@ function drupal_serve_page_from_cache(stdClass $cache, Response $response, Reque // response to reply to a subsequent request for a given URL without // revalidation. if (!isset($boot_headers['vary']) && !settings()->get('omit_vary_cookie')) { - $response->setVary('Cookie', FALSE); + header('Vary: Cookie'); } if ($page_compression) { - $response->setVary('accept-encoding', FALSE); + header('Vary: Accept-Encoding', FALSE); // If page_compression is enabled, the cache contains gzipped data. if ($return_compressed) { // $cache->data['body'] is already gzip'ed, so make sure // zlib.output_compression does not compress it once more. ini_set('zlib.output_compression', '0'); - $response->headers->set('content-encoding', 'gzip'); + header('Content-Encoding: gzip'); } else { // The client does not support compression, so unzip the data in the @@ -1317,7 +1307,8 @@ function drupal_serve_page_from_cache(stdClass $cache, Response $response, Reque } } - $response->setContent($cache->data['body']); + // Print the page. + print $cache->data['body']; } /** @@ -1761,15 +1752,18 @@ function drupal_set_title($title = NULL, $output = CHECK_PLAIN) { /** * Generates a default anonymous $user object. * - * @return object + * @return Drupal\user\Plugin\Core\Entity\User * The user object. */ function drupal_anonymous_user() { - return (object) array( + $values = array( 'uid' => 0, 'hostname' => Drupal::request()->getClientIP(), - 'roles' => array(DRUPAL_ANONYMOUS_RID), + 'roles' => array( + DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID, + ), ); + return new User($values, 'user'); } /** @@ -2072,34 +2066,27 @@ function _drupal_bootstrap_page_cache() { $config = config('system.performance'); $cache_enabled = $config->get('cache.page.use_internal'); } - - // @todo this is *criminal*. but, necessary, until we fix bootstrap ordering. - $request = Request::createFromGlobals(); // If there is no session cookie and cache is enabled (or forced), try // to serve a cached page. - if (!$request->cookies->has(session_name()) && $cache_enabled) { + if (!isset($_COOKIE[session_name()]) && $cache_enabled) { // Make sure there is a user object because its timestamp will be checked. $user = drupal_anonymous_user(); // Get the page from the cache. $cache = drupal_page_get_cache(); // If there is a cached page, display it. if (is_object($cache)) { - $response = new Response(); - $response->headers->set('X-Drupal-Cache', 'HIT'); + header('X-Drupal-Cache: HIT'); // Restore the metadata cached with the page. _current_path($cache->data['path']); drupal_set_title($cache->data['title'], PASS_THROUGH); date_default_timezone_set(drupal_get_user_timezone()); - drupal_serve_page_from_cache($cache, $response, $request); - + drupal_serve_page_from_cache($cache); // We are done. - $response->prepare($request); - $response->send(); exit; } else { - drupal_add_http_header('X-Drupal-Cache', 'MISS'); + header('X-Drupal-Cache: MISS'); } } } diff --git a/core/includes/common.inc b/core/includes/common.inc index 37b642d..a8ad43a 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -8,14 +8,11 @@ use Drupal\Core\Language\Language; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Yaml\Parser; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Request; use Drupal\Component\PhpStorage\PhpStorageFactory; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Database\Database; -use Drupal\Core\Routing\GeneratorNotInitializedException; use Drupal\Core\SystemListingInfo; use Drupal\Core\Template\Attribute; @@ -501,14 +498,42 @@ function drupal_get_query_array($query) { /** * Parses an array into a valid, rawurlencoded query string. * - * @see \Drupal\Core\Routing\PathBasedGeneratorInterface::httpBuildQuery() + * This differs from http_build_query() as we need to rawurlencode() (instead of + * urlencode()) all query parameters. + * + * @param $query + * The query parameter array to be processed, e.g. $_GET. + * @param $parent + * Internal use only. Used to build the $query array key for nested items. + * + * @return + * A rawurlencoded string which can be used as or appended to the URL query + * string. + * * @see drupal_get_query_parameters() - * @deprecated as of Drupal 8.0. Use - * Drupal::urlGenerator()->httpBuildQuery() instead. * @ingroup php_wrappers */ function drupal_http_build_query(array $query, $parent = '') { - return Drupal::urlGenerator()->httpBuildQuery($query, $parent); + $params = array(); + + foreach ($query as $key => $value) { + $key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key)); + + // Recurse into children. + if (is_array($value)) { + $params[] = drupal_http_build_query($value, $key); + } + // If a query parameter value is NULL, only append its key. + elseif (!isset($value)) { + $params[] = $key; + } + else { + // For better readability of paths in query strings, we decode slashes. + $params[] = $key . '=' . str_replace('%2F', '/', rawurlencode($value)); + } + } + + return implode('&', $params); } /** @@ -539,7 +564,7 @@ function drupal_get_destination() { } else { $path = current_path(); - $query = Drupal::urlGenerator()->httpBuildQuery(drupal_get_query_parameters()); + $query = drupal_http_build_query(drupal_get_query_parameters()); if ($query != '') { $path .= '?' . $query; } @@ -700,7 +725,8 @@ function drupal_goto($path = '', array $options = array(), $http_response_code = // The 'Location' HTTP header must be absolute. $options['absolute'] = TRUE; - $url = Drupal::urlGenerator()->generateFromPath($path, $options); + $url = url($path, $options); + header('Location: ' . $url, TRUE, $http_response_code); // The "Location" header sends a redirect status code to the HTTP daemon. In @@ -1397,24 +1423,153 @@ function datetime_default_format_type() { * When creating links in modules, consider whether l() could be a better * alternative than url(). * - * @see \Drupal\Core\Routing\PathBasedGeneratorInterface::generateFromPath(). + * @param $path + * (optional) The internal path or external URL being linked to, such as + * "node/34" or "http://example.com/foo". The default value is equivalent to + * passing in ''. A few notes: + * - If you provide a full URL, it will be considered an external URL. + * - If you provide only the path (e.g. "node/34"), it will be + * considered an internal link. In this case, it should be a system URL, + * and it will be replaced with the alias, if one exists. Additional query + * arguments for internal paths must be supplied in $options['query'], not + * included in $path. + * - If you provide an internal path and $options['alias'] is set to TRUE, the + * path is assumed already to be the correct path alias, and the alias is + * not looked up. + * - The special string '' generates a link to the site's base URL. + * - If your external URL contains a query (e.g. http://example.com/foo?a=b), + * then you can either URL encode the query keys and values yourself and + * include them in $path, or use $options['query'] to let this function + * URL encode them. + * @param $options + * (optional) An associative array of additional options, with the following + * elements: + * - 'query': An array of query key/value-pairs (without any URL-encoding) to + * append to the URL. + * - 'fragment': A fragment identifier (named anchor) to append to the URL. + * Do not include the leading '#' character. + * - 'absolute': Defaults to FALSE. Whether to force the output to be an + * absolute link (beginning with http:). Useful for links that will be + * displayed outside the site, such as in an RSS feed. + * - 'alias': Defaults to FALSE. Whether the given path is a URL alias + * already. + * - 'external': Whether the given path is an external URL. + * - 'language': An optional language object. If the path being linked to is + * internal to the site, $options['language'] is used to look up the alias + * for the URL. If $options['language'] is omitted, the language will be + * obtained from language(Language::TYPE_URL). + * - 'https': Whether this URL should point to a secure location. If not + * defined, the current scheme is used, so the user stays on HTTP or HTTPS + * respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS can + * only be enforced when the variable 'https' is set to TRUE. + * - 'base_url': Only used internally, to modify the base URL when a language + * dependent URL requires so. + * - 'prefix': Only used internally, to modify the path when a language + * dependent URL requires so. + * - 'script': Added to the URL between the base path and the path prefix. + * Defaults to empty string when clean URLs are in effect, and to + * 'index.php/' when they are not. + * - 'entity_type': The entity type of the object that called url(). Only + * set if url() is invoked by Drupal\Core\Entity\Entity::uri(). + * - 'entity': The entity object (such as a node) for which the URL is being + * generated. Only set if url() is invoked by Drupal\Core\Entity\Entity::uri(). + * + * @return + * A string containing a URL to the given path. */ function url($path = NULL, array $options = array()) { - $generator = Drupal::urlGenerator(); - try { - $url = $generator->generateFromPath($path, $options); + // Merge in defaults. + $options += array( + 'fragment' => '', + 'query' => array(), + 'absolute' => FALSE, + 'alias' => FALSE, + 'prefix' => '', + 'script' => $GLOBALS['script_path'], + ); + + if (!isset($options['external'])) { + // Return an external link if $path contains an allowed absolute URL. Only + // call the slow drupal_strip_dangerous_protocols() if $path contains a ':' + // before any / ? or #. Note: we could use url_is_external($path) here, but + // that would require another function call, and performance inside url() is + // critical. + $colonpos = strpos($path, ':'); + $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && drupal_strip_dangerous_protocols($path) == $path); } - catch (GeneratorNotInitializedException $e) { - // Fallback to using globals. - // @todo Remove this once there is no code that calls url() when there is - // no request. - global $base_url, $base_path, $script_path; - $generator->setBasePath($base_path); - $generator->setBaseUrl($base_url . '/'); - $generator->setScriptPath($script_path); - $url = $generator->generateFromPath($path, $options); + + // Preserve the original path before altering or aliasing. + $original_path = $path; + + // Allow other modules to alter the outbound URL and options. + drupal_alter('url_outbound', $path, $options, $original_path); + + if (isset($options['fragment']) && $options['fragment'] !== '') { + $options['fragment'] = '#' . $options['fragment']; + } + + if ($options['external']) { + // Split off the fragment. + if (strpos($path, '#') !== FALSE) { + list($path, $old_fragment) = explode('#', $path, 2); + // If $options contains no fragment, take it over from the path. + if (isset($old_fragment) && !$options['fragment']) { + $options['fragment'] = '#' . $old_fragment; + } + } + // Append the query. + if ($options['query']) { + $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . drupal_http_build_query($options['query']); + } + if (isset($options['https']) && settings()->get('mixed_mode_sessions', FALSE)) { + if ($options['https'] === TRUE) { + $path = str_replace('http://', 'https://', $path); + } + elseif ($options['https'] === FALSE) { + $path = str_replace('https://', 'http://', $path); + } + } + // Reassemble. + return $path . $options['fragment']; + } + + global $base_url, $base_secure_url, $base_insecure_url; + + // The base_url might be rewritten from the language rewrite in domain mode. + if (!isset($options['base_url'])) { + if (isset($options['https']) && settings()->get('mixed_mode_sessions', FALSE)) { + if ($options['https'] === TRUE) { + $options['base_url'] = $base_secure_url; + $options['absolute'] = TRUE; + } + elseif ($options['https'] === FALSE) { + $options['base_url'] = $base_insecure_url; + $options['absolute'] = TRUE; + } + } + else { + $options['base_url'] = $base_url; + } + } + + // The special path '' links to the default front page. + if ($path == '') { + $path = ''; + } + elseif (!empty($path) && !$options['alias']) { + $langcode = isset($options['language']) && isset($options['language']->langcode) ? $options['language']->langcode : ''; + $alias = drupal_container()->get('path.alias_manager')->getPathAlias($original_path, $langcode); + if ($alias != $original_path) { + $path = $alias; + } } - return $url; + + $base = $options['absolute'] ? $options['base_url'] . '/' : base_path(); + $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix']; + + $path = drupal_encode_path($prefix . $path); + $query = $options['query'] ? ('?' . drupal_http_build_query($options['query'])) : ''; + return $base . $options['script'] . $path . $query . $options['fragment']; } /** @@ -4234,15 +4389,15 @@ function _drupal_bootstrap_full($skip = FALSE) { * * @see drupal_page_header() */ -function drupal_page_set_cache(Response $response, Request $request) { +function drupal_page_set_cache($body) { global $base_root; if (drupal_page_is_cacheable()) { $cache = (object) array( - 'cid' => $base_root . $request->getRequestUri(), + 'cid' => $base_root . request_uri(), 'data' => array( - 'path' => $request->attributes->get('system_path'), - 'body' => $response->getContent(), + 'path' => current_path(), + 'body' => $body, 'title' => drupal_get_title(), 'headers' => array(), ), @@ -4251,18 +4406,16 @@ function drupal_page_set_cache(Response $response, Request $request) { 'created' => REQUEST_TIME, ); - $cache->data['headers'] = $response->headers->all(); - - // Hack: exclude the x-drupal-cache header; it may make it in here because - // of awkwardness in how we defer sending it over in _drupal_page_get_cache. - if (isset($cache->data['headers']['x-drupal-cache'])) { - unset($cache->data['headers']['x-drupal-cache']); - } - - // Use the actual timestamp from an Expires header, if available. - if ($date = $response->getExpires()) { - $date = new DrupalDateTime($date); - $cache->expire = $date->getTimestamp(); + // Restore preferred header names based on the lower-case names returned + // by drupal_get_http_header(). + $header_names = _drupal_set_preferred_header_name(); + foreach (drupal_get_http_header() as $name_lower => $value) { + $cache->data['headers'][$header_names[$name_lower]] = $value; + if ($name_lower == 'expires') { + // Use the actual timestamp from an Expires header if available. + $date = new DrupalDateTime($value); + $cache->expire = $date->getTimestamp(); + } } if ($cache->data['body']) { @@ -5188,7 +5341,7 @@ function drupal_render_cid_parts($granularity = NULL) { // resource drag for sites with many users, so when a module is being // equivocal, we favor the less expensive 'PER_ROLE' pattern. if ($granularity & DRUPAL_CACHE_PER_ROLE) { - $cid_parts[] = 'r.' . implode(',', $user->roles); + $cid_parts[] = 'r.' . implode(',', array_keys($user->roles)); } elseif ($granularity & DRUPAL_CACHE_PER_USER) { $cid_parts[] = "u.$user->uid"; diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php index 3d2a56a..8984c96 100644 --- a/core/includes/entity.api.php +++ b/core/includes/entity.api.php @@ -548,7 +548,7 @@ function hook_entity_field_info_alter(&$info, $entity_type) { * \Drupal\Core\TypedData\AccessibleInterface::access() for possible values. * @param \Drupal\Core\Entity\Field\Type\Field $field * The entity field object on which the operation is to be performed. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user account to check. * * @return bool|NULL diff --git a/core/includes/form.inc b/core/includes/form.inc index b328625..36e1654 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1320,8 +1320,7 @@ function drupal_redirect_form($form_state) { $function($form_state['redirect']); } } - $request = Drupal::request(); - drupal_goto($request->attributes->get('system_path'), array('query' => $request->query->all())); + drupal_goto(current_path(), array('query' => drupal_container()->get('request')->query->all())); } } diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 225def2..686facb 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -410,8 +410,6 @@ function install_begin_request(&$install_state) { // Register Twig template engine for use during install. CoreBundle::registerTwig($container); - $container->register('url_generator', 'Drupal\Core\Routing\NullGenerator'); - Drupal::setContainer($container); } @@ -1950,14 +1948,7 @@ function install_finished(&$install_state) { $messages = drupal_set_message(); $output = '

' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '

'; - // Ensure the URL that is generated for the home page does not have 'install.php' - // in it. - $request = Request::createFromGlobals(); - $generator = Drupal::urlGenerator(); - $generator->setBasePath(str_replace('/core', '', $request->getBasePath()) . '/'); - $generator->setScriptPath(''); - $url = $generator->generateFromPath(''); - $output .= '

' . (isset($messages['error']) ? st('Review the messages above before visiting your new site.', array('@url' => $url)) : st('Visit your new site.', array('@url' => $url))) . '

'; + $output .= '

' . (isset($messages['error']) ? st('Review the messages above before visiting your new site.', array('@url' => url(''))) : st('Visit your new site.', array('@url' => url('')))) . '

'; // Run cron to populate update status tables (if available) so that users // will be warned if they've installed an out of date Drupal version. diff --git a/core/includes/session.inc b/core/includes/session.inc index c68c33c..17c73d7 100644 --- a/core/includes/session.inc +++ b/core/includes/session.inc @@ -108,8 +108,9 @@ function _drupal_session_read($sid) { // active user. if ($user && $user->uid > 0 && $user->status == 1) { // Add roles element to $user. - $rids = db_query("SELECT ur.rid FROM {users_roles} ur WHERE ur.uid = :uid", array(':uid' => $user->uid))->fetchCol(); - $user->roles = array_merge(array(DRUPAL_AUTHENTICATED_RID), $rids); + $user->roles = array(); + $user->roles[DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID; + $user->roles += db_query("SELECT ur.rid FROM {users_roles} ur WHERE ur.uid = :uid", array(':uid' => $user->uid))->fetchAllKeyed(0, 0); } elseif ($user) { // The user is anonymous or blocked. Only preserve two fields from the diff --git a/core/includes/update.inc b/core/includes/update.inc index 9e6c91d..1af12f1 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -15,7 +15,6 @@ use Drupal\Core\DrupalKernel; use Drupal\Component\Uuid\Uuid; use Drupal\Component\Utility\NestedArray; -use Symfony\Component\HttpFoundation\Request; /** * Minimum schema version of Drupal 7 required for upgrade to Drupal 8. @@ -103,10 +102,8 @@ function update_prepare_d8_bootstrap() { $settings['cache']['default'] = 'cache.backend.memory'; new Settings($settings); - // Enable UpdateBundle service overrides. While the container_bundles array - // does not need a key, let's use so it can be removed once the upgrade are - // finished. @see update_flush_all_caches() - $GLOBALS['conf']['container_bundles']['UpdateBundle'] = 'Drupal\Core\DependencyInjection\UpdateBundle'; + // Enable UpdateBundle service overrides. + $GLOBALS['conf']['container_bundles'][] = 'Drupal\Core\DependencyInjection\UpdateBundle'; // Check whether settings.php needs to be rewritten. $settings_exist = !empty($GLOBALS['config_directories']); @@ -354,6 +351,10 @@ function update_prepare_d8_bootstrap() { ':schema_uninstalled' => SCHEMA_UNINSTALLED, )); + // Populate a fixed module list (again, why did it get lost?) to avoid + // errors due to the drupal_alter() in _system_rebuild_module_data(). + $module_list['system'] = 'core/modules/system/system.module'; + Drupal::moduleHandler()->setModuleList($module_list); $module_data = _system_rebuild_module_data(); // Migrate each extension into configuration, varying by the extension's @@ -451,9 +452,6 @@ function update_prepare_stored_includes() { */ function update_prepare_d8_language() { if (db_table_exists('languages')) { - - module_enable(array('language')); - $languages = db_select('languages', 'l') ->fields('l') ->execute(); @@ -492,6 +490,12 @@ function update_prepare_d8_language() { // Rename the languages table to language. db_rename_table('languages', 'language'); + // Install/enable the language module. We need to use the update specific + // version of this function to ensure schema conflicts don't happen due to + // our updated data. + $modules = array('language'); + update_module_enable($modules); + // Rename language column to langcode and set it again as the primary key. if (db_field_exists('language', 'language')) { db_drop_primary_key('language'); @@ -627,7 +631,7 @@ function update_fix_d8_requirements() { // Make sure that file.module is enabled as it is required for the user // picture upgrade path. - module_enable(array('file')); + update_module_enable(array('file')); $schema = array( 'description' => 'Generic key/value storage table with an expiration.', @@ -667,33 +671,73 @@ function update_fix_d8_requirements() { ); db_create_table('key_value_expire', $schema); - // Views module is required to convert all previously existing listings into - // views configurations. - // Like any other module APIs and services, Views' services are not available - // in update.php. Existing listings are migrated into configuration, using - // the limited standard tools of raw database queries and config(). - module_enable(array('views')); - update_variable_set('update_d8_requirements', TRUE); } } /** - * Forces a module to a given schema version. + * Installs a new module in Drupal 8 via hook_update_N(). * - * This function is rarely necessary. + * @param array $modules + * List of modules to enable. Dependencies are not checked and must be + * ensured by the caller. + * @param bool $update_schema_version + * (optional) The schema version the module should be set to. Defaults to 0 + * which works well for completely new modules. * - * @param string $module - * Name of the module. - * @param string $schema_version - * The schema version the module should be set to. + * @return array + * List of the old schema versions keyed by the module names, + * SCHEMA_UNINSTALLED if it was not installed before. Additional manual + * installation steps like installing default configuration might be necessary + * if the module was not installed before. */ -function update_set_schema($module, $schema_version) { - Drupal::keyValue('system.schema')->set($module, $schema_version); - // system_list_reset() is in module.inc but that would only be available - // once the variable bootstrap is done. - require_once __DIR__ . '/module.inc'; - system_list_reset(); +function update_module_enable(array $modules, $schema_version = 0) { + $schema_store = Drupal::keyValue('system.schema'); + $old_schema = array(); + foreach ($modules as $module) { + // Check for initial schema and install it. The schema version of a newly + // installed module is always 0. Using 8000 here would be inconsistent + // since $module_update_8000() may involve a schema change, and we want + // to install the schema as it was before any updates were added. + module_load_install($module); + $function = $module . '_schema_0'; + if (function_exists($function)) { + $schema = $function(); + foreach ($schema as $table => $spec) { + db_create_table($table, $spec); + } + } + // Enable the module with a weight of 0. + $module_config = config('system.module'); + $module_config + ->set("enabled.$module", 0) + ->set('enabled', module_config_sort($module_config->get('enabled'))) + ->save(); + // Ensure the module is not contained in disabled modules. + config('system.module.disabled') + ->clear($module) + ->save(); + + $current_schema = $schema_store->get($module); + // Set the schema version if the module was not just disabled before. + if ($current_schema === NULL || $current_schema === SCHEMA_UNINSTALLED) { + // Change the schema version to the given value (defaults to 0), so any + // module updates since the module's inception are executed in a core + // upgrade. + $schema_store->set($module, $schema_version); + $old_schema[$module] = SCHEMA_UNINSTALLED; + } + else { + $old_schema[$module] = $current_schema; + } + + // system_list_reset() is in module.inc but that would only be available + // once the variable bootstrap is done. + require_once __DIR__ . '/module.inc'; + system_list_reset(); + // @todo: figure out what to do about hook_install() and hook_enable(). + } + return $old_schema; } /** @@ -891,7 +935,7 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $ */ function update_finished($success, $results, $operations) { // Clear the caches in case the data has been updated. - update_flush_all_caches(); + drupal_flush_all_caches(); $_SESSION['update_results'] = $results; $_SESSION['update_success'] = $success; @@ -1227,7 +1271,7 @@ function update_retrieve_dependencies() { // Nothing to upgrade. continue; } - $function = $module . '_update_dependencies'; + $function = $module . '_update_dependencies'; // Ensure install file is loaded. module_load_install($module); if (function_exists($function)) { diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index 1b3dd4c..d8a68ba 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -361,14 +361,4 @@ public static function token() { return static::$container->get('token'); } - /** - * Returns the url generator service. - * - * @return \Drupal\Core\Routing\UrlGenerator - * The url generator service. - */ - public static function urlGenerator() { - return static::$container->get('url_generator'); - } - } diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index a45d338..913a43b 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -218,7 +218,7 @@ public function deleteMultiple(array $cids) { * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags(). */ public function deleteTags(array $tags) { - $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array()); + $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache'); foreach ($this->flattenTags($tags) as $tag) { unset($tag_cache[$tag]); try { @@ -277,7 +277,7 @@ public function invalidateMultiple(array $cids) { */ public function invalidateTags(array $tags) { try { - $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array()); + $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache'); foreach ($this->flattenTags($tags) as $tag) { unset($tag_cache[$tag]); $this->connection->merge('cache_tags') diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php index 70de42d..6e298da 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterPathProcessorsPass.php @@ -27,15 +27,9 @@ public function process(ContainerBuilder $container) { return; } $manager = $container->getDefinition('path_processor_manager'); - // Add inbound path processors. foreach ($container->findTaggedServiceIds('path_processor_inbound') as $id => $attributes) { $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; $manager->addMethodCall('addInbound', array(new Reference($id), $priority)); } - // Add outbound path processors. - foreach ($container->findTaggedServiceIds('path_processor_outbound') as $id => $attributes) { - $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; - $manager->addMethodCall('addOutbound', array(new Reference($id), $priority)); - } } } diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php b/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php index 91528e5..06a9522 100644 --- a/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php +++ b/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php @@ -32,12 +32,6 @@ public function build(SymfonyContainerBuilder $container) { $container ->register('config.storage', 'Drupal\Core\Config\FileStorage') ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY)); - $container->register('module_handler', 'Drupal\Core\Extension\UpdateModuleHandler') - ->addArgument('%container.modules%'); - $container - ->register("cache_factory", 'Drupal\Core\Cache\MemoryBackendFactory'); - $container - ->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic'); } } diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index f3a8790..bb8e2bb 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -191,8 +191,6 @@ public function resetCache(array $ids = NULL) { } else { $this->entityCache = array(); - $this->entityFieldInfo = NULL; - $this->fieldDefinitions = array(); } } diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 9798515..7ea8b62 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -10,7 +10,6 @@ use Drupal\Component\Uuid\Uuid; use Drupal\Core\Language\Language; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\user\UserInterface; use IteratorAggregate; /** @@ -258,7 +257,7 @@ public function getIterator() { /** * Implements \Drupal\Core\TypedData\AccessibleInterface::access(). */ - public function access($operation = 'view', UserInterface $account = NULL) { + public function access($operation = 'view', \Drupal\user\Plugin\Core\Entity\User $account = NULL) { return \Drupal::entityManager() ->getAccessController($this->entityType) ->access($this, $operation, Language::LANGCODE_DEFAULT, $account); diff --git a/core/lib/Drupal/Core/Entity/EntityAccessController.php b/core/lib/Drupal/Core/Entity/EntityAccessController.php index a4bba1c..da0c003 100644 --- a/core/lib/Drupal/Core/Entity/EntityAccessController.php +++ b/core/lib/Drupal/Core/Entity/EntityAccessController.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Entity; use Drupal\Core\Language\Language; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines a default implementation for entity access controllers. @@ -25,7 +25,7 @@ class EntityAccessController implements EntityAccessControllerInterface { /** * {@inheritdoc} */ - public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, UserInterface $account = NULL) { + public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, User $account = NULL) { // @todo Remove this once we can rely on $account. if (!$account) { @@ -73,14 +73,14 @@ public function access(EntityInterface $entity, $operation, $langcode = Language * 'delete'. * @param string $langcode * The language code for which to check access. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user for which to check access. * * @return bool|null * TRUE if access was granted, FALSE if access was denied and NULL if access * could not be determined. */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { return NULL; } @@ -94,7 +94,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U * 'delete'. * @param string $langcode * The language code for which to check access. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user for which to check access. * * @return bool|null @@ -102,7 +102,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U * is no record for the given user, operation, langcode and entity in the * cache. */ - protected function getCache(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function getCache(EntityInterface $entity, $operation, $langcode, User $account) { $uid = $account ? $account->id() : 0; $uuid = $entity->uuid(); @@ -122,13 +122,13 @@ protected function getCache(EntityInterface $entity, $operation, $langcode, User * 'delete'. * @param string $langcode * The language code for which to check access. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user for which to check access. * * @return bool * TRUE if access was granted, FALSE otherwise. */ - protected function setCache($access, EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function setCache($access, EntityInterface $entity, $operation, $langcode, User $account) { $uid = $account ? $account->id() : 0; $uuid = $entity->uuid(); diff --git a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php index 9f1ab5a..ea93c9d 100644 --- a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php @@ -9,7 +9,7 @@ use Drupal\Core\Language\Language; // @todo Don't depend on module level code. -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines a common interface for entity access controller classes. @@ -27,14 +27,14 @@ * @param string $langcode * (optional) The language code for which to check access. Defaults to * Language::LANGCODE_DEFAULT. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * (optional) The user for which to check access, or NULL to check access * for the current user. Defaults to NULL. * * @return bool * TRUE if access was granted, FALSE otherwise. */ - public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, UserInterface $account = NULL); + public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, User $account = NULL); /** * Clears all cached access checks. diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php index b27dae6..ffb0e0c 100644 --- a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php +++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php @@ -11,7 +11,6 @@ use IteratorAggregate; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\user\UserInterface; /** * Provides backwards compatible (BC) access to entity fields. @@ -214,7 +213,7 @@ function __clone() { /** * Forwards the call to the decorated entity. */ - public function access($operation = 'view', UserInterface $account = NULL) { + public function access($operation = 'view', \Drupal\user\Plugin\Core\Entity\User $account = NULL) { return $this->decorated->access($operation, $account); } diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php index 078094c..2ccbfa8 100644 --- a/core/lib/Drupal/Core/Entity/EntityNG.php +++ b/core/lib/Drupal/Core/Entity/EntityNG.php @@ -527,12 +527,4 @@ public function label($langcode = NULL) { } return $label; } - - /** - * {@inheritdoc} - */ - public function validate() { - // @todo: Add the typed data manager as proper dependency. - return \Drupal::typedData()->getValidator()->validate($this); - } } diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php index 610cb4d..365212a 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php @@ -153,14 +153,6 @@ public function save(EntityInterface $entity); * - translatable: Whether the field is translatable. Defaults to FALSE. * - configurable: A boolean indicating whether the field is configurable * via field.module. Defaults to FALSE. - * - property_constraints: An array of constraint arrays applying to the - * field item properties, keyed by property name. E.g. the following - * validates the value property to have a maximum length of 128: - * @code - * array( - * 'value' => array('Length' => array('max' => 128)), - * ) - * @endcode * * @see Drupal\Core\TypedData\TypedDataManager::create() * @see \Drupal::typedData() diff --git a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php index 7ba7ea6..cb25ab3 100644 --- a/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Entity/Field/FieldItemBase.php @@ -91,7 +91,6 @@ public function set($property_name, $value, $notify = TRUE) { // value that needs to be updated. if (isset($this->properties[$property_name])) { $this->properties[$property_name]->setValue($value, FALSE); - unset($this->values[$property_name]); } // Allow setting plain values for not-defined properties also. else { @@ -137,19 +136,4 @@ public function onChange($property_name) { // updated property object. unset($this->values[$property_name]); } - - /** - * {@inheritdoc} - */ - public function getConstraints() { - $constraints = parent::getConstraints(); - // If property constraints are present add in a ComplexData constraint for - // applying them. - if (!empty($this->definition['property_constraints'])) { - $constraints[] = \Drupal::typedData()->getValidationConstraintManager() - ->create('ComplexData', $this->definition['property_constraints']); - } - return $constraints; - } - -} +} \ No newline at end of file diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php index 2cc58f4..4dc7657 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityTranslation.php @@ -10,7 +10,6 @@ use Drupal\Core\TypedData\AccessibleInterface; use Drupal\Core\TypedData\ComplexDataInterface; use Drupal\Core\TypedData\TypedData; -use Drupal\user\UserInterface; use ArrayIterator; use Drupal\Core\TypedData\TypedDataInterface; use IteratorAggregate; @@ -211,7 +210,7 @@ public function onChange($property_name) { /** * Implements \Drupal\Core\TypedData\AccessibleInterface::access(). */ - public function access($operation = 'view', UserInterface $account = NULL) { + public function access($operation = 'view', \Drupal\user\Plugin\Core\Entity\User $account = NULL) { // Determine the language code of this translation by cutting of the // leading "@" from the property name to get the langcode. // @todo Add a way to set and get the langcode so that's more obvious what diff --git a/core/lib/Drupal/Core/Entity/Field/Type/Field.php b/core/lib/Drupal/Core/Entity/Field/Type/Field.php index c211c53..096d80f 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/Field.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/Field.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Entity\Field\Type; use Drupal\Core\Entity\Field\FieldInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; use Drupal\Core\TypedData\TypedDataInterface; use Drupal\Core\TypedData\ItemList; @@ -145,7 +145,7 @@ public function __unset($property_name) { /** * Implements \Drupal\Core\TypedData\AccessibleInterface::access(). */ - public function access($operation = 'view', UserInterface $account = NULL) { + public function access($operation = 'view', User $account = NULL) { global $user; if (!isset($account) && $user->uid) { $account = user_load($user->uid); @@ -190,23 +190,8 @@ public function access($operation = 'view', UserInterface $account = NULL) { * @return bool * TRUE if access to this field is allowed per default, FALSE otherwise. */ - public function defaultAccess($operation = 'view', UserInterface $account = NULL) { + public function defaultAccess($operation = 'view', User $account = NULL) { // Grant access per default. return TRUE; } - - /** - * {@inheritdoc} - */ - public function getConstraints() { - // Constraints usually apply to the field item, but required does make - // sense on the field only. So we special-case it to apply to the field for - // now. - // @todo: Separate list and list item definitions to separate constraints. - $constraints = array(); - if (!empty($this->definition['required'])) { - $constraints[] = \Drupal::typedData()->getValidationConstraintManager()->create('NotNull', array()); - } - return $constraints; - } } diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index 0b9bbad..163d5c8 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -47,7 +47,6 @@ public function onRespond(FilterResponseEvent $event) { return; } - $request = $event->getRequest(); $response = $event->getResponse(); // Set the X-UA-Compatible HTTP header to force IE to use the most recent @@ -61,7 +60,7 @@ public function onRespond(FilterResponseEvent $event) { // since the page is in fact being regenerated right now. // @todo Remove this and use a more intelligent default so that HTTP // caching can function properly. - $response->setLastModified(new \DateTime(gmdate(DATE_RFC1123, REQUEST_TIME))); + $response->headers->set('Last-Modified', gmdate(DATE_RFC1123, REQUEST_TIME)); // Also give each page a unique ETag. This will force clients to include // both an If-Modified-Since header and an If-None-Match header when doing @@ -83,31 +82,25 @@ public function onRespond(FilterResponseEvent $event) { // identical. // @todo Remove this line as no longer necessary per // http://drupal.org/node/1573064 - $response->setEtag(REQUEST_TIME); + $response->headers->set('ETag', '"' . REQUEST_TIME . '"'); // Authenticated users are always given a 'no-cache' header, and will fetch // a fresh page on every request. This prevents authenticated users from // seeing locally cached pages. // @todo Revisit whether or not this is still appropriate now that the - // Response object does its own cache control processing and we intend to + // Response object does its own cache control procesisng and we intend to // use partial page caching more extensively. // Commit the user session, if needed. drupal_session_commit(); - - // Attach globally-declared headers to the response object so that Symfony - // can send them for us correctly. - // @todo remove this once we have removed all drupal_add_http_header() calls - $headers = drupal_get_http_header(); - foreach ($headers as $name => $value) { - $response->headers->set($name, $value, FALSE); - } - $max_age = config('system.performance')->get('cache.page.max_age'); - if ($max_age > 0 && ($cache = drupal_page_set_cache($response, $request))) { - drupal_serve_page_from_cache($cache, $response, $request); + if ($max_age > 0 && ($cache = drupal_page_set_cache($response->getContent()))) { + drupal_serve_page_from_cache($cache); + // drupal_serve_page_from_cache() already printed the response. + $response->setContent(''); + $response->headers->remove('cache-control'); } else { - $response->setExpires(\DateTime::createFromFormat('j-M-Y H:i:s T', '19-Nov-1978 05:00:00 GMT')); + $response->headers->set('Expires', 'Sun, 19 Nov 1978 05:00:00 GMT'); $response->headers->set('Cache-Control', 'no-cache, must-revalidate, post-check=0, pre-check=0'); } } diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php index a5dc955..5915d4b 100644 --- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php @@ -9,7 +9,6 @@ use Drupal\Core\CacheDecorator\AliasManagerCacheDecorator; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; -use Drupal\Core\Routing\PathBasedGeneratorInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -21,18 +20,7 @@ */ class PathSubscriber extends PathListenerBase implements EventSubscriberInterface { - /** - * The alias manager that caches alias lookups based on the request. - * - * @var \Drupal\Core\CacheDecorator\AliasManagerCacheDecorator - */ protected $aliasManager; - - /** - * A path processor manager for resolving the system path. - * - * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface - */ protected $pathProcessor; public function __construct(AliasManagerCacheDecorator $alias_manager, InboundPathProcessorInterface $path_processor) { @@ -51,14 +39,6 @@ public function onKernelRequestConvertPath(GetResponseEvent $event) { $path = trim($request->getPathInfo(), '/'); $path = $this->pathProcessor->processInbound($path, $request); $request->attributes->set('system_path', $path); - // Also set an attribute that indicates whether we are using clean URLs. - $clean_urls = TRUE; - $base_url = $request->getBaseUrl(); - if (!empty($base_url) && strpos($base_url, $request->getScriptName()) !== FALSE) { - $clean_urls = FALSE; - } - $request->attributes->set('clean_urls', $clean_urls); - // Set the cache key on the alias manager cache decorator. if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $this->aliasManager->setCacheKey($path); } diff --git a/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php b/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php deleted file mode 100644 index 0ef5259..0000000 --- a/core/lib/Drupal/Core/Extension/UpdateModuleHandler.php +++ /dev/null @@ -1,144 +0,0 @@ - $spec) { - db_create_table($table, $spec); - } - } - // Enable the module with a weight of 0. - $module_config = config('system.module'); - $module_config - ->set("enabled.$module", 0) - ->set('enabled', module_config_sort($module_config->get('enabled'))) - ->save(); - // Ensure the module is not contained in disabled modules. - config('system.module.disabled') - ->clear($module) - ->save(); - - $current_schema = $schema_store->get($module); - // Set the schema version if the module was not just disabled before. - if ($current_schema === NULL || $current_schema === SCHEMA_UNINSTALLED) { - // Change the schema version to the given value (defaults to 0), so any - // module updates since the module's inception are executed in a core - // upgrade. - $schema_store->set($module, 0); - $old_schema[$module] = SCHEMA_UNINSTALLED; - } - else { - $old_schema[$module] = $current_schema; - } - - // Copy the default configuration of the module into the active storage. - // The default configuration is not altered in any way, and since the module - // is just being installed, none of its configuration can exist already, so - // this is a plain copy operation from one storage to another. - $module_config_path = drupal_get_path('module', $module) . '/config'; - if (is_dir($module_config_path)) { - $module_filestorage = new FileStorage($module_config_path); - $config_storage = drupal_container()->get('config.storage'); - foreach ($module_filestorage->listAll() as $config_name) { - // If this file already exists, something in the upgrade path went - // completely wrong and we want to know. - if ($config_storage->exists($config_name)) { - throw new ConfigException(format_string('Default configuration file @name of @module module unexpectedly exists already before the module was installed.', array( - '@module' => $module, - '@name' => $config_name, - ))); - } - $config_storage->write($config_name, $module_filestorage->read($config_name)); - } - } - - // system_list_reset() is in module.inc but that would only be available - // once the variable bootstrap is done. - require_once DRUPAL_ROOT . '/core/includes/module.inc'; - system_list_reset(); - $this->moduleList[$module] = drupal_get_filename('module', $module); - $this->load($module); - drupal_classloader_register($module, dirname($this->moduleList[$module])); - // @todo Figure out what to do about hook_install() and hook_enable(). - } - return $old_schema; - } - - /** - * {@inheritdoc} - */ - public function disable($module_list, $disable_dependents = TRUE) { - throw new \LogicException('Disabling modules is not supported during updates'); - } - - /** - * {@inheritdoc} - */ - public function uninstall($module_list = array(), $uninstall_dependents = TRUE) { - throw new \LogicException('Uninstalling modules is not supported during updates'); - } - -} diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index 3dea52a..673e8e3 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -134,7 +134,7 @@ public function reset($type = NULL) { * @return bool * TRUE if more than one language is enabled, FALSE otherwise. */ - public function isMultilingual() { + protected function isMultilingual() { return variable_get('language_count', 1) > 1; } diff --git a/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php b/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php deleted file mode 100644 index 347a877..0000000 --- a/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php +++ /dev/null @@ -1,35 +0,0 @@ -langcode : NULL; - $path = $this->aliasManager->getPathAlias($path, $langcode); - return $path; - } } diff --git a/core/lib/Drupal/Core/PathProcessor/PathProcessorFront.php b/core/lib/Drupal/Core/PathProcessor/PathProcessorFront.php index d03d19b..872885a 100644 --- a/core/lib/Drupal/Core/PathProcessor/PathProcessorFront.php +++ b/core/lib/Drupal/Core/PathProcessor/PathProcessorFront.php @@ -13,7 +13,7 @@ /** * Processes the inbound path by resolving it to the front page if empty. */ -class PathProcessorFront implements InboundPathProcessorInterface, OutboundPathProcessorInterface { +class PathProcessorFront implements InboundPathProcessorInterface { /** * A config factory for retrieving required config settings. @@ -45,15 +45,4 @@ public function processInbound($path, Request $request) { return $path; } - /** - * Implements Drupal\Core\PathProcessor\OutboundPathProcessorInterface::processOutbound(). - */ - public function processOutbound($path, &$options = array(), Request $request = NULL) { - // The special path '' links to the default front page. - if ($path == '') { - $path = ''; - } - return $path; - } - } diff --git a/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php b/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php index db8b799..1d0adff 100644 --- a/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php +++ b/core/lib/Drupal/Core/PathProcessor/PathProcessorManager.php @@ -7,6 +7,7 @@ namespace Drupal\Core\PathProcessor; +use Drupal\Core\PathProcessor\InboundPathProcessorInterface; use Symfony\Component\HttpFoundation\Request; /** @@ -15,10 +16,10 @@ * Holds an array of path processor objects and uses them to sequentially process * a path, in order of processor priority. */ -class PathProcessorManager implements InboundPathProcessorInterface, OutboundPathProcessorInterface { +class PathProcessorManager implements InboundPathProcessorInterface { /** - * Holds the array of inbound processors to cycle through. + * Holds the array of processors to cycle through. * * @var array * An array whose keys are priorities and whose values are arrays of path @@ -27,31 +28,13 @@ class PathProcessorManager implements InboundPathProcessorInterface, OutboundPat protected $inboundProcessors = array(); /** - * Holds the array of inbound processors, sorted by priority. + * Holds the array of processors, sorted by priority. * * @var array * An array of path processor objects. */ protected $sortedInbound = array(); - - /** - * Holds the array of outbound processors to cycle through. - * - * @var array - * An array whose keys are priorities and whose values are arrays of path - * processor objects. - */ - protected $outboundProcessors = array(); - - /** - * Holds the array of outbound processors, sorted by priority. - * - * @var array - * An array of path processor objects. - */ - protected $sortedOutbound = array(); - /** * Adds an inbound processor object to the $inboundProcessors property. * @@ -91,46 +74,6 @@ protected function getInbound() { return $this->sortedInbound; } - - /** - * Adds an outbound processor object to the $outboundProcessors property. - * - * @param \Drupal\Core\PathProcessor\OutboundPathProcessorInterface $processor - * The processor object to add. - * - * @param int $priority - * The priority of the processor being added. - */ - public function addOutbound(OutboundPathProcessorInterface $processor, $priority = 0) { - $this->outboundProcessors[$priority][] = $processor; - $this->sortedOutbound = array(); - } - - /** - * Implements Drupal\Core\PathProcessor\OutboundPathProcessorInterface::processOutbound(). - */ - public function processOutbound($path, &$options = array(), Request $request = NULL) { - $processors = $this->getOutbound(); - foreach ($processors as $processor) { - $path = $processor->processOutbound($path, $options, $request); - } - return $path; - } - - /** - * Returns the sorted array of outbound processors. - * - * @return array - * An array of processor objects. - */ - protected function getOutbound() { - if (empty($this->sortedOutbound)) { - $this->sortedOutbound = $this->sortProcessors('outboundProcessors'); - } - - return $this->sortedOutbound; - } - /** * Sorts the processors according to priority. * diff --git a/core/lib/Drupal/Core/Routing/GeneratorNotInitializedException.php b/core/lib/Drupal/Core/Routing/GeneratorNotInitializedException.php deleted file mode 100644 index ab2922c..0000000 --- a/core/lib/Drupal/Core/Routing/GeneratorNotInitializedException.php +++ /dev/null @@ -1,14 +0,0 @@ -pathProcessor = $path_processor; - $this->mixedModeSessions = $settings->get('mixed_mode_sessions', FALSE); - $allowed_protocols = $config->get('system.filter')->get('protocols') ?: array('http', 'https'); - UrlValidator::setAllowedProtocols($allowed_protocols); - } - - /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setRequest(). - */ - public function setRequest(Request $request) { - $this->request = $request; - // Set some properties, based on the request, that are used during path-based - // url generation. - $this->basePath = $request->getBasePath() . '/'; - $this->baseUrl = $request->getSchemeAndHttpHost() . $this->basePath; - $this->scriptPath = ''; - $base_path_with_script = $request->getBaseUrl(); - $script_name = $request->getScriptName(); - if (!empty($base_path_with_script) && strpos($base_path_with_script, $script_name) !== FALSE) { - $length = strlen($this->basePath); - $this->scriptPath = ltrim(substr($script_name, $length), '/') . '/'; - } + $this->aliasManager = $alias_manager; } /** - * Implements Symfony\Component\Routing\Generator\UrlGeneratorInterface::generate(). + * Implements Symfony\Component\Routing\Generator\UrlGeneratorInterface::generate(); */ public function generate($name, $parameters = array(), $absolute = FALSE) { + $path = parent::generate($name, $parameters, $absolute); - if ($name instanceof SymfonyRoute) { - $route = $name; - } - elseif (null === $route = $this->provider->getRouteByName($name, $parameters)) { - throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', $name)); - } - - // The Route has a cache of its own and is not recompiled as long as it does - // not get modified. - $compiledRoute = $route->compile(); - $hostTokens = $compiledRoute->getHostTokens(); - - $route_requirements = $route->getRequirements(); - // We need to bypass the doGenerate() method's handling of absolute URLs as - // we handle that ourselves after processing the path. - if (isset($route_requirements['_scheme'])) { - $scheme_req = $route_requirements['_scheme']; - unset($route_requirements['_scheme']); - } - $path = $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route_requirements, $compiledRoute->getTokens(), $parameters, $name, FALSE, $hostTokens); - - // The URL returned from doGenerate() will include the base path if there is - // one (i.e., if running in a subdirectory) so we need to strip that off - // before processing the path. - $base_url = $this->context->getBaseUrl(); - if (!empty($base_url) && strpos($path, $base_url) === 0) { - $path = substr($path, strlen($base_url)); - } - - $path = $this->processPath($path); - if (!$absolute || !$host = $this->context->getHost()) { - return $base_url . $path; - } - - // Prepare an absolute URL by getting the correct scheme, host and port from - // the request context. - $scheme = $this->context->getScheme(); - if (isset($scheme_req) && ($req = strtolower($scheme_req)) && $scheme !== $req) { - $scheme = $req; - } - $port = ''; - if ('http' === $scheme && 80 != $this->context->getHttpPort()) { - $port = ':' . $this->context->getHttpPort(); - } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { - $port = ':' . $this->context->getHttpsPort(); - } - return $scheme . '://' . $host . $port . $base_url . $path; - } - - /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::generateFromPath(). - * - * @param $path - * (optional) The internal path or external URL being linked to, such as - * "node/34" or "http://example.com/foo". The default value is equivalent to - * passing in ''. A few notes: - * - If you provide a full URL, it will be considered an external URL. - * - If you provide only the path (e.g. "node/34"), it will be - * considered an internal link. In this case, it should be a system URL, - * and it will be replaced with the alias, if one exists. Additional query - * arguments for internal paths must be supplied in $options['query'], not - * included in $path. - * - If you provide an internal path and $options['alias'] is set to TRUE, the - * path is assumed already to be the correct path alias, and the alias is - * not looked up. - * - The special string '' generates a link to the site's base URL. - * - If your external URL contains a query (e.g. http://example.com/foo?a=b), - * then you can either URL encode the query keys and values yourself and - * include them in $path, or use $options['query'] to let this method - * URL encode them. - * - * @param $options - * (optional) An associative array of additional options, with the following - * elements: - * - 'query': An array of query key/value-pairs (without any URL-encoding) to - * append to the URL. - * - 'fragment': A fragment identifier (named anchor) to append to the URL. - * Do not include the leading '#' character. - * - 'absolute': Defaults to FALSE. Whether to force the output to be an - * absolute link (beginning with http:). Useful for links that will be - * displayed outside the site, such as in an RSS feed. - * - 'alias': Defaults to FALSE. Whether the given path is a URL alias - * already. - * - 'external': Whether the given path is an external URL. - * - 'language': An optional language object. If the path being linked to is - * internal to the site, $options['language'] is used to look up the alias - * for the URL. If $options['language'] is omitted, the language will be - * obtained from language(Language::TYPE_URL). - * - 'https': Whether this URL should point to a secure location. If not - * defined, the current scheme is used, so the user stays on HTTP or HTTPS - * respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS can - * only be enforced when the variable 'https' is set to TRUE. - * - 'base_url': Only used internally, to modify the base URL when a language - * dependent URL requires so. - * - 'prefix': Only used internally, to modify the path when a language - * dependent URL requires so. - * - 'script': Added to the URL between the base path and the path prefix. - * Defaults to empty string when clean URLs are in effect, and to - * 'index.php/' when they are not. - * - 'entity_type': The entity type of the object that called url(). Only - * set if url() is invoked by Drupal\Core\Entity\Entity::uri(). - * - 'entity': The entity object (such as a node) for which the URL is being - * generated. Only set if url() is invoked by Drupal\Core\Entity\Entity::uri(). - * - * @return - * A string containing a URL to the given path. - * - * @throws \Drupal\Core\Routing\GeneratorNotInitializedException. - */ - public function generateFromPath($path = NULL, $options = array()) { - - if (!$this->initialized()) { - throw new GeneratorNotInitializedException(); - } - - // Merge in defaults. - $options += array( - 'fragment' => '', - 'query' => array(), - 'absolute' => FALSE, - 'prefix' => '', - ); - - if (!isset($options['external'])) { - // Return an external link if $path contains an allowed absolute URL. Only - // call the slow drupal_strip_dangerous_protocols() if $path contains a ':' - // before any / ? or #. Note: we could use url_is_external($path) here, but - // that would require another function call, and performance inside url() is - // critical. - $colonpos = strpos($path, ':'); - $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && UrlValidator::stripDangerousProtocols($path) == $path); - } - - if (isset($options['fragment']) && $options['fragment'] !== '') { - $options['fragment'] = '#' . $options['fragment']; - } - - if ($options['external']) { - // Split off the fragment. - if (strpos($path, '#') !== FALSE) { - list($path, $old_fragment) = explode('#', $path, 2); - // If $options contains no fragment, take it over from the path. - if (isset($old_fragment) && !$options['fragment']) { - $options['fragment'] = '#' . $old_fragment; - } - } - // Append the query. - if ($options['query']) { - $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . $this->httpBuildQuery($options['query']); - } - if (isset($options['https']) && $this->mixedModeSessions) { - if ($options['https'] === TRUE) { - $path = str_replace('http://', 'https://', $path); - } - elseif ($options['https'] === FALSE) { - $path = str_replace('https://', 'http://', $path); - } - } - // Reassemble. - return $path . $options['fragment']; - } - else { - $path = ltrim($this->processPath($path, $options), '/'); - } - - if (!isset($options['script'])) { - $options['script'] = $this->scriptPath; - } - // The base_url might be rewritten from the language rewrite in domain mode. - if (!isset($options['base_url'])) { - if (isset($options['https']) && $this->mixedModeSessions) { - if ($options['https'] === TRUE) { - $options['base_url'] = str_replace('http://', 'https://', $this->baseUrl); - $options['absolute'] = TRUE; - } - elseif ($options['https'] === FALSE) { - $options['base_url'] = str_replace('https://', 'http://', $this->baseUrl); - $options['absolute'] = TRUE; - } - } - else { - $options['base_url'] = $this->baseUrl; - } - } - elseif (rtrim($options['base_url'], '/') == $options['base_url']) { - $options['base_url'] .= '/'; - } - $base = $options['absolute'] ? $options['base_url'] : $this->basePath; - $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix']; - - $path = str_replace('%2F', '/', rawurlencode($prefix . $path)); - $query = $options['query'] ? ('?' . $this->httpBuildQuery($options['query'])) : ''; - return $base . $options['script'] . $path . $query . $options['fragment']; - } - - /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setBaseUrl(). - */ - public function setBaseUrl($url) { - $this->baseUrl = $url; - } - - /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setBasePath(). - */ - public function setBasePath($path) { - $this->basePath = $path; - } - - /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setScriptPath(). - */ - public function setScriptPath($path) { - $this->scriptPath = $path; - } - - /** - * Parses an array into a valid, rawurlencoded query string. - * - * This differs from http_build_query() as we need to rawurlencode() (instead of - * urlencode()) all query parameters. - * - * @param $query - * The query parameter array to be processed, e.g. $_GET. - * @param $parent - * Internal use only. Used to build the $query array key for nested items. - * - * @return - * A rawurlencoded string which can be used as or appended to the URL query - * string. - * - * @see drupal_get_query_parameters() - * @ingroup php_wrappers - */ - public function httpBuildQuery(array $query, $parent = '') { - $params = array(); - - foreach ($query as $key => $value) { - $key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key)); - - // Recurse into children. - if (is_array($value)) { - $params[] = $this->httpBuildQuery($value, $key); - } - // If a query parameter value is NULL, only append its key. - elseif (!isset($value)) { - $params[] = $key; - } - else { - // For better readability of paths in query strings, we decode slashes. - $params[] = $key . '=' . str_replace('%2F', '/', rawurlencode($value)); - } - } + // This method is expected to return a path with a leading /, whereas + // the alias manager has no leading /. + $path = '/' . $this->aliasManager->getPathAlias(trim($path, '/')); - return implode('&', $params); - } - - /** - * Passes the path to a processor manager to allow alterations. - */ - protected function processPath($path, &$options = array()) { - // Router-based paths may have a querystring on them. - if ($query_pos = strpos($path, '?')) { - // We don't need to do a strict check here because position 0 would mean we - // have no actual path to work with. - $actual_path = substr($path, 0, $query_pos); - $query_string = substr($path, $query_pos); - } - else { - $actual_path = $path; - $query_string = ''; - } - $path = '/' . $this->pathProcessor->processOutbound(trim($actual_path, '/'), $options, $this->request); - $path .= $query_string; return $path; } - /** - * Returns whether or not the url generator has been initialized. - * - * @return bool - * Returns TRUE if the basePath, baseUrl and scriptPath properties have been - * set, FALSE otherwise. - */ - protected function initialized() { - return isset($this->basePath) && isset($this->baseUrl) && isset($this->scriptPath); - } - } diff --git a/core/lib/Drupal/Core/TypedData/AccessibleInterface.php b/core/lib/Drupal/Core/TypedData/AccessibleInterface.php index a268573..1b0dacd 100644 --- a/core/lib/Drupal/Core/TypedData/AccessibleInterface.php +++ b/core/lib/Drupal/Core/TypedData/AccessibleInterface.php @@ -7,8 +7,6 @@ namespace Drupal\Core\TypedData; -use Drupal\user\UserInterface; - /** * Interface for checking access. */ @@ -24,7 +22,7 @@ * - update * - delete * Defaults to 'view'. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * (optional) The user for which to check access, or NULL to check access * for the current user. Defaults to NULL. * @@ -34,6 +32,6 @@ * * @todo Don't depend on module level code. */ - public function access($operation = 'view', UserInterface $account = NULL); + public function access($operation = 'view', \Drupal\user\Plugin\Core\Entity\User $account = NULL); } diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index 874ca6f..6e6d001 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -304,6 +304,28 @@ public function getValidationConstraintManager() { } /** + * Creates a validation constraint plugin. + * + * @param string $name + * The name or plugin id of the constraint. + * @param mixed $options + * The options to pass to the constraint class. Required and supported + * options depend on the constraint class. + * + * @return \Symfony\Component\Validator\Constraint + * A validation constraint plugin. + */ + public function createValidationConstraint($name, $options) { + if (!is_array($options)) { + // Plugins need an array as configuration, so make sure we have one. + // The constraint classes support passing the options as part of the + // 'value' key also. + $options = array('value' => $options); + } + return $this->getValidationConstraintManager()->createInstance($name, $options); + } + + /** * Gets configured constraints from a data definition. * * Any constraints defined for the data type, i.e. below the 'constraint' key @@ -343,28 +365,29 @@ public function getValidationConstraintManager() { */ public function getConstraints($definition) { $constraints = array(); - $validation_manager = $this->getValidationConstraintManager(); - + // @todo: Figure out how to handle nested constraint structures as + // collections. $type_definition = $this->getDefinition($definition['type']); // Auto-generate a constraint for the primitive type if we have a mapping. if (isset($type_definition['primitive type'])) { - $constraints[] = $validation_manager->create('PrimitiveType', array('type' => $type_definition['primitive type'])); + $constraints[] = $this->getValidationConstraintManager()-> + createInstance('PrimitiveType', array('type' => $type_definition['primitive type'])); } // Add in constraints specified by the data type. if (isset($type_definition['constraints'])) { foreach ($type_definition['constraints'] as $name => $options) { - $constraints[] = $validation_manager->create($name, $options); + $constraints[] = $this->createValidationConstraint($name, $options); } } // Add any constraints specified as part of the data definition. if (isset($definition['constraints'])) { foreach ($definition['constraints'] as $name => $options) { - $constraints[] = $validation_manager->create($name, $options); + $constraints[] = $this->createValidationConstraint($name, $options); } } // Add the NotNull constraint for required data. if (!empty($definition['required']) && empty($definition['constraints']['NotNull'])) { - $constraints[] = $validation_manager->create('NotNull', array()); + $constraints[] = $this->createValidationConstraint('NotNull', array()); } return $constraints; } diff --git a/core/lib/Drupal/Core/Validation/ConstraintManager.php b/core/lib/Drupal/Core/Validation/ConstraintManager.php index 859cfc1..da84d55 100644 --- a/core/lib/Drupal/Core/Validation/ConstraintManager.php +++ b/core/lib/Drupal/Core/Validation/ConstraintManager.php @@ -56,28 +56,6 @@ public function __construct(\Traversable $namespaces) { } /** - * Creates a validation constraint. - * - * @param string $name - * The name or plugin id of the constraint. - * @param mixed $options - * The options to pass to the constraint class. Required and supported - * options depend on the constraint class. - * - * @return \Symfony\Component\Validator\Constraint - * A validation constraint plugin. - */ - public function create($name, $options) { - if (!is_array($options)) { - // Plugins need an array as configuration, so make sure we have one. - // The constraint classes support passing the options as part of the - // 'value' key also. - $options = array('value' => $options); - } - return $this->createInstance($name, $options); - } - - /** * Callback for registering definitions for constraints shipped with Symfony. * * @see ConstraintManager::__construct() diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ComplexDataConstraint.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ComplexDataConstraint.php deleted file mode 100644 index 5eb7f35..0000000 --- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ComplexDataConstraint.php +++ /dev/null @@ -1,67 +0,0 @@ - $options); - } - parent::__construct($options); - $constraint_manager = \Drupal::service('validation.constraint'); - - // Instantiate constraint objects for array definitions. - foreach ($this->properties as &$constraints) { - foreach ($constraints as $id => $options) { - if (!is_object($options)) { - $constraints[$id] = $constraint_manager->create($id, $options); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function getDefaultOption() { - return 'properties'; - } - - /** - * {@inheritdoc} - */ - public function getRequiredOptions() { - return array('properties'); - } -} diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ComplexDataConstraintValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ComplexDataConstraintValidator.php deleted file mode 100644 index 31ffc5b..0000000 --- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ComplexDataConstraintValidator.php +++ /dev/null @@ -1,47 +0,0 @@ -context->getGroup(); - - foreach ($constraint->properties as $name => $constraints) { - $property = $value->get($name); - $is_container = $property instanceof ComplexDataInterface || $property instanceof ListInterface; - if (!$is_container) { - $property = $property->getValue(); - } - elseif ($property->isEmpty()) { - // @see \Drupal\Core\TypedData\Validation\PropertyContainerMetadata::accept(); - $property = NULL; - } - $this->context->validateValue($property, $constraints, $name, $group); - } - } -} diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 045cccf..d1fd1e5 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -84,7 +84,7 @@ Drupal.behaviors.AJAX = { */ Drupal.AjaxError = function(xmlhttp, uri) { - var statusCode, statusText, pathText, responseText, readyStateText; + var statusCode, statusText, pathText, responseText, readyStateText, message; if (xmlhttp.status) { statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status}); } diff --git a/core/modules/block/block.install b/core/modules/block/block.install index 8393d9b..8e0d224 100644 --- a/core/modules/block/block.install +++ b/core/modules/block/block.install @@ -180,7 +180,7 @@ function block_update_8005() { * Enable the Custom Block module. */ function block_update_8006() { - module_enable(array('custom_block')); + update_module_enable(array('custom_block')); } /** @@ -247,22 +247,22 @@ function block_update_8008() { // First, create the body field. $body_field = array( - 'id' => 'block_body', + 'field_name' => 'block_body', 'type' => 'text_with_summary', 'entity_types' => array('custom_block'), 'module' => 'text', 'cardinality' => 1, ); - _update_8003_field_create_field($body_field); + _update_7000_field_create_field($body_field); $instance = array( - 'id' => 'custom_block.basic.block_body', + 'field_name' => 'block_body', 'entity_type' => 'custom_block', 'bundle' => 'basic', 'label' => 'Block body', 'settings' => array('display_summary' => FALSE), ); - _update_8003_field_create_instance($body_field, $instance); + _update_7000_field_create_instance($body_field, $instance); module_load_install('entity'); // Assign form settings for the 'default' form mode. @@ -311,7 +311,7 @@ function block_update_8008() { ); // This is a core update and no contrib modules are enabled yet, so // we can assume default field storage for a faster update. - _update_8000_field_sql_storage_write('custom_block', 'basic', $block->bid, $block->bid, 'block_body', $data); + _update_7000_field_sql_storage_write('custom_block', 'basic', $block->bid, $block->bid, 'block_body', $data); $sandbox['last'] = $block->bid; $sandbox['count'] += 1; diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php index c8cc35a..69aee17 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php @@ -8,7 +8,7 @@ namespace Drupal\custom_block; use Drupal\Core\Entity\EntityInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; use Drupal\Core\Entity\EntityAccessController; /** @@ -19,7 +19,7 @@ class CustomBlockAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { if ($operation === 'view') { return TRUE; } diff --git a/core/modules/block/lib/Drupal/block/BlockAccessController.php b/core/modules/block/lib/Drupal/block/BlockAccessController.php index ec6b417..693fb32 100644 --- a/core/modules/block/lib/Drupal/block/BlockAccessController.php +++ b/core/modules/block/lib/Drupal/block/BlockAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Provides a Block access controller. @@ -19,7 +19,7 @@ class BlockAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { // Currently, only view access is implemented. if ($operation != 'view') { return FALSE; @@ -43,7 +43,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U // For blocks with roles associated, if none of the user's roles matches // the settings from this block, access is denied. $visibility = $entity->get('visibility'); - if (!empty($visibility['role']['roles']) && !array_intersect(array_filter($visibility['role']['roles']), $user->roles)) { + if (!empty($visibility['role']['roles']) && !array_intersect(array_filter($visibility['role']['roles']), array_keys($user->roles))) { // No match. return FALSE; } diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 629249f..0415f3a 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -1552,7 +1552,7 @@ function comment_prepare_author(Comment $comment) { if (!$account) { $account = entity_create('user', array('uid' => 0, 'name' => $comment->name->value, 'homepage' => $comment->homepage->value)); } - return $account->getBCEntity(); + return $account; } /** diff --git a/core/modules/comment/comment.tokens.inc b/core/modules/comment/comment.tokens.inc index 213f352..d938c27 100644 --- a/core/modules/comment/comment.tokens.inc +++ b/core/modules/comment/comment.tokens.inc @@ -218,7 +218,7 @@ function comment_tokens($type, $tokens, array $data = array(), array $options = } if (($author_tokens = $token_service->findwithPrefix($tokens, 'author')) && $account = $comment->uid->entity) { - $replacements += $token_service->generate('user', $author_tokens, array('user' => $account->getBCEntity()), $options); + $replacements += $token_service->generate('user', $author_tokens, array('user' => $account), $options); } } elseif ($type == 'node' & !empty($data['node'])) { diff --git a/core/modules/comment/lib/Drupal/comment/CommentAccessController.php b/core/modules/comment/lib/Drupal/comment/CommentAccessController.php index 1b06b07..b20d850 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentAccessController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Access controller for the comment entity. @@ -21,7 +21,7 @@ class CommentAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { switch ($operation) { case 'view': return user_access('access comments', $account); diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php index 6f61a65..315ab40 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php @@ -52,8 +52,7 @@ function testCommentLinks() { // Remove additional user permissions from $this->web_user added by setUp(), // since this test is limited to anonymous and authenticated roles only. - $roles = $this->web_user->roles; - entity_delete_multiple('user_role', array(reset($roles))); + entity_delete_multiple('user_role', array(key($this->web_user->roles))); // Matrix of possible environmental conditions and configuration settings. // See setEnvironment() for details. diff --git a/core/modules/contact/lib/Drupal/contact/CategoryAccessController.php b/core/modules/contact/lib/Drupal/contact/CategoryAccessController.php index 9009337..91114a7 100644 --- a/core/modules/contact/lib/Drupal/contact/CategoryAccessController.php +++ b/core/modules/contact/lib/Drupal/contact/CategoryAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines an access controller for the contact category entity. @@ -21,7 +21,7 @@ class CategoryAccessController extends EntityAccessController { /** * {@inheritdoc} */ - public function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + public function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { if ($operation == 'delete' || $operation == 'update') { // Do not allow delete 'personal' category used for personal contact form. return user_access('administer contact forms', $account) && $entity->id() !== 'personal'; diff --git a/core/modules/contact/lib/Drupal/contact/MessageFormController.php b/core/modules/contact/lib/Drupal/contact/MessageFormController.php index 723b8ca..c8bc85b 100644 --- a/core/modules/contact/lib/Drupal/contact/MessageFormController.php +++ b/core/modules/contact/lib/Drupal/contact/MessageFormController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityFormController; use Drupal\Core\Language\Language; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Form controller for contact message forms. @@ -167,7 +167,7 @@ public function save(array $form, array &$form_state) { $to = implode(', ', $category->recipients); $recipient_langcode = language_default()->langcode; } - elseif ($message->recipient instanceof UserInterface) { + elseif ($message->recipient instanceof User) { // Send to the user in the user's preferred language. $to = $message->recipient->mail; $recipient_langcode = user_preferred_langcode($message->recipient); @@ -211,7 +211,7 @@ public function save(array $form, array &$form_state) { // To avoid false error messages caused by flood control, redirect away from // the contact form; either to the contacted user account or the front page. - if ($message->recipient instanceof UserInterface && user_access('access user profiles')) { + if ($message->recipient instanceof User && user_access('access user profiles')) { $uri = $message->recipient->uri(); $form_state['redirect'] = array($uri['path'], $uri['options']); } diff --git a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php index d2018ac..51e9a51 100644 --- a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php +++ b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualUnitTest.php @@ -7,12 +7,12 @@ namespace Drupal\contextual\Tests; -use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\simpletest\UnitTestBase; /** * Tests _contextual_links_to_id() & _contextual_id_to_links(). */ -class ContextualUnitTest extends DrupalUnitTestBase { +class ContextualUnitTest extends UnitTestBase { public static function getInfo() { return array( 'name' => 'Conversion to and from "contextual id"s (for placeholders)', diff --git a/core/modules/field/field.install b/core/modules/field/field.install index ca367ee..24b2950 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -9,89 +9,217 @@ use Drupal\field\Plugin\Core\Entity\Field; /** - * Creates a field by writing directly to configuration. - * - * Upgrades using this function need to use hook_update_dependencies() to ensure - * they get executed after field_update_8003(). - * - * @param array $field_config - * An array of field properties. + * Creates a field by writing directly to the database. * * @ingroup update_api */ -function _update_8003_field_create_field(array &$field_config) { - $uuid = new Uuid(); - - // Merge in default values. - $field_config += array( - 'uuid' => $uuid->generate(), +function _update_7000_field_create_field(&$field) { + // Merge in default values.` + $field += array( 'entity_types' => array(), 'cardinality' => 1, 'translatable' => FALSE, 'locked' => FALSE, 'settings' => array(), 'indexes' => array(), + 'deleted' => FALSE, 'active' => TRUE, - 'status' => 1, - 'langcode' => 'und', ); - // Set the storage. - $field_config['storage'] = array( + // Set storage. + $field['storage'] = array( 'type' => 'field_sql_storage', + 'settings' => array(), 'module' => 'field_sql_storage', 'active' => TRUE, - 'settings' => array(), ); - // Save in config. - Drupal::config('field.field.' . $field_config['id']) - ->setData($field_config) - ->save(); - update_config_manifest_add('field.field', array($field_config['id'])); + // Fetch the field schema to initialize columns and indexes. The field module + // is not guaranteed to be loaded at this point. + module_load_install($field['module']); + $schema = (array) module_invoke($field['module'], 'field_schema', $field); + $schema += array('columns' => array(), 'indexes' => array()); + // 'columns' are hardcoded in the field type. + $field['columns'] = $schema['columns']; + // 'indexes' can be both hardcoded in the field type, and specified in the + // incoming $field definition. + $field['indexes'] += $schema['indexes']; + + // The serialized 'data' column contains everything from $field that does not + // have its own column and is not automatically populated when the field is + // read. + $data = $field; + unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']); + // Additionally, do not save the 'bundles' property populated by + // field_info_field(). + unset($data['bundles']); + + // Write the field to the database. + $record = array( + 'field_name' => $field['field_name'], + 'type' => $field['type'], + 'module' => $field['module'], + 'active' => (int) $field['active'], + 'storage_type' => $field['storage']['type'], + 'storage_module' => $field['storage']['module'], + 'storage_active' => (int) $field['storage']['active'], + 'locked' => (int) $field['locked'], + 'data' => serialize($data), + 'cardinality' => $field['cardinality'], + 'translatable' => (int) $field['translatable'], + 'deleted' => (int) $field['deleted'], + ); + // We don't use drupal_write_record() here because it depends on the schema. + $field_id = db_insert('field_config') + ->fields($record) + ->execute(); // Create storage for the field. This requires a field entity, but cannot use // the regular entity_create() function here. - $field_entity = new Field($field_config); + $field_entity = new Field($field); field_sql_storage_field_storage_create_field($field_entity); + + $field['id'] = $field_id; } /** - * Writes a field instance directly to configuration. + * Deletes a field stored in SQL storage directly from the database. * - * Upgrades using this function need to use hook_update_dependencies() to ensure - * they get executed after field_update_8003(). + * To protect user data, this function can only be used to delete fields once + * all information it stored is gone. Delete all data from the + * field_data_$field_name table before calling by either manually issuing + * delete queries against it or using _update_7000_field_delete_instance(). * - * @param array $field_config - * An array of field properties. - * @param array $instance_config - * An array of field instance properties. + * @param $field_name + * The field name to delete. * * @ingroup update_api */ -function _update_8003_field_create_instance(array $field_config, array &$instance_config) { - $uuid = new Uuid(); +function _update_7000_field_delete_field($field_name) { + $table_name = 'field_data_' . $field_name; + if (db_select($table_name)->range(0, 1)->countQuery()->execute()->fetchField()) { + $t = get_t(); + throw new Exception($t('This function can only be used to delete fields without data')); + } + // Delete all instances. + db_delete('field_config_instance') + ->condition('field_name', $field_name) + ->execute(); + + // Nuke field data and revision tables. + db_drop_table($table_name); + db_drop_table('field_revision_' . $field_name); + + // Delete the field. + db_delete('field_config') + ->condition('field_name', $field_name) + ->execute(); +} + +/** + * Deletes an instance and all its data of a field stored in SQL Storage. + * + * BEWARE: This function deletes user data from the field storage tables. + * + * @ingroup update_api + */ +function _update_7000_field_delete_instance($field_name, $entity_type, $bundle) { + // Delete field instance configuration data. + db_delete('field_config_instance') + ->condition('field_name', $field_name) + ->condition('entity_type', $entity_type) + ->condition('bundle', $bundle) + ->execute(); + + // Nuke data. + db_delete('field_data_' . $field_name) + ->condition('entity_type', $entity_type) + ->condition('bundle', $bundle) + ->execute(); + db_delete('field_revision_' . $field_name) + ->condition('entity_type', $entity_type) + ->condition('bundle', $bundle) + ->execute(); +} + +/** + * Fetches all of the field definitions from the database. + * + * Warning: Unlike the field_read_fields() API function, this function returns + * all fields by default, including deleted and inactive fields, unless + * specified otherwise in the $conditions parameter. + * + * @param $conditions + * An array of conditions to limit the select query to. + * @param $key + * The name of the field property the return array is indexed by. Using + * anything else than 'id' might cause incomplete results if the $conditions + * do not filter out deleted fields. + * + * @return + * An array of fields matching $conditions, keyed by the property specified + * by the $key parameter. + * @ingroup update_api + */ +function _update_7000_field_read_fields(array $conditions = array(), $key = 'id') { + $fields = array(); + $query = db_select('field_config', 'fc', array('fetch' => PDO::FETCH_ASSOC)) + ->fields('fc'); + foreach ($conditions as $column => $value) { + $query->condition($column, $value); + } + foreach ($query->execute() as $record) { + $field = unserialize($record['data']); + $field['id'] = $record['id']; + $field['field_name'] = $record['field_name']; + $field['type'] = $record['type']; + $field['module'] = $record['module']; + $field['active'] = $record['active']; + $field['storage']['type'] = $record['storage_type']; + $field['storage']['module'] = $record['storage_module']; + $field['storage']['active'] = $record['storage_active']; + $field['locked'] = $record['locked']; + $field['cardinality'] = $record['cardinality']; + $field['translatable'] = $record['translatable']; + $field['deleted'] = $record['deleted']; + + $fields[$field[$key]] = $field; + } + return $fields; +} +/** + * Writes a field instance directly to the database. + * + * @ingroup update_api + */ +function _update_7000_field_create_instance($field, &$instance) { // Merge in defaults. - $instance_config += array( + $instance += array( + 'field_id' => $field['id'], + 'field_name' => $field['field_name'], + 'deleted' => FALSE, 'description' => '', 'required' => FALSE, - 'uuid' => $uuid->generate(), - 'field_uuid' => $field_config['uuid'], - 'field_type' => $field_config['type'], - 'default_value' => array(), - 'default_value_function' => '', - 'settings' => array(), - 'widget' => array(), - 'status' => 1, - 'langcode' => 'und', ); - // Save in config. - Drupal::config('field.instance.' . $instance_config['id']) - ->setData($instance_config) - ->save(); - update_config_manifest_add('field.instance', array($instance_config['id'])); + // The serialized 'data' column contains everything from $instance that does + // not have its own column and is not automatically populated when the + // instance is read. + $data = $instance; + unset($data['id'], $data['field_id'], $data['field_name'], $data['entity_type'], $data['bundle'], $data['deleted']); + + $record = array( + 'field_id' => $instance['field_id'], + 'field_name' => $instance['field_name'], + 'entity_type' => $instance['entity_type'], + 'bundle' => $instance['bundle'], + 'data' => serialize($data), + 'deleted' => (int) $instance['deleted'], + ); + $instance['id'] = db_insert('field_config_instance') + ->fields($record) + ->execute(); } /** @@ -100,6 +228,22 @@ function _update_8003_field_create_instance(array $field_config, array &$instanc */ /** + * Implements hook_update_dependencies(). + */ +function field_update_dependencies() { + // Convert Field API to ConfigEntities after: + $dependencies['field'][8003] = array( + // - Custom block bodies have been turned to fields. + 'block' => 8008, + // - User pictures have been turned to fields. + 'user' => 8011, + // - The {file_usage}.id column has moved to varchar. + 'file' => 8001, + ); + return $dependencies; +} + +/** * Empty update - moved into field_update_8003(). */ function field_update_8001() { diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc index 4e7253e..59d068b 100644 --- a/core/modules/file/file.field.inc +++ b/core/modules/file/file.field.inc @@ -249,7 +249,7 @@ function file_field_update(EntityInterface $entity, $field, $instance, $langcode } // Compare the original field values with the ones that are being saved. - $original = $entity->original->getBCEntity(); + $original = $entity->original; $original_fids = array(); if (!empty($original->{$field['field_name']}[$langcode])) { foreach ($original->{$field['field_name']}[$langcode] as $original_item) { diff --git a/core/modules/file/file.install b/core/modules/file/file.install index 7ce65bb..2327bb3 100644 --- a/core/modules/file/file.install +++ b/core/modules/file/file.install @@ -234,18 +234,6 @@ function file_requirements($phase) { } /** - * Implements hook_update_dependencies(). - */ -function file_update_dependencies() { - // Convert fields and instances to ConfigEntities after the {file_usage}.id - // column has moved to varchar. - $dependencies['field'][8003] = array( - 'file' => 8001, - ); - return $dependencies; -} - -/** * Converts default_file_main variable to config. * * @ingroup config_upgrade diff --git a/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php b/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php index 2c1278f..0763507 100644 --- a/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/DownloadTest.php @@ -7,8 +7,6 @@ namespace Drupal\file\Tests; -use Symfony\Component\HttpFoundation\Request; - /** * Tests for download/file transfer functions. */ @@ -86,6 +84,7 @@ function testPrivateFileTransfer() { * Test file_create_url(). */ function testFileCreateUrl() { + global $base_url, $script_path; // Tilde (~) is excluded from this test because it is encoded by // rawurlencode() in PHP 5.2 but not in PHP 5.3, as per RFC 3986. @@ -101,18 +100,12 @@ function testFileCreateUrl() { // generated by url(), whereas private files should be served by Drupal, so // their URLs should be generated by url(). The difference is most apparent // when $script_path is not empty (i.e., when not using clean URLs). - $clean_url_settings = array( - 'clean' => '', - 'unclean' => 'index.php/', - ); - $generator = $this->container->get('url_generator'); - foreach ($clean_url_settings as $clean_url_setting => $script_path) { - $clean_urls = $clean_url_setting == 'clean'; - $request = $this->prepareRequestForGenerator($clean_urls); - $base_path = $request->getSchemeAndHttpHost() . $request->getBasePath(); - $this->checkUrl('public', '', $basename, $base_path . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded); - $this->checkUrl('private', '', $basename, $base_path . '/' . $script_path . 'system/files/' . $basename_encoded); + $script_path_original = $script_path; + foreach (array('', 'index.php/') as $script_path) { + $this->checkUrl('public', '', $basename, $base_url . '/' . file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath() . '/' . $basename_encoded); + $this->checkUrl('private', '', $basename, $base_url . '/' . $script_path . 'system/files/' . $basename_encoded); } + $script_path = $script_path_original; } /** diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php index 0b652c7..359c6b3 100644 --- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php @@ -241,7 +241,7 @@ function testPrivateFileComment() { $user = $this->drupalCreateUser(array('access comments')); // Grant the admin user required comment permissions. - user_role_grant_permissions($this->admin_user->roles[1], array('administer comment fields')); + user_role_grant_permissions(key($this->admin_user->roles), array('administer comment fields')); // Revoke access comments permission from anon user, grant post to // authenticated. diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php index 87ca50c..c811425 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php @@ -177,7 +177,9 @@ function testFormatPermissions() { */ function testFormatRoles() { // Get the role ID assigned to the regular user. - $rid = $this->web_user->roles[0]; + $roles = $this->web_user->roles; + unset($roles[DRUPAL_AUTHENTICATED_RID]); + $rid = key($roles); // Check that this role appears in the list of roles that have access to an // allowed text format, but does not appear in the list of roles that have diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php index f8c0479..9f4b89a 100644 --- a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php +++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php @@ -467,7 +467,7 @@ function testForumWithNewPost() { // Login as the first user. $this->drupalLogin($this->admin_user); // Create a forum container. - $this->forumContainer = $this->createForum('container'); + $this->container = $this->createForum('container'); // Create a forum. $this->forum = $this->createForum('forum'); // Create a topic. diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 2304c7d..17bb491 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -723,14 +723,12 @@ function image_style_flush($style) { * The name of the style to be used with this image. * @param $path * The path to the image. - * @param $clean_urls - * (optional) Whether clean URLs are in use. * @return * The absolute URL where a style image can be downloaded, suitable for use * in an tag. Requesting the URL will cause the image to be created. * @see image_style_deliver() */ -function image_style_url($style_name, $path, $clean_urls = NULL) { +function image_style_url($style_name, $path) { $uri = image_style_path($style_name, $path); // The token query is added even if the // 'image.settings:allow_insecure_derivatives' configuration is TRUE, so that @@ -745,22 +743,11 @@ function image_style_url($style_name, $path, $clean_urls = NULL) { $token_query = array(IMAGE_DERIVATIVE_TOKEN => image_style_path_token($style_name, file_stream_wrapper_uri_normalize($path))); } - if ($clean_urls === NULL) { - // Assume clean URLs unless the request tells us otherwise. - $clean_urls = TRUE; - try { - $request = Drupal::request(); - $clean_urls = $request->attributes->get('clean_urls'); - } - catch (ServiceNotFoundException $e) { - } - } - // If not using clean URLs, the image derivative callback is only available // with the script path. If the file does not exist, use url() to ensure // that it is included. Once the file exists it's fine to fall back to the // actual file path, this avoids bootstrapping PHP once the files are built. - if ($clean_urls === FALSE && file_uri_scheme($uri) == 'public' && !file_exists($uri)) { + if ($GLOBALS['script_path'] && file_uri_scheme($uri) == 'public' && !file_exists($uri)) { $directory_path = file_stream_wrapper_get_instance_by_uri($uri)->getDirectoryPath(); return url($directory_path . '/' . file_uri_target($uri), array('absolute' => TRUE, 'query' => $token_query)); } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php index 1b9e2db..52d3f4a 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php @@ -8,7 +8,6 @@ namespace Drupal\image\Tests; use Drupal\simpletest\WebTestBase; -use Symfony\Component\HttpFoundation\Request; /** * Tests the functions for generating paths and URLs for image styles. @@ -105,7 +104,8 @@ function testImageStyleUrlForMissingSourceImage() { * Tests image_style_url(). */ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE, $extra_slash = FALSE) { - $request = $this->prepareRequestForGenerator($clean_url); + $script_path_original = $GLOBALS['script_path']; + $GLOBALS['script_path'] = $clean_url ? '' : 'index.php/'; // Make the default scheme neither "public" nor "private" to verify the // functions work for other than the default scheme. @@ -129,7 +129,7 @@ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE, $extra_slash = FA // Get the URL of a file that has not been generated and try to create it. $generated_uri = image_style_path($this->style_name, $original_uri); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $generate_url = image_style_url($this->style_name, $original_uri, $clean_url); + $generate_url = image_style_url($this->style_name, $original_uri); // Ensure that the tests still pass when the file is generated by accessing // a poorly constructed (but still valid) file URL that has an extra slash @@ -137,10 +137,11 @@ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE, $extra_slash = FA if ($extra_slash) { $modified_uri = str_replace('://', ':///', $original_uri); $this->assertNotEqual($original_uri, $modified_uri, 'An extra slash was added to the generated file URI.'); - $generate_url = image_style_url($this->style_name, $modified_uri, $clean_url); + $generate_url = image_style_url($this->style_name, $modified_uri); } - if (!$clean_url) { - $this->assertTrue(strpos($generate_url, 'index.php/') !== FALSE, 'When using non-clean URLS, the system path contains the script name.'); + + if ($GLOBALS['script_path']) { + $this->assertTrue(strpos($generate_url, $GLOBALS['script_path']) !== FALSE, 'When using non-clean URLS, the system path contains the script name.'); } // Add some extra chars to the token. $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url)); @@ -193,7 +194,7 @@ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE, $extra_slash = FA $this->assertNoRaw( chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10), 'No PNG signature found in the response body.'); } } - elseif ($clean_url) { + elseif (!$GLOBALS['script_path']) { // Add some extra chars to the token. $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url)); $this->assertResponse(200, 'Existing image was accessible at the URL wih an invalid token.'); @@ -218,10 +219,11 @@ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE, $extra_slash = FA config('image.settings')->set('suppress_itok_output', TRUE)->save(); $generated_uri = image_style_path($this->style_name, $original_uri); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $generate_url = image_style_url($this->style_name, $original_uri, $clean_url); + $generate_url = image_style_url($this->style_name, $original_uri); $this->assertIdentical(strpos($generate_url, IMAGE_DERIVATIVE_TOKEN . '='), FALSE, 'The security token does not appear in the image style URL.'); $this->drupalGet($generate_url); $this->assertResponse(200, 'Image was accessible at the URL with a missing token.'); + $GLOBALS['script_path'] = $script_path_original; } } diff --git a/core/modules/language/language.install b/core/modules/language/language.install index 17828fd..b16c53b 100644 --- a/core/modules/language/language.install +++ b/core/modules/language/language.install @@ -117,13 +117,3 @@ function language_disable() { // will be FALSE, because the language module is disabled. variable_set('language_count', 1); } - -/** - * Implements hook_requirements(). - */ -function language_requirements($phase) { - if ($phase == 'update') { - // Load the include files to make constants available for updates. - language_negotiation_include(); - } -} diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 6b45fa1..a6ab9d2 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -634,6 +634,7 @@ function language_language_negotiation_info() { 'callbacks' => array( 'negotiation' => 'language_from_url', 'language_switch' => 'language_switcher_url', + 'url_rewrite' => 'language_url_rewrite_url', ), 'file' => $file, 'weight' => -8, @@ -770,6 +771,56 @@ function language_preprocess_block(&$variables) { } /** + * Implements hook_url_outbound_alter(). + * + * Rewrite outbound URLs with language based prefixes. + */ +function language_url_outbound_alter(&$path, &$options, $original_path) { + // Only modify internal URLs. + if (!$options['external'] && language_multilingual()) { + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['callbacks'] = &drupal_static(__FUNCTION__); + } + $callbacks = &$drupal_static_fast['callbacks']; + + if (!isset($callbacks)) { + $callbacks = array(); + include_once DRUPAL_ROOT . '/core/includes/language.inc'; + + foreach (language_types_get_configurable() as $type) { + // Get URL rewriter callbacks only from enabled language methods. + $negotiation = variable_get("language_negotiation_$type", array()); + + foreach ($negotiation as $method_id => $method) { + if (isset($method['callbacks']['url_rewrite'])) { + if (isset($method['file'])) { + require_once DRUPAL_ROOT . '/' . $method['file']; + } + // Avoid duplicate callback entries. + $callbacks[$method['callbacks']['url_rewrite']] = TRUE; + } + } + } + + $callbacks = array_keys($callbacks); + } + + // No language dependent path allowed in this mode. + if (empty($callbacks)) { + unset($options['language']); + return; + } + + foreach ($callbacks as $callback) { + if (function_exists($callback)) { + $callback($path, $options); + } + } + } +} + +/** * Returns language mappings between browser and Drupal language codes. * * @return array diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index 82bf713..d205d76 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -425,6 +425,83 @@ function language_switcher_session($type, $path) { } /** + * Rewrite URLs for the URL language negotiation method. + */ +function language_url_rewrite_url(&$path, &$options) { + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['languages'] = &drupal_static(__FUNCTION__); + } + $languages = &$drupal_static_fast['languages']; + + if (!isset($languages)) { + $languages = language_list(); + $languages = array_flip(array_keys($languages)); + } + + // Language can be passed as an option, or we go for current URL language. + if (!isset($options['language'])) { + $language_url = language(Language::TYPE_URL); + $options['language'] = $language_url; + } + // We allow only enabled languages here. + elseif (is_object($options['language']) && !isset($languages[$options['language']->langcode])) { + unset($options['language']); + return; + } + + if (isset($options['language'])) { + switch (config('language.negotiation')->get('url.source')) { + case LANGUAGE_NEGOTIATION_URL_DOMAIN: + $domains = language_negotiation_url_domains(); + if (is_object($options['language']) && !empty($domains[$options['language']->langcode])) { + // Save the original base URL. If it contains a port, we need to + // retain it below. + if (!empty($options['base_url'])) { + // The colon in the URL scheme messes up the port checking below. + $normalized_base_url = str_replace(array('https://', 'http://'), '', $options['base_url']); + + } + + // Ask for an absolute URL with our modified base URL. + $url_scheme = Drupal::request()->isSecure() ? 'https://' : 'http://'; + $options['absolute'] = TRUE; + $options['base_url'] = $url_scheme . $domains[$options['language']->langcode]; + + // In case either the original base URL or the HTTP host contains a + // port, retain it. + $http_host = $_SERVER['HTTP_HOST']; + if (isset($normalized_base_url) && strpos($normalized_base_url, ':') !== FALSE) { + list($host, $port) = explode(':', $normalized_base_url); + $options['base_url'] .= ':' . $port; + } + elseif (strpos($http_host, ':') !== FALSE) { + list($host, $port) = explode(':', $http_host); + $options['base_url'] .= ':' . $port; + } + + if (isset($options['https']) && settings()->get('mixed_mode_sessions', FALSE)) { + if ($options['https'] === TRUE) { + $options['base_url'] = str_replace('http://', 'https://', $options['base_url']); + } + elseif ($options['https'] === FALSE) { + $options['base_url'] = str_replace('https://', 'http://', $options['base_url']); + } + } + } + break; + + case LANGUAGE_NEGOTIATION_URL_PREFIX: + $prefixes = language_negotiation_url_prefixes(); + if (is_object($options['language']) &&!empty($prefixes[$options['language']->langcode])) { + $options['prefix'] = $prefixes[$options['language']->langcode] . '/'; + } + break; + } + } +} + +/** * Reads language prefixes and uses the langcode if no prefix is set. */ function language_negotiation_url_prefixes() { diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml index d6599b3..576f4f8 100644 --- a/core/modules/language/language.services.yml +++ b/core/modules/language/language.services.yml @@ -1,7 +1,6 @@ services: path_processor_language: class: Drupal\language\HttpKernel\PathProcessorLanguage - arguments: ['@config.factory', '@settings', '@language_manager'] tags: - { name: path_processor_inbound, priority: 300 } - - { name: path_processor_outbound, priority: 100 } + arguments: ['@config.factory'] diff --git a/core/modules/language/lib/Drupal/language/HttpKernel/PathProcessorLanguage.php b/core/modules/language/lib/Drupal/language/HttpKernel/PathProcessorLanguage.php index 21bbbc8..006b313 100644 --- a/core/modules/language/lib/Drupal/language/HttpKernel/PathProcessorLanguage.php +++ b/core/modules/language/lib/Drupal/language/HttpKernel/PathProcessorLanguage.php @@ -7,19 +7,15 @@ namespace Drupal\language\HttpKernel; -use Drupal\Component\Utility\Settings; use Drupal\Core\Config\ConfigFactory; -use Drupal\Core\Language\Language; -use Drupal\Core\Language\LanguageManager; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; -use Drupal\Core\PathProcessor\OutboundPathProcessorInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; /** * Processes the inbound path using path alias lookups. */ -class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPathProcessorInterface { +class PathProcessorLanguage implements InboundPathProcessorInterface { /** * A config factory for retrieving required config settings. @@ -29,27 +25,12 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa protected $config; /** - * Whether both secure and insecure session cookies can be used simultaneously. - * - * @var bool - */ - protected $mixedModeSessions; - - /** - * Language manager for retrieving the url language type. - * - * @var \Drupal\Core\Language\LanguageManager - */ - protected $languageManager; - - /** * An array of enabled languages. * * @var array */ protected $languages; - /** * Constructs a PathProcessorLanguage object. * @@ -60,10 +41,8 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa * An array of languages, keyed by language code, representing the languages * currently enabled on the site. */ - public function __construct(ConfigFactory $config, Settings $settings, LanguageManager $language_manager, array $languages = array()) { + public function __construct(ConfigFactory $config, array $languages = array()) { $this->config = $config; - $this->mixedModeSessions = $settings->get('mixed_mode_sessions', FALSE); - $this->languageManager = $language_manager; if (empty($languages)) { $languages = language_list(); } @@ -90,74 +69,4 @@ public function processInbound($path, Request $request) { return $path; } - /** - * Implements Drupal\Core\PathProcessor\InboundPathProcessorInterface::processOutbound(). - */ - public function processOutbound($path, &$options = array(), Request $request = NULL) { - if (!$this->languageManager->isMultilingual()) { - return $path; - } - $url_scheme = 'http'; - $port = 80; - if ($request) { - $url_scheme = $request->getScheme(); - $port = $request->getPort(); - } - $languages = array_flip(array_keys($this->languages)); - // Language can be passed as an option, or we go for current URL language. - if (!isset($options['language'])) { - $language_url = $this->languageManager->getLanguage(Language::TYPE_URL); - $options['language'] = $language_url; - } - // We allow only enabled languages here. - elseif (is_object($options['language']) && !isset($languages[$options['language']->langcode])) { - return $path; - } - $url_source = $this->config->get('language.negotiation')->get('url.source'); - // @todo Go back to using a constant instead of the string 'path_prefix' once we can use a class - // constant. - if ($url_source == 'path_prefix') { - $prefixes = $this->config->get('language.negotiation')->get('url.prefixes'); - if (is_object($options['language']) && !empty($prefixes[$options['language']->langcode])) { - return empty($path) ? $prefixes[$options['language']->langcode] : $prefixes[$options['language']->langcode] . '/' . $path; - } - } - elseif ($url_source == 'domain') { - $domains = $this->config->get('language.negotiation')->get('url.domains'); - if (is_object($options['language']) && !empty($domains[$options['language']->langcode])) { - - // Save the original base URL. If it contains a port, we need to - // retain it below. - if (!empty($options['base_url'])) { - // The colon in the URL scheme messes up the port checking below. - $normalized_base_url = str_replace(array('https://', 'http://'), '', $options['base_url']); - } - - // Ask for an absolute URL with our modified base URL. - $options['absolute'] = TRUE; - $options['base_url'] = $url_scheme . '://' . $domains[$options['language']->langcode]; - - // In case either the original base URL or the HTTP host contains a - // port, retain it. - if (isset($normalized_base_url) && strpos($normalized_base_url, ':') !== FALSE) { - list($host, $port) = explode(':', $normalized_base_url); - $options['base_url'] .= ':' . $port; - } - elseif ($port != 80) { - $options['base_url'] .= ':' . $port; - } - - if (isset($options['https']) && $this->mixedModeSessions) { - if ($options['https'] === TRUE) { - $options['base_url'] = str_replace('http://', 'https://', $options['base_url']); - } - elseif ($options['https'] === FALSE) { - $options['base_url'] = str_replace('https://', 'http://', $options['base_url']); - } - } - } - } - return $path; - } - } diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php index 8548f8e..799d8d5 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php @@ -452,7 +452,6 @@ function testLanguageDomain() { 'domain[it]' => 'it.example.com', ); $this->drupalPost('admin/config/regional/language/detection/url', $edit, t('Save configuration')); - $this->rebuildContainer(); // Build the link we're going to test. $link = 'it.example.com/admin'; @@ -467,19 +466,17 @@ function testLanguageDomain() { // Test HTTPS via options. $this->settingsSet('mixed_mode_sessions', TRUE); - $this->rebuildContainer(); - $italian_url = url('admin', array('https' => TRUE, 'language' => $languages['it'], 'script' => '')); $correct_link = 'https://' . $link; $this->assertTrue($italian_url == $correct_link, format_string('The url() function returns the right HTTPS URL (via options) (@url) in accordance with the chosen language', array('@url' => $italian_url))); $this->settingsSet('mixed_mode_sessions', FALSE); // Test HTTPS via current URL scheme. - $generator = $this->container->get('url_generator'); - $request = Request::create('', 'GET', array(), array(), array(), array('HTTPS' => 'on')); - $generator->setRequest($request); + $temp_https = $this->request->server->get('HTTPS'); + $this->request->server->set('HTTPS', 'on'); $italian_url = url('admin', array('language' => $languages['it'], 'script' => '')); $correct_link = 'https://' . $link; $this->assertTrue($italian_url == $correct_link, format_string('The url() function returns the right URL (via current URL scheme) (@url) in accordance with the chosen language', array('@url' => $italian_url))); + $this->request->server->set('HTTPS', $temp_https); } } diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageUrlRewritingTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageUrlRewritingTest.php index 0716484..3effed4 100644 --- a/core/modules/language/lib/Drupal/language/Tests/LanguageUrlRewritingTest.php +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUrlRewritingTest.php @@ -8,7 +8,6 @@ namespace Drupal\language\Tests; use Drupal\simpletest\WebTestBase; -use Symfony\Component\HttpFoundation\Request; /** * Test that URL rewriting works as expected. @@ -48,6 +47,8 @@ function setUp() { // Reset static caching. drupal_static_reset('language_list'); + drupal_static_reset('language_url_outbound_alter'); + drupal_static_reset('language_url_rewrite_url'); } /** @@ -59,7 +60,6 @@ function testUrlRewritingEdgeCases() { $non_existing->langcode = $this->randomName(); $this->checkUrl($non_existing, 'Path language is ignored if language is not installed.', 'URL language negotiation does not work with non-installed languages'); - $request = $this->prepareRequestForGenerator(); // Check that URL rewriting is not applied to subrequests. $this->drupalGet('language_test/subrequest'); $this->assertText($this->web_user->name, 'Page correctly retrieved'); @@ -109,9 +109,6 @@ function testDomainNameNegotiationPort() { 'domain[fr]' => $language_domain ); $this->drupalPost('admin/config/regional/language/detection/url', $edit, t('Save configuration')); - // Rebuild the container so that the new language gets picked up by services - // that hold the list of languages. - $this->rebuildContainer(); // Enable domain configuration. config('language.negotiation') @@ -120,12 +117,17 @@ function testDomainNameNegotiationPort() { // Reset static caching. drupal_static_reset('language_list'); + drupal_static_reset('language_url_outbound_alter'); + drupal_static_reset('language_url_rewrite_url'); // In case index.php is part of the URLs, we need to adapt the asserted // URLs as well. $index_php = strpos(url('', array('absolute' => TRUE)), 'index.php') !== FALSE; - $request = $this->prepareRequestForGenerator(TRUE, array('SERVER_PORT' => '88')); + // Remember current HTTP_HOST. + $http_host = $_SERVER['HTTP_HOST']; + // Fake a different port. + $_SERVER['HTTP_HOST'] .= ':88'; // Create an absolute French link. $language = language_load('fr'); @@ -135,18 +137,22 @@ function testDomainNameNegotiationPort() { )); $expected = $index_php ? 'http://example.fr:88/index.php/' : 'http://example.fr:88/'; + $this->assertEqual($url, $expected, 'The right port is used.'); // If we set the port explicitly in url(), it should not be overriden. $url = url('', array( 'absolute' => TRUE, 'language' => $language, - 'base_url' => $request->getBaseUrl() . ':90', + 'base_url' => $GLOBALS['base_url'] . ':90', )); $expected = $index_php ? 'http://example.fr:90/index.php/' : 'http://example.fr:90/'; + $this->assertEqual($url, $expected, 'A given port is not overriden.'); + // Restore HTTP_HOST. + $_SERVER['HTTP_HOST'] = $http_host; } } diff --git a/core/modules/language/tests/language_test/language_test.module b/core/modules/language/tests/language_test/language_test.module index a77767d..150e024 100644 --- a/core/modules/language/tests/language_test/language_test.module +++ b/core/modules/language/tests/language_test/language_test.module @@ -119,18 +119,5 @@ function language_test_menu() { * Page callback. Uses a subrequest to retrieve the 'user' page. */ function language_test_subrequest() { - $request = Request::createFromGlobals(); - $server = $request->server->all(); - if (basename($server['SCRIPT_FILENAME']) != basename($server['SCRIPT_NAME'])) { - // We need this for when the test is executed by run-tests.sh. - // @todo Remove this once run-tests.sh has been converted to use a Request - // object. - $server['SCRIPT_FILENAME'] = $server['SCRIPT_NAME']; - $base_path = ltrim($server['REQUEST_URI'], '/'); - } - else { - $base_path = $request->getBasePath(); - } - $subrequest = Request::create($base_path . '/user', 'GET', $request->query->all(), $request->cookies->all(), array(), $server); - return Drupal::service('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST); + return drupal_container()->get('http_kernel')->handle(Request::create('/user'), HttpKernelInterface::SUB_REQUEST); } diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php index 70406e8..123eded 100644 --- a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php +++ b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkFormatter.php @@ -150,17 +150,17 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) { $settings = $this->getSettings(); foreach ($items as $delta => $item) { - // By default use the full URL as the link text. + // By default use the full URL as the link title. $link_title = $item['url']; - // If the title field value is available, use it for the link text. + // If the title field value is available, use it for the link title. if (empty($settings['url_only']) && !empty($item['title'])) { // Unsanitizied token replacement here because $options['html'] is FALSE // by default in theme_link(). $link_title = \Drupal::token()->replace($item['title'], array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE)); } - // Trim the link text to the desired length. + // Trim the link title to the desired length. if (!empty($settings['trim_length'])) { $link_title = truncate_utf8($link_title, $settings['trim_length'], FALSE, TRUE); } diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php index 93826f1..b2d3882 100644 --- a/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php +++ b/core/modules/link/lib/Drupal/link/Plugin/field/formatter/LinkSeparateFormatter.php @@ -23,7 +23,7 @@ * @Plugin( * id = "link_separate", * module = "link", - * label = @Translation("Separate link text and URL"), + * label = @Translation("Separate title and URL"), * field_types = { * "link" * }, @@ -44,20 +44,20 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) { $settings = $this->getSettings(); foreach ($items as $delta => $item) { - // By default use the full URL as the link text. + // By default use the full URL as the link title. $link_title = $item['url']; - // If the link text field value is available, use it for the text. + // If the title field value is available, use it for the link title. if (empty($settings['url_only']) && !empty($item['title'])) { // Unsanitized token replacement here because $options['html'] is FALSE // by default in theme_link(). $link_title = \Drupal::token()->replace($item['title'], array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE)); } - // The link_separate formatter has two titles; the link text (as in the - // field values) and the URL itself. If there is no link text value, + // The link_separate formatter has two titles; the link title (as in the + // field values) and the URL itself. If there is no title value, // $link_title defaults to the URL, so it needs to be unset. - // The URL version may need to be trimmed as well. + // The URL title may need to be trimmed as well. if (empty($item['title'])) { $link_title = NULL; } diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php index 0784cae..8a1aebb 100644 --- a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php +++ b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php @@ -45,7 +45,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr ); $element['title'] = array( '#type' => 'textfield', - '#title' => t('Link text'), + '#title' => t('Title'), '#placeholder' => $this->getSetting('placeholder_title'), '#default_value' => isset($items[$delta]['title']) ? $items[$delta]['title'] : NULL, '#maxlength' => 255, @@ -93,7 +93,7 @@ public function settingsForm(array $form, array &$form_state) { ); $elements['placeholder_title'] = array( '#type' => 'textfield', - '#title' => t('Placeholder for link text'), + '#title' => t('Placeholder for link title'), '#default_value' => $this->getSetting('placeholder_title'), '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'), '#states' => array( diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php index 5748970..1ec4ec4 100644 --- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php +++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php @@ -111,7 +111,7 @@ function testURLValidation() { } /** - * Tests the link title settings of a link field. + * Tests the title settings of a link field. */ function testLinkTitle() { // Create a field with settings to validate. @@ -135,7 +135,7 @@ function testLinkTitle() { 'type' => 'link_default', 'settings' => array( 'placeholder_url' => 'http://example.com', - 'placeholder_title' => 'Enter the text for this link', + 'placeholder_title' => 'Enter a title for this link', ), )) ->save(); @@ -148,9 +148,9 @@ function testLinkTitle() { $langcode = Language::LANGCODE_NOT_SPECIFIED; - // Verify that the link text field works according to the field setting. + // Verify that the title field works according to the field setting. foreach (array(DRUPAL_DISABLED, DRUPAL_REQUIRED, DRUPAL_OPTIONAL) as $title_setting) { - // Update the link title field setting. + // Update the title field setting. $this->instance['settings']['title'] = $title_setting; field_update_instance($this->instance); @@ -162,41 +162,41 @@ function testLinkTitle() { $this->assertRaw('placeholder="http://example.com"'); if ($title_setting === DRUPAL_DISABLED) { - $this->assertNoFieldByName("{$this->field['field_name']}[$langcode][0][title]", '', 'Link text field not found.'); - $this->assertNoRaw('placeholder="Enter the text for this link"'); + $this->assertNoFieldByName("{$this->field['field_name']}[$langcode][0][title]", '', 'Title field not found.'); + $this->assertNoRaw('placeholder="Enter a title for this link"'); } else { - $this->assertRaw('placeholder="Enter the text for this link"'); + $this->assertRaw('placeholder="Enter a title for this link"'); - $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][title]", '', 'Link text field found.'); + $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][title]", '', 'Title field found.'); if ($title_setting === DRUPAL_REQUIRED) { - // Verify that the link text is required, if the URL is non-empty. + // Verify that the title is required, if the URL is non-empty. $edit = array( "{$this->field['field_name']}[$langcode][0][url]" => 'http://www.example.com', ); $this->drupalPost(NULL, $edit, t('Save')); - $this->assertText(t('!name field is required.', array('!name' => t('Link text')))); + $this->assertText(t('!name field is required.', array('!name' => t('Title')))); - // Verify that the link text is not required, if the URL is empty. + // Verify that the title is not required, if the URL is empty. $edit = array( "{$this->field['field_name']}[$langcode][0][url]" => '', ); $this->drupalPost(NULL, $edit, t('Save')); - $this->assertNoText(t('!name field is required.', array('!name' => t('Link text')))); + $this->assertNoText(t('!name field is required.', array('!name' => t('Title')))); - // Verify that a URL and link text meets requirements. + // Verify that a URL and title meets requirements. $this->drupalGet('test-entity/add/test_bundle'); $edit = array( "{$this->field['field_name']}[$langcode][0][url]" => 'http://www.example.com', "{$this->field['field_name']}[$langcode][0][title]" => 'Example', ); $this->drupalPost(NULL, $edit, t('Save')); - $this->assertNoText(t('!name field is required.', array('!name' => t('Link text')))); + $this->assertNoText(t('!name field is required.', array('!name' => t('Title')))); } } } - // Verify that a link without link text is rendered using the URL as text. + // Verify that a link without title is rendered using the URL as link text. $value = 'http://www.example.com/'; $edit = array( "{$this->field['field_name']}[$langcode][0][url]" => $value, @@ -211,7 +211,7 @@ function testLinkTitle() { $expected_link = l($value, $value); $this->assertRaw($expected_link); - // Verify that a link with text is rendered using the link text. + // Verify that a link with title is rendered using the title as link text. $title = $this->randomName(); $edit = array( "{$this->field['field_name']}[$langcode][0][title]" => $title, @@ -262,7 +262,7 @@ function testLinkFormatter() { // Create an entity with two link field values: // - The first field item uses a URL only. - // - The second field item uses a URL and link text. + // - The second field item uses a URL and title. // For consistency in assertion code below, the URL is assigned to the title // variable for the first field. $this->drupalGet('test-entity/add/test_bundle'); @@ -402,7 +402,7 @@ function testLinkSeparateFormatter() { // Create an entity with two link field values: // - The first field item uses a URL only. - // - The second field item uses a URL and link text. + // - The second field item uses a URL and title. // For consistency in assertion code below, the URL is assigned to the title // variable for the first field. $this->drupalGet('test-entity/add/test_bundle'); diff --git a/core/modules/link/lib/Drupal/link/Type/LinkItem.php b/core/modules/link/lib/Drupal/link/Type/LinkItem.php index 913a8f2..ad20400 100644 --- a/core/modules/link/lib/Drupal/link/Type/LinkItem.php +++ b/core/modules/link/lib/Drupal/link/Type/LinkItem.php @@ -35,7 +35,7 @@ public function getPropertyDefinitions() { ); self::$propertyDefinitions['title'] = array( 'type' => 'string', - 'label' => t('Link text'), + 'label' => t('Title'), ); self::$propertyDefinitions['attributes'] = array( 'type' => 'map', diff --git a/core/modules/link/link.module b/core/modules/link/link.module index 16091f1..9f0fa1e 100644 --- a/core/modules/link/link.module +++ b/core/modules/link/link.module @@ -15,7 +15,7 @@ function link_help($path, $arg) { case 'admin/help#link': $output = ''; $output .= '

' . t('About') . '

'; - $output .= '

' . t('The Link module defines a simple link field type for the Field module. Links are external URLs, can have an optional link text for each link, and they can be formatted when displayed. See the Field module help page for more information about fields.', array('@field-help' => url('admin/help/field'))) . '

'; + $output .= '

' . t('The Link module defines a simple link field type for the Field module. Links are external URLs, can have an optional title for each link, and they can be formatted when displayed. See the Field module help page for more information about fields.', array('@field-help' => url('admin/help/field'))) . '

'; return $output; } } @@ -26,7 +26,7 @@ function link_help($path, $arg) { function link_field_info() { $types['link'] = array( 'label' => t('Link'), - 'description' => t('Stores a URL string, optional varchar link text, and optional blob of attributes to assemble a link.'), + 'description' => t('Stores a URL string, optional varchar title, and optional blob of attributes to assemble a link.'), 'instance_settings' => array( 'title' => DRUPAL_OPTIONAL, ), @@ -43,7 +43,7 @@ function link_field_info() { function link_field_instance_settings_form($field, $instance) { $form['title'] = array( '#type' => 'radios', - '#title' => t('Allow link text'), + '#title' => t('Allow link title'), '#default_value' => isset($instance['settings']['title']) ? $instance['settings']['title'] : DRUPAL_OPTIONAL, '#options' => array( DRUPAL_DISABLED => t('Disabled'), @@ -84,7 +84,7 @@ function link_field_is_empty($item, $field) { */ function link_field_presave(EntityInterface $entity, $field, $instance, $langcode, &$items) { foreach ($items as $delta => &$item) { - // Trim any spaces around the URL and link text. + // Trim any spaces around the URL and title. $item['url'] = trim($item['url']); $item['title'] = trim($item['title']); @@ -105,7 +105,7 @@ function link_theme() { } /** - * Formats a link as separate link title and URL elements. + * Formats a link as separate title and URL elements. */ function theme_link_formatter_link_separate($vars) { $output = ''; diff --git a/core/modules/locale/lib/Drupal/locale/LocaleLookup.php b/core/modules/locale/lib/Drupal/locale/LocaleLookup.php index 7f7d272..cc515b4 100644 --- a/core/modules/locale/lib/Drupal/locale/LocaleLookup.php +++ b/core/modules/locale/lib/Drupal/locale/LocaleLookup.php @@ -46,7 +46,7 @@ public function __construct($langcode, $context, $stringStorage) { // Add the current user's role IDs to the cache key, this ensures that, for // example, strings for admin menu items and settings forms are not cached // for anonymous users. - $rids = implode(':', $GLOBALS['user']->roles); + $rids = implode(':', array_keys($GLOBALS['user']->roles)); parent::__construct("locale:$langcode:$context:$rids", 'cache', array('locale' => TRUE)); } diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php index 86e54c7..1c5d215 100644 --- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php +++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php @@ -62,12 +62,6 @@ function testUninstallProcess() { $language_manager->init(); // Check the UI language. - // @todo: If the global user is an EntityBCDecorator, getting the roles - // from it within LocaleLookup results in a loop that invokes LocaleLookup - // again. - global $user; - $user = drupal_anonymous_user(); - $this->assertEqual(language(Language::TYPE_INTERFACE)->langcode, $this->langcode, t('Current language: %lang', array('%lang' => language(Language::TYPE_INTERFACE)->langcode))); // Enable multilingual workflow option for articles. diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 92b28ea..04452ac 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -851,10 +851,6 @@ function locale_update_8011() { * Renames language_default language negotiation method to language_selected. */ function locale_update_8013() { - // @todo We only need language.inc here because LANGUAGE_NEGOTIATION_SELECTED - // is defined there. Remove this line once that has been converted to a class - // constant. - require_once DRUPAL_ROOT . '/core/includes/language.inc'; $weight = update_variable_get('language_negotiation_methods_weight_language_interface', NULL); if ($weight !== NULL) { $weight[LANGUAGE_NEGOTIATION_SELECTED] = $weight['language-default']; diff --git a/core/modules/node/lib/Drupal/node/NodeAccessController.php b/core/modules/node/lib/Drupal/node/NodeAccessController.php index 7e4f601..aacc22f 100644 --- a/core/modules/node/lib/Drupal/node/NodeAccessController.php +++ b/core/modules/node/lib/Drupal/node/NodeAccessController.php @@ -8,7 +8,7 @@ namespace Drupal\node; use Drupal\Core\Language\Language; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityNG; @@ -21,7 +21,7 @@ class NodeAccessController extends EntityAccessController { /** * {@inheritdoc} */ - public function access(EntityInterface $entity, $operation, $langcode = Language::LANGUAGE_DEFAULT, UserInterface $account = NULL) { + public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, User $account = NULL) { if (user_access('bypass node access', $account)) { return TRUE; } @@ -34,7 +34,7 @@ public function access(EntityInterface $entity, $operation, $langcode = Language /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $node, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $node, $operation, $langcode, User $account) { // Fetch information from the node object if possible. $status = isset($node->status) ? $node->status : NULL; $uid = isset($node->uid) ? $node->uid : NULL; @@ -75,7 +75,7 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Use * 'delete'. * @param string $langcode * The language code for which to check access. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user for which to check access. * * @return bool|null @@ -83,7 +83,7 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Use * module implements hook_node_grants(), the node does not (yet) have an id * or none of the implementing modules explicitly granted or denied access. */ - protected function accessGrants(EntityInterface $node, $operation, $langcode, UserInterface $account) { + protected function accessGrants(EntityInterface $node, $operation, $langcode, User $account) { // If no module implements the hook or the node does not have an id there is // no point in querying the database for access grants. if (!module_implements('node_grants') || !$node->id()) { @@ -111,7 +111,7 @@ protected function accessGrants(EntityInterface $node, $operation, $langcode, Us $query->range(0, 1); $grants = db_or(); - foreach (node_access_grants($operation, $account instanceof User ? $account->getBCEntity() : $account) as $realm => $gids) { + foreach (node_access_grants($operation, $account) as $realm => $gids) { foreach ($gids as $gid) { $grants->condition(db_and() ->condition('gid', $gid) diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTestBase.php b/core/modules/node/lib/Drupal/node/Tests/NodeTestBase.php index 02a16da..957e4ee 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTestBase.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTestBase.php @@ -41,7 +41,7 @@ function setUp() { * operation should be granted. * @param \Drupal\node\Plugin\Core\Entity\Node $node * The node object to check. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user account for which to check access. * @param string|null $langcode * (optional) The language code indicating which translation of the node diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php index e390d83..b458392 100644 --- a/core/modules/node/node.api.php +++ b/core/modules/node/node.api.php @@ -393,8 +393,8 @@ function hook_node_grants_alter(&$grants, $account, $op) { if ($op != 'view' && !empty($restricted)) { // Now check the roles for this account against the restrictions. - foreach ($account->roles as $rid) { - if (in_array($rid, $restricted)) { + foreach ($restricted as $role_id) { + if (isset($account->roles[$role_id])) { $grants = array(); } } diff --git a/core/modules/node/node.install b/core/modules/node/node.install index 2e761ae..1110615 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -789,7 +789,7 @@ function node_update_8011() { */ function node_update_8012() { // Enable the history module without re-installing the schema. - module_enable(array('history')); + update_module_enable(array('history')); } /** @@ -812,7 +812,7 @@ function node_update_8013() { */ function node_update_8014() { // Enable the datetime module. - module_enable(array('datetime')); + update_module_enable(array('datetime')); } /** diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 9206798..d4cd961 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -20,7 +20,7 @@ use Drupal\Core\Template\Attribute; use Drupal\entity\Plugin\Core\Entity\EntityDisplay; use Drupal\file\Plugin\Core\Entity\File; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Denotes that the node is not published. @@ -2490,7 +2490,7 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) { // Make sure that if an account is passed, that it is a fully loaded user // object. - if ($account && !($account instanceof UserInterface)) { + if ($account && !($account instanceof User)) { $account = user_load($account->uid); } diff --git a/core/modules/overlay/overlay.install b/core/modules/overlay/overlay.install index 29e6fa9..588f871 100644 --- a/core/modules/overlay/overlay.install +++ b/core/modules/overlay/overlay.install @@ -24,7 +24,7 @@ function overlay_enable() { function overlay_update_dependencies() { // Migrate users.data after User module prepared the tables. $dependencies['overlay'][8000] = array( - 'user' => 8016, + 'user' => 8011, ); return $dependencies; } diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module index 4cf68c2..d34f175 100644 --- a/core/modules/overlay/overlay.module +++ b/core/modules/overlay/overlay.module @@ -8,7 +8,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Drupal\block\Plugin\Core\Entity\Block; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Implements hook_help(). @@ -402,7 +402,7 @@ function theme_overlay_disable_message($variables) { /** * Implements hook_block_access(). */ -function overlay_block_access(Block $block, $operation, UserInterface $account, $langcode) { +function overlay_block_access(Block $block, $operation, User $account, $langcode) { // If we are limiting rendering to a subset of page regions, hide all blocks // which appear in regions not on that list. Note that overlay_page_alter() // does a more comprehensive job of preventing unwanted regions from being diff --git a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php index c3d13cf..f592b72 100644 --- a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php +++ b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php @@ -97,10 +97,10 @@ function testAliasTranslation() { // Confirm that the alias is returned by url(). Languages are cached on // many levels, and we need to clear those caches. drupal_static_reset('language_list'); - $this->rebuildContainer(); + drupal_static_reset('language_url_outbound_alter'); + drupal_static_reset('language_url_rewrite_url'); $languages = language_list(); - $url = $this->container->get('url_generator')->generateFromPath('node/' . $french_node->nid, array('language' => $languages[$french_node->langcode])); - + $url = url('node/' . $french_node->nid, array('language' => $languages[$french_node->langcode])); $this->assertTrue(strpos($url, $edit['path[alias]']), 'URL contains the path alias.'); // Confirm that the alias works even when changing language negotiation diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php index a20440a..2c92696 100644 --- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php +++ b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/BundleSchema.php @@ -49,7 +49,7 @@ public function __construct($site_schema, $entity_type, $bundle) { */ public function getUri() { $path = str_replace(array('{entity_type}', '{bundle}'), array($this->entityType, $this->bundle), static::$uriPattern); - return $this->siteSchema->getUri() . '/' . $path; + return $this->siteSchema->getUri() . $path; } /** diff --git a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php index 282c904..48a69fc 100644 --- a/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php +++ b/core/modules/rdf/lib/Drupal/rdf/SiteSchema/EntitySchema.php @@ -58,7 +58,7 @@ public function getGraph() { */ public function getUri() { $path = str_replace('{entity_type}', $this->entityType , static::$uriPattern); - return $this->siteSchema->getUri() . '/' . $path; + return $this->siteSchema->getUri() . $path; } /** diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php index 986118b..0cfe07f 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/SiteSchemaTest.php @@ -47,6 +47,7 @@ function testSiteSchema() { 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' => 'http://www.w3.org/2000/01/rdf-schema#class', 'http://www.w3.org/2000/01/rdf-schema#subClassOf' => url("$schema_path$entity_type", array('absolute' => TRUE)), ); + $this->assertEqual($bundle_schema->getUri(), $bundle_uri, 'Bundle term URI is generated correctly.'); $this->assertEqual($bundle_schema->getProperties(), $bundle_properties, 'Bundle term properties are generated correctly.'); } diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php index 83a2388..4d2a7ed 100644 --- a/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php +++ b/core/modules/search/lib/Drupal/search/Tests/SearchCommentTest.php @@ -127,7 +127,9 @@ function testSearchResultsComment() { function testSearchResultsCommentAccess() { $comment_body = 'Test comment body'; $this->comment_subject = 'Test comment subject'; - $this->admin_role = $this->admin_user->roles[0]; + $this->admin_role = $this->admin_user->roles; + unset($this->admin_role[DRUPAL_AUTHENTICATED_RID]); + $this->admin_role = key($this->admin_role); // Create a node. variable_set('comment_preview_article', DRUPAL_OPTIONAL); diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php index b42fe65..2a9c397 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityAccessController; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines the access controller for the shortcut entity type. @@ -19,7 +19,7 @@ class ShortcutAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { switch ($operation) { case 'edit': if (user_access('administer shortcuts', $account)) { diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php index 2c80dcd..b1102be 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php @@ -174,16 +174,6 @@ public function containerBuild(ContainerBuilder $container) { ->setFactoryMethod('get') ->addArgument('state'); } - - if ($container->hasDefinition('path_processor_alias')) { - // Prevent the alias-based path processor, which requires a url_alias db - // table, from being registered to the path processor manager. We do this - // by removing the tags that the compiler pass looks for. This means the - // url generator can safely be used within DUTB tests. - $definition = $container->getDefinition('path_processor_alias'); - $definition->clearTag('path_processor_inbound')->clearTag('path_processor_outbound'); - } - } /** diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 6e17d86..c51473c 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -19,7 +19,6 @@ use DOMXPath; use SimpleXMLElement; use Drupal\Core\Datetime\DrupalDateTime; -use Symfony\Component\HttpFoundation\Request; /** * Test case for typical Drupal tests. @@ -492,7 +491,7 @@ protected function drupalCreateUser(array $permissions = array(), $name = NULL) $edit['pass'] = user_password(); $edit['status'] = 1; if ($rid) { - $edit['roles'] = array($rid); + $edit['roles'] = array($rid => $rid); } $account = entity_create('user', $edit); @@ -624,7 +623,7 @@ protected function checkPermissions(array $permissions, $reset = FALSE) { * $account->pass_raw = $pass_raw; * @endcode * - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * User object representing the user to log in. * * @see drupalCreateUser() @@ -653,7 +652,7 @@ protected function drupalLogin($account) { /** * Returns whether a given user account is logged in. * - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\User $account * The user account object to check. */ protected function drupalUserIsLoggedIn($account) { @@ -907,16 +906,6 @@ protected function writeSettings($settings) { } /** - * Overrides Drupal\simpletest\TestBase::rebuildContainer(). - */ - protected function rebuildContainer() { - parent::rebuildContainer(); - // Make sure the url generator has a request object, otherwise calls to - // $this->drupalGet() will fail. - $this->prepareRequestForGenerator(); - } - - /** * Reset all data structures after having enabled new modules. * * This method is called by Drupal\simpletest\WebTestBase::setUp() after enabling @@ -1206,7 +1195,7 @@ protected function parse() { * @param $path * Drupal path or URL to load into internal browser * @param $options - * Options to be forwarded to the url generator. + * Options to be forwarded to url(). * @param $headers * An array containing additional HTTP request headers, each formatted as * "name: value". @@ -1219,8 +1208,7 @@ protected function drupalGet($path, array $options = array(), array $headers = a // We re-using a CURL connection here. If that connection still has certain // options set, it might change the GET into a POST. Make sure we clear out // previous options. - $url = $this->container->get('url_generator')->generateFromPath($path, $options); - $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => $url, CURLOPT_NOBODY => FALSE, CURLOPT_HTTPHEADER => $headers)); + $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_NOBODY => FALSE, CURLOPT_HTTPHEADER => $headers)); $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up. // Replace original page output with new output from redirected page(s). @@ -1337,7 +1325,7 @@ protected function drupalGetAJAX($path, array $options = array(), array $headers * textfield: under these conditions, no button information is added to the * POST data. * @param $options - * Options to be forwarded to the url generator. + * Options to be forwarded to url(). * @param $headers * An array containing additional HTTP request headers, each formatted as * "name: value". @@ -1462,7 +1450,7 @@ protected function drupalPost($path, $edit, $submit, array $options = array(), a * element. In the absence of both the triggering element's Ajax path and * $ajax_path 'system/ajax' will be used. * @param $options - * (optional) Options to be forwarded to the url generator. + * (optional) Options to be forwarded to url(). * @param $headers * (optional) An array containing additional HTTP request headers, each * formatted as "name: value". Forwarded to drupalPost(). @@ -1670,7 +1658,7 @@ protected function checkForMetaRefresh() { * @param $path * Drupal path or URL to load into internal browser * @param $options - * Options to be forwarded to the url generator. + * Options to be forwarded to url(). * @param $headers * An array containing additional HTTP request headers, each formatted as * "name: value". @@ -1679,8 +1667,7 @@ protected function checkForMetaRefresh() { */ protected function drupalHead($path, array $options = array(), array $headers = array()) { $options['absolute'] = TRUE; - $url = $this->container->get('url_generator')->generateFromPath($path, $options); - $out = $this->curlExec(array(CURLOPT_NOBODY => TRUE, CURLOPT_URL => $url, CURLOPT_HTTPHEADER => $headers)); + $out = $this->curlExec(array(CURLOPT_NOBODY => TRUE, CURLOPT_URL => url($path, $options), CURLOPT_HTTPHEADER => $headers)); $this->refreshVariables(); // Ensure that any changes to variables in the other thread are picked up. if ($this->dumpHeaders) { @@ -2268,7 +2255,7 @@ protected function drupalSetSettings($settings) { * @param $path * The expected system path. * @param $options - * (optional) Any additional options to pass for $path to the url generator. + * (optional) Any additional options to pass for $path to url(). * @param $message * (optional) A message to display with the assertion. Do not translate * messages: use format_string() to embed variables in the message text, not @@ -2285,11 +2272,11 @@ protected function drupalSetSettings($settings) { protected function assertUrl($path, array $options = array(), $message = '', $group = 'Other') { if (!$message) { $message = t('Current URL is @url.', array( - '@url' => var_export($this->container->get('url_generator')->generateFromPath($path, $options), TRUE), + '@url' => var_export(url($path, $options), TRUE), )); } $options['absolute'] = TRUE; - return $this->assertEqual($this->getUrl(), $this->container->get('url_generator')->generateFromPath($path, $options), $message, $group); + return $this->assertEqual($this->getUrl(), url($path, $options), $message, $group); } /** @@ -3279,50 +3266,4 @@ protected function verboseEmail($count = 1) { $this->verbose(t('Email:') . '
' . print_r($mail, TRUE) . '
'); } } - - /** - * Creates a mock request and sets it on the generator. - * - * This is used to manipulate how the generator generates paths during tests. - * It also ensures that calls to $this->drupalGet() will work when running - * from run-tests.sh because the url generator no longer looks at the global - * variables that are set there but relies on getting this information from a - * request object. - * - * @param bool $clean_urls - * Whether to mock the request using clean urls. - * - * @param $override_server_vars - * An array of server variables to override. - * - * @return $request - * The mocked request object. - */ - protected function prepareRequestForGenerator($clean_urls = TRUE, $override_server_vars = array()) { - $generator = $this->container->get('url_generator'); - $request = Request::createFromGlobals(); - $server = $request->server->all(); - if (basename($server['SCRIPT_FILENAME']) != basename($server['SCRIPT_NAME'])) { - // We need this for when the test is executed by run-tests.sh. - // @todo Remove this once run-tests.sh has been converted to use a Request - // object. - $cwd = getcwd(); - $server['SCRIPT_FILENAME'] = $cwd . '/' . basename($server['SCRIPT_NAME']); - $base_path = rtrim($server['REQUEST_URI'], '/'); - } - else { - $base_path = $request->getBasePath(); - } - if ($clean_urls) { - $request_path = $base_path ? $base_path . '/user' : 'user'; - } - else { - $request_path = $base_path ? $base_path . '/index.php/user' : '/index.php/user'; - } - $server = array_merge($server, $override_server_vars); - - $request = Request::create($request_path, 'GET', array(), array(), array(), $server); - $generator->setRequest($request); - return $request; - } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php index ca2d7b3..253c463 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Bootstrap/PageCacheTest.php @@ -92,25 +92,21 @@ function testPageCache() { $config = config('system.performance'); $config->set('cache.page.use_internal', 1); $config->set('cache.page.max_age', 300); - $config->set('response.gzip', 1); $config->save(); // Fill the cache. $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar'))); $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.'); - $this->assertEqual(strtolower($this->drupalGetHeader('Vary')), 'cookie,accept-encoding', 'Vary header was sent.'); - // Symfony's Response logic determines a specific order for the subvalues - // of the Cache-Control header, even if they are explicitly passed in to - // the response header bag in a different order. - $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'max-age=300, public', 'Cache-Control header was sent.'); + $this->assertEqual($this->drupalGetHeader('Vary'), 'Cookie,Accept-Encoding', 'Vary header was sent.'); + $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'public, max-age=300', 'Cache-Control header was sent.'); $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.'); // Check cache. $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar'))); $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.'); - $this->assertEqual(strtolower($this->drupalGetHeader('Vary')), 'cookie,accept-encoding', 'Vary: Cookie header was sent.'); - $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'max-age=300, public', 'Cache-Control header was sent.'); + $this->assertEqual($this->drupalGetHeader('Vary'), 'Cookie,Accept-Encoding', 'Vary: Cookie header was sent.'); + $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'public, max-age=300', 'Cache-Control header was sent.'); $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.'); @@ -118,14 +114,14 @@ function testPageCache() { $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Expires', 'value' => 'Fri, 19 Nov 2008 05:00:00 GMT'))); $this->assertEqual($this->drupalGetHeader('Expires'), 'Fri, 19 Nov 2008 05:00:00 GMT', 'Default header was replaced.'); $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Vary', 'value' => 'User-Agent'))); - $this->assertEqual(strtolower($this->drupalGetHeader('Vary')), 'user-agent,accept-encoding', 'Default header was replaced.'); + $this->assertEqual($this->drupalGetHeader('Vary'), 'User-Agent,Accept-Encoding', 'Default header was replaced.'); // Check that authenticated users bypass the cache. $user = $this->drupalCreateUser(); $this->drupalLogin($user); $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar'))); $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Caching was bypassed.'); - $this->assertTrue(strpos(strtolower($this->drupalGetHeader('Vary')), 'cookie') === FALSE, 'Vary: Cookie header was not sent.'); + $this->assertTrue(strpos($this->drupalGetHeader('Vary'), 'Cookie') === FALSE, 'Vary: Cookie header was not sent.'); $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'must-revalidate, no-cache, post-check=0, pre-check=0, private', 'Cache-Control header was sent.'); $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.'); @@ -152,7 +148,6 @@ function testPageCompression() { $config = config('system.performance'); $config->set('cache.page.use_internal', 1); $config->set('cache.page.max_age', 300); - $config->set('response.gzip', 1); $config->save(); // Fill the cache and verify that output is compressed. diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php index c3b46a2..a502e82 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php @@ -8,7 +8,6 @@ namespace Drupal\system\Tests\Common; use Drupal\simpletest\WebTestBase; -use Symfony\Component\HttpFoundation\Request; /** * Tests for URL generation functions. @@ -265,6 +264,50 @@ function testDrupalParseUrl() { } /** + * Tests url() functionality. + * + * Tests url() with/without query, with/without fragment, absolute on/off and + * asserts all that works when clean URLs are on and off. + */ + function testUrl() { + global $base_url, $script_path; + + $script_path_original = $script_path; + foreach (array('', 'index.php/') as $script_path) { + foreach (array(FALSE, TRUE) as $absolute) { + // Get the expected start of the path string. + $base = ($absolute ? $base_url . '/' : base_path()) . $script_path; + $absolute_string = $absolute ? 'absolute' : NULL; + + $url = $base . 'node/123'; + $result = url('node/123', array('absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123#foo'; + $result = url('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo'; + $result = url('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo=bar&bar=baz'; + $result = url('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo#bar'; + $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + + $url = $base; + $result = url('', array('absolute' => $absolute)); + $this->assertEqual($url, $result, "$url == $result"); + } + } + $script_path = $script_path_original; + } + + /** * Tests external URL handling. */ function testExternalUrls() { diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php index c1c7ea8..c29e4f3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php @@ -9,7 +9,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\TypedData\AccessibleInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; use Drupal\Core\Entity\EntityAccessController; /** @@ -45,7 +45,7 @@ function setUp() { /** * Asserts entity access correctly grants or denies access. */ - function assertEntityAccess($ops, AccessibleInterface $object, UserInterface $account = NULL) { + function assertEntityAccess($ops, AccessibleInterface $object, User $account = NULL) { foreach ($ops as $op => $result) { $message = format_string("Entity access returns @result with operation '@op'.", array( '@result' => !isset($result) ? 'null' : ($result ? 'true' : 'false'), diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php index a9fd8bf..b626ead 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiTest.php @@ -8,7 +8,7 @@ namespace Drupal\system\Tests\Entity; use Drupal\Core\Entity\EntityStorageException; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Tests the basic Entity API. @@ -51,10 +51,10 @@ public function testCRUD() { * * @param string $entity_type * The entity type to run the tests with. - * @param \Drupal\user\UserInterface $user1 + * @param \Drupal\user\Plugin\Core\Entity\User $user1 * The user to run the tests with. */ - protected function assertCRUD($entity_type, UserInterface $user1) { + protected function assertCRUD($entity_type, User $user1) { // Create some test entities. $entity = entity_create($entity_type, array('name' => 'test', 'user_id' => $user1->uid)); $entity->save(); diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php index 93fc552..6b74ce3 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php @@ -118,19 +118,19 @@ protected function assertReadWrite($entity_type) { $this->assertTrue($entity->user_id[0] instanceof FieldItemInterface, format_string('%entity_type: Field item implements interface', array('%entity_type' => $entity_type))); $this->assertEqual($this->entity_user->uid, $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type))); - $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type))); + $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type))); // Change the assigned user by entity. $new_user = $this->createUser(); $entity->user_id->entity = $new_user; $this->assertEqual($new_user->uid, $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type))); - $this->assertEqual($new_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type))); + $this->assertEqual($new_user->name, $entity->user_id->entity->name, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type))); // Change the assigned user by id. $new_user = $this->createUser(); $entity->user_id->target_id = $new_user->uid; $this->assertEqual($new_user->uid, $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type))); - $this->assertEqual($new_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type))); + $this->assertEqual($new_user->name, $entity->user_id->entity->name, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type))); // Try unsetting a field. $entity->name->value = NULL; @@ -218,7 +218,7 @@ protected function assertReadWrite($entity_type) { )); $this->assertEqual($this->entity_name, $entity->name->value, format_string('%entity_type: Name value can be read.', array('%entity_type' => $entity_type))); $this->assertEqual($this->entity_user->uid, $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type))); - $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type))); + $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type))); $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type))); // Test copying field values. @@ -329,7 +329,7 @@ protected function assertSave($entity_type) { $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type))); $this->assertEqual(language_load(Language::LANGCODE_NOT_SPECIFIED), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type))); $this->assertEqual($this->entity_user->uid, $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type))); - $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type))); + $this->assertEqual($this->entity_user->name, $entity->user_id->entity->name, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type))); $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type))); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php index 5e73dbc..4da3b21 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php @@ -51,7 +51,7 @@ protected function createUser($values = array(), $permissions = array()) { )); $role->save(); user_role_grant_permissions($role->id(), $permissions); - $values['roles'][] = $role->id(); + $values['roles'][$role->id()] = $role->id(); } $account = entity_create('user', $values + array( diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php deleted file mode 100644 index f1a0fdb..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityValidationTest.php +++ /dev/null @@ -1,138 +0,0 @@ - 'Entity Validation API', - 'description' => 'Tests the Entity Validation API', - 'group' => 'Entity API', - ); - } - - /** - * {@inheritdoc} - */ - public function setUp() { - parent::setUp(); - $this->installSchema('user', array('users_roles', 'users_data')); - $this->installSchema('entity_test', array( - 'entity_test_mul', - 'entity_test_mul_property_data', - 'entity_test_rev', - 'entity_test_rev_revision', - 'entity_test_mulrev', - 'entity_test_mulrev_property_data', - 'entity_test_mulrev_property_revision' - )); - - // Create the test field. - entity_test_install(); - - // Install required default configuration for filter module. - $this->installConfig(array('system', 'filter')); - } - - /** - * Creates a test entity. - * - * @param string $entity_type - * An entity type. - * - * @return \Drupal\Core\Entity\EntityInterface - * The created test entity. - */ - protected function createTestEntity($entity_type) { - $this->entity_name = $this->randomName(); - $this->entity_user = $this->createUser(); - $this->entity_field_text = $this->randomName(); - - // Pass in the value of the name field when creating. With the user - // field we test setting a field after creation. - $entity = entity_create($entity_type, array()); - $entity->user_id->target_id = $this->entity_user->uid; - $entity->name->value = $this->entity_name; - - // Set a value for the test field. - $entity->field_test_text->value = $this->entity_field_text; - - return $entity; - } - - /** - * Tests validating test entity types. - */ - public function testValidation() { - // All entity variations have to have the same results. - foreach (entity_test_entity_types() as $entity_type) { - $this->checkValidation($entity_type); - } - } - - /** - * Executes the validation test set for a defined entity type. - * - * @param string $entity_type - * The entity type to run the tests with. - */ - protected function checkValidation($entity_type) { - $entity = $this->createTestEntity($entity_type); - $violations = $entity->validate(); - $this->assertEqual($violations->count(), 0, 'Validation passes.'); - - // Test triggering a fail for each of the constraints specified. - $test_entity = clone $entity; - $test_entity->uuid->value = $this->randomString(129); - $violations = $test_entity->validate(); - $this->assertEqual($violations->count(), 1, 'Validation failed.'); - $this->assertEqual($violations[0]->getMessage(), t('This value is too long. It should have %limit characters or less.', array('%limit' => '128'))); - - $test_entity = clone $entity; - $test_entity->langcode->value = $this->randomString(13); - $violations = $test_entity->validate(); - $this->assertEqual($violations->count(), 1, 'Validation failed.'); - $this->assertEqual($violations[0]->getMessage(), t('This value is too long. It should have %limit characters or less.', array('%limit' => '12'))); - - - $test_entity = clone $entity; - $test_entity->type->value = NULL; - $violations = $test_entity->validate(); - $this->assertEqual($violations->count(), 1, 'Validation failed.'); - $this->assertEqual($violations[0]->getMessage(), t('This value should not be null.')); - - $test_entity = clone $entity; - $test_entity->name->value = $this->randomString(33); - $violations = $test_entity->validate(); - $this->assertEqual($violations->count(), 1, 'Validation failed.'); - $this->assertEqual($violations[0]->getMessage(), t('This value is too long. It should have %limit characters or less.', array('%limit' => '32'))); - - // Make sure the information provided by a violation is correct. - $violation = $violations[0]; - $this->assertEqual($violation->getRoot(), $test_entity, 'Violation root is entity.'); - $this->assertEqual($violation->getPropertyPath(), 'name.0.value', 'Violation property path is correct.'); - $this->assertEqual($violation->getInvalidValue(), $test_entity->name->value, 'Violation contains invalid value.'); - } - -} diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php index a5db46a..b00bfea 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/FieldAccessTest.php @@ -70,12 +70,12 @@ function testFieldAccess() { $values = array('name' => 'test'); $account = entity_create('user', $values); - $this->assertFalse($entity->field_test_text->access('view', $account->getNGEntity()), 'Access to the field was denied.'); + $this->assertFalse($entity->field_test_text->access('view', $account), 'Access to the field was denied.'); $entity->field_test_text = 'access alter value'; - $this->assertFalse($entity->field_test_text->access('view', $account->getNGEntity()), 'Access to the field was denied.'); + $this->assertFalse($entity->field_test_text->access('view', $account), 'Access to the field was denied.'); $entity->field_test_text = 'standard value'; - $this->assertTrue($entity->field_test_text->access('view', $account->getNGEntity()), 'Access to the field was granted.'); + $this->assertTrue($entity->field_test_text->access('view', $account), 'Access to the field was granted.'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php index eef40d4..6b53b22 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php @@ -46,8 +46,7 @@ function testUrlAlter() { // Test that a path always uses its alias. $path = array('source' => "user/$uid/test1", 'alias' => 'alias/test1'); - $this->container->get('path.crud')->save($path['source'], $path['alias']); - $this->rebuildContainer(); + drupal_container()->get('path.crud')->save($path['source'], $path['alias']); $this->assertUrlInboundAlter('alias/test1', "user/$uid/test1"); $this->assertUrlOutboundAlter("user/$uid/test1", 'alias/test1'); @@ -101,7 +100,7 @@ function testCurrentUrlRequestedPath() { */ protected function assertUrlOutboundAlter($original, $final) { // Test outbound altering. - $result = $this->container->get('url_generator')->generateFromPath($original); + $result = url($original); $base_path = base_path() . $GLOBALS['script_path']; $result = substr($result, strlen($base_path)); $this->assertIdentical($result, $final, format_string('Altered outbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result))); diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php index 5d5fb63..882ae96 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php @@ -104,10 +104,10 @@ function testContext() { $this->assertEqual($user->label(), $plugin->getTitle()); // Test the getContextDefinitions() method. - $this->assertIdentical($plugin->getContextDefinitions(), array('user' => array('class' => 'Drupal\user\UserInterface'))); + $this->assertIdentical($plugin->getContextDefinitions(), array('user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'))); // Test the getContextDefinition() method for a valid context. - $this->assertEqual($plugin->getContextDefinition('user'), array('class' => 'Drupal\user\UserInterface')); + $this->assertEqual($plugin->getContextDefinition('user'), array('class' => 'Drupal\user\Plugin\Core\Entity\User')); // Test the getContextDefinition() method for an invalid context. try { diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php index c580338..7b8aa9a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php @@ -74,7 +74,7 @@ public function setUp() { 'label' => 'User name', 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock', 'context' => array( - 'user' => array('class' => 'Drupal\user\UserInterface') + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User') ), ), 'string_context' => array( @@ -88,7 +88,7 @@ public function setUp() { 'label' => 'Complex context', 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock', 'context' => array( - 'user' => array('class' => 'Drupal\user\UserInterface'), + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'), 'node' => array('class' => 'Drupal\Core\Entity\EntityBCDecorator'), ), ), diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php new file mode 100644 index 0000000..0e9f13e --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php @@ -0,0 +1,76 @@ + 'UrlGenerator', + 'description' => 'Confirm that the UrlGenerator is functioning properly.', + 'group' => 'Routing', + ); + } + + function setUp() { + parent::setUp(); + + $routes = new RouteCollection(); + $routes->add('test_1', new Route('/test/one')); + $routes->add('test_2', new Route('/test/two/{narf}')); + $provider = new MockRouteProvider($routes); + + $this->aliasManager = new MockAliasManager(); + $this->aliasManager->addAlias('test/one', 'hello/world'); + + $context = new RequestContext(); + $context->fromRequest(Request::create('/some/path')); + + $generator = new UrlGenerator($provider, $this->aliasManager); + $generator->setContext($context); + + $this->generator = $generator; + } + + /** + * Confirms that generated routes will have aliased paths. + */ + public function testAliasGeneration() { + $url = $this->generator->generate('test_1'); + + $this->assertEqual($url, '/hello/world', 'Correct URL generated including alias.'); + } + + /** + * Confirms that generated routes will have aliased paths. + */ + public function testAliasGenerationWithParameters() { + $this->aliasManager->addAlias('test/two/5', 'goodbye/cruel/world'); + + $url = $this->generator->generate('test_2', array('narf' => '5')); + + $this->assertEqual($url, '/goodbye/cruel/world', 'Correct URL generated including alias and parameters.'); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php b/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php index f96b13e..d1a601a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php @@ -18,8 +18,6 @@ class SessionTest extends WebTestBase { */ public static $modules = array('session_test'); - protected $dumpHeaders = TRUE; - public static function getInfo() { return array( 'name' => 'Session tests', diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php index b0e255e..2bb96b9 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php @@ -21,8 +21,6 @@ class UpdateScriptTest extends WebTestBase { */ public static $modules = array('update_script_test', 'dblog'); - protected $dumpHeaders = TRUE; - private $update_url; private $update_user; diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUIUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUIUpgradePathTest.php index 6f44942..f344afb 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUIUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUIUpgradePathTest.php @@ -63,7 +63,7 @@ function testFieldUIPermissions() { ), ); - $role_permissions = user_role_permissions(array($this->normal_role_id, $this->admin_role_id)); + $role_permissions = user_role_permissions(array($this->normal_role_id => $this->normal_role_name, $this->admin_role_id => $this->admin_role_name)); foreach ($permissions as $old_permission => $new_permissions) { $this->assertFalse(isset($role_permissions[$this->normal_role_id][$old_permission]), format_string('%role_name does not have the old %permission permission', array('%role_name' => $this->normal_role_name, '%permission' => $old_permission))); $this->assertTrue(isset($role_permissions[$this->admin_role_id][$old_permission]), format_string('%role_name still has the old %permission permission', array('%role_name' => $this->admin_role_name, '%permission' => $old_permission))); diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php index ba62946..4771869 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php @@ -120,11 +120,6 @@ public function testLanguageUpgrade() { $this->assertTrue(isset($current_weights['language-selected']), 'Language-selected is present.'); $this->assertFalse(isset($current_weights['language-default']), 'Language-default is not present.'); - // @todo We only need language.inc here because LANGUAGE_NEGOTIATION_SELECTED - // is defined there. Remove this line once that has been converted to a class - // constant. - require_once DRUPAL_ROOT . '/core/includes/language.inc'; - // Check that negotiation callback was added to language_negotiation_language_interface. $language_negotiation_language_interface = update_variable_get('language_negotiation_language_interface', NULL); $this->assertTrue(isset($language_negotiation_language_interface[LANGUAGE_NEGOTIATION_SELECTED]['callbacks']['negotiation']), 'Negotiation callback was added to language_negotiation_language_interface.'); diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php index b613121..73edd7a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php @@ -9,8 +9,6 @@ use Drupal\Component\Utility\Crypt; use Drupal\Core\Database\Database; -use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\Core\DrupalKernel; use Drupal\simpletest\WebTestBase; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\HttpFoundation\Request; @@ -21,11 +19,6 @@ abstract class UpgradePathTestBase extends WebTestBase { /** - * @var array - */ - protected $configDirectories; - - /** * The file path(s) to the dumped database(s) to load into the child site. * * @var array @@ -110,12 +103,6 @@ protected function setUp() { $conf = array(); drupal_static_reset(); - - // Build a minimal, partially mocked environment for unit tests. - $this->containerBuild(drupal_container()); - // Make sure it survives kernel rebuilds. - $conf['container_bundles'][] = 'Drupal\simpletest\TestBundle'; - // Change the database prefix. // All static variables need to be reset before the database prefix is // changed, since Drupal\Core\Utility\CacheArray implementations attempt to @@ -314,27 +301,6 @@ protected function performUpgrade($register_errors = TRUE) { } /** - * Overrides some core services for the upgrade tests. - */ - public function containerBuild(ContainerBuilder $container) { - // Keep the container object around for tests. - $this->container = $container; - - $container - ->register('config.storage', 'Drupal\Core\Config\FileStorage') - ->addArgument($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]); - - if ($this->container->hasDefinition('path_processor_alias')) { - // Prevent the alias-based path processor, which requires a url_alias db - // table, from being registered to the path processor manager. We do this - // by removing the tags that the compiler pass looks for. This means the - // url generator can safely be used within upgrade path tests. - $definition = $this->container->getDefinition('path_processor_alias'); - $definition->clearTag('path_processor_inbound')->clearTag('path_processor_outbound'); - } - } - - /** * Gets update.php without calling url(). * * Required since WebTestBase::drupalGet() calls t(), which calls into diff --git a/core/modules/system/system.install b/core/modules/system/system.install index def6429..e7a2a34 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -1,13 +1,13 @@ condition('aid', 'system_block_ip_action') ->execute(); // Enable the new Ban module. - module_enable(array('ban')); + update_module_enable(array('ban')); } else { // Drop old table. @@ -1552,7 +1552,7 @@ function system_update_8020() { */ function system_update_8021() { // Enable the module without re-installing the schema. - module_enable(array('action')); + update_module_enable(array('action')); // Rename former System module actions. $map = array( 'system_message_action' => 'action_message_action', @@ -1857,7 +1857,7 @@ function system_update_8041() { * Enable the new Entity module. */ function system_update_8042() { - module_enable(array('entity')); + update_module_enable(array('entity')); } /** @@ -1922,21 +1922,18 @@ function system_update_8045() { function system_update_8046() { $front_page = config('system.site')->get('page.front'); if (!isset($front_page) || $front_page == 'node') { + update_module_enable(array('views')); + + // Register views to the container, so views can use it's services. + $module_list = drupal_container()->getParameter('container.modules'); + drupal_load('module', 'views'); + + drupal_container()->get('kernel')->updateModules($module_list, array('views' => 'core/modules/views/views.module')); + + // This does not fire a hook just calls views. + config_install_default_config('module', 'views'); // This imports the node frontpage view. - $module = 'node'; - $config_name = 'views.view.frontpage'; - $module_config_path = drupal_get_path('module', $module) . '/config'; - $module_filestorage = new FileStorage($module_config_path); - $config_storage = drupal_container()->get('config.storage'); - // If this file already exists, something in the upgrade path went - // completely wrong and we want to know. - if ($config_storage->exists($config_name)) { - throw new ConfigException(format_string('Default configuration file @name of @module module unexpectedly exists already before the module was installed.', array( - '@module' => $module, - '@name' => $config_name, - ))); - } - $config_storage->write($config_name, $module_filestorage->read($config_name)); + config_install_default_config('module', 'node'); } } @@ -1963,7 +1960,7 @@ function system_update_8047() { */ function system_update_8048() { // Enable the module without re-installing the schema. - module_enable(array('menu_link')); + update_module_enable(array('menu_link')); // Add the langcode column if it doesn't exist. if (!db_field_exists('menu_inks', 'langcode')) { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index f8d4482..db6ecc1 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2280,11 +2280,6 @@ function system_data_type_info() { 'description' => t('An entity field referencing a language.'), 'class' => '\Drupal\Core\Entity\Field\Type\LanguageItem', 'list class' => '\Drupal\Core\Entity\Field\Type\Field', - 'constraints' => array( - 'ComplexData' => array( - 'value' => array('Length' => array('max' => 12)), - ), - ), ), 'entity_reference_field' => array( 'label' => t('Entity reference field item'), diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php index e509c15..cc2bd45 100644 --- a/core/modules/system/tests/https.php +++ b/core/modules/system/tests/https.php @@ -3,9 +3,6 @@ /** * @file * Fake an HTTPS request, for use during testing. - * - * @todo Fix this to use a new request rather than modifying server variables, - * see http.php. */ // Set a global variable to indicate a mock HTTPS request. diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php index dd60560..fe12b22 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php @@ -10,7 +10,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Language\Language; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines the access controller for the test entity type. @@ -20,7 +20,7 @@ class EntityTestAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { if ($operation === 'view') { if ($langcode != Language::LANGCODE_DEFAULT) { return user_access('view test entity translations', $account); diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php index 1d2b879..8c5e23f 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php @@ -41,9 +41,6 @@ public function baseFieldDefinitions() { 'label' => t('UUID'), 'description' => t('The UUID of the test entity.'), 'type' => 'string_field', - 'property_constraints' => array( - 'value' => array('Length' => array('max' => 128)), - ), ); $fields['langcode'] = array( 'label' => t('Language code'), @@ -55,16 +52,11 @@ public function baseFieldDefinitions() { 'description' => t('The name of the test entity.'), 'type' => 'string_field', 'translatable' => TRUE, - 'property_constraints' => array( - 'value' => array('Length' => array('max' => 32)), - ), ); $fields['type'] = array( 'label' => t('Type'), 'description' => t('The bundle of the test entity.'), 'type' => 'string_field', - 'required' => TRUE, - // @todo: Add allowed values validation. ); $fields['user_id'] = array( 'label' => t('User ID'), diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php index a897160..157e583 100644 --- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php @@ -72,7 +72,7 @@ public function __construct() { 'label' => t('User name'), 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock', 'context' => array( - 'user' => array('class' => 'Drupal\user\UserInterface') + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User') ), )); @@ -90,7 +90,7 @@ public function __construct() { 'label' => t('Complex context'), 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock', 'context' => array( - 'user' => array('class' => 'Drupal\user\UserInterface'), + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'), 'node' => array('class' => 'Drupal\Core\Entity\EntityBCDecorator'), ), )); diff --git a/core/modules/system/tests/modules/url_alter_test/lib/Drupal/url_alter_test/PathProcessorTest.php b/core/modules/system/tests/modules/url_alter_test/lib/Drupal/url_alter_test/PathProcessorTest.php deleted file mode 100644 index e649f6d..0000000 --- a/core/modules/system/tests/modules/url_alter_test/lib/Drupal/url_alter_test/PathProcessorTest.php +++ /dev/null @@ -1,61 +0,0 @@ - ''); - $path = 'user/' . $account->uid . $matches[2]; - } - } - - // Rewrite community/ to forum/. - if ($path == 'community' || strpos($path, 'community/') === 0) { - $path = 'forum' . substr($path, 9); - } - - if ($path == 'url-alter-test/bar') { - $path = 'url-alter-test/foo'; - } - return $path; - } - - /** - * Implements Drupal\Core\PathProcessor\OutboundPathProcessorInterface::processOutbound(). - */ - public function processOutbound($path, &$options = array(), Request $request = NULL) { - // Rewrite user/uid to user/username. - if (preg_match('!^user/([0-9]+)(/.*)?!', $path, $matches)) { - if ($account = user_load($matches[1])) { - $matches += array(2 => ''); - $path = 'user/' . $account->name . $matches[2]; - } - } - - // Rewrite forum/ to community/. - if ($path == 'forum' || strpos($path, 'forum/') === 0) { - $path = 'community' . substr($path, 5); - } - return $path; - } - -} diff --git a/core/modules/system/tests/modules/url_alter_test/url_alter_test.module b/core/modules/system/tests/modules/url_alter_test/url_alter_test.module index a7567a3..8bacb9b 100644 --- a/core/modules/system/tests/modules/url_alter_test/url_alter_test.module +++ b/core/modules/system/tests/modules/url_alter_test/url_alter_test.module @@ -25,3 +25,21 @@ function url_alter_test_foo() { print 'current_path=' . current_path() . ' request_path=' . request_path(); exit; } + +/** + * Implements hook_url_outbound_alter(). + */ +function url_alter_test_url_outbound_alter(&$path, &$options, $original_path) { + // Rewrite user/uid to user/username. + if (preg_match('!^user/([0-9]+)(/.*)?!', $path, $matches)) { + if ($account = user_load($matches[1])) { + $matches += array(2 => ''); + $path = 'user/' . $account->name . $matches[2]; + } + } + + // Rewrite forum/ to community/. + if ($path == 'forum' || strpos($path, 'forum/') === 0) { + $path = 'community' . substr($path, 5); + } +} diff --git a/core/modules/system/tests/modules/url_alter_test/url_alter_test.services.yml b/core/modules/system/tests/modules/url_alter_test/url_alter_test.services.yml index 58b98ba..a05b363 100644 --- a/core/modules/system/tests/modules/url_alter_test/url_alter_test.services.yml +++ b/core/modules/system/tests/modules/url_alter_test/url_alter_test.services.yml @@ -1,6 +1,5 @@ services: - url_alter_test.path_processor: - class: Drupal\url_alter_test\PathProcessorTest + url_alter_test.path_subscriber: + class: Drupal\url_alter_test\PathProcessor tags: - { name: path_processor_inbound, priority: 800 } - - { name: path_processor_outbound, priority: 100 } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php index 0d6dbd0..bd1cff8 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines an access controller for the taxonomy term entity. @@ -21,7 +21,7 @@ class TermAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { switch ($operation) { case 'view': return user_access('access content', $account); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php index 8f6e54f..bd02c30 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines an access controller for the vocabulary entity. @@ -21,7 +21,7 @@ class VocabularyAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { return user_access('administer taxonomy', $account); } diff --git a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php index 118d98f..9aed6ee 100644 --- a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php @@ -230,7 +230,9 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) { $format = filter_format_load($edit['format']); $format_id = $format->format; $permission = filter_permission_name($format); - $rid = $this->web_user->roles[0]; + $roles = $this->web_user->roles; + unset($roles[DRUPAL_AUTHENTICATED_RID]); + $rid = key($roles); user_role_grant_permissions($rid, array($permission)); $this->drupalLogin($this->web_user); diff --git a/core/modules/toolbar/toolbar.install b/core/modules/toolbar/toolbar.install index 3d4f517..6732bb9 100644 --- a/core/modules/toolbar/toolbar.install +++ b/core/modules/toolbar/toolbar.install @@ -18,7 +18,7 @@ */ function toolbar_update_8000() { // Enable the modules without re-installing the schema. - module_enable(array('breakpoint')); + update_module_enable(array('breakpoint')); } /** diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index e1d55f3..c9f0c22 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -9,7 +9,6 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Drupal\Core\Template\Attribute; use Drupal\Component\Utility\Crypt; -use Symfony\Component\HttpFoundation\Response; /** * Implements hook_help(). @@ -130,23 +129,19 @@ function _toolbar_initialize_page_cache() { // @see _drupal_bootstrap_page_cache() $cache = drupal_page_get_cache(); if (is_object($cache)) { - $response = new Response(); - $request = \Drupal::request(); - $response->headers->set('X-Drupal-Cache', 'HIT'); + header('X-Drupal-Cache: HIT'); // Restore the metadata cached with the page. $_GET['q'] = $cache->data['path']; date_default_timezone_set(drupal_get_user_timezone()); - drupal_serve_page_from_cache($cache, $response, $request); + drupal_serve_page_from_cache($cache); - $response->prepare($request); - $response->send(); // We are done. exit; } // Otherwise, create a new page response (that will be cached). - drupal_add_http_header('X-Drupal-Cache', 'MISS'); + header('X-Drupal-Cache: MISS'); // The Expires HTTP header is the heart of the client-side HTTP caching. The // additional server-side page cache only takes effect when the client diff --git a/core/modules/tour/css/tour-rtl.css b/core/modules/tour/css/tour-rtl.css index 5e19f7b..cef3d00 100644 --- a/core/modules/tour/css/tour-rtl.css +++ b/core/modules/tour/css/tour-rtl.css @@ -3,7 +3,7 @@ * RTL styling for tour module. */ -.js .toolbar .bar .tour-toolbar-tab.tab { +.js .toolbar .tour-toolbar-tab.tab { float: left; } diff --git a/core/modules/tour/css/tour.css b/core/modules/tour/css/tour.css index 945e9e3..7754abe 100644 --- a/core/modules/tour/css/tour.css +++ b/core/modules/tour/css/tour.css @@ -4,7 +4,7 @@ */ /* Tab appearance. */ -.js .toolbar .bar .tour-toolbar-tab.tab { +.js .toolbar .tour-toolbar-tab.tab { float: right; /* LTR */ } .js .toolbar .tour-toolbar-tab button { diff --git a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php index ff55606..4fc436a 100644 --- a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php +++ b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php @@ -281,7 +281,8 @@ function testTranslateOwnContentRole() { */ function resetCaches() { drupal_static_reset('language_list'); - $this->rebuildContainer(); + drupal_static_reset('language_url_outbound_alter'); + drupal_static_reset('language_url_rewrite_url'); } /** diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php b/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php index 261dfe1..30f9058 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManager; +use Drupal\Core\Entity\Field\FieldInterface; /** * Provides field translation synchronization capabilities. @@ -33,7 +34,7 @@ public function __construct(EntityManager $entityManager) { } /** - * Implements \Drupal\translation_entity\FieldTranslationSynchronizerInterface::synchronizeFields(). + * {@inheritdoc} */ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $original_langcode = NULL) { $translations = $entity->getTranslationLanguages(); @@ -52,17 +53,14 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig return; } - // Enable compatibility mode for NG entities. - $entity_unchanged = $entity_unchanged->getBCEntity(); - // @todo Use Entity Field API to retrieve field definitions. $instances = field_info_instances($entity_type, $entity->bundle()); foreach ($instances as $field_name => $instance) { - $field = field_info_field($field_name); + $field = $instance->getField(); // Sync when the field is not empty, when the synchronization translations // setting is set, and the field is translatable. - if (!empty($entity->{$field_name}) && !empty($instance['settings']['translation_sync']) && field_is_translatable($entity_type, $field)) { + if (!$entity->{$field_name}->isEmpty() && !empty($instance['settings']['translation_sync']) && field_is_translatable($entity_type, $field)) { // Retrieve all the untranslatable column groups and merge them into // single list. $groups = array_keys(array_diff($instance['settings']['translation_sync'], array_filter($instance['settings']['translation_sync']))); @@ -78,8 +76,8 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig // used as the unchanged items. In fact there are no unchanged items // to check against. $langcode = $original_langcode ?: $sync_langcode; - $unchanged_items = !empty($entity_unchanged->{$field_name}[$langcode]) ? $entity_unchanged->{$field_name}[$langcode] : array(); - $this->synchronizeItems($entity->{$field_name}, $unchanged_items, $sync_langcode, array_keys($translations), $columns); + $unchanged_items = $entity_unchanged->getTranslation($langcode)->{$field_name}; + $this->synchronizeItems($entity, $field_name, $unchanged_items, $sync_langcode, array_keys($translations), $columns); } } } @@ -87,10 +85,10 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig } /** - * Implements \Drupal\translation_entity\FieldTranslationSynchronizerInterface::synchronizeItems(). + * {@inheritdoc} */ - public function synchronizeItems(array &$field_values, array $unchanged_items, $sync_langcode, array $translations, array $columns) { - $source_items = $field_values[$sync_langcode]; + public function synchronizeItems(EntityInterface $entity, $field_name, FieldInterface $unchanged_items, $sync_langcode, array $translations, array $columns) { + $source_items = $entity->getTranslation($sync_langcode)->{$field_name}; // Make sure we can detect any change in the source items. $change_map = array(); @@ -112,20 +110,27 @@ public function synchronizeItems(array &$field_values, array $unchanged_items, $ } // Backup field values and the change map. - $original_field_values = $field_values; + foreach ($translations as $langcode) { + $original_field_values[$langcode] = $entity->getTranslation($sync_langcode)->{$field_name}->getValue(); + } $original_change_map = $change_map; // Reset field values so that no spurious one is stored. Source values must // be preserved in any case. - $field_values = array($sync_langcode => $source_items); + foreach ($translations as $langcode) { + $entity->getTranslation($langcode)->{$field_name}->setValue(array()); + } + $entity->getTranslation($sync_langcode)->{$field_name}->setValue($source_items); // Update field translations. foreach ($translations as $langcode) { + // We need to synchronize only values different from the source ones. if ($langcode != $sync_langcode) { // Reinitialize the change map as it is emptied while processing each // language. $change_map = $original_change_map; + $new_values = array(); // By using the maximum cardinality we ensure to process removed items. for ($delta = 0; $delta < $total; $delta++) { @@ -155,7 +160,7 @@ public function synchronizeItems(array &$field_values, array $unchanged_items, $ // If a synchronized column has changed or has been created from // scratch we need to override the full items array for all languages. elseif ($created) { - $field_values[$langcode][$delta] = $source_items[$delta]; + $new_values[$delta] = $source_items->offsetGet($delta); } // Otherwise the current item might have been reordered. elseif (isset($old_delta) && isset($new_delta)) { @@ -164,10 +169,12 @@ public function synchronizeItems(array &$field_values, array $unchanged_items, $ // the new values are at least propagated to all the translations. // If the value has only been reordered we just move the old one in // the new position. - $item = isset($original_field_values[$langcode][$old_delta]) ? $original_field_values[$langcode][$old_delta] : $source_items[$new_delta]; - $field_values[$langcode][$new_delta] = $item; + $new_values[$delta] = isset($original_field_values[$langcode][$old_delta]) ? $original_field_values[$langcode][$old_delta] : $source_items[$new_delta]; } } + + $entity->getTranslation($langcode)->{$field_name}->setValue($new_values); + } } } @@ -185,13 +192,13 @@ public function synchronizeItems(array &$field_values, array $unchanged_items, $ * @returns string * A hash code that can be used to identify the item. */ - protected function itemHash(array $items, $delta, array $columns) { + protected function itemHash(FieldInterface $items, $delta, array $columns) { $values = array(); - if (isset($items[$delta])) { + if ($items->offsetExists($delta)) { foreach ($columns as $column) { - if (!empty($items[$delta][$column])) { - $value = $items[$delta][$column]; + $value = $items->offsetGet($delta)->get($column)->getValue(); + if (!empty($value)) { // String and integer values are by far the most common item values, // thus we special-case them to improve performance. $values[] = is_string($value) || is_int($value) ? $value : hash('sha256', serialize($value)); diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizerInterface.php b/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizerInterface.php index 1ae361c..9fd3040 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizerInterface.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizerInterface.php @@ -8,6 +8,7 @@ namespace Drupal\translation_entity; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\Field\FieldInterface; /** * Provides field translation synchronization capabilities. @@ -45,9 +46,11 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig * order. Subsequently the detected changes are performed on the field items * in other available languages. * + * @todo Adjust phpdoc + * * @param array $field_values * The field values to be synchronized. - * @param array $unchanged_items + * @param \Drupal\Core\Entity\Field\FieldInterface $unchanged_items * The unchanged items to be used to detect changes. * @param string $sync_langcode * The language code of the items to use as source values. @@ -56,6 +59,6 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig * @param array $columns * An array of column names to be synchronized. */ - public function synchronizeItems(array &$field_values, array $unchanged_items, $sync_langcode, array $translations, array $columns); + public function synchronizeItems(EntityInterface $entity, $field_name, FieldInterface $unchanged_items, $sync_langcode, array $translations, array $columns); } diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php index cb90b6d..d94cd78 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSettingsTest.php @@ -88,7 +88,6 @@ function testSettingsUI() { 'settings[comment][comment_node_article][fields][comment_body]' => TRUE, ); $this->assertSettings('comment', 'comment_node_article', TRUE, $edit); - field_info_cache_clear(); $field = field_info_field('comment_body'); $this->assertTrue($field['translatable'], 'Comment body is translatable.'); diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php index aa9c626..63d7218 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationSyncImageTest.php @@ -98,7 +98,8 @@ function testImageFieldSync() { 'user_id' => mt_rand(1, 128), 'langcode' => $default_langcode, ); - $entity = entity_create($this->entityType, $values)->getBCEntity(); + $entity = entity_create($this->entityType, $values); +// $entity = entity_create($this->entityType, $values)->getBCEntity(); // Create some file entities from the generated test files and store them. $values = array(); @@ -125,7 +126,7 @@ function testImageFieldSync() { 'alt' => $this->randomName(), 'title' => $this->randomName(), ); - $entity->{$this->fieldName}[$default_langcode][$delta] = $item; + $entity->{$this->fieldName}->offsetGet($delta)->setValue($item); // Store the generated values keying them by fid for easier lookup. $values[$default_langcode][$fid] = $item; @@ -150,7 +151,7 @@ function testImageFieldSync() { 'alt' => $this->randomName(), 'title' => $this->randomName(), ); - $entity->{$this->fieldName}[$langcode][$delta] = $item; + $entity->getTranslation($langcode)->{$this->fieldName}->offsetGet($delta)->setValue($item); // Again store the generated values keying them by fid for easier lookup. $values[$langcode][$fid] = $item; @@ -161,16 +162,20 @@ function testImageFieldSync() { $entity = $this->saveEntity($entity); // Check that one value has been dropped from the original values. - $assert = count($entity->{$this->fieldName}[$default_langcode]) == 2; + $assert = count($entity->{$this->fieldName}) == 2; $this->assertTrue($assert, 'One item correctly removed from the synchronized field values.'); // Check that fids have been synchronized and translatable column values // have been retained. $fids = array(); - foreach ($entity->{$this->fieldName}[$default_langcode] as $delta => $item) { + foreach ($entity->{$this->fieldName} as $delta => $item) { $value = $values[$default_langcode][$item['fid']]; - $source_item = $entity->{$this->fieldName}[$langcode][$delta]; + $source_item = $entity->getTranslation($langcode)->{$this->fieldName}->offsetGet($delta); $assert = $item['fid'] == $source_item['fid'] && $item['alt'] == $value['alt'] && $item['title'] == $value['title']; + debug($source_item['fid'], 'source item fid'); + debug($item->fid, 'item fid'); + debug($item->getValue(), 'item'); + debug($value, 'value'); $this->assertTrue($assert, format_string('Field item @fid has been successfully synchronized.', array('@fid' => $item['fid']))); $fids[$item['fid']] = TRUE; } @@ -188,20 +193,20 @@ function testImageFieldSync() { 'alt' => $this->randomName(), 'title' => $this->randomName(), ); - $entity->{$this->fieldName}[$langcode] = array_values($values[$langcode]); + $entity->getTranslation($langcode)->{$this->fieldName}->setValue(array_values($values[$langcode])); $entity = $this->saveEntity($entity); // Check that the value has been added to the default language. - $assert = count($entity->{$this->fieldName}[$default_langcode]) == 3; + $assert = count($entity->{$this->fieldName}->getValue()) == 3; $this->assertTrue($assert, 'One item correctly added to the synchronized field values.'); - foreach ($entity->{$this->fieldName}[$default_langcode] as $delta => $item) { + foreach ($entity->{$this->fieldName} as $delta => $item) { // When adding an item its value is copied over all the target languages, // thus in this case the source language needs to be used to check the // values instead of the target one. $fid_langcode = $item['fid'] != $removed_fid ? $default_langcode : $langcode; $value = $values[$fid_langcode][$item['fid']]; - $source_item = $entity->{$this->fieldName}[$langcode][$delta]; + $source_item = $entity->getTranslation($langcode)->{$this->fieldName}->offsetGet($delta); $assert = $item['fid'] == $source_item['fid'] && $item['alt'] == $value['alt'] && $item['title'] == $value['title']; $this->assertTrue($assert, format_string('Field item @fid has been successfully synchronized.', array('@fid' => $item['fid']))); } @@ -219,7 +224,7 @@ function testImageFieldSync() { protected function saveEntity(EntityInterface $entity) { $entity->save(); $entity = entity_test_mul_load($entity->id(), TRUE); - return $entity->getBCEntity(); + return $entity; } } diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php index 31592c7..870321f 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationTestBase.php @@ -82,10 +82,6 @@ function setUp() { $this->setupTestFields(); $this->controller = translation_entity_controller($this->entityType); - - // Rebuild the container so that the new languages are picked up by services - // that hold a list of languages. - $this->rebuildContainer(); } /** diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationWorkflowsTest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationWorkflowsTest.php index 9475ab0..de7db85 100644 --- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationWorkflowsTest.php +++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationWorkflowsTest.php @@ -8,7 +8,7 @@ namespace Drupal\translation_entity\Tests; use Drupal\Core\Language\Language; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Tests entity translation workflows. @@ -68,7 +68,6 @@ protected function setupEntity() { $this->drupalLogin($this->translator); $add_translation_path = $this->controller->getBasePath($this->entity) . "/translations/add/$default_langcode/{$this->langcodes[2]}"; $this->drupalPost($add_translation_path, array(), t('Save')); - $this->rebuildContainer(); } /** @@ -109,13 +108,13 @@ function testWorkflows() { /** * Checks that workflows have the expected behaviors for the given user. * - * @param \Drupal\user\UserInterface $user + * @param \Drupal\user\Plugin\Core\Entity\User $user * The user to test the workflow behavior against. * @param array $expected_status * The an associative array with the operation name as key and the expected * status as value. */ - protected function assertWorkflows(UserInterface $user, $expected_status) { + protected function assertWorkflows(User $user, $expected_status) { $default_langcode = $this->langcodes[0]; $languages = language_list(); $args = array('@user_label' => $user->name); diff --git a/core/modules/translation_entity/translation_entity.module b/core/modules/translation_entity/translation_entity.module index 1ef2df5..f51c2cb 100644 --- a/core/modules/translation_entity/translation_entity.module +++ b/core/modules/translation_entity/translation_entity.module @@ -289,7 +289,7 @@ function translation_entity_translate_access(EntityInterface $entity) { * The entity whose translation overview should be displayed. * @param $langcode * The language code of the translation to be displayed. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * (optional) The account for which view access should be checked. Defaults to * the current user. */ diff --git a/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php b/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php index cb44b96..104763d 100644 --- a/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php +++ b/core/modules/user/lib/Drupal/user/Access/RoleAccessCheck.php @@ -40,14 +40,14 @@ public function access(Route $route, Request $request) { $explode_and = array_filter(array_map('trim', explode('+', $rid_string))); if (count($explode_and) > 1) { - $diff = array_diff($explode_and, $account->roles); + $diff = array_diff($explode_and, array_keys($account->roles)); if (empty($diff)) { return TRUE; } } else { $explode_or = array_filter(array_map('trim', explode(',', $rid_string))); - $intersection = array_intersect($explode_or, $account->roles); + $intersection = array_intersect($explode_or, array_keys($account->roles)); if (!empty($intersection)) { return TRUE; } diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php index 13ad217..082b15c 100644 --- a/core/modules/user/lib/Drupal/user/AccountFormController.php +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php @@ -148,7 +148,7 @@ public function form(array $form, array &$form_state) { $form['account']['roles'] = array( '#type' => 'checkboxes', '#title' => t('Roles'), - '#default_value' => (!$register ? $account->roles : array()), + '#default_value' => (!$register && isset($account->roles) ? array_keys($account->roles) : array()), '#options' => $roles, '#access' => $roles && user_access('administer permissions'), DRUPAL_AUTHENTICATED_RID => $checkbox_authenticated, @@ -227,22 +227,6 @@ public function form(array $form, array &$form_state) { } /** - * {@inheritdoc} - */ - public function buildEntity(array $form, array &$form_state) { - // Change the roles array to a list of enabled roles. - // @todo: Alter the form state as the form values are directly extracted and - // set on the field, which throws an exception as the list requires - // numeric keys. Allow to override this per field. As this function is - // called twice, we have to prevent it from getting the array keys twice. - if (empty($this->roles_filtered)) { - $form_state['values']['roles'] = array_keys(array_filter($form_state['values']['roles'])); - $this->roles_filtered = TRUE; - } - return parent::buildEntity($form, $form_state); - } - - /** * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function validate(array $form, array &$form_state) { diff --git a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php index 6c95606..6797848 100644 --- a/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php +++ b/core/modules/user/lib/Drupal/user/Plugin/Core/Entity/User.php @@ -7,12 +7,11 @@ namespace Drupal\user\Plugin\Core\Entity; -use Drupal\Core\Entity\EntityNG; +use Drupal\Core\Entity\Entity; use Drupal\Core\Entity\Annotation\EntityType; use Drupal\Core\Annotation\Translation; -use Drupal\user\UserBCDecorator; -use Drupal\user\UserInterface; use Drupal\Core\Language\Language; +use Drupal\user\UserInterface; /** * Defines the user entity class. @@ -44,68 +43,68 @@ * } * ) */ -class User extends EntityNG implements UserInterface { +class User extends Entity implements UserInterface { /** * The user ID. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var integer */ public $uid; /** * The user UUID. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ public $uuid; /** * The unique user name. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ - public $name; + public $name = ''; /** * The user's password (hashed). * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ public $pass; /** * The user's email address. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ - public $mail; + public $mail = ''; /** * The user's default theme. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ public $theme; /** * The user's signature. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ public $signature; /** * The user's signature format. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ public $signature_format; /** * The timestamp when the user was created. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var integer */ public $created; @@ -113,127 +112,71 @@ class User extends EntityNG implements UserInterface { * The timestamp when the user last accessed the site. A value of 0 means the * user has never accessed the site. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var integer */ - public $access; + public $access = 0; /** * The timestamp when the user last logged in. A value of 0 means the user has * never logged in. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var integer */ - public $login; + public $login = 0; /** * Whether the user is active (1) or blocked (0). * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var integer */ - public $status; + public $status = 1; /** * The user's timezone. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ public $timezone; /** * The user's langcode. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ - public $langcode; + public $langcode = Language::LANGCODE_NOT_SPECIFIED; /** * The user's preferred langcode for receiving emails and viewing the site. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ - public $preferred_langcode; + public $preferred_langcode = Language::LANGCODE_NOT_SPECIFIED; /** * The user's preferred langcode for viewing administration pages. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ - public $preferred_admin_langcode; + public $preferred_admin_langcode = Language::LANGCODE_NOT_SPECIFIED; /** * The email address used for initial account creation. * - * @var \Drupal\Core\Entity\Field\FieldInterface + * @var string */ - public $init; + public $init = ''; /** * The user's roles. * - * @var \Drupal\Core\Entity\Field\FieldInterface - */ - public $roles; - - /** - * The plain data values of the contained properties. - * - * Define default values. - * * @var array */ - protected $values = array( - 'langcode' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => Language::LANGCODE_NOT_SPECIFIED))), - 'preferred_langcode' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => Language::LANGCODE_NOT_SPECIFIED))), - 'admin_preffered_langcode' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => Language::LANGCODE_NOT_SPECIFIED))), - 'name' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => ''))), - 'mail' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => ''))), - 'init' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => ''))), - 'access' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), - 'login' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 0))), - 'status' => array(Language::LANGCODE_DEFAULT => array(0 => array('value' => 1))), - ); + public $roles = array(); /** - * {@inheritdoc} + * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { - return $this->get('uid')->value; - } - - /** - * {@inheritdoc} - */ - protected function init() { - parent::init(); - unset($this->access); - unset($this->created); - unset($this->init); - unset($this->login); - unset($this->mail); - unset($this->name); - unset($this->pass); - unset($this->preferred_admin_langcode); - unset($this->preferred_langcode); - unset($this->roles); - unset($this->signature); - unset($this->signature_format); - unset($this->status); - unset($this->theme); - unset($this->timezone); - unset($this->uid); - unset($this->uuid); + return $this->uid; } - - /** - * {@inheritdoc} - */ - public function getBCEntity() { - if (!isset($this->bcEntity)) { - // Initialize field definitions so that we can pass them by reference. - $this->getPropertyDefinitions(); - $this->bcEntity = new UserBCDecorator($this, $this->fieldDefinitions); - } - return $this->bcEntity; - } - } diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php b/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php index d00769f..d9ce035 100644 --- a/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php +++ b/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php @@ -26,8 +26,8 @@ protected function valueForm(&$form, &$form_state) { if ($this->value) { $result = entity_load_multiple_by_properties('user', array('uid' => $this->value)); foreach ($result as $account) { - if ($account->id()) { - $values[] = $account->name->value; + if ($account->uid) { + $values[] = $account->name; } else { $values[] = 'Anonymous'; // Intentionally NOT translated. @@ -130,8 +130,8 @@ function validate_user_strings(&$form, $values) { $result = entity_load_multiple_by_properties('user', array('name' => $args)); foreach ($result as $account) { - unset($missing[strtolower($account->name->value)]); - $uids[] = $account->id(); + unset($missing[strtolower($account->name)]); + $uids[] = $account->uid; } if ($missing) { @@ -156,10 +156,10 @@ public function adminSummary() { $result = entity_load_multiple_by_properties('user', array('uid' => $this->value)); foreach ($result as $account) { if ($account->uid) { - $this->value_options[$account->id()] = $account->label(); + $this->value_options[$account->uid] = $account->name; } else { - $this->value_options[$account->id()] = 'Anonymous'; // Intentionally NOT translated. + $this->value_options[$account->uid] = 'Anonymous'; // Intentionally NOT translated. } } } diff --git a/core/modules/user/lib/Drupal/user/RoleAccessController.php b/core/modules/user/lib/Drupal/user/RoleAccessController.php index 64973df..3fe0100 100644 --- a/core/modules/user/lib/Drupal/user/RoleAccessController.php +++ b/core/modules/user/lib/Drupal/user/RoleAccessController.php @@ -19,7 +19,7 @@ class RoleAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { switch ($operation) { case 'delete': if ($entity->id() == DRUPAL_ANONYMOUS_RID || $entity->id() == DRUPAL_AUTHENTICATED_RID) { diff --git a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php index 0769fff..3b83b52 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php @@ -60,8 +60,8 @@ function testUserAdmin() { // Filter the users by role. Grab the system-generated role name for User C. $roles = $user_c->roles; - unset($roles[array_search(DRUPAL_AUTHENTICATED_RID, $roles)]); - $edit['role'] = reset($roles); + unset($roles[DRUPAL_AUTHENTICATED_RID]); + $edit['role'] = key($roles); $this->drupalPost('admin/people', $edit, t('Refine')); // Check if the correct users show up when filtered by role. diff --git a/core/modules/user/lib/Drupal/user/Tests/UserEntityCallbacksTest.php b/core/modules/user/lib/Drupal/user/Tests/UserEntityCallbacksTest.php index a4bfd52..15894ad 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserEntityCallbacksTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserEntityCallbacksTest.php @@ -33,7 +33,7 @@ function setUp() { parent::setUp(); $this->account = $this->drupalCreateUser(); - $this->anonymous = entity_create('user', (array) drupal_anonymous_user()); + $this->anonymous = drupal_anonymous_user(); } /** diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php index 3fc3b4b..2455b10 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php @@ -28,8 +28,8 @@ function setUp() { // Find the new role ID. $all_rids = $this->admin_user->roles; - unset($all_rids[array_search(DRUPAL_AUTHENTICATED_RID, $all_rids)]); - $this->rid = reset($all_rids); + unset($all_rids[DRUPAL_AUTHENTICATED_RID]); + $this->rid = key($all_rids); } /** diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php index 8da2c2b..0462424 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php @@ -46,7 +46,7 @@ function testRegistrationWithEmailVerification() { $this->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), 'User registered successfully.'); $accounts = entity_load_multiple_by_properties('user', array('name' => $name, 'mail' => $mail)); $new_user = reset($accounts); - $this->assertTrue($new_user->status->value, 'New account is active after registration.'); + $this->assertTrue($new_user->status, 'New account is active after registration.'); // Allow registration by site visitors, but require administrator approval. $config->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)->save(); @@ -57,7 +57,7 @@ function testRegistrationWithEmailVerification() { $this->container->get('plugin.manager.entity')->getStorageController('user')->resetCache(); $accounts = entity_load_multiple_by_properties('user', array('name' => $name, 'mail' => $mail)); $new_user = reset($accounts); - $this->assertFalse($new_user->status->value, 'New account is blocked until approved by an administrator.'); + $this->assertFalse($new_user->status, 'New account is blocked until approved by an administrator.'); } function testRegistrationWithoutEmailVerification() { @@ -115,7 +115,7 @@ function testRegistrationWithoutEmailVerification() { $edit = array( 'status' => 1, ); - $this->drupalPost('user/' . $new_user->id() . '/edit', $edit, t('Save')); + $this->drupalPost('user/' . $new_user->uid . '/edit', $edit, t('Save')); $this->drupalLogout(); // Login after administrator approval. @@ -178,16 +178,16 @@ function testRegistrationDefaultValues() { // Check user fields. $accounts = entity_load_multiple_by_properties('user', array('name' => $name, 'mail' => $mail)); $new_user = reset($accounts); - $this->assertEqual($new_user->name->value, $name, 'Username matches.'); - $this->assertEqual($new_user->mail->value, $mail, 'E-mail address matches.'); - $this->assertEqual($new_user->theme->value, '', 'Correct theme field.'); - $this->assertEqual($new_user->signature->value, '', 'Correct signature field.'); - $this->assertTrue(($new_user->created->value > REQUEST_TIME - 20 ), 'Correct creation time.'); - $this->assertEqual($new_user->status->value, $config_user_settings->get('register') == USER_REGISTER_VISITORS ? 1 : 0, 'Correct status field.'); - $this->assertEqual($new_user->timezone->value, $config_system_timezone->get('default'), 'Correct time zone field.'); - $this->assertEqual($new_user->langcode->value, language_default()->langcode, 'Correct language field.'); - $this->assertEqual($new_user->preferred_langcode->value, language_default()->langcode, 'Correct preferred language field.'); - $this->assertEqual($new_user->init->value, $mail, 'Correct init field.'); + $this->assertEqual($new_user->name, $name, 'Username matches.'); + $this->assertEqual($new_user->mail, $mail, 'E-mail address matches.'); + $this->assertEqual($new_user->theme, '', 'Correct theme field.'); + $this->assertEqual($new_user->signature, '', 'Correct signature field.'); + $this->assertTrue(($new_user->created > REQUEST_TIME - 20 ), 'Correct creation time.'); + $this->assertEqual($new_user->status, $config_user_settings->get('register') == USER_REGISTER_VISITORS ? 1 : 0, 'Correct status field.'); + $this->assertEqual($new_user->timezone, $config_system_timezone->get('default'), 'Correct time zone field.'); + $this->assertEqual($new_user->langcode, language_default()->langcode, 'Correct language field.'); + $this->assertEqual($new_user->preferred_langcode, language_default()->langcode, 'Correct preferred language field.'); + $this->assertEqual($new_user->init, $mail, 'Correct init field.'); } /** @@ -244,7 +244,7 @@ function testRegistrationWithUserFields() { // Check user fields. $accounts = entity_load_multiple_by_properties('user', array('name' => $name, 'mail' => $mail)); $new_user = reset($accounts); - $this->assertEqual($new_user->test_user_field->value, $value, 'The field value was correclty saved.'); + $this->assertEqual($new_user->test_user_field[Language::LANGCODE_NOT_SPECIFIED][0]['value'], $value, 'The field value was correclty saved.'); // Check that the 'add more' button works. $field['cardinality'] = FIELD_CARDINALITY_UNLIMITED; @@ -272,9 +272,9 @@ function testRegistrationWithUserFields() { // Check user fields. $accounts = entity_load_multiple_by_properties('user', array('name' => $name, 'mail' => $mail)); $new_user = reset($accounts); - $this->assertEqual($new_user->test_user_field[0]->value, $value, format_string('@js : The field value was correclty saved.', array('@js' => $js))); - $this->assertEqual($new_user->test_user_field[1]->value, $value + 1, format_string('@js : The field value was correclty saved.', array('@js' => $js))); - $this->assertEqual($new_user->test_user_field[2]->value, $value + 2, format_string('@js : The field value was correclty saved.', array('@js' => $js))); + $this->assertEqual($new_user->test_user_field[Language::LANGCODE_NOT_SPECIFIED][0]['value'], $value, format_string('@js : The field value was correclty saved.', array('@js' => $js))); + $this->assertEqual($new_user->test_user_field[Language::LANGCODE_NOT_SPECIFIED][1]['value'], $value + 1, format_string('@js : The field value was correclty saved.', array('@js' => $js))); + $this->assertEqual($new_user->test_user_field[Language::LANGCODE_NOT_SPECIFIED][2]['value'], $value + 2, format_string('@js : The field value was correclty saved.', array('@js' => $js))); } } } diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRolesAssignmentTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRolesAssignmentTest.php index e612374..349b2a9 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRolesAssignmentTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRolesAssignmentTest.php @@ -94,10 +94,10 @@ function testCreateUserWithRole() { private function userLoadAndCheckRoleAssigned($account, $rid, $is_assigned = TRUE) { $account = user_load($account->uid, TRUE); if ($is_assigned) { - $this->assertTrue(array_search($rid, $account->roles), 'The role is present in the user object.'); + $this->assertTrue(array_key_exists($rid, $account->roles), 'The role is present in the user object.'); } else { - $this->assertFalse(array_search($rid, $account->roles), 'The role is not present in the user object.'); + $this->assertFalse(array_key_exists($rid, $account->roles), 'The role is not present in the user object.'); } } } diff --git a/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php b/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php index fe3fa0f..171a976 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserTranslationUITest.php @@ -39,8 +39,6 @@ function setUp() { $this->testLanguageSelector = FALSE; $this->name = $this->randomName(); parent::setUp(); - - entity_get_controller('user')->resetCache(); } /** diff --git a/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php b/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php index c1a26fc..5455eaa 100644 --- a/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php +++ b/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php @@ -54,11 +54,11 @@ protected function setUp() { $this->adminUser = $this->drupalCreateUser(array('access all views')); $this->webUser = $this->drupalCreateUser(); - $this->webRole = $this->webUser->roles[0]; + $this->webRole = current($this->webUser->roles); $this->normalRole = $this->drupalCreateRole(array()); $this->normalUser = $this->drupalCreateUser(array('views_test_data test permission')); - $this->normalUser->getNGEntity()->roles[2] = $this->normalRole; + $this->normalUser->roles[$this->normalRole] = $this->normalRole; // @todo when all the plugin information is cached make a reset function and // call it here. } diff --git a/core/modules/user/lib/Drupal/user/Tests/Views/HandlerFieldRoleTest.php b/core/modules/user/lib/Drupal/user/Tests/Views/HandlerFieldRoleTest.php index 476b5cd..22fa93f 100644 --- a/core/modules/user/lib/Drupal/user/Tests/Views/HandlerFieldRoleTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/Views/HandlerFieldRoleTest.php @@ -41,9 +41,9 @@ public function testRole() { $this->drupalCreateRole(array('access content'), $rolename_not_assigned, $rolename_not_assigned); // Add roles to user 1. - $user = entity_load('user', 1); - $user->roles[1]->value = $rolename_a; - $user->roles[2]->value = $rolename_b; + $user = user_load(1); + $user->roles[$rid_a] = $rolename_a; + $user->roles[$rid_b] = $rolename_b; $user->save(); $view = views_get_view('test_views_handler_field_role'); diff --git a/core/modules/user/lib/Drupal/user/UserAccessController.php b/core/modules/user/lib/Drupal/user/UserAccessController.php index 2651933..4332fbc 100644 --- a/core/modules/user/lib/Drupal/user/UserAccessController.php +++ b/core/modules/user/lib/Drupal/user/UserAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityAccessController; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Defines the access controller for the user entity type. @@ -19,7 +19,7 @@ class UserAccessController extends EntityAccessController { /** * {@inheritdoc} */ - protected function checkAccess(EntityInterface $entity, $operation, $langcode, UserInterface $account) { + protected function checkAccess(EntityInterface $entity, $operation, $langcode, User $account) { switch ($operation) { case 'view': return $this->viewAccess($entity, $langcode, $account); @@ -32,14 +32,14 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U case 'update': // Users can always edit their own account. Users with the 'administer // users' permission can edit any account except the anonymous account. - return (($account->uid == $entity->id()) || user_access('administer users', $account)) && $entity->id() > 0; + return (($account->uid == $entity->uid) || user_access('administer users', $account)) && $entity->uid > 0; break; case 'delete': // Users with 'cancel account' permission can cancel their own account, // users with 'administer users' permission can cancel any account // except the anonymous account. - return ((($account->uid == $entity->id()) && user_access('cancel account', $account)) || user_access('administer users', $account)) && $entity->id() > 0; + return ((($account->uid == $entity->uid) && user_access('cancel account', $account)) || user_access('administer users', $account)) && $entity->uid > 0; break; } } @@ -49,16 +49,16 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, U * * See EntityAccessControllerInterface::view() for parameters. */ - protected function viewAccess(EntityInterface $entity, $langcode, UserInterface $account) { + protected function viewAccess(EntityInterface $entity, $langcode, User $account) { // Never allow access to view the anonymous user account. - if ($entity->id()) { + if ($entity->uid) { // Admins can view all, users can view own profiles at all times. - if ($account->uid == $entity->id() || user_access('administer users', $account)) { + if ($account->uid == $entity->uid || user_access('administer users', $account)) { return TRUE; } elseif (user_access('access user profiles', $account)) { // Only allow view access if the account is active. - return $entity->status->value; + return $entity->status; } } return FALSE; diff --git a/core/modules/user/lib/Drupal/user/UserBCDecorator.php b/core/modules/user/lib/Drupal/user/UserBCDecorator.php deleted file mode 100644 index 586bc0a..0000000 --- a/core/modules/user/lib/Drupal/user/UserBCDecorator.php +++ /dev/null @@ -1,32 +0,0 @@ -getNGEntity()->roles as $role) { - $roles[] = $role->value; - } - return $roles; - } - return parent::__get($name); - } -} diff --git a/core/modules/user/lib/Drupal/user/UserConfigContext.php b/core/modules/user/lib/Drupal/user/UserConfigContext.php index 1d5f497..137b915 100644 --- a/core/modules/user/lib/Drupal/user/UserConfigContext.php +++ b/core/modules/user/lib/Drupal/user/UserConfigContext.php @@ -8,7 +8,7 @@ namespace Drupal\user; use Drupal\Core\Config\Context\ConfigContext; -use Drupal\user\UserInterfaceInterface; +use Drupal\user\Plugin\Core\Entity\User; /** @@ -29,13 +29,13 @@ class UserConfigContext extends ConfigContext { /** * Creates the configuration context for user accounts. * - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The account to add to the config context. * * @return \Drupal\user\UserConfigContext * The user config context object. */ - public function setAccount(UserInterface $account) { + public function setAccount(User $account) { $this->set(self::USER_KEY, $account); // Re-initialize since the user change changes the context fundamentally. $this->init(); diff --git a/core/modules/user/lib/Drupal/user/UserInterface.php b/core/modules/user/lib/Drupal/user/UserInterface.php index 3a98dd5..99818a8 100644 --- a/core/modules/user/lib/Drupal/user/UserInterface.php +++ b/core/modules/user/lib/Drupal/user/UserInterface.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\user\UserInterface. + * Contains \Drupal\user\Plugin\Core\Entity\UserInterface. */ namespace Drupal\user; diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php index c8d40fd..e282226 100644 --- a/core/modules/user/lib/Drupal/user/UserStorageController.php +++ b/core/modules/user/lib/Drupal/user/UserStorageController.php @@ -7,13 +7,13 @@ namespace Drupal\user; -use Drupal\Core\Entity\EntityBCDecorator; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityMalformedException; +use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Password\PasswordInterface; use Drupal\Core\Database\Connection; use Drupal\user\UserDataInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Entity\DatabaseStorageControllerNG; /** * Controller class for users. @@ -21,7 +21,7 @@ * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding * required special handling for user objects. */ -class UserStorageController extends DatabaseStorageControllerNG { +class UserStorageController extends DatabaseStorageController { /** * Provides the password hashing service object. @@ -78,17 +78,17 @@ function attachLoad(&$queried_users, $load_revision = FALSE) { foreach ($queried_users as $key => $record) { $queried_users[$key]->roles = array(); if ($record->uid) { - $queried_users[$record->uid]->roles[] = DRUPAL_AUTHENTICATED_RID; + $queried_users[$record->uid]->roles[DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID; } else { - $queried_users[$record->uid]->roles[] = DRUPAL_ANONYMOUS_RID; + $queried_users[$record->uid]->roles[DRUPAL_ANONYMOUS_RID] = DRUPAL_ANONYMOUS_RID; } } // Add any additional roles from the database. $result = db_query('SELECT rid, uid FROM {users_roles} WHERE uid IN (:uids)', array(':uids' => array_keys($queried_users))); foreach ($result as $record) { - $queried_users[$record->uid]->roles[] = $record->rid; + $queried_users[$record->uid]->roles[$record->rid] = $record->rid; } // Call the default attachLoad() method. This will add fields and call @@ -104,24 +104,19 @@ public function create(array $values) { $values['created'] = REQUEST_TIME; } // Users always have the authenticated user role. - $values['roles'][] = DRUPAL_AUTHENTICATED_RID; + $values['roles'][DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID; - return parent::create($values)->getBCEntity(); + return parent::create($values); } /** * Overrides Drupal\Core\Entity\DatabaseStorageController::save(). */ public function save(EntityInterface $entity) { - if (!$entity->id()) { - $entity->uid->value = $this->database->nextId($this->database->query('SELECT MAX(uid) FROM {users}')->fetchField()); + if (empty($entity->uid)) { + $entity->uid = $this->database->nextId(db_query('SELECT MAX(uid) FROM {users}')->fetchField()); $entity->enforceIsNew(); } - // There are some cases that pre-set ->original for performance. Make sure - // original is not a BC decorator. - if ($entity->original instanceof EntityBCDecorator) { - $entity->original = $entity->original->getNGEntity(); - } parent::save($entity); } @@ -130,11 +125,11 @@ public function save(EntityInterface $entity) { */ protected function preSave(EntityInterface $entity) { // Update the user password if it has changed. - if ($entity->isNew() || ($entity->pass->value && $entity->pass->value != $entity->original->pass->value)) { + if ($entity->isNew() || (!empty($entity->pass) && $entity->pass != $entity->original->pass)) { // Allow alternate password hashing schemes. - $entity->pass->value = $this->password->hash(trim($entity->pass->value)); + $entity->pass = $this->password->hash(trim($entity->pass)); // Abort if the hashing failed and returned FALSE. - if (!$entity->pass->value) { + if (!$entity->pass) { throw new EntityMalformedException('The entity does not have a password.'); } } @@ -142,11 +137,16 @@ protected function preSave(EntityInterface $entity) { if (!$entity->isNew()) { // If the password is empty, that means it was not changed, so use the // original password. - if (empty($entity->pass->value)) { - $entity->pass->value = $entity->original->pass->value; + if (empty($entity->pass)) { + $entity->pass = $entity->original->pass; } } + // Prepare user roles. + if (isset($entity->roles)) { + $entity->roles = array_filter($entity->roles); + } + // Store account cancellation information. foreach (array('user_cancel_method', 'user_cancel_notify') as $key) { if (isset($entity->{$key})) { @@ -163,26 +163,28 @@ protected function postSave(EntityInterface $entity, $update) { if ($update) { // If the password has been changed, delete all open sessions for the // user and recreate the current one. - if ($entity->pass->value != $entity->original->pass->value) { - drupal_session_destroy_uid($entity->id()); - if ($entity->id() == $GLOBALS['user']->uid) { + if ($entity->pass != $entity->original->pass) { + drupal_session_destroy_uid($entity->uid); + if ($entity->uid == $GLOBALS['user']->uid) { drupal_session_regenerate(); } } - // Update user roles if changed. - if ($entity->roles->getValue() != $entity->original->roles->getValue()) { - db_delete('users_roles') - ->condition('uid', $entity->id()) + // Remove roles that are no longer enabled for the user. + $entity->roles = array_filter($entity->roles); + + // Reload user roles if provided. + if ($entity->roles != $entity->original->roles) { + $this->database->delete('users_roles') + ->condition('uid', $entity->uid) ->execute(); $query = $this->database->insert('users_roles')->fields(array('uid', 'rid')); - foreach ($entity->roles as $role) { - if (!in_array($role->value, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { - + foreach (array_keys($entity->roles) as $rid) { + if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { $query->values(array( - 'uid' => $entity->id(), - 'rid' => $role->value, + 'uid' => $entity->uid, + 'rid' => $rid, )); } } @@ -190,26 +192,26 @@ protected function postSave(EntityInterface $entity, $update) { } // If the user was blocked, delete the user's sessions to force a logout. - if ($entity->original->status->value != $entity->status->value && $entity->status->value == 0) { - drupal_session_destroy_uid($entity->id()); + if ($entity->original->status != $entity->status && $entity->status == 0) { + drupal_session_destroy_uid($entity->uid); } // Send emails after we have the new user object. - if ($entity->status->value != $entity->original->status->value) { + if ($entity->status != $entity->original->status) { // The user's status is changing; conditionally send notification email. - $op = $entity->status->value == 1 ? 'status_activated' : 'status_blocked'; - _user_mail_notify($op, $entity->getBCEntity()); + $op = $entity->status == 1 ? 'status_activated' : 'status_blocked'; + _user_mail_notify($op, $entity); } } else { // Save user roles. if (count($entity->roles) > 1) { $query = $this->database->insert('users_roles')->fields(array('uid', 'rid')); - foreach ($entity->roles as $role) { - if (!in_array($role->value, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { + foreach (array_keys($entity->roles) as $rid) { + if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { $query->values(array( - 'uid' => $entity->id(), - 'rid' => $role->value, + 'uid' => $entity->uid, + 'rid' => $rid, )); } } @@ -227,123 +229,4 @@ protected function postDelete($entities) { ->execute(); $this->userData->delete(NULL, array_keys($entities)); } - - /** - * {@inheritdoc} - */ - protected function invokeHook($hook, EntityInterface $entity) { - $function = 'field_attach_' . $hook; - // @todo: field_attach_delete_revision() is named the wrong way round, - // consider renaming it. - if ($function == 'field_attach_revision_delete') { - $function = 'field_attach_delete_revision'; - } - if (!empty($this->entityInfo['fieldable']) && function_exists($function)) { - $function($entity->getBCEntity()); - } - - // Invoke the hook. - \Drupal::moduleHandler()->invokeAll($this->entityType . '_' . $hook, array($entity->getBCEntity())); - // Invoke the respective entity-level hook. - \Drupal::moduleHandler()->invokeAll('entity_' . $hook, array($entity->getBCEntity(), $this->entityType)); - } - - /** - * {@inheritdoc} - */ - public function baseFieldDefinitions() { - $properties['uid'] = array( - 'label' => t('User ID'), - 'description' => t('The user ID.'), - 'type' => 'integer_field', - 'read-only' => TRUE, - ); - $properties['uuid'] = array( - 'label' => t('UUID'), - 'description' => t('The user UUID.'), - 'type' => 'string_field', - 'read-only' => TRUE, - ); - $properties['langcode'] = array( - 'label' => t('Language code'), - 'description' => t('The user language code.'), - 'type' => 'language_field', - ); - $properties['preferred_langcode'] = array( - 'label' => t('Language code'), - 'description' => t("The user's preferred langcode for receiving emails and viewing the site."), - 'type' => 'language_field', - ); - $properties['preferred_admin_langcode'] = array( - 'label' => t('Language code'), - 'description' => t("The user's preferred langcode for viewing administration pages."), - 'type' => 'language_field', - ); - $properties['name'] = array( - 'label' => t('Name'), - 'description' => t('The name of this user'), - 'type' => 'string_field', - ); - $properties['pass'] = array( - 'label' => t('Name'), - 'description' => t('The password of this user (hashed)'), - 'type' => 'string_field', - ); - $properties['mail'] = array( - 'label' => t('Name'), - 'description' => t('The e-mail of this user'), - 'type' => 'string_field', - ); - $properties['signature'] = array( - 'label' => t('Name'), - 'description' => t('The signature of this user'), - 'type' => 'string_field', - ); - $properties['signature_format'] = array( - 'label' => t('Name'), - 'description' => t('The signature format of this user'), - 'type' => 'string_field', - ); - $properties['theme'] = array( - 'label' => t('Theme'), - 'description' => t('The default theme of this user'), - 'type' => 'string_field', - ); - $properties['timezone'] = array( - 'label' => t('Timeone'), - 'description' => t('The timezone of this user'), - 'type' => 'string_field', - ); - $properties['status'] = array( - 'label' => t('User status'), - 'description' => t('Whether the user is active (1) or blocked (0).'), - 'type' => 'boolean_field', - ); - $properties['created'] = array( - 'label' => t('Created'), - 'description' => t('The time that the node was created.'), - 'type' => 'integer_field', - ); - $properties['access'] = array( - 'label' => t('Last access'), - 'description' => t('The time that the user last accessed the site.'), - 'type' => 'integer_field', - ); - $properties['login'] = array( - 'label' => t('Last login'), - 'description' => t('The time that the user last logged in.'), - 'type' => 'integer_field', - ); - $properties['init'] = array( - 'label' => t('Init'), - 'description' => t('The email address used for initial account creation.'), - 'type' => 'string_field', - ); - $properties['roles'] = array( - 'label' => t('Roles'), - 'description' => t('The roles the user has.'), - 'type' => 'string_field', - ); - return $properties; - } } diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc index 0f199e6..adb5259 100644 --- a/core/modules/user/user.admin.inc +++ b/core/modules/user/user.admin.inc @@ -303,7 +303,7 @@ function user_admin_permissions($form, $form_state, $rid = NULL) { $role_names = array($rid => $role_names[$rid]); } // Fetch permissions for all roles or the one selected role. - $role_permissions = user_role_permissions(array_keys($role_names)); + $role_permissions = user_role_permissions($role_names); // Store $role_names for use when saving the data. $form['role_names'] = array( diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php index 51ed678..5309f81 100644 --- a/core/modules/user/user.api.php +++ b/core/modules/user/user.api.php @@ -18,7 +18,7 @@ * This hook runs after a new user object has just been instantiated. It can be * used to set initial values, e.g. to provide defaults. * - * @param \Drupal\user\UserInterface $user + * @param \Drupal\user\Plugin\Core\Entity\User $user * The user object. */ function hook_user_create(\Drupal\user\Plugin\Core\Entity\User $user) { @@ -346,7 +346,7 @@ function hook_user_logout($account) { * The module should format its custom additions for display and add them to the * $account->content array. * - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user object on which the operation is being performed. * @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display * The entity_display object holding the display options configured for the @@ -359,7 +359,7 @@ function hook_user_logout($account) { * @see hook_user_view_alter() * @see hook_entity_view() */ -function hook_user_view(\Drupal\user\UserInterface $account, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) { +function hook_user_view(\Drupal\user\Plugin\Core\Entity\User $account, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) { // Only do the extra work if the component is configured to be displayed. // This assumes a 'mymodule_addition' extra field has been defined for the // user entity type in hook_field_extra_fields(). @@ -386,7 +386,7 @@ function hook_user_view(\Drupal\user\UserInterface $account, \Drupal\entity\Plug * * @param $build * A renderable array representing the user. - * @param \Drupal\user\UserInterface $account + * @param \Drupal\user\Plugin\Core\Entity\User $account * The user account being rendered. * @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display * The entity_display object holding the display options configured for the diff --git a/core/modules/user/user.install b/core/modules/user/user.install index a8e9168..ed56aed 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -377,18 +377,6 @@ function user_install_picture_field() { } /** - * Implements hook_update_dependencies(). - */ -function user_update_dependencies() { - // Convert user picture to field after the fields and instances are converted - // to ConfigEntities. - $dependencies['user'][8011] = array( - 'field' => 8003, - ); - return $dependencies; -} - -/** * @addtogroup updates-7.x-to-8.x * @{ */ @@ -669,11 +657,13 @@ function user_update_8011() { // User pictures can only be migrated to the new user picture image field // if Image module is installed. if (!module_exists('image')) { - $old_schema = module_enable(array('image')); + // Install image.module with schema version 8002 as a previous version + // would have to create tables that would be removed again. + $old_schema = update_module_enable(array('image'), 8002); if ($old_schema['image'] == SCHEMA_UNINSTALLED) { - // Install image.module with schema version 8002 as a previous version - // would have to create tables that would be removed again. - update_set_schema('image', 8002); + // If image.module was not installed before, install default + // configuration and run the install hook. + config_install_default_config('module', 'image'); // Inlined version of image_install(), make sure that the styles // directory exists. $directory = update_variable_get('file_default_scheme', 'public') . '://styles'; @@ -711,7 +701,7 @@ function user_update_8011() { // Create the field and instance. $field = array( - 'id' => 'user_picture', + 'field_name' => 'user_picture', 'module' => 'image', 'type' => 'image', 'cardinality' => 1, @@ -721,11 +711,15 @@ function user_update_8011() { 'uri_scheme' => 'public', 'default_image' => FALSE, ), + 'storage' => array( + 'type' => 'field_sql_storage', + 'settings' => array(), + ), ); - _update_8003_field_create_field($field); + _update_7000_field_create_field($field); $instance = array( - 'id' => 'user.user.user_picture', + 'field_name' => 'user_picture', 'entity_type' => 'user', 'label' => 'Picture', 'bundle' => 'user', @@ -742,7 +736,7 @@ function user_update_8011() { 'default_image' => !empty($default_image_fid) ? array($default_image_fid) : array(), ), ); - _update_8003_field_create_instance($field, $instance); + _update_7000_field_create_instance($field, $instance); module_load_install('entity'); if (update_variable_get('user_pictures', 0)) { @@ -789,11 +783,8 @@ function user_update_8011() { 'image_link' => 'content', ), 'weight' => 0, - )); - $display->set('content.member_for', array( - 'visible' => FALSE, - )); - $display->save(); + )) + ->save(); update_config_manifest_add('entity.display', array($display->get('id'))); // Add file usage for the default field. @@ -803,12 +794,20 @@ function user_update_8011() { 'fid' => $default_image_fid, 'module' => 'image', 'type' => 'default_image', - 'id' => $field['uuid'], + 'id' => $field['id'], 'count' => 1, )) ->execute(); } + // Update the user bundle settings and hide the member_for extra field. + $settings = update_variable_get('field_bundle_settings_user__user'); + $settings['extra_fields']['display']['member_for']['compact'] = array( + 'weight' => 0, + 'visible' => FALSE, + ); + update_variable_set('field_bundle_settings_user__user', $settings); + // Delete old variables. update_variable_del('user_pictures'); update_variable_del('user_picture_path'); diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 593d35a..abfe84b 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -7,7 +7,6 @@ use Drupal\entity\Plugin\Core\Entity\EntityDisplay; use Drupal\file\Plugin\Core\Entity\File; use Drupal\user\Plugin\Core\Entity\User; -use Drupal\user\UserInterface; use Drupal\user\UserRole; use Drupal\Core\Template\Attribute; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -135,7 +134,7 @@ function user_entity_bundle_info() { */ function user_uri($user) { return array( - 'path' => 'user/' . $user->id(), + 'path' => 'user/' . $user->uid, ); } @@ -156,7 +155,7 @@ function user_uri($user) { * @see user_format_name() */ function user_label($entity_type, $entity) { - return user_format_name($entity->getBCEntity()); + return user_format_name($entity); } /** @@ -272,12 +271,7 @@ function user_field_extra_fields() { * @see \Drupal\Core\Entity\Query\QueryInterface */ function user_load_multiple(array $uids = NULL, $reset = FALSE) { - $entities = entity_load_multiple('user', $uids, $reset); - // Return BC-entities. - foreach ($entities as $id => $entity) { - $entities[$id] = $entity->getBCEntity(); - } - return $entities; + return entity_load_multiple('user', $uids, $reset); } /** @@ -305,8 +299,7 @@ function user_load_multiple(array $uids = NULL, $reset = FALSE) { * @see user_load_multiple() */ function user_load($uid, $reset = FALSE) { - $user = entity_load('user', $uid, $reset); - return $user ? $user->getBCEntity() : FALSE; + return entity_load('user', $uid, $reset); } /** @@ -322,7 +315,7 @@ function user_load($uid, $reset = FALSE) { */ function user_load_by_mail($mail) { $users = entity_load_multiple_by_properties('user', array('mail' => $mail)); - return $users ? reset($users)->getBCEntity() : FALSE; + return reset($users); } /** @@ -338,7 +331,7 @@ function user_load_by_mail($mail) { */ function user_load_by_name($name) { $users = entity_load_multiple_by_properties('user', array('name' => $name)); - return $users ? reset($users)->getBCEntity() : FALSE; + return reset($users); } /** @@ -408,7 +401,7 @@ function user_password($length = 10) { * Determine the permissions for one or more roles. * * @param $roles - * An array whose values are the role IDs of interest, such as $user->roles. + * An array whose keys are the role IDs of interest, such as $user->roles. * * @return * An array indexed by role ID. Each value is an array whose keys are the @@ -419,7 +412,7 @@ function user_role_permissions($roles) { $role_permissions = $fetch = array(); - foreach ($roles as $rid) { + foreach ($roles as $rid => $name) { if (isset($cache[$rid])) { $role_permissions[$rid] = $cache[$rid]; } @@ -470,9 +463,6 @@ function user_access($string, $account = NULL) { $account = $user; } - // Make sure we are working with the BC decorator. - $account = $account instanceof User ? $account->getBCEntity() : $account; - // User #1 has all privileges: if ($account->uid == 1) { return TRUE; @@ -611,7 +601,7 @@ function user_search_execute($keys = NULL, $conditions = NULL) { /** * Implements hook_user_view(). */ -function user_user_view(UserInterface $account, EntityDisplay $display) { +function user_user_view(User $account, EntityDisplay $display) { if ($display->getComponent('member_for')) { $account->content['member_for'] = array( '#type' => 'item', @@ -732,9 +722,6 @@ function user_template_preprocess_default_variables_alter(&$variables) { */ function template_preprocess_username(&$variables) { $account = $variables['account']; - if ($account instanceof User) { - $account = $account->getBCEntity(); - } $variables['extra'] = ''; if (empty($account->uid)) { @@ -2116,11 +2103,12 @@ function user_multiple_role_edit($accounts, $operation, $rid) { $accounts = user_load_multiple($accounts); foreach ($accounts as $account) { // Skip adding the role to the user if they already have it. - if ($account !== FALSE && !in_array($rid, $account->roles)) { + if ($account !== FALSE && !isset($account->roles[$rid])) { + $roles = $account->roles + array($rid => $role_name); // For efficiency manually save the original account before applying // any changes. $account->original = clone $account; - $account->roles[] = $rid; + $account->roles = $roles; $account->save(); } } @@ -2129,8 +2117,8 @@ function user_multiple_role_edit($accounts, $operation, $rid) { $accounts = user_load_multiple($accounts); foreach ($accounts as $account) { // Skip removing the role from the user if they already don't have it. - if ($account !== FALSE && in_array($rid, $account->roles)) { - $roles = array_diff($account->roles, array($rid)); + if ($account !== FALSE && isset($account->roles[$rid])) { + $roles = array_diff($account->roles, array($rid => $role_name)); // For efficiency manually save the original account before applying // any changes. $account->original = clone $account; @@ -2297,10 +2285,9 @@ function user_build_filter_query(SelectInterface $query) { // the authenticated role. If so, then all users would be listed, and we can // skip adding it to the filter query. if ($key == 'permission') { - $account = entity_create('user', array( - 'uid' => 'user_filter', - 'roles' => array(DRUPAL_AUTHENTICATED_RID), - )); + $account = entity_create('user', array()); + $account->uid = 'user_filter'; + $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1); if (user_access($value, $account)) { continue; } @@ -2360,7 +2347,6 @@ function theme_user_signature($variables) { */ function user_preferred_langcode($account, $type = NULL, $default = NULL) { $language_list = language_list(); - $account = $account->getBCEntity(); if (isset($type)) { $preferred_langcode = $account->{'preferred_' . $type . '_langcode'}; } diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index 648a3b3..ed1e029 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -78,7 +78,7 @@ function user_pass_submit($form, &$form_state) { $account = $form_state['values']['account']; // Mail one time login URL and instructions using current language. - $mail = _user_mail_notify('password_reset', $account->getBCEntity(), $language_interface->langcode); + $mail = _user_mail_notify('password_reset', $account, $language_interface->langcode); if (!empty($mail)) { watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail)); drupal_set_message(t('Further instructions have been sent to your e-mail address.')); diff --git a/core/modules/views/config/views.view.glossary.yml b/core/modules/views/config/views.view.glossary.yml index 23e095c..e73a417 100644 --- a/core/modules/views/config/views.view.glossary.yml +++ b/core/modules/views/config/views.view.glossary.yml @@ -361,7 +361,7 @@ display: break_phrase: '0' displays: default: default - page_1: page_1 + page: page_1 inherit_arguments: '0' label: Glossary module: node diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/access/AccessPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/access/AccessPluginBase.php index d5713b4..18d3cfe 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/access/AccessPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/access/AccessPluginBase.php @@ -57,7 +57,7 @@ public function summaryTitle() { /** * Determine if the current user has access or not. * - * @param \Drupal\user\UserInterface $account + * @param Drupal\user\User $account * The user who wants to access this view. * * @return TRUE diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php index 819cf95..8a2cb0c 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php @@ -285,7 +285,7 @@ public function generateResultsKey() { } $key_data = array( 'build_info' => $build_info, - 'roles' => $user->roles, + 'roles' => array_keys($user->roles), 'super-user' => $user->uid == 1, // special caching for super user. 'langcode' => language(Language::TYPE_INTERFACE)->langcode, 'base_url' => $GLOBALS['base_url'], @@ -313,7 +313,7 @@ public function generateOutputKey() { if (!isset($this->outputKey)) { $key_data = array( 'result' => $this->view->result, - 'roles' => $user->roles, + 'roles' => array_keys($user->roles), 'super-user' => $user->uid == 1, // special caching for super user. 'theme' => $GLOBALS['theme'], 'langcode' => language(Language::TYPE_INTERFACE)->langcode, diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php index 63fc004..11a7444 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php @@ -1367,7 +1367,7 @@ public function storeExposedInput($input, $status) { // Check if we store exposed value for current user. global $user; $allowed_rids = empty($this->options['expose']['remember_roles']) ? array() : array_filter($this->options['expose']['remember_roles']); - $intersect_rids = array_intersect(array_keys($allowed_rids), $user->roles); + $intersect_rids = array_intersect_key($allowed_rids, $user->roles); if (empty($intersect_rids)) { return; } diff --git a/core/modules/views/lib/Drupal/views/Tests/GlossaryTest.php b/core/modules/views/lib/Drupal/views/Tests/GlossaryTest.php index 601c953..ad0dfe3 100644 --- a/core/modules/views/lib/Drupal/views/Tests/GlossaryTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/GlossaryTest.php @@ -6,25 +6,17 @@ */ namespace Drupal\views\Tests; -use Drupal\Component\Utility\Unicode; /** * Tests glossary view ( summary of arguments ). */ class GlossaryTest extends ViewTestBase { - /** - * Modules to enable. - * - * @var array - */ - public static $modules = array('node'); - public static function getInfo() { return array( 'name' => 'Glossary tests', 'description' => 'Tests glossary functionality of views.', - 'group' => 'Views Config', + 'group' => 'Views', ); } @@ -63,24 +55,6 @@ public function testGlossaryView() { foreach ($view->result as $item) { $this->assertEqual($nodes_per_char[$item->title_truncated], $item->num_records); } - - // Enable the glossary to be displayed. - $view->storage->enable()->save(); - // Check the actual page response. - $this->drupalGet('glossary'); - $this->assertResponse(200); - - foreach ($nodes_per_char as $char => $count) { - $href = url('glossary/' . $char); - $label = Unicode::strtoupper($char); - // Get the summary link for a certain character. Filter by label and href - // to ensure that both of them are correct. - $result = $this->xpath('//a[contains(@href, :href) and normalize-space(text())=:label]/..', array(':href' => $href, ':label' => $label)); - $this->assertTrue(count($result)); - // The rendered output looks like "| (count)" so let's figure out the int. - $result_count = trim(str_replace(array('|', '(', ')'), '', (string) $result[0])); - $this->assertEqual($result_count, $count, 'The expected number got rendered.'); - } } } diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php index d5c4375..03dbbad 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/AccessTest.php @@ -41,13 +41,12 @@ protected function setUp() { $this->admin_user = $this->drupalCreateUser(array('access all views')); $this->web_user = $this->drupalCreateUser(); - $this->web_role = $this->web_user->roles[0]; + $this->web_role = current($this->web_user->roles); $this->normal_role = $this->drupalCreateRole(array()); $this->normal_user = $this->drupalCreateUser(array('views_test_data test permission')); + $this->normal_user->roles[$this->normal_role] = $this->normal_role; - // @todo: How to add a new item to the roles field list. - $this->normal_user->getNGEntity()->roles[2]->value = $this->normal_role; // @todo when all the plugin information is cached make a reset function and // call it here. } diff --git a/core/modules/views/views.install b/core/modules/views/views.install index d3c0dee..aea8d0c 100644 --- a/core/modules/views/views.install +++ b/core/modules/views/views.install @@ -17,7 +17,7 @@ function views_install() { /** * Provide an initial schema. * - * @see UpdateModuleHandler::enable(). + * @see update_module_enable(). */ function views_schema_0() { module_load_install('system'); 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 abe1e45..42d58d9 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -14,7 +14,7 @@ use Drupal\views\Plugin\views\query\Sql; use Drupal\views\Plugin\Core\Entity\View; use Drupal\views\ViewStorageInterface; -use Drupal\user\UserInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Stores UI related temporary settings. @@ -943,7 +943,7 @@ public function language() { /** * Implements \Drupal\Core\TypedData\AccessibleInterface::access(). */ - public function access($operation = 'view', UserInterface $account = NULL) { + public function access($operation = 'view', User $account = NULL) { return $this->storage->access($operation, $account); } diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 49b1a44..62fca07 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -285,10 +285,8 @@ function simpletest_script_init($server_software) { if (!empty($args['url'])) { $parsed_url = parse_url($args['url']); $host = $parsed_url['host'] . (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''); - $path = isset($parsed_url['path']) ? rtrim($parsed_url['path']) : ''; - if ($path == '/') { - $path = ''; - } + $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; + // If the passed URL schema is 'https' then setup the $_SERVER variables // properly so that testing will run under HTTPS. if ($parsed_url['scheme'] == 'https') { diff --git a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php index fdbcee6..f150ace 100644 --- a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php +++ b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php @@ -7,7 +7,6 @@ namespace Drupal\Tests\Core\PathProcessor; -use Drupal\Component\Utility\Settings; use Drupal\Core\PathProcessor\PathProcessorAlias; use Drupal\Core\PathProcessor\PathProcessorDecode; use Drupal\Core\PathProcessor\PathProcessorFront; @@ -23,7 +22,6 @@ class PathProcessorTest extends UnitTestCase { protected $languages; - protected $languageManager; public static function getInfo() { return array( @@ -45,13 +43,6 @@ public function setUp() { } $this->languages = $languages; - // Create a language manager stub. - $language_manager = $this->getMock('Drupal\Core\Language\LanguageManager'); - $language_manager->expects($this->any()) - ->method('getLanguage') - ->will($this->returnValue($languages['en'])); - - $this->languageManager = $language_manager; } /** @@ -95,7 +86,7 @@ function testProcessInbound() { $alias_processor = new PathProcessorAlias($alias_manager); $decode_processor = new PathProcessorDecode(); $front_processor = new PathProcessorFront($config_factory_stub); - $language_processor = new PathProcessorLanguage($config_factory_stub, new Settings(array()), $this->languageManager, $this->languages); + $language_processor = new PathProcessorLanguage($config_factory_stub, $this->languages); // First, test the processor manager with the processors in the incorrect // order. The alias processor will run before the language processor, meaning diff --git a/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php index b072412..9285899 100644 --- a/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php +++ b/core/tests/Drupal/Tests/Core/Route/RoleAccessCheckTest.php @@ -106,26 +106,17 @@ public function roleAccessProvider() { // Setup one user with the first role, one with the second, one with both // and one final without any of these two roles. + $account_1 = new User(array('uid' => 1), 'user'); + $account_1->roles[$rid_1] = $rid_1; - $account_1 = (object) array( - 'uid' => 1, - 'roles' => array($rid_1), - ); + $account_2 = new User(array('uid' => 2), 'user'); + $account_2->roles[$rid_2] = $rid_2; - $account_2 = (object) array( - 'uid' => 2, - 'roles' => array($rid_2), - ); + $account_12 = new User(array('uid' => 3), 'user'); + $account_12->roles[$rid_1] = $rid_1; + $account_12->roles[$rid_2] = $rid_2; - $account_12 = (object) array( - 'uid' => 3, - 'roles' => array($rid_1, $rid_2), - ); - - $account_none = (object) array( - 'uid' => 1, - 'roles' => array(), - ); + $account_none = new User(array('uid' => 4), 'user'); // Setup expected values; specify which paths can be accessed by which user. return array( @@ -171,7 +162,7 @@ public function testRoleAccess($path, $grant_accounts, $deny_accounts) { $GLOBALS['user'] = $account; $subrequest = Request::create($path, 'GET'); - $message = sprintf('Access denied for user %s with the roles %s on path: %s', $account->uid, implode(', ', $account->roles), $path); + $message = sprintf('Access denied for user %s with the roles %s on path: %s', $account->id(), implode(', ', $account->roles), $path); $has_access = $role_access_check->access($collection->get($path), $subrequest); $this->assertEmpty($has_access , $message); } diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php deleted file mode 100644 index 079213e..0000000 --- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php +++ /dev/null @@ -1,167 +0,0 @@ - 'UrlGenerator', - 'description' => 'Confirm that the UrlGenerator is functioning properly.', - 'group' => 'Routing', - ); - } - - function setUp() { - - $routes = new RouteCollection(); - $first_route = new Route('/test/one'); - $second_route = new Route('/test/two/{narf}'); - $routes->add('test_1', $first_route); - $routes->add('test_2', $second_route); - - // Create a route provider stub. - $provider = $this->getMockBuilder('Drupal\Core\Routing\RouteProvider') - ->disableOriginalConstructor() - ->getMock(); - $route_name_return_map = array( - array('test_1', array(), $first_route), - array('test_2', array('narf' => '5'), $second_route), - ); - $provider->expects($this->any()) - ->method('getRouteByName') - ->will($this->returnValueMap($route_name_return_map)); - $routes_names_return_map = array( - array(array('test_1'), array(), array($first_route)), - array(array('test_2'), array('narf' => '5'), array($second_route)), - ); - $provider->expects($this->any()) - ->method('getRoutesByNames') - ->will($this->returnValueMap($routes_names_return_map)); - - // Create an alias manager stub. - $alias_manager = $this->getMockBuilder('Drupal\Core\Path\AliasManager') - ->disableOriginalConstructor() - ->getMock(); - $alias_map = array( - array('test/one', NULL, 'hello/world'), - array('test/two/5', NULL, 'goodbye/cruel/world'), - array('node/123', NULL, 'node/123'), - ); - $alias_manager->expects($this->any()) - ->method('getPathAlias') - ->will($this->returnValueMap($alias_map)); - - $this->aliasManager = $alias_manager; - - $context = new RequestContext(); - $context->fromRequest(Request::create('/some/path')); - - $processor = new PathProcessorAlias($this->aliasManager); - $processor_manager = new PathProcessorManager(); - $processor_manager->addOutbound($processor, 1000); - - $config_factory_stub = $this->getConfigFactoryStub(array('system.filter' => array('protocols' => array('http', 'https')))); - - $generator = new UrlGenerator($provider, $processor_manager, $config_factory_stub, new Settings(array())); - $generator->setContext($context); - - $this->generator = $generator; - } - - /** - * Confirms that generated routes will have aliased paths. - */ - public function testAliasGeneration() { - $url = $this->generator->generate('test_1'); - $this->assertEquals('/hello/world', $url); - } - - /** - * Confirms that generated routes will have aliased paths. - */ - public function testAliasGenerationWithParameters() { - $url = $this->generator->generate('test_2', array('narf' => '5')); - $this->assertEquals('/goodbye/cruel/world', $url, 'Correct URL generated including alias and parameters.'); - } - - /** - * Confirms that absolute URLs work with generated routes. - */ - public function testAbsoluteURLGeneration() { - $url = $this->generator->generate('test_1', array(), TRUE); - $this->assertEquals('http://localhost/hello/world', $url); - } - - /** - * Tests path-based URL generation. - */ - public function testPathBasedURLGeneration() { - $base_path = '/subdir'; - $base_url = 'http://www.example.com' . $base_path; - $this->generator->setBasePath($base_path . '/'); - $this->generator->setBaseUrl($base_url . '/'); - foreach (array('', 'index.php/') as $script_path) { - $this->generator->setScriptPath($script_path); - foreach (array(FALSE, TRUE) as $absolute) { - // Get the expected start of the path string. - $base = ($absolute ? $base_url . '/' : $base_path . '/') . $script_path; - $absolute_string = $absolute ? 'absolute' : NULL; - $url = $base . 'node/123'; - $result = $this->generator->generateFromPath('node/123', array('absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - - $url = $base . 'node/123#foo'; - $result = $this->generator->generateFromPath('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo'; - $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo=bar&bar=baz'; - $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo#bar'; - $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - - $url = $base; - $result = $this->generator->generateFromPath('', array('absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - } - } - } - -} diff --git a/core/update.php b/core/update.php index a3dd4bb..823ac27 100644 --- a/core/update.php +++ b/core/update.php @@ -14,7 +14,6 @@ * back to its original state! */ -use Drupal\Core\DrupalKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\DependencyInjection\Reference; @@ -135,7 +134,7 @@ function update_script_selection_form($form, &$form_state) { ); // No updates to run, so caches won't get flushed later. Clear them now. - update_flush_all_caches(); + drupal_flush_all_caches(); } else { $form['help'] = array( @@ -180,20 +179,6 @@ function update_helpful_links() { } /** - * Remove update overrides and flush all caches. - * - * This will need to be run once all (if any) updates are run. Do not call this - * while updates are running. - */ -function update_flush_all_caches() { - unset($GLOBALS['conf']['container_bundles']['UpdateBundle']); - Drupal::service('kernel')->updateModules(Drupal::moduleHandler()->getModuleList()); - - // No updates to run, so caches won't get flushed later. Clear them now. - drupal_flush_all_caches(); -} - -/** * Displays results of the update script with any accompanying errors. */ function update_results_page() { @@ -317,7 +302,6 @@ function update_info_page() { */ function update_access_denied_page() { drupal_add_http_header('Status', '403 Forbidden'); - header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); watchdog('access denied', 'update.php', NULL, WATCHDOG_WARNING); drupal_set_title('Access denied'); return '

Access denied. You are not authorized to access this page. Log in using either an account with the administer software updates permission or the site maintenance account (the account you created during installation). If you cannot log in, you will have to edit settings.php to bypass this access check. To do this:

@@ -451,6 +435,13 @@ function update_check_requirements($skip_warnings = FALSE) { require_once __DIR__ . '/includes/install.inc'; require_once DRUPAL_ROOT . '/core/modules/system/system.install'; + // Load module basics. + include_once __DIR__ . '/includes/module.inc'; + $module_list['system'] = 'core/modules/system/system.module'; + $module_handler = Drupal::moduleHandler(); + $module_handler->setModuleList($module_list); + $module_handler->load('system'); + // Set up $language, since the installer components require it. drupal_language_initialize();