Quantcast
Channel: Issues for Drupal core
Viewing all 295701 articles
Browse latest View live

Create a tooltip component


Overhaul SearchQuery; make search redirects use GET query params for keywords

$
0
0

Problem/Motivation

This issue attempts to solve a couple of inter-related problems with the Search module:

1. Submitting a search form (either from the Search block or the Search page) is currently redirecting you to a page with URL "search/(specific_page_URL)/(keywords)". This is not great because:
- If you submit the form again, you have a mixture of the previous keywords and the new submission, which caused various problems, including sometimes not being able to get rid of a problematic search submission.
- It wasn't a very standard URL pattern. Most search engines use GET parameters for the keywords.
- It causes problems if you try to search for something like "../../admin" and that gets into the URL.

2. When submitting a new search from a search results page, you ended up doing the old search query first, and then the new one, leading to inefficiency and sometimes carrying over error/warning messages from the previous search to the new results page.

3. The SearchQuery extender was calling drupal_set_message() and form_set_error(). form_set_error() calls would not work anyway (it is not a form and doesn't know what form the error should go to), and other query extenders do not call drupal_set_message(), so this is non-standard behavior. So it needs to have a different method for passing information back to users of the search query that there were problems parsing or executing the search query.

The warnings and errors are as follows:
a) In parseSearchExpression() if someone searches for something like "cat or dog" instead of using "cat OR dog", they get a warning message.
b) In executeFirstPass() it calls form_set_error() if there are no "positive keywords" (as opposed to "negative keywords" that are excluded) to search for, and aborts the query. We need to fix that, but see also #1126688: Allow users to use advanced search without keywords entered -- this message is not actually desirable in all cases, such as an advanced search.
c) In executeFirstPass() it calls drupal_set_message() if there was a large number of search terms (to prevent DOS attacks). The query can still work in this case, but the user needs to be warned. (Came from #1265946: DoS against core using a large number of OR search query terms.)

As a note... These issues may not seem related, but it proved to be impossible to fix them separately, so they were combined into one issue.

Proposed resolution

1. Change the redirection so that instead of going to "search/(specific_page_url)/(keywords)" we instead redirect to "search/(type of search)" with a GET param named "keys", and other GET parameters as needed for certain search plugins. See also #894486: Use the query string for search keys rather than appending them to the URL.

2. SearchQuery needs to not call any warning/error/message functions. Instead, it should keep track of query "status" and provide a method for users of SearchQuery to check and see what happened after a search query, and generate the appropriate messages itself. This will also take care of #1789768: search_box_form_submit() improperly calls form_set_error().

3. We need to be more flexible than in the past about generating the "Please enter some keywords" message, because in a Node advanced search, keywords can come from the main keywords field or some of the "advanced" sections (where you can enter "or" words and phrases). But we still need the message if no keywords or advanced stuff is entered at all. We have a searchIsExecutable() method for search plugins, which was set up for this exact purpose; we need NodeSearch to implement this method. See #2170411: Please enter some keywords message has vanished and #1126688: Allow users to use advanced search without keywords entered, which are fixed by this issue's patch.

[As a note, it turned out that there wasn't really a good way to fix #2 and #3 here without also fixing #1. We needed to separate out the query, the plugin, the page, the form, and the messages properly. This has since them became the main goal of this patch.]

4. The SearchQuery class methods and documentation needed to be somewhat overhauled, after which we probably won't need to do any more in #582938: Fix up documentation and member names in SearchQuery, and it may also be possible to take care of #1435834: Cannot alter search queries, tag added too late during the overhaul.

Remaining tasks

a) Get the patch fully working and reviewed. As of the patch in #34, it works when tested manually and all the Search module tests also pass. [Patch still needs a review.]

b) Add tests for all the Related Issues that are supposedly fixed by this patch, to verify that they are in fact fixed. [This has been done]

c) Note that there is one @todo added to in the SearchBlockForm::submitForm() -- but it's been filed as a separate issue and it was not introduced by this patch:
#2174521: Page processing order: form submits vs. main page content is inefficient if form submit is a redirect

User interface changes

a) The URL for searching when you submit keywords is changing from (page url)/(keywords)?(additional query params) to (page url)?keys=(keywords)&(additional query params).

b) All the error and warning messages from searching are generated with drupal_set_message and not form_set_error, so they might look very slightly different.

c) Some warning/error messages that weren't working in 8 due to regression bugs will reappear.

d) The form element in the Search block form where you type in your keywords is changed from being named 'search_block_form' to being 'keys', and the search block form submits directly to the default search page with GET instead of redirecting.

API changes

(See also the UI changes, which may affect themers and modules that use form alters on the search form.)

a) Users of SearchQuery will need to check query status using the new getStatus() method and warn the user accordingly, instead of having the messages generated in SearchQuery itself.

b) Search plugins using the searchFormAlter() method to add fields to the search form (e.g., for advanced search) no longer need to define their own form submit, and in fact are discouraged from doing so. Instead, they should implement the new buildSearchUrlQuery() method. Search plugins that do not use searchFormAlter do not need to change in any way.

c) The misleadingly-named mostly-internal executeFirstPass() method in SearchQuery is renamed prepareAndNormalize(). After this patch, there are actually no core calls to this method.

Create Available Tours block

$
0
0

Problem/Motivation

As discussed in #1921152: META: Start providing tour tips for other core modules. we should add a block that shows the Available Tours. Availability depends on whether the module they belong to is enabled.

This block should be added by default to the main help page (admin/help). This screenshot visualizes what this should look like:

proposed help page w tours

Proposed resolution

Create Available Tours block

Remaining tasks

- create block. Some work on this was already done in https://drupal.org/comment/7964451#comment-7964451
- create test
- enable block by default (in standard profile?)

User interface changes

- the main help page (admin/help) will be affected

API changes

No api changes

Add a Yaml class to Drupal\Core\Serialization

$
0
0

Preparing for
#2208609: Move Json utility class into Drupal\Core\Serialization
#1920902: Add a Drupal Yaml wrapper so we can default to PECL Yaml component if it is available
#2190723: Add a KeyValueStore\FileStorage to replace e.g. ConfigStorage

Problem

  1. Various classes are needlessly instantiating Symfony\Component\Yaml\Dumper and Symfony\Component\Yaml\Parser.
  2. ...but only to set parameters to produce YAML that is consistent with Drupal coding standard.
  3. Yaml is actually a serialization format we want to standardize on.

Proposed solution

  1. Add a generic Drupal\Core\Serialization\Yaml helper class.

Ultimate goal

Drupal\Core\Serialization\Json
Drupal\Core\Serialization\PhpSerialize
Drupal\Core\Serialization\Yaml
Drupal\Core\Serialization\Xml

Add a ParamConverter for upcasting TypedData objects

$
0
0

I've been playing with this around in my head for the past couple of days and after discussions with Kris, Sam, Larry, etc. I came back to the conclusion that we -really- need this. And before the end of next week too. I am not going to go into the argument about why this is so fundamentally important as that has been explained in previous comments already. To summarize: A unified concept for explicitly describing the parameters of a route with metadata buys us generic implementation with all sorts of page manager features that Kris and Sam are working on in princess. Without that, we are making a huge leap backwards to D7 time where every route needs to be introduced to the pager manager through some sort of plugin. I hope everyone understand how much of a win this would be for sitebuilding...

Anyways... After a quick chat with @berdir about typed data and the planned changes that have been discussed at Portland (especially #2002102: Move TypedData primitive types to interfaces) and the LoadableInterface for typed data objects that I proposed over at #1983100: Provide a LoadableInterface for Typed Data objects there is a great opportunity for us to achieve this goal and even address the DX concerns people were having in this issue together. Let me go back in time and explain how we got to where we are now and then outline the idea that I have in mind:

How we ended up here

One of the first patches around param conversion (I think initially written by @katbailey?!) was built around the concept of reflection. While incredibly simple in terms of DX it did have some conceptual flaws and limitations and only covered entity upcasting back then. So we threw it out the window. After that, @Crell and @g.oechsler came up with the concept of "guessing" route arguments based on their naming pattern (e.g. {node} == Node entity). This looked pretty cool initially but turned out to be rather error-prone/unstable as explained in #1943846: Change notice: Improve ParamConverterManager and developer experience for ParamConverters. So we decided to throw it out the window just as well and agreed that we need explicit declaration of parameter types. This is where we stand now...

However, when I saw how Routes and ParamConverters play together in SensioFrameworkExtraBundle I drooled and started thinking about this again. Now, after speaking with @EclipseGc and @sdboyer and also seeing that @effulgentsia has been more and more +1 on this lately (as well as some other folks, I guess Portland was a big help with that) as well as talking to @Crell last night I sense that it is time to start discussing this issue again and ultimately make a decision.

Pre-requisites for the following concept

Why TypedData?

TypedData is the perfect solution for our parameter conversion problem as we can use it as a generic object factory/object factory location with a unified pattern for defining the parameter types so they can be identified by other sub-systems such as a page manager which would then be capable of fully understanding any defined route without requiring an intermediate plugin layer for every single route definition.

Furthermore it becomes very easy to make custom objects "upcastable" by simply implementing them as typed data objects. And that is pretty much a no-brainer. In many cases this is probably going to be a by-product anyways as many objects will want to be typed data anyways as that buys them integration with other systems as well. Implement it once, integrate with all the things.

TypedData upcasting through Reflection (or other means of type discovery) and explicit parameter definition

Now, how to we implement this without turning route definition DX into a nightmare? The latest patch in this issue is solely based on defining the type and constraints of typed data types. However, as #2002102: Move TypedData primitive types to interfaces has been started lately (and there is already a patch) we will be able to take another look at Reflection to provide an absolutely straight-forward concept for benefiting from Upcasting by simply typehinting the controller arguments with the desired typed data interface as an alternative to manually defining the typed data type in the route options.

The ultimate goal is to end up with a nice typed data definition for each parameter that should be upcast (basically everything except for things that should remain the original input values). The typed data definition can either be manually defined in the route options or automatically discovered by Reflection of the controller or other means during RouteBuildEvent (which then writes the discovered definition into the route options). So whatever scenario applies, in the end we will have the typed data definition in the route options.

How would that work?

First scenario - Reflection

Let's assume we have a route definition that looks something like this:

aggregator_feed_refresh:
  pattern: '/admin/config/services/aggregator/update/{aggregator_feed}'
  defaults:
    _controller: '\Drupal\aggregator\Controller\AggregatorController::feedRefresh'
  requirements:
    _permission: 'administer news feeds'

And a controller that looks something like this:

<?php
 
/**
   * Refreshes a feed, then redirects to the overview page.
   *
   * @param \Drupal\aggregator\FeedInterface $aggregator_feed
   *   An object describing the feed to be refreshed.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request object containing the search string.
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse
   *   A redirection to the admin overview page.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
   *   If the query token is missing or invalid.
   */
 
public function feedRefresh(FeedInterface $aggregator_feed, Request $request) {
   
// @todo CSRF tokens are validated in page callbacks rather than access
    //   callbacks, because access callbacks are also invoked during menu link
    //   generation. Add token support to routing: http://drupal.org/node/755584.
   
$token = $request->query->get('token');
    if (!isset(
$token) || !drupal_valid_token($token, 'aggregator/update/'. $aggregator_feed->id())) {
      throw new
AccessDeniedHttpException();
    }
   
// @todo after https://drupal.org/node/1972246 find a new place for it.
   
aggregator_refresh($aggregator_feed);
    return new
RedirectResponse(url('admin/config/services/aggregator', array('absolute'=> TRUE)));
  }
?>

Now, due to the fact that FeedInterface extends EntityInterface we already know that what we have here is an entity. Now, since all entities should define a unique interface like FeedInterface or NodeInterface we can iterate over the $entityManager->getDefinitions() and check (with Reflection) which entity type uses an entity class that implements FeedInterface. This is the entity type we want to upcast to. This obviously only works if the typehinted interface is unique for a given entity type. If it is ambiguous like an EntityInterface typehint or some other, custom SomethingBaseInterface the reflection discovery skips the given route.

Second scenario - Automatic discovery for ambigious or missing typehints

Things like HtmlEntityFormController::content() do not have typehints. However, they make other assumptions. A route definition for an entity form looks something like this:

   pattern: '/foo/{node}/baz'
     defaults:
       _entity_form: 'node'
   // Or like this:
   pattern: '/foo/{node}/baz/edit'
     defaults:
       _entity_form: 'node.edit'

We know that this is an entity form because the controller class is a HtmlEntityFormController. Hence, we can use the same type discovery logic that the controller uses: Retrieve the entity type from $route->getDefault('_enitty_form') by reading it from the string (@see HtmlEntityFormController::getFormObject()). Once retrieved we can, again, write it's typed data definition into the route options. Different discovery, same outcome.

The same process can be applied to basically everything we got. The only criteria we need is that, in the end, we get a nice typed data definition in the route options.

Third scenario - Manual definition in the route options

You might have single, custom routes in your module which do not justify writing a proper parameter type detection service for the RouteBuildEvent. In those cases, it is more convenient to manually define the typed data type for your parameter in the route options. Manual parameter type definitions always overrule the automatic discovery obviously meaning that the ParamConverterManager (or whatever we call the thing that subscribes to the RouteBuildEvent to iterate over each parameter and request type detection from the services that have been registered with it) would simply skip those arguments.

I am very optimistic that this describes a very nice, reliable and developer-friendly solution to our problem. Thoughts?

I would like to bump this issue to critical if we can agree that this is the way to go. I am also going to push Sam and Kris to comment on this once again to express how important this is for what they are building.

Convert custom_block.js into a library

Convert locale.admin.css into a library

Remove book_library_info()


♪♫ Question the sun ♥, the moon, and the stars ♫♪ [Test that stuff.]

Merge html.html.twig & page.html.twig into one file

$
0
0

Why:
1 themers arent idiots & can understand that "dont remove {{ page_top }}     {{ page }}    {{ page_bottom }}
if you do this - stuff wont show up- there done

2. Less files makes it easier to figure out wtf is going on

3. if you wanna do variations over the same base fx adding in elements in the html.html.twig file and then have variations with the page.twig files you can do that with "twigblocks" (blogs in twigs)

blockers:
twigblocks must work (they do)

Improve naming of Path-related classes

$
0
0

Updated: Comment #0

Problem/Motivation

Some classes in Path subsystem have strange naming conventions. We should re-think this and make naming more clear and logic.

This issue is dependent on #2199381: Add \Drupal\Core\Path\PathInterface.

Proposed resolution

Remaining tasks

- identify classes that need to be fixed
- discuss new naming conventions
- implement renaming

User interface changes

N/A

API changes

Some classes will be renamed.

Remove & deprecate filter_xss_admin() -> \Drupal\Component\Utility\Xss::filterAdmin()

Add a settings.php variable to allow to discover/enable test extensions at regular runtime

$
0
0

Objective

  1. #2188661: Extension System, Part II: ExtensionDiscovery changes the extension discovery process to ignore all test extensions at regular runtime.
  2. Sometimes it is useful to enable a test module for manual (test) debugging purposes.

Proposed solution

  1. Add a settings.php variable to allow to discover test extensions at regular runtime.

Remove deprecated URL helper functions from common.inc

$
0
0

drupal_parse_url
drupal_encode_path
_external_url_is_local
_drupal_http_use_proxy
valid_url

Require settings.php to exist in the root folder and to explicitly opt-in for multi-site functionality

$
0
0

Problem

  • With the changes to the directory layout in Drupal 8 some parts of the multi-site feature are hidden away from those that don't use it, which is a good thing: Top-level /modules, /themes and /profiles directories can be used for the site modules.
  • However, the settings file for sites must still be places into sites/default/settings.php. This is unnecessary and forces the multi-site concept onto users that shouldn't need to care about it.
  • Moreover, since the multi-site set-up is still supported code cannot simply assume that the sites/default/settings.php file exists. This increases the number of file_exists() checks and makes code paths more complex.

Goal

  • Simplify the Drupal bootstrap by requiring /settings.php to exist and an explicit opt-in for the multi-site functionality.

Proposed solution

  1. Require a top-level, global /settings.php to exist in any case (set up by the installer).
  2. Merge /sites/sites.php into the top-level /settings.php, and turn the $sites variable into that explicit flag for enabling the multi-site functionality.

    This means:

    • If /settings.php does not define the $sites variable at all, then there is no multi-site functionality and no site directory discovery process.
    • If /settings.php defines a bare $sites = array();, then the multi-site functionality is enabled and the site directory is discovered on every request (no change).
    • If /settings.php defines site aliases in the form of $sites['localhost.example'] = 'example.com';, then aliases are applied and resolved before the site directory discovery happens (no change).

    This also means:

    • When the multi-site functionality is enabled, then the top-level/global /settings.php acts as if it was a /sites/all/settings.php, which is a concept that does not exist thus far.
    • The top-level /settings.php is always loaded first. The site-specific settings.php has access to all of the global variables and is able to override them in a granular way. (Big difference to today: Common settings can be shared between sites, only overrides and additions need to be specified.)
  3. Move /sites/default/default.settings.php into /core/default.settings.php, so it is updated when Drupal core is updated.

    This last step could possibly mean that there may not be a /sites/default directory when downloading and extracting Drupal core. The Drupal installer would create /sites/default directory though. It is out of scope and not the intention of this issue to change or remove the /sites/default directory.

Related issues


Original summary by @naxoc

This is a split-out from #760992: Where should site specific modules, themes and settings be kept? to move the settings file to the root folder where modules/ themes/ and profiles/ are also going at some point.

It would go for "default" - but not multisite settings files that would still go in the sites folder.

The existence of a sites.php can trigger trying to find multisite settings as suggested in #1055862: Require sites.php to opt-in for multi-site support/functionality


Repetitive config in breakpoint.module

$
0
0

Problem/Motivation

The format of multipliers array in the breakpoint.*.yml files is

multipliers:
  1x: 1x

This is repetitive, and should be

multipliers:
  - 1x
  - 1.5x
  - 2x

Proposed resolution

Fix the breakpoint config set to only save allowed multipliers, and to match the format of the sequence with the -

Remaining tasks

discuss proposed resolution
implement

User interface changes

No UI changes.

API changes

No API changes.

Steps to reproduce

View an example breakpoint file:

core/modules/toolbar/config/breakpoint.breakpoint.module.toolbar.wide.yml
sites/default/files/config_*/active/breakpoint.breakpoint.theme.bartik.wide.yml

Original report by @vijaycs85

Follow up for #1912308-28: Create configuration schemas for breakpoint module
Similar to #1933548: Book allowed_types settings repetitive and in under certain conditions can change unexpectedly

Make cache_form $expiry a variable, to mitigate runaway cache_form table or key:value store growth

$
0
0

Problem/Motivation

Busy sites that use a lot of forms can make a lot of entries in the cache_form table. This is particuarly true of sites using Ubercart, Commerce, or other modules like Fivestar, Ideal Comments, or Hierarchical Select.

This is a very common problem which I have seen cause problems for my clients, especially when database replication is involved. A search shows how widespread the issue is: https://www.google.com/search?q=cache_form%20big

The cache_form table is truncated via cron, in system_cron. The default expiry for cache_form entries is 6 hours, hardcoded in form_set_cache.

Proposed resolution

By changing $expiry = 21600; from a hardcoded variable to variable_get('cache_form_expiry', 21600);, users can choose how often entries are pruned from cache. With shorter lifetimes, the form_cache table will be truncated more often, and will not grow as large.

I would suggest making the default expiry one hour, rather than 6, also.

Remaining tasks

None, subject to community review (especially of the comment).

User interface changes

None.

API changes

None.

#226728: Temporary cache table entries are not flushed
#1694574: drupal_process_form() deletes cached form + form_state despite still needed for later POSTs with enabled page caching

Create generic layout classes

$
0
0

There are some repetitive width properties set in the admin interface. We can make these more consistent by created generic layout classes and applying them the relevant elements. Contrib modules could also use these for more complex admin interfaces without having to write their own layout CSS.

Convert ViewsHandlerManager to DefaultPluginManager

Notice: Undefined variable: label_element in form_process_table()

$
0
0

I'm getting

Notice: Undefined variable: label_element in form_process_table() (line 1855 of core\includes\form.inc).

Trivial patch coming up...

Viewing all 295701 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>