When the client requests an image style which is already being generated then Drupal responds with 503 (ServiceUnavailableHttpException) and set the header Retry-after:3, which means to retry again after 3 seconds. But browsers do not support this header, so no image is displayed. Would be nice to wait couple of seconds before giving up.
Drupal responding with HTTP 503 if image style is already being generated may lead to broken images
Validate configuration upon saving (prevents invalid config imports a.o.)
Problem/Motivation
Quoting #2969065: Use typed config validation constraints for validation of cdn.settings simple config:
Since #1928868: Typed config incorrectly implements Typed Data interfaces, it's possible to validate configuration, even simple configuration, through Symfony validation constraints. Just like we validate entities. #2952037: Add constraints to all simple configuration exists to add it to all of core's simple configuration.
At the recent DrupalCon Nashville, we discussed how Drupal's API-First Initiative can make config entities validatable and hence modifiable (see #2300677-241: [PP-1] POST/PATCH config entities via REST for config entity types that support validation and #2300677-242: [PP-1] POST/PATCH config entities via REST for config entity types that support validation). That got me thinking.
Why not add validation constraints to
cdn.settings
? That'd allow both the CDN UI module to use it and config imports to also use it.
(Emphasis added.)
When importing configuration, no validation occurs. Consequence: it's fairly easy to break a site in obvious or subtle ways (depending on which configuration).
Proposed resolution
-
The patch at #2969065: Use typed config validation constraints for validation of cdn.settings simple config is explicitly adding a
ConfigEvents::SAVE
event subscriber that invokes the configuration system's validation capabilities. Specifically for the CDN module's simple config. This works fine:Why not move this into core? That should be the end goal.
Of course, it's not realistic to enable this right away. But any configuration that is fully covered by validation constraints (see #2300677-241: [PP-1] POST/PATCH config entities via REST for config entity types that support validation and #2300677-242: [PP-1] POST/PATCH config entities via REST for config entity types that support validation) could (and I'd argue should) have this happen automatically.
-
Sadly, the above only happens after saving (because the data is written first by
\Drupal\Core\Config\Config::save()
and thenConfigEvents::SAVE
is dispatched). But that's still a step forward compared to today, where we'll just silently accept the data. It seems the real solution is for config importing to first validate all config it will import, and only then save it. Perhaps that should be done as part of this issue, perhaps it's a follow-up, perhaps it's a blocker. TBD.
Remaining tasks
TBd
User interface changes
TBD
API changes
TBD
Data model changes
None.
PHP 7.2: Warning: count(): Parameter must be an array or an object that implements Countable n Drupal\views\Plugin\views\argument_validator\Entity->validateEntity()
If I use Entity argument validator with custom entity without bundles I got the following warning:
Warning: count(): Parameter must be an array or an object that implements Countable in Drupal\views\Plugin\views\argument_validator\Entity->validateEntity() (line 203 of core/modules/views/src/Plugin/views/argument_validator/Entity.php).
Drupal\views\Plugin\views\argument_validator\Entity->validateEntity(Object) (Line: 180)
Drupal\views\Plugin\views\argument_validator\Entity->validateArgument('22522') (Line: 999)
Drupal\views\Plugin\views\argument\ArgumentPluginBase->validateArgument('22522') (Line: 1034)
Drupal\views\Plugin\views\argument\ArgumentPluginBase->setArgument('22522') (Line: 1100)
Drupal\views\ViewExecutable->_buildArguments() (Line: 1264)
Drupal\views\ViewExecutable->build() (Line: 390)
Drupal\views\Plugin\views\display\PathPluginBase->execute() (Line: 180)
Drupal\views\Plugin\views\display\Page->execute() (Line: 1627)
Drupal\views\ViewExecutable->executeDisplay('page_users', Array) (Line: 77)
Drupal\views\Element\View::preRenderViewElement(Array)
call_user_func(Array, Array) (Line: 378)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 226)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 582)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 227)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 117)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 156)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 664)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
[Clean Code] Remove unnecessary returns
follow-ups of #2925064: [1/2] JS codestyle: no-restricted-syntax
Add helpful exception message in CustomAccessCheck
Problem/Motivation
When you write a routing.yml file with a _custom_access check which points to a non existing method/class you get the following message:
InvalidArgumentException: The controller for URI "" is not callable. in Drupal\Core\Controller\ControllerResolver->getControllerFromDefinition() (line 81 of core/lib/Drupal/Core/Controller/ControllerResolver.php).
Drupal\Core\Access\CustomAccessCheck->access(Object, Object, Object)
call_user_func_array(Array, Array)
Drupal\Core\Access\AccessManager->performCheck('access_check.custom', Object)
Drupal\Core\Access\AccessManager->checkAll(Array, Object)
Drupal\Core\Access\AccessManager->check(Object, Object, Object, )
Drupal\Core\Access\AccessManager->checkRequest(Object, Object)
Drupal\Core\Routing\AccessAwareRouter->checkAccess(Object)
Drupal\Core\Routing\AccessAwareRo
Its not helpful
Proposed resolution
CustomAccessCheck should catch the InvalidArgumentException and convert it into a new exception
which explains which route / custom access check exactly is broken
Remaining tasks
User interface changes
API changes
[PP-1] REST should respond with a 409 for a POST request to an existing entity
Problem/Motivation
First reported at #2866736: JSON API should reply with a 409 status when sending a POST request to an existing entity for the JSON API contrib module.
Also see https://httpstatuses.com/409
Proposed resolution
Return a 409 for POST requests to an existing resource.
Remaining tasks
Make it work.
User interface changes
None.
API changes
None.
Data model changes
None.
Pass the raw exception to logger implementations
Third-party error tracking software - e.g. https://drupal.org/project/raven - can extract metadata from a raw PHP exception. So it would be helpful to pass the raw exception to loggers.
Duplicate values in ajaxPageState.libraries
If a library is added during an ajax request, the drupalSettings.ajaxPageState.libraries
contains duplicate values.
This is a performance issue when using POST ajax request but becomes an major issue if the ajax is made with GET because after each ajax request the URI for the next ajax request becomes larger and at some point it becomes larger than allowed and a "414 Request-URI Too Large" is possible.
Add views render caching on views ajax requests.
Problem/Motivation
#2381277: Make Views use render caching and remove Views' own "output caching" replaces output caching with render caching.
Render caching though is disabled on POST requests, so that ajax requests aren't cacheable.
We need to get #956186: Allow AJAX to use GET requests in, to be able to get render caching done.
Proposed resolution
- Add setting for query type to views pagers
- Make views pager respect that setting so that it uses the correct protocol
- Get render caching to work on views AJAX paging responses
Remaining tasks
- Fix broken tests on 8.3 re-roll.
- Get #956186: Allow AJAX to use GET requests committed
- Verify that we have enough test coverage on this issue
- QA testing to get to RBTC
User interface changes
I added a "pager query type" selector to sql-base pagers which becomes active if you set the view to use AJAX.
API changes
- Added a "getParam" method to ViewAjaxController to make it easier to get parameters off of a request.
How to test
- Install a new site
- Apply most recent patch from this issue (currently: https://www.drupal.org/files/issues/2500313--views-get-paging-support-83...)
- Apply https://www.drupal.org/files/issues/ajax-956186-65_2x_1.patch from #956186: Allow AJAX to use GET requests
- Create at least five articles
- Create two views as follows
View 1
- Add a block display
- Call it "GET pager view"
- List all nodes
- Turn on AJAX for the view
- Use a pager (try them all if you can); 2 per page, set query type to GET
View 2
Same as View 1, except:
- Call it "POST pager view"
- Set query type on the pager settings to POST
Now:
- Place both blocks somewhere on the page
- Start using the pager, and use the network tab (helpful to filter by XHR) to ensure that the views are using the correct protocol for their requests.
Some other things to try:
- Using a table display, ensure that column sorting is respected after paging back and forth.
- Add an exposed filter and make sure paging works after the setting the filter value.
- Test the render caching somehow. Make sure page cache is turned on, and put a breakpoint or something inside a function that runs when rendering a row. The breakpoint should hit a) when the cache is first populated and b) if something invalidates the cache (i.e. that node is updated).
Assertions in \Drupal\Template\TwigEnvironment
Splitting up #2444003: Optimize Drupal\Core\Template\Attribute. This patch deals only with the \Drupal\Template\TwigEnvironment class.
Create an interface for \Drupal\Core\Access\CsrfTokenGenerator
Problem/Motivation
See #2580739: [META] All core services should implement an interface
Remaining tasks
User interface changes
API changes
Data model changes
Unrouted URLs cannot have have overridden query or fragments
Problem/Motivation
Url::fromUri('http://example.com/foo?_format=foobar', ['query' => ['_format' => 'json']])->toString(TRUE)->getGeneratedUrl()
will generate
http://example.com/foo?_format=foobar&_format=json
instead of http://example.com/foo?_format=json
https://www.drupal.org/project/drupal/issues/2955383#comment-12540701
Proposed resolution
Update the UnroutedUrlAssembler so that a unrouted URL created from a URI w/ query and/or fragment allow both to be overridden from the $options.
Remaining tasks
User interface changes
API changes
Data model changes
After enabling or disabling a view, convey changes to screen reader users.
Follow up to #1848940: When enabling or disabling a View, don't move the cursor to the top of the page. Further accessibility improvements.
When a screen-reader user enables or disables a view, the screen content changes - a table row jumps from the enabled list, to the disabled list. I think it'll be important to inform a screen reader:
1. The outcome of the enable/disable operation was successful
2. The page content has changed - the row is has now gone to the other table.
3. The user is now IN the other table.
Drupal.announce() can provide this. Let's see if we can add custom callbacks for the enable/disable AJAX operations.
Convert taxonomy terms to be revisionable and publishable
Problem/Motivation
As decided in #2745619: [policy, no patch] Which core entities get revisions?, taxonomy terms should be converted to be revisionable and publishable.
Proposed resolution
Do it.
Remaining tasks
Decide how we want to deal with term hierarchies, see #2705389-48: Selected content entities should extend EditorialContentEntityBase or RevisionableContentEntityBase.
User interface changes
None yet, revision support is only enabled at the API level.
API changes
Nope.
Data model changes
Taxonomy terms are now revisionable and publishable.
Make extension services tagged services
Problem/Motivation
From #2659940-119: Extension System, Part III: ThemeExtensionList and ThemeEngineExtensionList:
Starting to feel like these might need to be tagged services with a collector to clear them all in one go? That would be the path to deprecating system_list_reset right? Follow up?
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Extension System, Part III: ThemeExtensionList and ThemeEngineExtensionList
Follow-up to #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList, which provides new extension listing classes ExtensionList
, ProfileExtensionList
, ModuleExtensionList
.
Problem/Motivation
Due to the size of the theme list refactoring scope, we need a separate issue.
Proposed resolution
Create new ThemeExtensionList
and ThemeEngineExtensionList
classes, refactor theme discovery functionality into this class.
Remaining tasks
Patch
Reviews
Commit
User interface changes
None
API changes
ThemeHandler
constructor has new argument$theme_list
of typeThemeExtensionList
but is an optional argument. Service signature not changed in core.services.yml.ThemeInstaller
constructor has new argument$theme_list
of typeThemeExtensionList
but is an optional argument. Service signature not changed in core.services.yml.- New
ThemeExtensionList
class andextension.list.theme
service. Class marked internal. - New
ThemeEngineExtensionList
class andextension.list.theme_engine
service. Class marked internal. - The
ModuleExtensionList
andProfileExtensionList
classes also marked internal. - The protected
$defaultFeatures
class property removed fromThemeHandler
- The protected
$extensionDiscovery
class property removed fromThemeHandler
Data model changes
None.
Private file download returns access denied, when file attached to node revision other than current
This is the follow-up issue of Private file download returns access denied, as was suggested by @Berdir here.
Once upon a time a patch was committed to D7 core to make private files accessible, when there are nodes with revisions on your site (see "Private file download returns access denied" issue mentioned above). To achieve this, they changed some code at modules/file/file.module, namely file_get_file_references function parameter to FIELD_LOAD_CURRENT from FIELD_LOAD_REVISION.
But FIELD_LOAD_REVISION parameter was there for a good reason, with FIELD_LOAD_CURRENT we are not able to open files attached to all entity revisions except current. It's fatal in case you're trying to build, say, intranet with library for documents.
Steps to reproduce:
1.Set up clean Drupal 7.12 with private document folder (say, sites/default/files/private) and a content type with just a title and file field called field_file. It should store files in your private folder.
2.Login as UID1, create a node and add a file "testfile1.txt" to it's file field.
3.Save the node
4.Click edit
5.Remove the old file, "testfile1.txt"
6.Add "testfile2.txt"
7.Check "Create new revision" option
8.Click save
9. Click revisions tab, open first revision of your node
10. Node is fine, link to file is there, but when you'll click on this link to the file "testfile1.txt", you'll get "Page not Found"
It is possible to open old version of your file - if you'll revert old revision. But it is not an option in case you use revisions as revisions, not as backups for inaccurate users, because it will produce awful mess of revisions.
In short:
So if a user has access to a revision he should also be able to access its files. If not, not.
Move UI helper functions from BTB into a trait
Problem/Motivation
BTB has lots of helpful methods that could be re-used in https://github.com/weitzman/drupal-test-traits for testing against existing websites.
Debug ones relevant to this issue:
- formatHtmlOutputHeaders
- getHtmlOutputHeaders
- htmlOutput
- initBrowserOutputFile
Others
We could split these up a few ways I guess but they're all pretty much related to UI testing.
- submitForm - Handles submitting forms.
- drupalLogin()
- drupalLogout()
- assertSession() - Handy helper to get a web assertion object.
- drupalGet() - Handles converting URL objects to path strings.
- drupalPostForm() - Same as drupalGet() + handles MarkupInterface objects for the text on buttons.
- click()
- clickLink()
- getTextContent()
- getUrl()
- assertEquals() - Handles markup interface
Proposed resolution
Move them to a trait so the code can be shared.
Remaining tasks
Patch.
Do not create field revisions when field data hasn't changed
The problem
Database performance degrades with the exponential increase in revisions generated by Entity Reference Revisions fields (commonly used for Paragraphs). Each new node revision means a new revision of each paragraph, which means a new revision of each field on the paragraph... Things can get out of hand pretty quick on sites that aren't even ginormous.
Note that the general problem of revision bloat and the proposed resolution are not specific to ERR or Paragraphs. I have zero hard performance data on hand at the moment, but if that is needed I'm sure they could be gotten.
Not a solution?
On sites with frequent, small changes to entities, we end up with tons of field revision table rows with identical values, their only difference being the revision ID. #2083451: Reconsider the separate field revision data tables aims to improve things by avoiding revisions entirely, which is not my goal.
I'm pretty sure this would be absurd and break some fundamental law of relational databasing, but would it be possible to somehow not duplicate field data when creating a new revision of an entity? Let me 'splain: In #2297817: Do not attempt field storage write when field content did not change, we made it possible to prevent unnecessary db writes when updating an existing revision with field data that has not changed. But when creating a new revision, we, of course, need a new table row with that revision ID. But what if we somehow said "Hey, I'm an entity revision collecting all my associated field data OH WAIT THAT FIELD TABLE DOESN'T HAVE AN ENTRY FOR MY REVISION WTF oh hmmm maybe that just means the field data hasn't changed since the last revision... Lemme just grab the data for that field from the last available revision." E.g., say the current revision of node X is 99, but the latest row in node_revision__field_foo
for Node X is 95, so Entity API "magically" grabs that row when populating field data on node X.
Now, even if what I'm trying to explain makes sense, is there any sort of "magic" we could do in Entity API to make it (a) not suck from a performance standpoint and/or (b) not break lots of unintended things?
Anonymous users can edit the authoring information
I'm building an intranet, IP restricted to only reasonably trustworthy users.
I've given "anonymous" and "authenticated" the following permissions:
- 'create news content' so that they can submit news articles (nodes) without logging in
- 'create image media' so that they can submit images to attach to their news articles
At /node/add/news, an anonymous user does not get access to change the authoring information.
At /media/add/image, an anonymous user does get access to change the authoring information, and can change the "authored by" from anonymous to anyone they want, and the same with "authored on" (see attached image).
I think the media form should act similarly to the node form, i.e. hide the authoring information from anonymous users. NodeForm.php seems to gate this information behind '#access' => $this->currentUser->hasPermission('administer nodes'),
.