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

Allow forms to easily determine whether they are shown in a modal

$
0
0

Forms that are intended to be shown in a modal dialog also have a fallback for when javascript is disabled. For example, a "Cancel" button should be shown on the fallback, but not when displayed in a modal.

The information whether a form is displayed in a modal can be found on the request, but this is not very DX friendly and hard to discover:

  $this->getRequest()->query->get(MainContentViewSubscriber::WRAPPER_FORMAT) === 'drupal_modal';

[regression] Roles should depend on objects that are building the granted permissions

$
0
0

Problem/Motivation

Scenario:

  • A new node type 'article' creates a new 'edit any article content' permission.
  • A new text format 'safe_html' creates a new 'use text format safe_html' permission.

When those permissions are granted to a role, that role config entity will contain the 2 permissions.

If an object that is the foundation of a permission is removed the role doesn't revoke that permission. This is proved in the attached test.

(Steps to reproduce are in this duplicate issue -- it's for a D8 site, but I think they'll work regardless -- in case it helps anyone with testing.)

This is a bug because when a module is uninstalled roles are not cleaned up. This dangerous because if the module is re-enabled a role could have an unintended permission already configured.

Proposed resolution

  1. Make role config entity dependent on the provider of each granted permission.
  2. Make role config entity dependent on each entity (config or content) that was used to build that permission.
  3. The dynamic permission callbacks should optionally, return the dependencies used to build a specific permission (except the module which is already added as 'provider').
  4. The user_role config entity should implement onDependencyRemoval().
  5. Add proper dependencies to all dynamic permissions
  6. Trigger a deprecation if a permission does not exist when saving a role. Skip this for migrations - this will be resolved in #3055557: Role migration results in migration permissions that do not exist on the target site

The changes in this issue require updates to several existing tests.

  • Only use permissions defined by modules. Fix typos. Do not use random strings.
  • If a test uninstalls a module and then installs it again, related permissions need to be restored to test users.
  • Some tests install config_translation but not locale. If any user role is saved, then all permission callbacks are exercised, and a service provided by the locale module is called.

Remaining tasks

User interface changes

None.

API changes

Dynamic permission callbacks to optionally return the permission dependencies in the array.

Data model changes

Roles will have dependency information according to what permissions are assigned.

Release notes snippet

Each user role now depends on the modules that provide the role's permissions. This means that permissions will be cleaned up when a module is uninstalled. Additionally, if a custom or contributed module uses a permission callback, see how to add additional dependency to the callback's return value. Existing roles will be updated to remove permissions that do not exist and dependencies will be added.

put each entity type table into a details element on admin/config/regional/content-language

$
0
0

Problem/Motivation

The form at admin/config/regional/content-language can easily get really big and complicated. On a site with several types for nodes, media, paragraphs, and taxonomy, it becomes very hard to navigate.

Steps to reproduce

Proposed resolution

In #3027607: Submitting the form on admin/config/regional/content-language times out because it is enormous, it's been suggested that the form be split up, for UX and performance. But that is going to be a complex change.

A quick easy interim fix would be to convert the 'container' form elements for each entity type into collapsed 'details' elements. This would allow admin users to only show the settings for the entity type they are working on.

Remaining tasks

User interface changes

The form has collapsible details elements.

API changes

We'd probably remove the H4 element from the twig template, as it just repeats the title on the details element.

Data model changes

Release notes snippet

The "media" entity cannot have a URI as it does not have an ID

$
0
0

When linking the name of a media file to the media (see screenshot) in manage display, I cannot access layoutbuilder and get:

The website encountered an unexpected error. Please try again later.

Drupal\Core\Entity\EntityMalformedException: The "media" entity cannot have a URI as it does not have an ID in Drupal\Core\Entity\EntityBase->toUrl() (line 192 of core/lib/Drupal/Core/Entity/EntityBase.php).

Drupal\Core\Field\Plugin\Field\FieldFormatter\StringFormatter->getEntityUrl(Object) (Line: 127)
Drupal\Core\Field\Plugin\Field\FieldFormatter\StringFormatter->viewElements(Object, 'en') (Line: 89)
Drupal\Core\Field\FormatterBase->view(Object, 'en') (Line: 263)
Drupal\Core\Entity\Entity\EntityViewDisplay->buildMultiple(Array) (Line: 267)
Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay->buildMultiple(Array) (Line: 351)
Drupal\Core\Entity\EntityViewBuilder->buildComponents(Array, Array, Array, 'event_files') (Line: 293)
Drupal\Core\Entity\EntityViewBuilder->buildMultiple(Array) (Line: 250)
Drupal\Core\Entity\EntityViewBuilder->build(Array)
call_user_func_array(Array, Array) (Line: 100)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. Support for this callback implementation is deprecated in 8.8.0 and will be removed in Drupal 9.0.0. See https://www.drupal.org/node/2966725', 'silenced_deprecation', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 781)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 372)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 200)
Drupal\Core\Render\Renderer->render(Array) (Line: 501)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 138)
__TwigTemplate_f162914866e1cb2807b4f0c587486e61449700187d2856026e39cf19d03e4bce->doDisplay(Array, Array) (Line: 455)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 422)
Twig\Template->display(Array) (Line: 434)
Twig\Template->render(Array) (Line: 64)
twig_render_template('themes/custom/showcaseplus/templates/field--entity-reference.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 431)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 200)
Drupal\Core\Render\Renderer->render(Array) (Line: 501)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 101)
__TwigTemplate_e7ccb531163dd570637d.....e3c105a5f7a7f32ee843a9472->block_content(Array, Array) (Line: 216)
Twig\Template->displayBlock('content', Array, Array) (Line: 86)
__TwigTemplate_e7ccb531163dd570637d11b....19a3f24e3c105a5f7a7f32ee843a9472->doDisplay(Array, Array) (Line: 455)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 422)
Twig\Template->display(Array) (Line: 434)
Twig\Template->render(Array) (Line: 64)
twig_render_template('themes/custom/showcaseplus/templates/block.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('block', Array) (Line: 431)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 444)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 200)
Drupal\Core\Render\Renderer->render(Array) (Line: 501)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 104)
__TwigTemplate_8e7d8e2898e403a235c00....05797b9525dda30b5af4617ddf->doDisplay(Array, Array) (Line: 455)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 422)
Twig\Template->display(Array) (Line: 434)
Twig\Template->render(Array) (Line: 64)
twig_render_template('core/themes/stable/layouts/fourcol_section/layout--fourcol-section.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('layout__fourcol_section', Array) (Line: 431)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 444)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 444)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 444)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 444)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 200)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 226)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 573)
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: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Unsetting the link makes the error go away.

Steps to reproduce

Copied from #5:

  1. Go to the admin site.
  2. Go to admin/modules.
  3. Enable the Layout builder and click on install.
  4. Go to admin/structure/media/manage/image/display/default , against the name field , there is a settings icon , click it and enable the checkbox against Link to the Media and click on update.
  5. In the Layout options -> enable Use Layout Builder -> Save.
  6. Go to reports/dblog
  7. Verify if any of the error and warning(such as "The field "name" failed to render with the error of "The "media" entity cannot have a URI as it does not have an ID".") shouldn't appear after applying the patch.

StringFormatter should not offer the 'link_to_entity' setting if the entity type has no canonical link template

$
0
0

Problem/Motivation

The StringFormatter formatter has a setting 'link_to_entity'.

However, this setting makes no sense (and will cause a crash!) if the entity type in question does not have a canonical link template.

Steps to reproduce

1. Install Paragraphs module
2. Create a view of paragraphs
3. Add a field, such as 'parent field name'
4. Enable 'link to the paragraph' in the field setting

When trying to load the view page, you get this crash:

> Drupal\Core\Entity\Exception\UndefinedLinkTemplateException: No link template 'canonical' found for the 'paragraph' entity type in Drupal\Core\Entity\EntityBase->toUrl() (line 227 of core/lib/Drupal/Core/Entity/EntityBase.php).

Proposed resolution

settingsForm() should check the target entity type for a canonical link, and disable the form element and set it to FALSE

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

[PP-1] Deprecate passing path (instead of true URI) to ImageStyleInterface::buildUri($uri)

$
0
0

Problem/Motivation

According to the docblock for ImageStyleInterface::buildUri():

  /**
   * Returns the URI of this image when using this style.
   *
   * The path returned by this function may not exist. The default generation
   * method only creates images when they are requested by a user's browser.
   * Modules may implement this method to decide where to place derivatives.
   *
   * @param string $uri
   *   The URI or path to the original image.
   *
   * @return string
   *   The URI to the image derivative for this style.
   */

It appears the only real cases of a path being used instead of a true URI are for files inside of core (or *maybe* contrib modules?) such as the image style sample image. This results in a URI in the form of:

public://styles/large/public/core/modules/image/sample.png

This is the result of the URI pattern $scheme://styles/{$this->id()}/$source_scheme/{$this->addExtension($path)} in this method.

Interestingly, this URI would result in failed image generation if we waited to create the derivative on first request. This is of course how the vast majority (if not *all*) other derivatives are created. The failure would stem from the image style controller and path processor converting the source file URI "back" to:

public://core/modules/image/sample.png

which of course doen't exist. Why does the image style preview shown during editing work? The derivative is actually created during the handling of the initial page request, contra usual image style practice.

This is likely due to "good" historical reason - there is no stream wrapper for accessing extension files, though there is a core proposal for this (#1308152: Add stream wrappers to access extension files) as well as support in contrib.

Steps to reproduce

n/a

Proposed resolution

Deprecate passing a non-URI $uri to the method (we already check if there is a scheme present, which would be sufficient to trigger the deprecation notice) and refactor existing uses of path strings, likely mostly (only?) present in core.

Remaining tasks

User interface changes

API changes

Deprecated shape for argument, but no change in data type (string for string.)

Data model changes

Release notes snippet

Some calls to assertEquals have expected/actual parameters reversed

$
0
0

I noticed a couple calls to phpunit assertEquals which clearly had the "expected" and "actual" parameters reversed, which can lead to confusing failure messages (and accidental propagation of the incorrect form, when other people copy/paste code blocks that look good). Anyway, I did a search and found a few more where obvious strings or integers, etc, were in the "actual" position. This is a very simple issue, but might as well be fixed...

Move state entries out of migrate_drupal.migrate_drupal.yml

$
0
0

Problem/Motivation

In #2936365: Migrate UI - allow modules to declare the state of their migrations the noUpgradePath arrays were removed and replaced with entries in migrate_drupal/migrations/state/migrate_drupal.migrate_drupal.yml. There entries need to be reviewed to decide if any can be moved to a more appropriate module and then move them.

At least the i18m ones need a closer look and so do any modules that provide fields.
In #3175729: Mark i18n migrations as finished all the i18n properties were moved out of migrate_drupal.migrate_drupal.yml.

Proposed resolution

Review each migration state entry in migrate_drupal and move any that can be moved.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet


Add uid 0 to the migrate test fixtures

$
0
0

Problem/Motivation

Creating an issue from item #1 in the parent, #2578483: [meta] Keep dumps up-to-date and improve DX.

The dumps omit uid 0. Find a way to include uid 0 so that this doesn't need to be done manually. It should be possible to import the db and use it straight away without making changes to the fixture.

Proposed resolution

TBD

Remaining tasks

Decide how to do it
Do it

User interface changes

None

API changes

None

Data model changes

None

Remove redundant call $this->requestStack->getCurrentRequest() in FormBuilder::buildForm

$
0
0

Problem/Motivation

In FormBuilder::formBuilder function the variable $request is assigned twice with the same vaue:

$request = $this->requestStack->getCurrentRequest();

Probably, one call is enough.

Proposed resolution

Remove the second call.

Remaining tasks

Provide patch.

Ready!

User interface changes

None.

API changes

None.

Data model changes

None.

Localize url in menu

$
0
0

Hi,

I'm loading a menu programmatically and building a renderable array then to display it.

Here's how:

    $menu_tree = \Drupal::menuTree();

    // Build the typical default set of menu tree parameters.
    $parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
    // Load the tree based on this set of parameters.
    $tree = $menu_tree->load($menu_name, $parameters);
    // Transform the tree using the manipulators you want.
    $manipulators = array(
      // Only show links that are accessible for the current user.
      array('callable' => 'menu.default_tree_manipulators:checkAccess'),
      // Use the default sorting of menu links.
      array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
    );
    $tree = $menu_tree->transform($tree, $manipulators);

    // Finally, build a renderable array from the transformed tree.
    return $menu_tree->build($tree);

The issue is that on a multilingual website, only the links title are being translated and not the url. The menu link content is well configured as I can have a different value for the url for each language.

A patch is coming up.

Entity Autocomplete element expecting an array, but getting a scalar value for target_id instead

$
0
0

When using Layout Builder with a View block display (having configuration parameters added by a patch from #2657060: Add Configure Filter functionality to block views configuration.) containing a footer link to a Page display on the same view with matching exposed filters, the linked page expects each filter to be an array containing a target_id key with a numeric ID, but a scalar value is provided instead.

The following error is observed when saving the block configuration in Layout Builder:

An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /layout_builder/update/block/overrides/node.XXX/0/content/UUIDv4?destination=/node/XXX/layout&_wrapper_format=drupal_dialog.off_canvas&ajax_form=1
StatusText: parsererror
ResponseText: TypeError: Argument 1 passed to Drupal\Core\Entity\Element\EntityAutocomplete::Drupal\Core\Entity\Element\{closure}() must be of the type array, null given in Drupal\Core\Entity\Element\EntityAutocomplete::Drupal\Core\Entity\Element\{closure}() (line 80 of /app/web/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php).

Once the layout is saved, the page becomes inaccessible due to the following error:

#1 /app/web/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php(83): array_map(Object(Closure), Array)
#2 [internal function]: Drupal\Core\Entity\Element\EntityAutocomplete::valueCallback(Array, Array, Object(Drupal\Core\Form\FormState))
#3 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(1256): call_user_func_array(Array, Array)
#4 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(991): Drupal\Core\Form\FormBuilder->handleInputElement('views_exposed_f...', Array, Object(Drupal\Core\Form\FormState))
#5 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(1061): Drupal\Core\Form\FormBuilder->doBuildForm('views_exposed_f...', Array, Object(Drupal\Core\Form\FormState))
#6 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(562): Drupal\Core\Form\FormBuilder->doBuildForm('views_exposed_f...', Array, Object(Drupal\Core\Form\FormState))
#7 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(319): Drupal\Core\Form\FormBuilder->processForm('views_exposed_f...', Array, Object(Drupal\Core\Form\FormState))
#8 /app/web/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php(154): Drupal\Core\Form\FormBuilder->buildForm('\\Drupal\\views\\F...', Object(Drupal\Core\Form\FormState))
#9 /app/web/core/modules/views/src/ViewExecutable.php(1238): Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm()
#10 /app/web/core/modules/views/src/ViewExecutable.php(1391): Drupal\views\ViewExecutable->build(NULL)
#11 /app/web/core/modules/views/src/ViewExecutable.php(1454): Drupal\views\ViewExecutable->execute(NULL)
#12 /app/web/core/modules/views/src/Plugin/views/display/Block.php(131): Drupal\views\ViewExecutable->render()
#13 /app/web/core/modules/views/src/ViewExecutable.php(1630): Drupal\views\Plugin\views\display\Block->execute()
#14 /app/web/core/modules/views/src/Element/View.php(77): Drupal\views\ViewExecutable->executeDisplay('bibliographic_r...', Array)
#15 /app/web/core/modules/views/src/Plugin/Block/ViewsBlock.php(59): Drupal\views\Element\View::preRenderViewElement(Array)
#16 /app/web/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php(116): Drupal\views\Plugin\Block\ViewsBlock->build()
#17 [internal function]: Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray->onBuildRender(Object(Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent), 'section_compone...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#18 /app/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent), 'section_compone...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#19 /app/web/core/modules/layout_builder/src/SectionComponent.php(90): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('section_compone...', Object(Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent))
#20 /app/web/core/modules/layout_builder/src/Section.php(86): Drupal\layout_builder\SectionComponent->toRenderArray(Array, true)
#21 /app/web/core/modules/layout_builder/src/Element/LayoutBuilder.php(247): Drupal\layout_builder\Section->toRenderArray(Array, true)
#22 /app/web/modules/contrib/layout_builder_st/src/Element/LayoutBuilder.php(80): Drupal\layout_builder\Element\LayoutBuilder->buildAdministrativeSection(Object(Drupal\layout_builder_st\Plugin\SectionStorage\OverridesSectionStorage), 0)
#23 /app/web/core/modules/layout_builder/src/Element/LayoutBuilder.php(123): Drupal\layout_builder_st\Element\LayoutBuilder->buildAdministrativeSection(Object(Drupal\layout_builder_st\Plugin\SectionStorage\OverridesSectionStorage), 0)
#24 /app/web/core/modules/layout_builder/src/Element/LayoutBuilder.php(97): Drupal\layout_builder\Element\LayoutBuilder->layout(Object(Drupal\layout_builder_st\Plugin\SectionStorage\OverridesSectionStorage))
#25 [internal function]: Drupal\layout_builder\Element\LayoutBuilder->preRender(Array)
#26 /app/web/core/lib/Drupal/Core/Render/Renderer.php(378): call_user_func(Array, Array)
#27 /app/web/core/lib/Drupal/Core/Render/Renderer.php(195): Drupal\Core\Render\Renderer->doRender(Array, true)
#28 /app/web/core/lib/Drupal/Core/Render/Renderer.php(139): Drupal\Core\Render\Renderer->render(Array, true)
#29 /app/web/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}()
#30 /app/web/core/lib/Drupal/Core/Render/Renderer.php(140): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#31 /app/web/core/lib/Drupal/Core/Ajax/CommandWithAttachedAssetsTrait.php(33): Drupal\Core\Render\Renderer->renderRoot(Array)
#32 /app/web/core/lib/Drupal/Core/Ajax/ReplaceCommand.php(31): Drupal\Core\Ajax\InsertCommand->getRenderedContent()
#33 /app/web/core/lib/Drupal/Core/Ajax/AjaxResponse.php(43): Drupal\Core\Ajax\ReplaceCommand->render()
#34 /app/web/core/modules/layout_builder/src/Controller/LayoutRebuildTrait.php(47): Drupal\Core\Ajax\AjaxResponse->addCommand(Object(Drupal\Core\Ajax\ReplaceCommand))
#35 /app/web/core/modules/layout_builder/src/Controller/LayoutRebuildTrait.php(26): Drupal\layout_builder\Form\ConfigureBlockFormBase->rebuildLayout(Object(Drupal\layout_builder_st\Plugin\SectionStorage\OverridesSectionStorage))
#36 /app/web/core/modules/layout_builder/src/Form/ConfigureBlockFormBase.php(242): Drupal\layout_builder\Form\ConfigureBlockFormBase->rebuildAndClose(Object(Drupal\layout_builder_st\Plugin\SectionStorage\OverridesSectionStorage))
#37 /app/web/core/lib/Drupal/Core/Ajax/AjaxFormHelperTrait.php(39): Drupal\layout_builder\Form\ConfigureBlockFormBase->successfulAjaxSubmit(Array, Object(Drupal\Core\Form\FormState))
#38 [internal function]: Drupal\layout_builder\Form\ConfigureBlockFormBase->ajaxSubmit(Array, Object(Drupal\Core\Form\FormState), Object(Symfony\Component\HttpFoundation\Request))
#39 /app/web/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php(69): call_user_func_array(Array, Array)
#40 /app/web/core/lib/Drupal/Core/Form/EventSubscriber/FormAjaxSubscriber.php(109): Drupal\Core\Form\FormAjaxResponseBuilder->buildResponse(Object(Symfony\Component\HttpFoundation\Request), Array, Object(Drupal\Core\Form\FormState), Array)
#41 [internal function]: Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber->onException(Object(Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent), 'kernel.exceptio...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#42 /app/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent), 'kernel.exceptio...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#43 /app/vendor/symfony/http-kernel/HttpKernel.php(228): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.exceptio...', Object(Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent))
#44 /app/vendor/symfony/http-kernel/HttpKernel.php(79): Symfony\Component\HttpKernel\HttpKernel->handleException(Object(Drupal\Core\Form\FormAjaxException), Object(Symfony\Component\HttpFoundation\Request), 1)
#45 /app/web/modules/contrib/simple_oauth/src/HttpMiddleware/BasicAuthSwap.php(67): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#46 /app/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#47 /app/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#48 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#49 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#50 /app/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#51 /app/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#52 /app/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#53 /app/web/core/lib/Drupal/Core/DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#54 /app/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#55 {main}.

Add 'drupal_internal__target_id' to JSON:API representation of entity reference fields, because that can't be retrieved from the target resource for target entity types without corresponding resources

$
0
0

Problem/Motivation

In preparation for adding JSON:API to Drupal core, we released the 2.x branch. In it, we tried to clean up many of JSON:API's rough edges. One of which was that while we represented entities as "resource objects" that don't directly match the structure of the underlying entity, when you filtered collections, one would have to filter by entities using their exact structure, even bits that were missing from the resource object representation. We published a change record to this effect.

That change introduced and unintended consequence, anyone filtering by the target_id property of an entity reference item would have their clients broken. This target_id property is omitted from resource identifiers because it was believed that it was unnecessary because it sort of duplicated the id member.

This was a wrong assumption, it may be necessary to filter a the target ID when filtering for an entity referencing a config entity. This might be the case if your client is filtering users by a role machine name, for example.

Proposed resolution

Add a drupal_internal__target_id property to resource identifiers and make it possible to filter by this value (this ensures that filters still closely match JSON:API's output structure (the purpose of the CR that broke this behavior))

User interface changes

None.

API changes

A new property will be added to JSON:API's output. This is not a breaking change.

Data model changes

None.

Release notes snippet

drupal_internal__target_id has been added to JSON:API responses, see the change record for more information.

Original report

:

I am trying to upgrade my site from the 1.x branch to 2.x but am running in to some confusion and a bit of a performance problem.

When filtering by an entity reference field, I used to be able to do something as simple as /api/entity_type?filter[ref_field]=123, where 123 is the ID of the entity. This is beneficial to using the UUID because it does not require a JOIN on the referenced entity table. The query would be something like:

SELECT base_table.id AS id, base_table.id AS base_table_id FROM {entity_type} WHERE ref_field = 123

Now, when trying to perform the same API request, I get this error: "Invalid nested filtering. The field `ref_field`, given in the path `ref_field` is incomplete, it must end with one of the following specifiers: `id`."

If I change the filter to ?filter[ref_field.id]=123, the query becomes overly complex and performance degrades seriously (we have over 2M entities):

SELECT base_table.id AS id, base_table.id AS base_table_id FROM @entity_type base_table INNER JOIN @entity_type entity_type ON entity_type.id = base_table.id LEFT OUTER JOIN @ref_field ref_field ON ref_field.id = entity_type.ref_field INNER JOIN @ref_field ref_field_2 ON ref_field_2.id = ref_field.id WHERE ref_field_2.uuid LIKE :db_condition_placeholder_0

I am curious: 1) Why was this change added? and 2) Is there anyway I can force the former, more simple approach

Add a #disable_inline_form_errors_summary property to disable the Inline Form Errors summary

$
0
0

Problem/Motivation

In certain cases we want to disable duplicate messages (on top - summary - and inline).
We currently have the #error_no_message property which allowed us to disable errors messages for individual elements.

There may be some field that does not display the inline error, so the message is only visible in the summary. As an example, the Captcha field.
We should then keep the messages in the summary - even when the new property to disable the summary is requested - for fields that contain errors but can't display them inline (Eg. invisible elements, missing elements, ...).

Proposed resolution

Add a form property which can be used to disable IFE summary$form['#disable_inline_form_errors_summary'] = TRUE.
Keep the message in the summary for fields which can't show inline-error (Eg. invisible elements, missing elements, ...).

Completed tasks

Remaining tasks

User interface changes

  • Developers will be able to remove the Summary message when IFE is enable.
  • The summary should still be visible for an element which can't show inline-error (invisible element, missing element, ...).

API changes

The form element will have an optional #disable_inline_form_errors_summary boolean, that if TRUE, disables the duplicate messages from summary & inline-error elements. If one or more elements with errors can't show inline-error (Eg. invisible elements, missing elements, ...) , the summary will remain visible with those messages only.

Use assertSameSize() to check same size of two countable variables

$
0
0

Problem/Motivation

Follow-up from #3135538: Replace remaining assert* involving use of count() where relevant. In some cases we are doing assertSame(count($foo), count($bar)), we could instead use assertSameSize($foo, $bar).

See the API docs for assertSameSize()

Original issue summary, which suggested creating a new assertion method

Follow-up from [#3135538. IN some cases we are doing assertSame(count($foo), count($bar)), we could add a custom assertion to make this assertSameCount($foo, $bar).


Allow the user to choose their language upon registration

$
0
0

Language selector is not displayed on /user/register

Yet on admin/config/people/accounts/form-display the selector is set to be displayed

bah

Fix Claro styles for exposed views filters wrapped in fieldsets

$
0
0

Problem/Motivation

#2625136: Fix label visibility and add wrapper container for exposed numeric/date filters with multiple form elements is fixing a long standing bug in Views exposed forms. If a given filter requires multiple form elements (e.g. the operator is exposed, or it's a numeric filter with 'between' operation that needs min/max, etc), prior to #2625136 things were all kinds of broken:

Screenshot of exposed views filter with multiple elements in Claro before #2625136

Now, for these sorts of filters to make sense (both to folks using screen readers and other assistive technology, or to sighted users), those elements are wrapped in a fieldset. However, the default styles for Claro don't look perfect:

Screenshot of exposed views filter with multiple elements in Claro after the fix from #2625136 so the elements are in a fieldset

Proposed resolution

Tweak Claro's (p)CSS to give better spacing / alignment for these sorts of exposed form elements.

Remaining tasks

  1. Wait for #2625136: Fix label visibility and add wrapper container for exposed numeric/date filters with multiple form elements to land so we have something to style.
  2. Design what this should look like in Claro.
  3. Implement.
  4. Reviews.
  5. RTBC.
  6. Commit.

User interface changes

TBD.

API changes

N/A

Data model changes

N/A

Release notes snippet

TBD. Probably not.

[meta] Replace assertions with more appropriate ones

$
0
0

Problem/Motivation

Wherever possible, use specific PHPUnit default assertions, that also provide standard messaging in case of assertion failure. PHPUnit's list @ https://phpunit.readthedocs.io/en/8.5/assertions.html is the best starting point to understand what default PHPUnit provides.

However, beware of PHPUnit's own deprecations -- the most accurate list is PHPUnit 9 at the moment, https://phpunit.readthedocs.io/en/9.1/assertions.html. Drupal does not support PHPUnit 9 yet, but has already removed usage of methods deprecated in PHPUnit 8 in #3110543: [meta] Support PHPUnit 9 in Drupal 9.

For example: assertSame(*, count()) can be replaced by assertCount().

Issues open:

Done:

Proposed resolution

Add child issues for each case and replace them.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Typo in the description of class MenuLinkContentAccessControlHandler

$
0
0

Problem/Motivation

The description of the class MenuLinkContentAccessControlHandler refers to User entity type instead of "menu link content" entity type.

List and count all changes made in a workspace

$
0
0

Problem/Motivation

The goal of this issue is to finalise certain aspects of the Workspaces UI. Specifically this screen (with adaptations): https://marvelapp.com/2db8i71/screen/26996437

At a high level, there are three features:

  1. Users want to see the number (count) of changes in each workspace to get a better sense of the activity and relevance of each workspace.
  2. Users want to see more details, the list of revisions, that changed for a specific workspace.
  3. Users should be able to publish changes straight from the overview page to make it easier to publish changes with fewer clicks.

Proposed resolution

  1. Count the number of changes and add a descriptive string under the name of each workspace in the top off-canvas interface.
  2. Implement a new page that list all changed revisions, with operation links
  3. Add the deploy form at the top of the page that list the changes

Remaining tasks

Implement it all.

User interface changes

Mostly additions to the UI.

API changes

None

Data model changes

None, so far

Viewing all 296540 articles
Browse latest View live


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