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

Cannot update to 8.7.0 because of taxonomy_post_update_make_taxonomy_term_revisionable

$
0
0

Hi, When I try to update Drupal 8.7.0 db br drush updb I get the following error.

>  [notice] Update started: taxonomy_post_update_make_taxonomy_term_revisionable
>  [error]  Drupal\Core\Database\IntegrityConstraintViolationException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null: INSERT INTO {tmp_d305d9taxonomy_term_field_data} (tid, revision_id, vid, langcode, name, description__value, description__format, weight, changed, default_langcode, status, revision_translation_affected) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11); Array
> (
>     [:db_insert_placeholder_0] => 1
>     [:db_insert_placeholder_1] => 1
>     [:db_insert_placeholder_2] => tags
>     [:db_insert_placeholder_3] => tr
>     [:db_insert_placeholder_4] =>
>     [:db_insert_placeholder_5] =>
>     [:db_insert_placeholder_6] =>
>     [:db_insert_placeholder_7] =>
>     [:db_insert_placeholder_8] =>
>     [:db_insert_placeholder_9] =>
>     [:db_insert_placeholder_10] =>
>     [:db_insert_placeholder_11] => 1
> )
>  in Drupal\Core\Database\Connection->handleQueryException() (line 689 of /var/www/drupal8/web/core/lib/Drupal/Core/Database/Connection.php).
>  [error]  The entity update process failed while processing the entity type taxonomy_term, ID: 1.
>  [error]  Update failed: taxonomy_post_update_make_taxonomy_term_revisionable
 [error]  Update aborted by: taxonomy_post_update_make_taxonomy_term_revisionable
 [error]  Finished performing updates.

Exposed Filters Does not show up in a block

$
0
0

I have created a new view with the following settings

Format: Unformatted List
Show: Fields

Filter Criteria:
Published = Yes (AND)
Content-Type = News (AND)
has a taxonomy term (Exposed).

Advanced:
Exposed form style: Basic
Use Ajax: Yes
Caching: Tag-based

I have saved the view and added the block to a region on the theme. Now I cannot see anything on the screen. If I remove "has a taxonomy term (Exposed)." in Filter criteria, then I can see the block and content populated to the block.

If I do the same with a view page and use the same filter criteria and set advanced settings, then the view works fine there.

[policy, no patch] replace jQueryUI autocomplete with awesomplete

$
0
0

Problem/Motivation

We are in the process of deprecating jQuery UI in core. jQueryUI's autocomplete is among the components that need to be removed/replaced.
As mentioned in the parent issue: #3067261: [Plan] Remove jQuery UI components used by Drupal core and replace with a set of supported solutions
The OpenJS Foundation lists jQuery UI as an Emeritus project in https://openjsf.org/projects/ which is described as:

Emeritus projects are those which the maintainers feel have reached or are nearing end-of-life

Well before the need to deprecate jQueryUI emerged in mid-2019, there has been interest in replacing jQueryUI with something with better UX and accessibility (which is evident in this issue being created several years prior to mid-2019).

Proposed resolution

Replace jQuery autocomplete with the Awesomplete library. Awesomplete was one of ten libraries evaluated as a replacement for jQueryUI autocomplete. The full evaluation (with a prototype that can be used with taxonomy fields) is in comment #223. This was chosen over the others for several reasons, including

  • It was the only library reviewed to not have any glaring accessibility issues
  • Unlike most candidates, the functionality is applied to the existing text field. Most of the other options require select elements or hide the text field and create pseudo-inputs from other elements, creating entirely new markup that could result in broken forms and frustrated contrib developers.
  • Awesomplete is in the Joomla 4 alpha, which means another large project has vetted it and has interest in its continued support
  • A review of its Github suggests that important issues actually get addressed

(in other words, it's easily the most accessible, least disruptive option chosen so far)

Steps taken prior to the proposed resolution

Other than Awesomplete, nontrivial accessibility problems identified in each evaluation. These problems were discovered from general accessibility testing. In each case, enough issues were found that it wasn't worth devoting additional time to strictly checking against W3 specs.

Remaining tasks

  • Accessibility review
  • FE Manager review
  • UX review
  • Product Manager review
  • (probably more reviews, this is a major change)

User interface changes

Yes.

API changes

Yes.

Core version key in module's .info.yml doesn't respect core semantic versioning

$
0
0

Problem/Motivation

Drupal modules and themes need to be able to specify that they depend on specific versions of Drupal because a new minor version of Drupal may introduce new APIs and a patch version may fix bugs. Drupal modules and themes also need to specify they are compatible with 2 major versions of Drupal such as 8 and 9 if they don't use any APIs that will be removed in Drupal 9. Modules and Themes should not have to create a new major branches to achieve this as per #2608062: [META] Requirements for opening the Drupal 9 branch

Currently the core key in info.yml files only supports core: 8.x which denotes that they support any version of Drupal 8.

Currently get around this limitation many modules use the dependencies: key in info.yml files. For example
- "drupal:system (>8.6)"
But this method is ineffective because of #2641658: Module version dependency in .info.yml is ineffective for patch releases

While we could change the core: key to accept semantic version constraints to allow requiring specific core patch version, for example core: ^8.7, or multiple branch compatibility core: ^8 || ^9, or both core: ^8.7 || ^9 this would cause problems for any sites using previous versions of Drupal core, for example the recent 8.7.6, if they attempted to update a module they currently have installed that switched to the new format.

A Drupal 8.7.5 stie that has my_module 8.x-1.1 that uses core: 8.x and then updates to my_module 8.x-1.2 that uses core: ^8(anything beside 8.x) will have this this module silently disabled though the config for this module would still be enabled. There would be no message that this happened. See #138 and #2917600: Disabling missing modules results in a "Unable to install MODULE already exists in active configuration" warning or PreExistingConfigException (via Drush).

Proposed resolution

Introduce a new key core_dependency:(better name?) that would accept Composer Semantic version constraints.
The version constraints will be evaluated by \Composer\Semver\Semver::satisfies(). The rules for this can be found here: https://getcomposer.org/doc/articles/versions.md

This key could be used at the same time as the core:.

But in certain cases it would be used in instead of the core: key.

For example assuming this issue gets committed to 8.8.x:

core: 8.x
core_dependency: ^8.8

This would not make sense because it would not actually restrict anyone from installing it on Drupal 8.7.1 since the core_dependency would be ignored and would therefore would allow the module to be enabled. We can enforce this by in this case not allowing core: key. Not having the core: would give a hard fail in Drupal 8.7.x sites but because it fails in \Drupal\Core\Extension\InfoParserDynamic::parse this would not cause problem in #138 and #2917600: Disabling missing modules results in a "Unable to install MODULE already exists in active configuration" warning or PreExistingConfigException (via Drush).

Also

core: 8.x
core_dependency: ^8.7.4

Would also not make sense because Drupal 8.7.3 would not enforce core_dependency: ^8.7.4. We can enforce this by not allowing restrictions that cover versions before issue is committed because these will not actually be enforced.

In both these cases it would hard for a contrib author to be aware for these problems if they working on Drupal 8.8.x unless they also tested their module on previous versions of Drupal. So we should not allow this as valid values for info.yml files.

Therefore we should add validation to \Drupal\Core\Extension\InfoParserDynamic::parse() to make sure that module authors don't these problems.

Examples of supported core_dependency: values:

core_dependency: valueevaluates to constraintsComments
^8.8>= 8.8.0.0-dev < 9.0.0.0-devrecommended for modules that are only compatible with 8.8.x and above but not 9
^8 || ^9>= 8.0.0.0-dev < 10.0.0.0-devrecommended for modules that are compatible with both Drupal 8 & 9. Most modules aren't actually compatible with all version of Drupal if they have remove deprecations and used the new replacements

Remaining tasks

Determine if core: 9.x should be allowed or if just core_dependency: ^9 should be used for only Drupal 9 modules.

User interface changes

Small string change for modules page

API changes

Support core semantic versioning for Drupal core via new core_dependency key

'view_path' is set to /views/ajax after second ajax request

$
0
0

Problem/Motivation

Steps to reproduce

  • Create like 5 pieces of content
  • Edit the /admin/content view to use 1 item per page and enable ajax
  • Use the pager multiple times

Expected result

settings.view_path points to /admin/content

Actual result

settings.view_path points to /views/ajax

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Migrate taxonomy term references for D7 Node translations

$
0
0

Problem/Motivation

D7 follow-up for #2859297: Migrate taxonomy term references for D6 Node translations.

This issue is about the references from the migrated Node translations to the terms.

Proposed resolution

Write the migration in the same fashion as we did for D6 in #2859297: Migrate taxonomy term references for D6 Node translations.

The scope of this issue is the reference from the node translation to the taxonomy term.

Test case 1 when using 'Localized' vocabulary together with 'Node translation' concept.

  • Have two node entities in Drupal 7, one in English (nid A) and one for example in Finnish (nid B). Associate these as translations of each other.
  • Have one taxonomy term in Drupal 7 which is translated in Drupal 7 using the 'Localized' concept.
  • Make sure that both English and Finnish versions of the Drupal 7 node have a reference to the term.

Expected result:

  • The Finnish language version of the node is migrated as a translation to the English node. In other words, there were 2 nodes in Drupal 7 but there will only be 1 node in Drupal 8.
  • Both language versions of the Drupal 8 node must have a reference to the term.

Implementation in D7 fixture: TODO, document here which terms and nodes are used in the fixture tests.

Test case 2 when using 'Per language' vocabulary.

  • Have two node entities in Drupal 7, one in English and one for example in Finnish. Associate these as translations of each other.
  • Have two taxonomy terms in Drupal 7. The vocabulary must have the 'Per language' multilingual setting. Both taxonomy terms will have their language defined.
  • Make sure that the English node has a reference to the English term in Drupal 7.
  • Make sure that the Finnish node has a reference to the Finnish term in Drupal 7.

Expected result:

  • The Finnish language version of the node is migrated as a translation to the English node. In other words, there were 2 nodes in Drupal 7 but there will only be 1 node in Drupal 8.
  • When viewing the English version of the Drupal 8 node (original language of the node), it must have a reference to the English term.
  • When viewing the Finnish translation of the Drupal 8 node, it must have a reference to the Finnish term.

Implementation: TODO, document here which term and node are used in the fixture tests for this test case.

Remaining tasks

Patch
Test & Review
Commit

User interface changes

N/A

API changes

N/A

Data model changes

N/A

[meta] How to deprecate Simpletest with minimal disruption

$
0
0

Problem/Motivation

Simpletest is one of the biggest deprecations in Drupal 8 and one of the least trivial to update for.

Also, when porting modules to Drupal 9, if a module has simpletests, they're one of the ways to ensure that the porting hasn't introduced a regression.

Proposed resolution

Locate all hard dependencies of run-tests.sh within the simpletest module. (Excluding WebTestBase.)

Move those dependencies to a third location (ie, not within simpletest module, not within run-tests.sh). There are some issues already about this. This is moving the test runner support parts out of simpletest, not the WebTestBase framework.

The test runner parts in simpletest can then be deprecated in 8.8.0 for removal before 9.0.0. There is still time, this is not rocket science, patches already exist. The elements being deprecated are for the test runner itself and are basically almost @internal, not for the testing framework which is used by users.

The remainder of simpletest module is split into simpletest and testing_ui. Alternately, if we're going to turn simpletest into contrib, we don't need to do this step because we can just have the UI be in the contrib module.

Whatever's left of simpletest module after that basically supports WebTestBase only, and that can be moved to contrib during D9 dev time. It'll even still be called 'simpletest' so no one has to change the namespace in their tests.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Page cache breaks nondefault ajax theme on GET

$
0
0

Steps to reproduce

  1. An ajax-enabled form that's accessible for the anonymous user. -- in my case a multi-page webform with webform_ajax enabled.
  2. Some custom theme is displayed. -- in my case by a module that sets it via hook_custom_theme()
  3. Either the page cache is enabled or the browser doesn't accept cookies (leading to the session_id() changing between the original form generation and the ajax request).

Result

The ajax request is handled using the default theme which means the styles for the default theme are loaded additionally to the styles of the custom theme (at least with less enabled) - but at the very least use the wrong template files.

What happens exactly?

ajax_base_page_theme() is responsible for setting the same theme that was used in the original form generation. It uses drupal_valid_token() to check whether the the user is allowed to set the theme via $_POST['ajax_page_state']['theme']. drupal_valid_token() uses the session_id() to check the token and thus fails (because the session_id() has changed).

In a broader picture drupal_valid_token() can't work reliably for anonymous in general in this form, because it relies on the session_id().

Proposed solution

Use another token generation/verification method that uses the form_build_id instead of the session_id().


Add a new view mode for embedded media

$
0
0

Problem/Motivation

In #2940029: Add an input filter to display embedded Media entities, we added the ability to embed media entities into WYSIWYG text editors and HTML content, using an input filter. By default, the media items are embedded by rendering them through their "full" view mode (although this can be overridden by changing a special data attribute in the raw HTML). The "full" view mode might not be entirely appropriate for an embedded representation of a media item, so this issue is where we can explore the possibility of adding a new view mode specifically for use when embedding media items in HTML, and changing the input filter to use it as the default view mode.

Proposed resolution

Discuss whether we should create an "embed" view mode, and what should be in the corresponding view displays for each media type we ship with Standard.

Remaining tasks

Once we've decided what we want, make it happen.

User interface changes

TBD.

API changes

TBD, but likely none.

Data model changes

None anticipated.

Release notes snippet

TBD

Ajax validation only works when I am connected

$
0
0

Hello !
I am new in Drupal world and I'm trying to use the Drupal From API to create a contact form with Ajax validation.
I'm facing an issues:

  • My following form (see below) works well but only when the user is connected as administrator. When I am not logged in as an administrator, ajax validation does not work.

Here is the form I created:

namespace Drupal\dalcom_contact\Form;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class DalcomContactForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'dlcm_cform';
  }

  public function buildForm(array $form, FormStateInterface $form_state, $params = NULL) {

    // Disable caching.
    $form['#cache']['max-age'] = 0;

    // Disable browser HTML5 validation.
    $form['#attributes']['novalidate'] = 'novalidate';

    // This will generate an anchor scroll to the form when submitting.
    $form['#action'] = '#dlcm_cform';

    $form['mail_visitor'] = [
      '#type' => 'email',
      '#placeholder' => t('E-mail*'),
      '#description' => 'Your mail',
      '#required' => TRUE,
      '#ajax' => [
        'callback' => 'Drupal\dalcom_contact\Form\DalcomContactForm::mailValidateCallback',
        'effect' => 'fade',
        'event' => 'change',
        'progress' => [
          'type' => 'throbber',
          'message' => NULL,
        ],
      ],
    ];

    $form['message_visitor'] = [
      '#type' => 'textarea',
      '#placeholder' => t('Message*'),
      '#description' => 'Your message',
      '#required' => TRUE,
      '#ajax' => [
        'callback' => 'Drupal\dalcom_contact\Form\DalcomContactForm::messValidateCallback',
        'effect' => 'fade',
        'event' => 'change',
        'progress' => [
          'type' => 'throbber',
          'message' => NULL,
        ],
      ],
    ];

    $form['accept_box'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('I accept the CME terms of use'),
      '#required' => TRUE,
      '#ajax' => [
        'callback' => 'Drupal\dalcom_contact\Form\DalcomContactForm::acceptboxalidateCallback',
        'effect' => 'fade',
        'event' => 'change',
        'progress' => [
          'type' => 'throbber',
          'message' => NULL,
        ],
      ],
    ];

    $form['candidate_copy'] = [
      '#type' => 'checkbox',
      '#title' => t('Send me a copy of my message.'),
    ];

    $form['actions']['#type'] = 'actions';

    $form['actions']['submit'] = [
      '#type' => 'button',
      '#value' => $this->t('Send'),
      '#ajax' => [
        'event' => 'click',
        'progress' => [
          'type' => 'throbber',
          'message' => 'Sending...',
        ],

      ],
    ];

    $form['#theme'] = 'dalcom_contact_theme';

    return $form;
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    foreach ($form_state->getValues() as $key => $value) {
      drupal_set_message($key . ': ' . $value);
    }
  }

  public function mailValidateCallback(array &$form, FormStateInterface $form_state) {
    $ajax_response = new AjaxResponse();

    if (!$form_state->getValue('mail_visitor') || empty($form_state->getValue('mail_visitor'))) {
      $text = 'No email registered';
      $color = 'red';
    }
    elseif (!filter_var($form_state->getValue('mail_visitor'), FILTER_VALIDATE_EMAIL)) {
      $text = 'Invalid email address';
      $color = 'red';
    }
    else {
      $text = 'Valid mail';
      $color = 'green';
    }

    $ajax_response->addCommand(new HtmlCommand('#edit-mail-visitor--description', $text));

    $ajax_response->addCommand(new InvokeCommand('#edit-mail-visitor--description', 'css', ['color', $color]));

    return $ajax_response;
  }

  public function messValidateCallback(array &$form, FormStateInterface $form_state) {
    $ajax_response = new AjaxResponse();

    if (!$form_state->getValue('message_visitor') || empty($form_state->getValue('message_visitor'))) {
      $text = 'No messages written';
      $color = 'red';
    }
    elseif (strlen($form_state->getValue('message_visitor')) < 6) {
      $text = 'At least 7 characters';
      $color = 'red';
    }
    else {
      $text = 'Messages written';
      $color = 'green';
    }

    $ajax_response->addCommand(new HtmlCommand('#edit-message-visitor--description', $text));

    $ajax_response->addCommand(new InvokeCommand('#edit-message-visitor--description', 'css', ['color', $color]));

    return $ajax_response;
  }

  public function acceptboxValidateCallback(array &$form, FormStateInterface $form_state) {
    $ajax_response = new AjaxResponse();

    if (empty($form_state->getValue('accept-box'))) {
      $text = 'You must accept our termes of use to continue';
      $color = 'red';
    }

    $ajax_response->addCommand(new HtmlCommand('#edit-accept-box--description', $text));

    $ajax_response->addCommand(new InvokeCommand('#edit-accept-box--description', 'css', ['color', $color]));

    return $ajax_response;
  }

}

It works very well. But Ajax validation only works when I am connected. When I am not logged in as an administrator, it does not work.

Here is the block to display the form in my footer.

namespace Drupal\dalcom_contact_block\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormInterface;

/**
 * Provides a 'dalcom contact' block.
 *
 * @Block(
 *   id = "dalcom_contact_block",
 *   admin_label = @Translation("Dalcom Contact Block"),
 *   category = @Translation("Block du formulaire Dalcom Contact")
 * )
 */
class DalcomContactBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $form = \Drupal::formBuilder()->getForm('\Drupal\dalcom_contact\Form\DalcomContactForm');
    return $form;
  }
}

Here is the module.routing.yml file

dalcom_contact.form:
  path: '/contact-us.html'
  defaults:
    _title: 'Contact Us'
    _form: 'Drupal\dalcom_contact\Form\DalcomContactForm'
  requirements:
    _permission: 'access content'

block.info.yml

name: Dalcom Contact Block
type: module
description: Block du formulaire Dalcom Contact.
core: 8.x
package: Custom
dependencies:
- node
- block

Does anyone have any idea what could cause this? Please help me.

Remember the page you were on and take you back there when switching Workspaces

$
0
0

Problem/Motivation

Remember the page you were on and take you back there when switching Workspaces.

Proposed resolution

- Set a destination query string for the workspace button in hook_toolbar in workspace.module
- Set a destination query string for the workspace activate form in WorkspaceListBuilder
- Remove the redirect from \Drupal\workspace\Form\WorkspaceActivateForm::submitForm
- Find a way to bypass the caching of the link in hook_toolbar

Remaining tasks

User interface changes

API changes

Data model changes

FAPI #radios form elements do not have an accessible required attribute

$
0
0

Problem/Motivation

The #radios elements that are provided by core do not apply the required attribute to the generated <input> elements. Instead the required attribute is applied to the wrapping <fieldset>.

There are two issues with this:

  1. screen readers use required attribute on <input type="radio">. If the attribute is not present on the , then the required state will not be communicated to the screen reader user.
  2. the required attribute is not valid when applied to a <fieldset>, thus causing the page to fail W3C validation.

Proposed resolution

  1. Remove the required and aria-required attributes from the <fieldset> of Form API #radios elements.
  2. Add (aria-)required attribute to the <input type=radio> elements instead.
  3. CSS updates, to ensure no visual regression in Seven and Bartik.

Remaining tasks

  • DONE. Remove required + and aria required attributes from the <fieldset> element to the <input> element.
  • CSS to avoid visual regression. Asterisk should be after the fieldset legend, not the individual radio buttons.
  • Evaluate impact on Classy - Can the CSS go into Classy?
  • Tests?

Manual testing tips

We need a required #radios element to test this, e.g. add a "favourite colour" field to a content type. Use a field of type "List", mark it required, and use the radios/checkboxes widget under "manage form display".

User interface changes

Markup + CSS changes to

  1. Fix invalid HTML
  2. Convey required radio buttons correctly to assistive tech.
  3. Avoid visual regression.

API changes

None.

Data model changes

None.

Original report by @mfairchild365

This issue is split off from #2950999: FAPI #checkboxes form elements do not have an accessible required attribute. That issue originally addressed #radios and #checkboxes, but it looks like they need different solutions, so we're using separate issues now.

AJAX filter submission results in form's action attribute being rewritten to '/views/ajax'

$
0
0

When a view is setup to use the "Embed" display in a view, using AJAX in the form in any way will cause the action attribute of the HTML form object to be rewritten to submit to '/views/ajax' instead of the current page. This issue is harmless unless the filter in your embedded view uses the Reset button to clear the form and reload the page. When the Reset button is pressed, it'll direct you to /views/ajax instead of your current page.

A variation of this bug is if you have both a Page display setup and an Embed display setup in the view. If both of these displays exist in the same view, then the form's action attribute for the filter in the Embed display will be rewritten to submit to whatever path you setup for the Page display. I'll use this more elaborate scenario in my steps below.

To reproduce this bug:

  1. Create a new view named "Ajax Test"
  2. Change the format to Table. In the settings make the title field sortable
  3. Edit the Title field to give it a label of "Title"
  4. Add the Title field to the Filter Criteria with the filter configured to use the Contains operator. Check the "Expose this filter to visitors" box.
  5. Under Advanced Options, enable AJAX for this view
  6. In the Exposed Form options, make sure Basic is chosen as the type and in the settings check off the box that inserts a Reset button.
  7. Add a "Page" display to this view. Keep all the same settings. Only edit the path for the Page display. Use "/wrong-endpoint" as the path
  8. Save the view

Now we need to embed this view into a page. I'm going to use the Page Example module from the Drupal Examples for Developers set of modules for the dummy page needed to create an embedded view display, but it can be embedded in other ways and would still work the same.

  1. Install and enable the Page Example module to create a sample page we can embed into.
  2. Open 'Drupal\page_example\Controller\PageExampleController'
  3. Edit the description method and append the following before the "return $build" line:

    $build['test'] = views_embed_view('ajax_test', 'embed_1');

Go to the example page at '/examples/page-example'. Your embedded view should be there with the exposed filter. Inspect the HTML form object. The action attribute at this time should be '/examples/page-example'.

Now use the exposed filter to filter the table results. The results will narrow to match your search terms and the "Reset" button will appear. Inspect the form object again. The form will now submit to '/wrong-endpont'. The AJAX parts of the view will continue to work. You can use the table header sort. You can use new search terms and your results will filter as expected, but if you press the Reset button, you'll be redirected to the '/wrong-endpoint' page that was created as a Page type of display for this view.

If you skipped that step of creating the Page type display, and your AJAX Test view only has an Embed display, you will instead get redirected to /views/ajax.

This issue does not occur if the view in question is not an embedded view. If you try to repeat this behavior on the Views Page that we created at /wrong-endpoint, you will get the correct behavior. The form's action attribute will not get changed to direct to the wrong page when AJAX rebuilds the form.

Allow AJAX to use GET requests

$
0
0

Problem summary

AJAX requests are always made using POST, which disables render caching.

However most AJAX requests could be cached safely, and the POST requirement was previously due to the large amount of information sent with the request - mainly ajax_page_state containing css/js and html IDS.

Now that libraries are used in place of individual css and js, and html IDS are no longer sent, it should be possible to switch to GET requests safely.

Proposed solution

Allow AJAX requests to use GET. Continue to default to POST and make this opt-in for backwards compatibility.

Convert at least one core AJAX request to use GET.

Original report

  • AJAX request size is very large. Out of the box in Drupal core it can be around 5k, on a reasonable site build using some contrib modules I have seen 15k+ HTTP requests. The size of the request is directly related to the number of DOM elements with id attributes on a given page and the original number of css/javascript files for the page (ie, css/js aggregation has no effect).
  • Problem #1: AJAX framework cannot be used with HTTP GET as such a large HTTP request payload requires POST to handle such a large request body. Trying to use GET quickly fails due to URL length limits.
  • Problem #2: This is a performance issue. As described here minimizing HTTP request size is good practice for high performance, and HTTP request sizes are generally talked about in terms of bytes, not kilobytes.

Why is the AJAX request so large?

The changes introduced by #561858: [Tests added] Fix drupal_add_js() and drupal_add_css() to work for AJAX requests too by adding lazy-load to AJAX framework added some killer functionality to the AJAX framework. Unfortunately, it also greatly increasing the size of requests made by the browser back to Drupal.

Currently every AJAX request made back to Drupal contains two pieces of information that can be very large on even a simple Drupal site and are likely to grow very quickly as additional modules and site building is done:

  1. ajax_html_ids is an array of every HTML element's id attribute collected by ajax.js before making the HTTP request. These are used by drupal_html_id() to ensure that when the AJAX response is delivered it contains unique HTML ids and not ones that may conflict with existing ids in the DOM.

  2. ajax_page_state, amongst other things, contains two large arrays -- a full set of css file paths and js file paths that were served with the original page. These are used in ajax_render() to ensure that only new css/js assets are delivered with the AJAX response and not force a client-side reload of every css/js asset. Note that the size of this list is not mitigated by css/js aggregation -- it is intentionally a list of "original" assets even if the page is using an aggregated css or js file.

I ran into this issue when updating Views (see #591302: Rewrite ajax_view.js based on ctools AJAX) and attempting to use HTTP GET with the AJAX framework.

Possible solution

Drop ajax_html_ids and full list of css/js files in ajax_page_state from AJAX requests:

  • Switch drupal_html_id() from using integer increments to a randomized short hash. Makes collision between requests extremely unlikely and drops the need for ajax_html_ids in the request.
  • Generate a page state css hash and js hash for any given array of css/js files. Store it in the cache table. Transfer this in ajax_page_state instead of the full list of CSS/JS files, e.g.

    ajax_page_state.css = 'fj519x9029120x ...'; // Some real hash
    ajax_page_state.js = '9810b0za121jkl ...';  // Some real hash
    

    Upon receiving an AJAX request, use cached list of css/js files looked up by page state hashes. Eliminates the need for client to send the list of css/js files back to Drupal.

This plan is implemented in the attached patch.

Some numbers

HTTP POST for the &lt;create new book&gt; dropdown on node/add/article

  • D7 HEAD: 6156 bytes
  • With patch: 1003 bytes

HTTP GET using Views AJAX pager on test_view

  • D7 HEAD: 4399 bytes
  • With patch: 421 bytes

Layout builder's "Add Block" sidebar menu UX improvements

$
0
0

Problem/Motivation

I am still having trouble showing customers the Layout Builder re: adding inline blocks to landing pages. They're confused. I want them to build using inline blocks as I believe this is the common "Squarespace/Wix/SaaS cms" type workflow that people ask for (landing page node with inline blocks). Not all content should be this way in Drupal, sure, but there's a big internet out there and we want Drupal to crack the DXP space as best it can. This means supporting building landing pages and making this UX as easy as possible. The problems we see:

1. The CTA is dark, and often overlooked
2. The CTA text "Create Custom Block" feels more like a Drupalism than UX for everybody.
3. The existing block search and fieldset listings aren't labeled so its unclear what they do.

Proposed resolution

1. Change the CTA to use the Drupal blues from core. Normal state, #5181c6, Hover state. #004875 - I found these colors in /core/misc/icons

2. Change the CTA text and add accessibility text. What I've done in this patch is change the text to "Add new block" which lines up much more cleanly with "Add a new Inline Block" (the text you see once you click on "Add Custom Block" currently) - I also added a "title" to the link retaining the call that loads the bundle name for the help text.

3. Add an "item" to the form that serves as a guide/label for the existing blocks. It says "Add existing block"

The changes look like this:

layout builder inline block add ux changes

Remaining tasks

Reviews needed, discussion requested

User interface changes

Minor form item and CSS changes to the Layout Builder "Add Block" controller (modules/layout_builder/src/Controller/ChooseBlockController.php)

Data model changes

N/A

Release notes snippet

Improved UX of Layout Builder's "Add Block" menu

Original report by brantwynn on github.com/acquia/df

https://github.com/acquia/df/issues/131


Document DrupalKernel::findSitePath()

$
0
0

DrupalKernel::findSitePath() is the successor of D7's conf_path(). It contains a code blurb that

So people (like me) who are debugging some sites.php related stuff will come across this code and go cross-eyed. Personally, after I deciphered what it does in detail and read it again 3 months later... I have forgotten the details by then and need to start deciphering again.

I don't want to touch this code... I just want to insert comments in here to break that cycle.

Make Workspaces and Content Moderation work together

$
0
0

Problem/Motivation

At the moment, the Workspaces module can not be installed if Content Moderation is also installed, see #2971699: Content Moderation and Workspace don't work together.

After #3027598: Omit workspaces entity presave and predelete hooks for internal entities is done, there is very little work needed to make them compatible.

Proposed resolution

Remove the 'latest-revision' link template when both Workspaces and Content Moderation are installed, because Workspaces always shows the active revision on the canonical page of an entity, so the latest revision tab is not needed.

Make Content Moderation skip and pre-save logic if an entity is syncing, for example when it is being published from a non-default workspace to the Live one.

Remaining tasks

Add test coverage.

User interface changes

The Latest revision tab will not be shown when both Workspaces and Content Moderation are installed.

API changes

Nope.

Data model changes

Nope.

Release notes snippet

Workspaces and Content Moderation are no longer incompatible and can be installed and used together. Advanced workflows like moderating an entire workspace are possible as well.

Mechanism to disable preprocessing of base fields in non-node entity types so they can be configured via the field UI

PageTitle block is non-functional when not handled directly by \Drupal\block\Plugin\DisplayVariant\BlockPageVariant

$
0
0

Problem/Motivation

Page titles in Drupal are determined in two different ways.
One is via the title_resolver service, which delegates to the route.
The other is by inspecting the render array of the main content of the page for a top-level #title key.

While the first approach can be used by any code in Drupal, the #title approach is only available at the very end of the rendering process.
The only code that gets access to the real title is whichever @PageDisplayVariant plugin is used to render the page.

The block.module provides a @PageDisplayVariant plugin that passes on the title directly to the page_title_block block.

Without any code setting the title directly on that block, it will always print an empty string.

Since there can only be one @PageDisplayVariant plugin selected at a time, this means that only one module can have access to the true actual title (in the case of a #title being used).

Proposed resolution

There are two approaches to be considered here.

First, the page_title_block block should use the title_resolver service as a fallback when setTitle() is not called.
This still allows the block.module usecase to properly respect the #title if applicable.
All non-block.module usages will not have that title, but the routing-based title.

This is acceptable as using the page title block within Layout Builder is rare, and using a top-level #title is also very rare, and unlikely to occur on a page using Layout Builder.

Furthermore, with #2359901: Discourage $main_content['#title'] in favor of route titles and title callbacks as a major task, eventually the #title approach will no longer be used.

If this approach is not acceptable, then Layout Builder can use hook_plugin_filter_TYPE__CONSUMER_alter() to remove the page title block from being placeable by Layout Builder. Each contrib solution that also has encountered this problem will also have to implement that hook for their own CONSUMER case.

Remaining tasks

Get sign-off on the proposed resolution above, or abandon it for the backup solution.

User interface changes

The page title block will function the same as before for block.module usages.
For alternate usages, the block will no longer be empty. It will contain the title for that route. It will not display the correct title if the top-level render array contains a #title key (aka Views Pages).

API changes

N/A

Data model changes

N/A

#states doesn't work correctly with type text_format

$
0
0

When using type "text_format", it generates a textarea and the filter form fieldset.
But in html, fieldset element is out of the div .form-item.
When you add #states on this element, it apply only to .form-item and not on fieldset.

One solution could be to add parents jquery function on states.js to the text-format-wrapper ?, sample line 372:

$(e.target).parents('.text-format-wrapper')[e.value ? 'show' : 'hide']();

But i'm not sure it's a good way...

An other solution could be to change the way the text_format is render to add filter form fieldset in the div.form-item ?

Or perhaps you can consider it's not a bug and text_format need to be in a container or a fieldest to get states working.

Regards
Mog.

Viewing all 291486 articles
Browse latest View live


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