title: Show message after redirection

text:
# Question
Title: Show message after redirection
This will be mostly a Drupal question rather may not have any relation to Drupal commerce checkout.

I have an Offsite Checkout redirect payment method in which I have a `buildRedirectFrom` as stated in https://docs.drupalcommerce.org/commerce2/developer-guide/payments/create-payment-gateway/off-site-gateways/off-site-redirect which will redirect to a vendor site for payment. I have the `CompleteUrl` which will come back the call to the controller method after payment completion.

I need to show a custom error message after redirecting to the checkout page, when the `payment fails` or `canceled` the payment based on the status I receive from vendor API.

But somehow the message is not showing up after the redirection. I tried to show the message first and then redirect too. Is there any solution in Drupal or particularly in commerce for this?

# My try

In controller method:

```
if( $statusFromAPI != 'PAYSUCCESS' ){
        $redirect = new RedirectResponse('/checkout/' .$order_id . '/review');
        $redirect->send();
        if($statusFromAPI == 'ERROR'){
          $this->messenger()->addError("Payment has been failed. Please check the payment details.", TRUE);
        } else if($statusFromAPI == 'PAYSTART'){
          $this->messenger()->addWarning("Please review the payment details again.");
        } else{
          $this->messenger()->addWarning("Please review the payment details.", TRUE);
  }

```

# Answer
A controller has to return the result, this includes the redirect response. But before you have to set the message:

```
$redirect = new RedirectResponse('/checkout/' . $order_id . '/review');
$this->messenger()->addWarning('This is a warning!');
return $redirect;

```

BTW in Drupal it's not allowed to send responses. If you are in a form you can set it in $form\_state, in an event subscriber set it in the event if it is one of the three main Symfony kernel events.
> 1 votes

---
Tags: commerce, 9, redirection, status-messages
---


title: How to mass-unpublish nodes?

text:
# Question
Title: How to mass-unpublish nodes?
I have a site with a tremendous number of nodes of various content types. I want to set them all to unpublished, and I don't see a way to do that easily without going through page after page after page of content pieces.

I was thinking of doing a query directly on the database: `UPDATE node SET published = 0;` -- but will this correctly unpublish all content?

**Edit:** We're dealing with several thousand nodes, and as I understand, there's a hard-coded limit of 50 nodes displayed on the bulk edit page. So I am trying to avoid flipping through dozens of pages.

# Answer
If you want unpublish all nodes, quick and dirty method is simple sql query `UPDATE node SET status = 0;` Then clear cache and its done. But if you use Views, they could still show unpublish content depends on settings.
> 11 votes

# Answer
If you do not want to do this through SQL, the Content Management Filter module allows you to filter your content greatly, and determine how many rows are displayed on a page (therefore, allowing you to do bulk operations with ease).

Another module worth checking is Views Bulk Operations (aka VBO). It'll make it easy to create a view entirely geared towards bulk updates.
> 5 votes

# Answer
I am going to throw out one more option.

Write a test script that

1. Bootstraps.
2. Queries the database to find the nids you want to unpublish, then loops over the nids
3. $node = node\_load($nid);
4. $node-\>status = 0;
5. node\_save($node);

Depending on your version of Drupal, you may be able to optimize this with node\_load\_multiple(). Just be sure you have enough memory available and you adjust execution time, if necessary.

Doing it this way should take care of any housekeeping that the node\_save() fires.
> 2 votes

# Answer
On the Find Content page at `admin/content` there's an option for you to do bulk updates including unpublishing of selected nodes. See http://www.gingerfeet.net/drupal-userguide-siteadmin-node

If this doesn't suit your needs, you might want to also look into Views Bulk Operations module.
> 1 votes

# Answer
In Drupal 8 (same in Drupal 7), one of the best ways to mass-unpublish nodes is to do something like the following:

```
$nodes = node_load_multiple($nids, TRUE);
foreach ($nodes as $nid => $node) {
  $node = $node->setPublished(FALSE);
  $node->save();
}

```

(Assuming you have an array of `$nids` to begin with.)

Note that we set `TRUE` for the node\_load\_multiple `$reset`, to conserve memory if there are hundreds or thousands of nodes being operated on.

If you need to do it in a place where there's a normal page load/UI, it would be best to use Batch API to batch the operation... but use the same code as above inside the batch.
> 1 votes

# Answer
Install the Admin\_Views module (which is a requirement on all my sites anyway) and then you can use the /admin/content menu to select all Published nodes and bulk-change them to Unpublished. It uses VBO so the interface should be pretty natural (Just look for the "Select all #### nodes" button above the content when you click the SELECT ALL checkbox to do more than 50 at a time). It will use the normal Drupal hooks so it will take longer than an "UPDATE nodes SET status=0" but won't have any bizarre side effects.
> 0 votes

# Answer
I would recommend to use VBO or entity actions as other people suggested in this issue. But if you need publish/unpublish entities via drush then here is a custom drush command for that.

```
  /**
   * Update entities.
   *
   * @command mymodule:eup
   * @aliases mymodule-eup
   */
  public function updateEntities(string $entityType, string $bundle, string $op) {
    if (!in_array($op, ['publish', 'unpublish'])) {
      $this->logger()->notice("Only 'publish' or 'unpublish' methods supported.");
      return;
    }
    /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
    $storage = \Drupal::entityTypeManager()->getStorage($entityType);

    $query = $storage->getQuery()->accessCheck(FALSE);
    $query->condition('type', $bundle);
    $ids = $query->execute() ?? [];
    $ids = array_values($ids);

    if (count($ids) === 0) {
      $this->logger()->notice('No entities found with specified bundle');
      return;
    }

    $entity = $storage->load(current($ids));

    if (!$entity instanceof EntityPublishedInterface) {
      $this->logger()->notice("Entity type doesn't support status update.");
      return;
    }

    $count = 0;
    $processed = 0;
    $skipped = 0;

    $progress = new ProgressBar($this->output(), count($ids));
    $progress->start();

    foreach ($ids as $entityId) {
      $entity = $storage->load($entityId);

      $op === 'publish'
        ? $entity->setPublished()
        : $entity->setUnpublished();

      try {
        $entity->save();
        $processed++;
      }
      catch (\Exeption $e) {
        $this->logger()->error($e->getMessage());
        $skipped++;
      }

      // Reset entity cache to prevent memory limit issues.
      if ($count > 10) {
        $storage->resetCache();
        $count = 0;
      }
      else {
        $count++;
      }
      $progress->advance();
    }

    $progress->finish();
    $this->output->writeln('');

    $this->logger()->notice('Processed entities: ' . $processed);
    if ($skipped > 0) {
      $this->logger()->notice('Skipped entities: ' . $skipped);
    }
    return;
  }

```

Example to run: `drush mymodule-eup node event publish`.

Alternativelly you can copy method's code (you need to delete logger/progress methods) into standalone php script and run it with `drush php:script`.
> 0 votes

---
Tags: nodes
---


# Question
Title: Discount for emails with specific domain
I am trying to apply a discount automatically for customers who sign up using emails from partner companies. I tried using the conditions section with * or % as a wildcard, but that did not work

Any suggestions?

# Answer
This is not possible in the current state of the plugin (`OrderEmail`) that provides this condition. It uses an email element, meaning the Drupal Forms API will validate input to ensure it's an email address, ruling out any sort of wildcard inclusion. I'm going to open a feature request against the module, as I believe converting this to a textfield and revising `OrderEmail::evaluate()` to support wildcard matching can be implemented in a backwards compatible fashion.

Feedback welcome, as I'm not sure if we should support more than just a leading wildcard to match against any address from a specific domain or support more complex arrangements:

https://www.drupal.org/project/commerce/issues/3390184
> 1 votes

---
Tags: commerce
---


# Question
Title: Using views_query_alter() hook to dynamically add a OR "where" to a Search API View?
We have a Search API View that we need to dynamically include results to the query that where filtered out.

The use case is that the Search Index View shows a filtered list of node but we have a checkbox to "Include National Listings" where nodes that are marked as "National" should show in the results even if the do not meet the current search or facet filters.

The below code is probably on the right track but it filters all results and produces no output:

```
 if ($view->id() == 'services_search_index'){

    $query->setGroupOperator('OR');
    $query->setWhereGroup('OR', 1);
    $operator = '=';
    $field = 'field_resource_location_type';
    $value = 'National';
    $query->addWhere(1, $field, $value, $operator);

  }

```

Here's the Views Query output with the above alter added:

```
Index: services
Keys: NULL
Conditions:
  field_resource_location_type = 'National'
Sorting: administrative_area ASC, title ASC
Options: array (
    'search_api_view' => 'object (Drupal\\views\\ViewExecutable)',
  )

```

# Answer
> 0 votes
You may be overwriting your original "where" by forcing the index of 1. The method setWhereGroup() will return a unique Where group id if you don't specify one.

```
if ($view->id() == 'services_search_index') {
  // Accept any where group success.
  $query->setGroupOperator('OR');
  // Get a unique where group id.
  $groupId = $query->setWhereGroup('AND');
  $operator = '=';
  $field = 'field_resource_location_type';
  $value = 'National';
  // Add a new condition group for filtering.
  $query->addWhere($groupId, $field, $value, $operator);
}

```

---
Tags: views, search
---


# Question
Title: Unable to upgrade from Drupal 9.5.10 to 10.1.1
I'm stuck on my efforts to upgrade my sites (I have 5 in total that I manage) from Drupal 9.5.10 to 10.1.1. I'm using PHP 8.1.8.

I'm following the instruction from https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-a-composer-based-site.

Upgrade Status gives me two problems:

* **Dynamic Entity Reference**: there is no version compatible with both 9.5.10 and 10 so I've followed the instructions in the same document mentioned above and edited my composer.json to have this line under "require" (originally it made reference only to "2.0@alpha"):

"drupal/dynamic\_entity\_reference": "^2.0@alpha || ^4.0@alpha",
* **CKEditor 5 Anchor**: this is a custom module and the messages from upgrade status are shown below. Yet, from reading other articles, I'm disregarding them. Should I do something? This is the error:

PHPStan command failed: /usr/local/bin/php /var/www/vendor/bin/phpstan analyse --memory-limit=1500M --error-format=json --configuration=/tmp/upgrade\_status/deprecation\_testing.neon /var/www/docroot/modules/custom/ckeditor5\_anchor

Command output: Empty.

Command error: ! \[NOTE\] No files found to analyse. \[WARNING\] This will cause a non-zero exit code in PHPStan 2.0.

This is my composer.json, after running the instructions in the documentation mentioned above, which updates the entries for drupal/core-xxx and drupal/recommended-project, as well as the change mentioned above for the Dynamic Entity Reference module:

```
{
    "name": "rru/drupal",
    "description": "Project template for Drupal 9 projects with a relocated document root",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "homepage": "https://www.drupal.org/project/drupal",
    "support": {
        "docs": "https://www.drupal.org/docs/user_guide/en/index.html",
        "chat": "https://www.drupal.org/node/314178"
    },
    "repositories": {
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        "dropzone-js": {
            "type": "package",
            "package": {
                "name": "dropzone/dropzone",
                "version": "5.7.2",
                "type": "drupal-library",
                "dist": {
                    "type": "zip",
                    "url": "https://github.com/dropzone/dropzone/archive/v5.7.2.zip"
                }
            }
        },
        "jquery-ui-touch-punch": {
            "type": "package",
            "package": {
                "name": "furf/jquery-ui-touch-punch",
                "version": "1.0",
                "type": "drupal-library",
                "source": {
                    "url": "https://github.com/furf/jquery-ui-touch-punch.git",
                    "type": "git",
                    "reference": "master"
                }
            }
        },
        "ckeditor-fakeobjects": {
            "type": "package",
            "package": {
                "name": "ckeditor/fakeobjects",
                "version": "4.16",
                "type": "drupal-library",
                "dist": {
                    "type": "zip",
                    "url": "https://download.ckeditor.com/fakeobjects/releases/fakeobjects_4.16.0.zip"
                }
            }
        },
        "ckeditor-indent-block": {
            "type": "package",
            "package": {
                "name": "ckeditor/indentblock",
                "version": "4.15",
                "type": "drupal-library",
                "dist": {
                    "type": "zip",
                    "url": "https://download.ckeditor.com/indentblock/releases/indentblock_4.15.0.zip"
                }
            }
        },
        "ckeditor-link": {
            "type": "package",
            "package": {
                "name": "ckeditor/link",
                "version": "4.16",
                "type": "drupal-library",
                "dist": {
                    "type": "zip",
                    "url": "https://download.ckeditor.com/link/releases/link_4.16.0.zip"
                }
            }
        },
        "ckeditor-youtube": {
            "type": "package",
            "package": {
                "name": "ckeditor/youtube",
                "version": "2.1.18",
                "type": "drupal-library",
                "dist": {
                    "type": "zip",
                    "url": "https://download.ckeditor.com/youtube/releases/youtube_2.1.18.zip"
                }
            }
        },
        "ew-packagist": {
            "type": "composer",
            "url": "https://packagist.ewdev.ca",
            "canonical": true
        },
        "asset-packagist": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    },
    "replace": {
        "drupal/ckeditor": "*"
    },
    "require": {
        "acquia/blt": "^13.0",
        "acquia/memcache-settings": "^1.1",
        "behat/behat": "^3.8",
        "behat/mink": "^1.8",
        "behat/mink-extension": "^2.3",
        "ckeditor/fakeobjects": "^4.16",
        "ckeditor/indentblock": "^4.15",
        "ckeditor/link": "^4.16",
        "ckeditor/youtube": "^2.1",
        "composer/installers": "^2.2",
        "cweagans/composer-patches": "^1.7",
        "dropzone/dropzone": "^5.7.2",
        "drupal/acquia_purge": "^1.2",
        "drupal/admin_toolbar": "^3.2",
        "drupal/admin_toolbar_tools": "^3.0",
        "drupal/administerusersbyrole": "^3.0",
        "drupal/animated_gif": "^2.0",
        "drupal/better_exposed_filters": "^6.0",
        "drupal/chosen": "^4.0",
        "drupal/clientside_validation": "^4.0",
        "drupal/conditional_fields": "^4",
        "drupal/config_filter": "^2.4",
        "drupal/config_ignore": "^3.0@beta",
        "drupal/config_split": "^2.0@RC",
        "drupal/contact_emails": "^1.20",
        "drupal/contact_storage": "^1.1",
        "drupal/core-composer-scaffold": "^10",
        "drupal/core-project-message": "^10",
        "drupal/core-recommended": "^10",
        "drupal/ctools": "^4.0",
        "drupal/devel": "^5.1",
        "drupal/diff": "^1.0",
        "drupal/draggableviews": "^2.0",
        "drupal/dropzonejs": "^2.5",
        "drupal/drupal-extension": "^4.1",
        "drupal/dynamic_entity_reference": "^2.0@alpha || ^4.0@alpha",
        "drupal/easy_email": "^2.1@beta",
        "drupal/editor_advanced_link": "^2.2",
        "drupal/entity_browser": "^2.5",
        "drupal/entity_usage": "^2.0@beta",
        "drupal/field_group": "^3.1",
        "drupal/file_delete": "^2.0",
        "drupal/filter_perms": "^1.0@alpha",
        "drupal/google_tag": "^2.0",
        "drupal/honeypot": "^2.0",
        "drupal/link_attributes": "^2.0",
        "drupal/linkit": "^6.0@beta",
        "drupal/mail_safety": "^2.0",
        "drupal/mailsystem": "^4.3",
        "drupal/maxlength": "^2.1",
        "drupal/media_bulk_upload": "^3.0",
        "drupal/media_entity_file_replace": "^1.0",
        "drupal/memcache": "^2.3",
        "drupal/menu_block": "^1.6",
        "drupal/menu_breadcrumb": "^2.0@alpha",
        "drupal/metatag": "^2.0",
        "drupal/mimemail": "^1.0@alpha",
        "drupal/node_edit_protection": "^1.0",
        "drupal/node_title_help_text": "^1.2",
        "drupal/onpoint_search": "^1.2",
        "drupal/paragraphs": "^1.12",
        "drupal/pathauto": "^1.8",
        "drupal/rabbit_hole": "^2.0@alpha",
        "drupal/recaptcha": "^3.0",
        "drupal/recommended-project": "^10",
        "drupal/redirect": "^1.6",
        "drupal/scheduled_transitions": "^2.4@beta",
        "drupal/seckit": "^2.0",
        "drupal/sendgrid_integration": "^2.1",
        "drupal/shield": "^1.6",
        "drupal/simple_sitemap": "^4.1",
        "drupal/stage_file_proxy": "^2.1",
        "drupal/svg_image": "^3.0",
        "drupal/swiftmailer": "^2.0",
        "drupal/symfony_mailer": "^1.2",
        "drupal/tablefield": "^2.2",
        "drupal/token": "^1.9",
        "drupal/twig_field_value": "^2.0",
        "drupal/twig_tweak": "^3.0",
        "drupal/ultimate_cron": "^2.0@alpha",
        "drupal/upgrade_status": "^4.0",
        "drupal/username_enumeration_prevention": "^1.2",
        "drupal/views_bulk_operations": "^4",
        "drupal/views_infinite_scroll": "^2.0",
        "drupal/viewsreference": "^2.0@beta",
        "drupal/webform": "^6.2@beta",
        "drush/drush": "~11.0",
        "evolvingweb/drupal-ci": "^1",
        "furf/jquery-ui-touch-punch": "^1.0"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "acquia/blt": true,
            "composer/installers": true,
            "cweagans/composer-patches": true,
            "dealerdirect/phpcodesniffer-composer-installer": true,
            "drupal/core-composer-scaffold": true,
            "drupal/core-project-message": true,
            "oomphinc/composer-installers-extender": true,
            "phpstan/extension-installer": true
        }
    },
    "extra": {
        "enable-patching": true,
        "patches": {
            "drupal/tablefield": {
                "enable rich text editor for table cell : https://www.drupal.org/project/tablefield/issues/3076448": "https://www.drupal.org/files/issues/2023-01-27/reroll_wysiwyg_support_3076448_30.patch",
                "Fix for import csv": "./patches/tablefield/fix-csv-import-issue.patch"
            },
            "drupal/contact_storage": {
                "get all options -including dynamic callback- instead of just static allowed_values": "./patches/contact_storage/options_allowed_values_function.patch",
                "Undefined index notice": "https://www.drupal.org/files/issues/2021-01-12/3191567-9.patch"
            },
            "drupal/paragraphs": {
                "https://www.drupal.org/project/paragraphs/issues/2973358#comment-13756793 ": "https://www.drupal.org/files/issues/2020-07-21/paragraphs-widget-ellipsis-title-2973358-4_1.patch"
            },
            "drupal/honeypot": {
                "getProtectedForms returns null": "patches/fix-null-protected-forms.patch"
            },
            "drupal/file_delete": {
                "#3115158 Add functionality to immediately delete files and override usage check": "https://www.drupal.org/files/issues/2022-10-10/3115158-instant-delete-25.patch"
            },
            "drupal/core": {
                "CKEditor5 indent.IndentBlock plugin": "patches/core/core_ckeditor5_indent_block.patch"
            },
            "drupal/onpoint_search": {
                "#3297757 Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2022-07-18/onpoint_search.1.2.5.rector.patch",
                "Drupal 10 Info File fix": "./patches/onpoint_search/fix-d10-info-file.patch"
            }
        },
        "drupal-scaffold": {
            "locations": {
                "web-root": "docroot/"
            },
            "file-mapping": {
                "[web-root]/sites/development.services.yml": false,
                "[web-root]/sites/default/default.services.yml": false,
                "[web-root]/.htaccess": false
            }
        },
        "installer-paths": {
            "docroot/core": [
                "type:drupal-core"
            ],
            "docroot/libraries/{$name}": [
                "type:drupal-library"
            ],
            "docroot/libraries/ckeditor/plugins/{$name}": [
                "type:drupal-ckeditor-plugin"
            ],
            "docroot/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "docroot/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "docroot/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "docroot/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "docroot/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "docroot/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        }
    },
    "require-dev": {
        "kint-php/kint": "^5.0",
        "kint-php/kint-twig": "^5.0",
        "palantirnet/drupal-rector": "^0.15.1",
        "rector/rector": "~0.15.2"
    }
}

```

After following the instructions from the document I cited above, this is what I get when running composer update:

```
        Gathering patches for root package.
        Loading composer repositories with package information
        Updating dependencies
        Your requirements could not be resolved to an installable set of packages.

          Problem 1
            - drupal/core 8.0.0-beta6 requires doctrine/common dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5 -> found doctrine/common[dev-remove-int-cast, dev-deprec-proxy, 2.1.3, ..., 2.13.x-dev, 3.0.0, ..., 3.5.x-dev] but it does not match the constraint.
            - drupal/core[8.0.0-beta13, ..., 8.0.0-beta15] require guzzlehttp/guzzle dev-master#1879fbe853b0c64d109e369c7aeff09849e62d1e -> found guzzlehttp/guzzle[v1.0.3, v1.0.4, v2.0.0, ..., v2.8.8, v3.0.0, ..., v3.8.1, 4.0.0-rc.1, ..., 4.x-dev, 5.0.0, ..., 5.3.x-dev, 6.0.0, ..., 6.5.x-dev, 7.0.0-beta.1, ..., 7.7.x-dev] but it does not match the constraint.
            - drupal/core[8.9.11, ..., 8.9.x-dev] require php ^7.0.8 -> your php version (8.1.8) does not satisfy that requirement.
            - drupal/core[9.0.10, ..., 9.0.x-dev] require php ^7.3 -> your php version (8.1.8) does not satisfy that requirement.
            - rru/drupal is present at version dev-master and cannot be modified by Composer
            - drupal/core-recommended 10.0.0-alpha7 requires drupal/core 10.0.0-alpha7 -> satisfiable by drupal/core[10.0.0-alpha7].
            - Conclusion: don't install drupal/core 10.0.0-alpha7 (conflict analysis result)
            - drupal/core-recommended 10.1.0-alpha1 requires drupal/core 10.1.0-alpha1 -> satisfiable by drupal/core[10.1.0-alpha1].
            - Conclusion: don't install drupal/core 10.1.0-alpha1 (conflict analysis result)
            - drupal/core-recommended 10.0.0-beta1 requires drupal/core 10.0.0-beta1 -> satisfiable by drupal/core[10.0.0-beta1].
            - Conclusion: don't install drupal/core 10.0.0-beta1 (conflict analysis result)
            - drupal/core-recommended 10.0.0-beta2 requires drupal/core 10.0.0-beta2 -> satisfiable by drupal/core[10.0.0-beta2].
            - Conclusion: don't install drupal/core 10.0.0-beta2 (conflict analysis result)
            - drupal/core-recommended 10.1.0-beta1 requires drupal/core 10.1.0-beta1 -> satisfiable by drupal/core[10.1.0-beta1].
            - Conclusion: don't install drupal/core 10.1.0-beta1 (conflict analysis result)
            - drupal/core-recommended 10.0.0-rc1 requires drupal/core 10.0.0-rc1 -> satisfiable by drupal/core[10.0.0-rc1].
            - Conclusion: don't install drupal/core 10.0.0-rc1 (conflict analysis result)
            - drupal/core-recommended 10.0.0-rc2 requires drupal/core 10.0.0-rc2 -> satisfiable by drupal/core[10.0.0-rc2].
            - Conclusion: don't install drupal/core 10.0.0-rc2 (conflict analysis result)
            - drupal/core-recommended 10.0.0-rc3 requires drupal/core 10.0.0-rc3 -> satisfiable by drupal/core[10.0.0-rc3].
            - Conclusion: don't install drupal/core 10.0.0-rc3 (conflict analysis result)
            - drupal/core-recommended 10.1.0-rc1 requires drupal/core 10.1.0-rc1 -> satisfiable by drupal/core[10.1.0-rc1].
            - Conclusion: don't install drupal/core 10.1.0-rc1 (conflict analysis result)
            - drupal/core-recommended 10.0.0 requires drupal/core 10.0.0 -> satisfiable by drupal/core[10.0.0].
            - Conclusion: don't install drupal/core 10.0.0 (conflict analysis result)
            - drupal/core-recommended 10.0.1 requires drupal/core 10.0.1 -> satisfiable by drupal/core[10.0.1].
            - Conclusion: don't install drupal/core 10.0.1 (conflict analysis result)
            - drupal/core-recommended 10.0.2 requires drupal/core 10.0.2 -> satisfiable by drupal/core[10.0.2].
            - Conclusion: don't install drupal/core 10.0.2 (conflict analysis result)
            - drupal/core-recommended 10.0.3 requires drupal/core 10.0.3 -> satisfiable by drupal/core[10.0.3].
            - Conclusion: don't install drupal/core 10.0.3 (conflict analysis result)
            - drupal/core-recommended 10.0.4 requires drupal/core 10.0.4 -> satisfiable by drupal/core[10.0.4].
            - Conclusion: don't install drupal/core 10.0.4 (conflict analysis result)
            - drupal/core-recommended 10.0.5 requires drupal/core 10.0.5 -> satisfiable by drupal/core[10.0.5].
            - Conclusion: don't install drupal/core 10.0.5 (conflict analysis result)
            - drupal/core-recommended 10.0.6 requires drupal/core 10.0.6 -> satisfiable by drupal/core[10.0.6].
            - Conclusion: don't install drupal/core 10.0.6 (conflict analysis result)
            - drupal/core-recommended 10.0.7 requires drupal/core 10.0.7 -> satisfiable by drupal/core[10.0.7].
            - Conclusion: don't install drupal/core 10.0.7 (conflict analysis result)
            - drupal/core-recommended 10.0.8 requires drupal/core 10.0.8 -> satisfiable by drupal/core[10.0.8].
            - Conclusion: don't install drupal/core 10.0.8 (conflict analysis result)
            - drupal/core-recommended 10.0.9 requires drupal/core 10.0.9 -> satisfiable by drupal/core[10.0.9].
            - Conclusion: don't install drupal/core 10.0.9 (conflict analysis result)
            - drupal/core-recommended 10.0.10 requires drupal/core 10.0.10 -> satisfiable by drupal/core[10.0.10].
            - Conclusion: don't install drupal/core 10.0.10 (conflict analysis result)
            - drupal/core-recommended 10.1.0 requires drupal/core 10.1.0 -> satisfiable by drupal/core[10.1.0].
            - Conclusion: don't install drupal/core 10.1.0 (conflict analysis result)
            - drupal/core-recommended 10.1.1 requires drupal/core 10.1.1 -> satisfiable by drupal/core[10.1.1].
            - Conclusion: don't install drupal/core 10.1.1 (conflict analysis result)
            - drupal/core-recommended 10.0.0-alpha6 requires drupal/core 10.0.0-alpha6 -> satisfiable by drupal/core[10.0.0-alpha6].
            - drupal/core-recommended 10.0.0-alpha5 requires drupal/core 10.0.0-alpha5 -> satisfiable by drupal/core[10.0.0-alpha5].
            - drupal/core-recommended 10.0.0-alpha4 requires drupal/core 10.0.0-alpha4 -> satisfiable by drupal/core[10.0.0-alpha4].
            - drupal/core-recommended 10.0.0-alpha3 requires drupal/core 10.0.0-alpha3 -> satisfiable by drupal/core[10.0.0-alpha3].
            - drupal/core-recommended 10.0.0-alpha2 requires drupal/core 10.0.0-alpha2 -> satisfiable by drupal/core[10.0.0-alpha2].
            - drupal/core-recommended 10.0.0-alpha1 requires drupal/core 10.0.0-alpha1 -> satisfiable by drupal/core[10.0.0-alpha1].
            - drupal/core[8.0.0-beta12, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.4.3, 10.0.0-alpha1, ..., 10.0.0-alpha6] cannot be installed as that would require removing rru/drupal[dev-master]. They all replace drupal/ckeditor and thus cannot coexist.
            - Root composer.json requires drupal/onpoint_search ^1.2 -> satisfiable by drupal/onpoint_search[1.2.0, ..., 1.2.5].
            - drupal/core-recommended 10.1.x-dev requires drupal/core 10.1.x-dev -> satisfiable by drupal/core[10.1.x-dev].
            - Conclusion: don't install drupal/core 10.1.x-dev (conflict analysis result)
            - drupal/onpoint_search[1.2.0, ..., 1.2.5] require drupal/core ^8 || ^9 -> satisfiable by drupal/core[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev].
            - You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev, 10.0.0-alpha1, ..., 10.1.x-dev, 11.x-dev].
            - You can only install one version of a package, so only one of these can be installed: drupal/core[8.7.0-alpha1, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev, 10.0.0-alpha1, ..., 10.1.x-dev, 11.x-dev].
            - drupal/core-recommended 10.0.x-dev requires drupal/core 10.0.x-dev -> satisfiable by drupal/core[10.0.x-dev].
            - Root composer.json requires drupal/core-recommended ^10 -> satisfiable by drupal/core-recommended[10.0.0-alpha1, ..., 10.1.x-dev].

        Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

```

From all those messages, a lot of lines about "older versions" (Drupal core 8, 9), and "satisfiable", which I'm disregarding. From the ones that are left, these are the ones I don't understand:

```
- rru/drupal is present at version dev-master and cannot be modified by Composer
- drupal/core[8.0.0-beta12, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.4.3, 10.0.0-alpha1, ..., 10.0.0-alpha6] cannot be installed as that would require removing rru/drupal[dev-master]. They all replace drupal/ckeditor and thus cannot coexist.

```

Both lines mention "dev-master", which has references only in composer.lock. (I even deleted and recreated it and it's still there.)

Not sure what they mean or how to move forward from here. Any help is appreciated.

# Answer
> 3 votes
I was able to upgrade from 9.5.10 to 10.1.1 using a number of the comments and solutions listed here so just wanted to have it in one place, in case someone else hits the wall like I did:

* First, ensure that your underlying tools are up to date and are compatible with Drupal 10. I'm talking about PHP, Drush, BLT, node, etc (whatever you use)
* Identified two groups of modules: modules that had versions which were only compatible with either Drupal 9 or Drupal 10 (ex: dynamic entity reference); modules for which there were patches for Drupal 10 but were not "officially" compatible with Drupal 10, i.e., in packagist.org were still shown as being compatible only with Drupal 9.
* From the groups above, remove all of those for which it made more sense to remove them now and reinstall them later, than to try and upgrade them. For example, a module with simple or no configuration, and no impact on other modules, might be easer to remove and reinstall later. One example for me was OnPointSearch.
* For the modules that I decided not to remove, I've installed and configured mglaman/composer-drupal-lenient and configured it for all of them. After installing this module, here is an example of a composer command to add a new module to the list of lenient modules:

composer config --merge --json extra.drupal-lenient.allowed-list '\["drupal/dynamic\_entity\_reference"\]'
* In my case I also had to remove the following modules: behat/behat, behat/mink-extension, and drupal/drupal-extension (I've reinstalled them after upgrade)
* I have 5 projects and for some of them, after failing repeatedly on the core upgrade itself, I just "gave up" and ran a `composer require` with the flag **"-W"** for each contributed module (I'm pretty sure the previous administrator didn't use that flag so a few modules had updates available for their dependencies). Yet, I can't be sure which ones (if any) were holding me back.
* Nevertheless, at this point I was able to finally upgrade to D10
* Update all modules you included in your "lenient" list
* Reinstall and configure all modules you removed

If you are using composer (which I'm assuming you are), don't forget to update the database and export the configuration so you can deploy to production.

One last bit of advise: don't forget to inspect your pages on a browser to be sure that not only your custom code but also contributed modules have moved away from the jQuery **"Once"** library in favor of the Drupal library of the same name (the JavaScript code has to be updated accordingly.)

Hope it helps for others. Good luck!

# Answer
> 0 votes
The reason is in the command output:

drupal/onpoint\_search\[1.2.0, ..., 1.2.5\] require drupal/core ^8 || ^9 -\> satisfiable by drupal/core\[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev\].

drupal/onpoint\_search release versions do not support Drupal 10.

# Answer
> 0 votes
You get that error because the OnPoint Search module requires either Drupal 8 or Drupal 9. That causes the error you are seeing when upgrading to Drupal 10.
In fact, its .info.yml contains the following lines (when I posted this answer).

```
name: OnPoint Search
type: module
description: Integrates OnPoint Search into your site.
package: Search
core: 8.x
version: 1.0
configure: onpoint_search.settings
core_version_requirement: ^8 || ^9

```

Telling Composer to apply a patch that changes the required Drupal versions will not work, as Composer first downloads the module checking if one of its releases does not create compatibility issues, and then applies the patches provided in the `patch` section of the *composer.json* file. (To apply a patch, Composer needs to first download the file to patch.)

As for what to do next, I would rather wait the project maintainers make a release for Drupal 10.
Since they do not declare their project to be compatible with Drupal 10, they can make changes that are not compatible with Drupal 10; for example, they could use a class, function, method, or service that has been removed in Drupal 10. As long as the module works on Drupal 9, as per the `core_version_requirement` value, those changes are fine.

# Answer
> -4 votes
In order to update to Drupal 10 with modules that still are not compatible, you can require the drupal core as an older version

```
drupal/core:10.1.1 as 9.5.10

```

When your module are upgraded, you then will be able to remove that.

---
Tags: composer, 10
---


# Question
Title: Why is the Charts module not working for anonymous visitors?
I'm using the Charts module in my project. I've configured Google Chart in my custom view which needs to be shown to anonymous users. The view is shown, but the chart is not rendered for anonymous users.

>

It is shown for logged-in users.

>

Acquia is used. For Graph chart, I've used the storage and feed module.

I changed the view permission to unrestricted and changed the module permission to "allowed for anonymous users" but the chart is still not rendered.

# Answer
> 0 votes
As I've mention, I'm using the storage module for storage entities. So need to give the anonymous user permission to this module too.

Giving anonymous user permission solved the issue.

---
Tags: views, commerce, hooks
---


# Question
Title: Drupal::entityQuery add CASE to have NULL values displayed last
I want to sort some entities in ascending expiration date, but I want those without expiration date to be at the end. Is there a way to add a CASE expression like this to the Drupal::entityQuery?

```
    $entity_query = \Drupal::entityQuery($entity_type)
     ->accessCheck(FALSE)
     ->condition($some_condition)
     ->addExpression("CASE WHEN $table.$sorting_field IS NULL THEN 1 ELSE 0 END")
     ->sort($values)

```

# Answer
> 2 votes
You can add a tag to the entity query, and then use `hook_query_TAG_alter()` to manipulate it when it's been converted to a standard SQL query. e.g.

```
$entity_query = \Drupal::entityQuery($entity_type)
  ->addTag('advanced_sort')
  ->accessCheck(FALSE)
  ->condition($some_condition)
  ->sort($values);

...

function my_module_query_advanced_sort_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  // Add a field for the sort value.
  $alias = $query->addExpression(
    "CASE WHEN $table.$sorting_field IS NULL THEN 1 ELSE 0 END",
    'foo_alias',
    []
  );

  // Sort by it.
  $query->orderBy($alias);
}

```

The docs linked above have some examples on how to determine the alias for `$table`, you'll probably need to inspect the query a bit further to get a reliable value for `$sorting_field`.

---
Tags: entities, database
---


# Question
Title: AJAX doesn't work in custom form element
I want to create a custom form element for email that have a textfield and button and when click button send an email but ajax not working inside form elemen class. I test it in form api and it's ok but when move in form element on button click nothing happend this is my code

```
<?php
/**
 * Created by IntelliJ IDEA.
 * User: peter
 * Date: 24/12/18
 * Time: 13:59
 */

namespace Drupal\aqr_basic\Element;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\FormElement;

/**
 * Provides a form element to display a email.
 *
 *
 * @FormElement("aqr_email")
 */
class EmailElement extends FormElement {

  public function getInfo() {
    $class = get_class($this);
    return [
      '#pre_render' => [
        [$class, 'preRenderSelect'],
      ],
    ];
  }

  public static function preRenderSelect($element) {
    dump($element);
    $email = [
      '#type' => 'email',
      '#title' => $element['#emailTitle'],
    ];
    $email = array_merge($email,$element['email']);
    $btnSendCode = [
      '#type' => 'ajax_button',
      '#value' => $element['#btnSendCodeTitle'],
      '#ajax' => [                  //////this ajax not work
        'callback' => '::email',
        'event' => 'click',
      ],
    ];

    $btnSendCode = array_merge($btnSendCode,$element['btnSendCode']);
    $verifyGroup = [
      '#type' => 'fieldgroup',
      '#attributes' => ['class' => ['hidden']],

    ];
    $verifyGroup['emailCode'] = [
      '#type' => 'textfield',
      '#title' => $element['#emailCodeTitle'],
    ];
    $verifyGroup['emailCode'] = array_merge($verifyGroup['emailCode'],$element['verifyGroup']['emailCode']);
    $verifyGroup['btnVerifyCode'] = [
      '#type' => 'ajax_button',
      '#value' => $element['#btnVerifyCodeTitle'],
      '#suffix' => '<div class="verification-desc email_verify">' . $element['#description'] . '</div>',
    ];
    $verifyGroup['btnVerifyCode'] = array_merge($verifyGroup['btnVerifyCode'],$element['verifyGroup']['btnVerifyCode']);

    $element = [
//      '#attached'=>[
//        'library' => ['aqr_basic/state'],
//        'drupalSettings' => [
//          'id' => $element['#id'],
//          'cities' => json_encode($cities),
//        ],
//      ],
      'email' => $email,
      'btnSendCode' => $btnSendCode,
      'verifyGroup' => $verifyGroup,
      '#attributes' => ['id' => ['email-wrapper-id'], 'class' => ['email_verify']],
    ];
    dump($element);
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    return $input;
  }

  public static function email(array &$form, FormStateInterface $form_state) {

    dump($form);

    return $form;
  }
}

```

# Answer
> 1 votes
I believe you may need this syntax as your callback, I think because everything went to being 'static' when you moved your demo code from a form to a Element.

```
 $btnSendCode = [
  '#type' => 'ajax_button',
  '#value' => $element['#btnSendCodeTitle'],
  '#ajax' => [
    'callback' => ['\Drupal\aqr_basic\Element\EmailElement', 'email'],
    'event' => 'click',
  ],
];

```

# Answer
> 0 votes
You need to add a wrapper and div ID to where you want the ajax to load

```
  '#ajax' => [
    'callback' => '::email',
    'wrapper' => 'load-me-here', // we tell ajax to target this ID
    'event' => 'click',
  ],
  // attach the ID you targeted above to some element.
  '#attributes' => ['id' => 'load-me-here'],

  // you could create a new element if you want.
  // there is so many variations you can do to add the ID.

  //  $element['load'] = [
  //   '#type' => 'fieldset',
  //   '#title' => t('Load the stuff here'),
  //   '#attributes' => ['id' => 'load-me-here'],
  //  ];

  // OR

  //  $element['load'] = [
  //   '#type' => 'markup',
  //   '#title' => t('Load the stuff here'),
  //   '#markup' => '<div id="load-me-here"></div>',
  //  ];

  // OR

  //  $element['load'] = [
  //   '#type' => 'fieldset',
  //   '#title' => t('Load the stuff here'),
  //   '#prefix' => '<div id="load-me-here">',
  //   '#suffix' => '</div>',
  //  ];

```

Also, remove the `dump($form);` from your ajax email callback function, this prevents it from working.

You'll have to install Devel and use `dpm($form);` if you want to see the structure of the array. Also, note that Devel's `kint($form);` wont work on ajax callback either.

# Answer
> 0 votes
Might be too late to help the OP but I ran into a similar issue with a custom RenderElement.

In my case i'm running Drupal 10.1.x. The issue was with the AJAX event attaching logic in the base RenderElement class (See: RenderElement::preRenderAjaxForm). It doesn't recognise the new element type so doesn't assign a default `$element['#ajax']['event']` property.

You can either update the RenderElement to make sure a default event is assigned:

```
/**
 * @FormElement("my_element")
 */
class MyElement extends FormElement {

  //... Some other methods and stuff.

  /**
   * {@inheritdoc}
   */
  public static function preRenderAjaxForm($element) {
    // Do this before calling the parent because the Drupal Ajax libraries
    // are attached based on the existence of $element['#ajax']['event']
    // which won't be set in time if we do it after the parent call
    if (isset($element['#ajax']) && !isset($element['#ajax']['event'])) {
      if ($element['#type'] === 'my_element') {
        $element['#ajax']['event'] = 'change';
      }
    }

    return parent::preRenderAjaxForm($element);
  }

}

```

If you don't have access to modify the RenderElement (I.e. it's contributed), a work around is to make sure you define an event whenever you attach AJAX to an element of that type:

```
$form['some_element'] = [
  '#type' => 'my_element',
  '#title' => t('My Cool Element'),
  '#ajax' => [
    'callback' => 'someCallback',
    'wrapper' => 'some-wrapper-id',
    // Make sure you define this. Don't rely on the default
    'event' => 'change'
  ],
];

```

---
Tags: 8, ajax
---


# Question
Title: How to create a page with a specific form display?
And how do form displays work?

I have a content type (*Sketch*) with an image. As an authenticated user, I can create a node of that type from /node/add/sketch, but that uses the default form.

How do I override the form display to use a new form display?

Additionally, how do I put this form on a separate path (for example /sketches/new)?

# Answer
**To Enable new form display mode for content type follow these steps:**

A. Go to specific content type(sketch) \> click on "manage form display"

B. You will find "Custom display settings" at the end of page click on it

c. then newly added display form displaying here, checked it & form mode 'll enable.

**Additionally, how do I put this form on a separate path: /sketches/new**

**There are two approaches to achieve this:**

**A. Create custom page(controller) with this route /sketches/new**

```
 Get node form object & return it from controller

 **Snippet code:**

 $values = array('type' => 'sketch');

 $node = \Drupal::entityTypeManager()
    ->getStorage('node')
    ->create($values);

 $form = \Drupal::entityTypeManager()
    ->getFormObject('node', 'sketch_multicolor')
    ->setEntity($node);
  $form =  \Drupal::formBuilder()->getForm($form);

```

Here **'sketch\_multicolor'** **machine name of newly added form mode.**

**Additional Info:** if you are using this approach & custom form mode then you need to use below code in .module file: (otherwise you 'll face mentioned error)

```
function module_name_entity_type_build(array &$entity_types) {
  $entity_types['node']->setFormClass('sketch_multicolor', 'Drupal\node\NodeForm');
}

```

Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "node" entity type did not specify a "sketch\_multicolor" form class. in Drupal\Core\Entity\EntityTypeManager-\>getFormObject() (line 207 of /var/www/html/web/core/lib/Drupal/Core/Entity/EntityTypeManager.php).

**B Alter route path : By use of RouteSubscriber:** In this basically you alter the path from '/node/add/sketch' to this '/sketches/new'

Click on this reference link to use Routesubscriber approach

```
 Here you can check **'alterRoutes()'** to update the path.

```
> 1 votes

---
Tags: forms
---


title: How to do Do a redirect in buildForm()?

text:
# Question
Title: How to do Do a redirect in buildForm()?
I send a link to a URL by email. This page is created with a controller which contains a form (FormAPI). I pass a token as a parameter to secure access to this form. So I check if this token exists and I display the form. Everything works correctly.

If the token does not exist, I would like to redirect in the buildform to a custom route. But I can not.

I tried different things like this but it doesn't seem to work in the buid form.

```
 public function buildForm(array $form, FormStateInterface $form_state, $token = null): array {

        $nodes = \Drupal::entityTypeManager()
            ->getStorage('node')
            ->loadByProperties([
                'field_token' => $token,
            ]);

        // Checks if the node array is not empty.
        if (!empty($nodes)) {
            $node = reset($nodes);
            $nid = $node->id();
        } else {
            // Here, I want to redirect to custom route
            dump('ko');

            //return new RedirectResponse(Url::fromRoute('my_custom_route')->toString());
            //$form_state->setRedirect('my_custom_route');

            //return $this->redirect('my_custom_route');
            // return $form_state->setRedirect('('my_custom_route')');
        }
}

```

Do you know how I can do it? Otherwise, rather than using a controller and a custom route, I will generate a different form depending on the condition (a form without fields but with custom markup). But I prefer a controller.

I know how to redirect in `submitForm()` or in a controller. Here, the redirect is in `buildForm()`

# Answer
You need to use RedirectResponse, e.g.

```
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;

$response = new RedirectResponse(URL::fromRoute('my_custom_route')->toString());
$response->send();

```
> 0 votes

# Answer
If the form is in a route via the `_form` key you can return the redirect the same as in a controller, the core form controller is able to pass the response to the Drupal kernel. If the form is in a custom controller you have to pass it from the form to the controller and return it.

BTW the response send method is a low-level method not suitable for a Symfony app like Drupal. The Symfony kernel has to return a response and not send one.
> 3 votes

---
Tags: forms, redirection
---


# Question
Title: Why are media items no longer available at /media/{id}?
I'm using the Media module, but I noticed there isn't a path like /media/%id where I can see the media and its fields.

The only path available seems to be media/%id/edit and media/%id/delete.

On Drupal 8, it was possible to access a media page. What's wrong?

# Answer
This was an announced change that released in Drupal 8.7.0—"Media items no longer available at /media/{id}". The change added a new setting to enable the "id" route and turned it on for existing sites. New sites must have the setting enabled at /admin/config/media/media-settings.
> 6 votes

# Answer
**Steps: To enable this '/media/%id' path:**: In Drupal9/10

Enable the 'Media' module and then go to this page: your\_site\_url/admin/config/media/media-settings

Enable this checkbox 'Standalone media URL'

**Additonal info:**

**#1: Basically this route '/media/%id' disabled by core.**

#2: May be in your case module 'Media' enabled, you just need to enable this checkbox 'Standalone media URL' and save the form.
> 2 votes

---
Tags: media, 10
---


title: Form #states visible for numeric values

text:
# Question
Title: Form #states visible for numeric values
The form has two radio buttons like follows.The "design" radio field should be visible only when user selects 'Ten' or 'hundred' from the "price" field.

If user choose 'other' it should not be visible.

I tried like follows, it's working but by default the 'design' field is come with visible state.

```
//$options array is dynamic.
$options =  array(10 => 'Ten', 100 => 'hundred', 'other' => 'Other');

  $form['price'] = array(
    '#type' => 'radios',
    '#title' => t('Price?'),
    '#options' => $options,
    );
  $form['design'] = array(
   '#type' => 'radios',
   '#title' => t('Designs'),
    '#options' => $designs,
   );
  $form['design']['#states'] = array(
    'visible' => array(
        array(':input[name="price"]' => array('!value' => 'other')),
    ),
  );

```

I've tried several ways like follows with no luck.

```
array(':input[name="price"]' => array('!value' => '')),
array(':input[name="price"]' => array('checked' => TRUE)),

```

Is there any option like to check the selected value is numeric or not? like

```
array(':input[name="price"]' => array('value' => isNumeric)),

```

or the other option would loop through the dynamic option values?

```
      array(':input[name="category"]' => array('value' => 10)),
      'or',
      array(':input[name="category"]' => array('value' => 100)),
      'or',
        .
        .
        etc

```

Any suggestions or input would be much appreciated.

# Answer
> 0 votes
I've ended up the issue as follows.

```
$options =  array(10 => 'Ten', 100 => 'hundred', 'other' => 'Other'); // Dynamic array
$conditions = array();
  foreach ($options as $key => $value) {
    if (is_numeric($key)) {
      $conditions[] = array(':input[name="price"]' => array('value' => $key));
    }
  }

  $form['design']['#states'] = array(
    'visible' => $conditions,
  );

```

Hope this helps someone. Any better answers would be much appreciated.

# Answer
> 0 votes
Try this:

```
$form['design']['#states'] = array(
  'visible' => array(
    ':input[name="price"]' => array('!value' => 'other'),
  ),
);

```

though, to be honest I'm much more a fan of:

```
$form['design']['#states'] = array(
  'invisible' => array(
    ':input[name="price"]' => array('value' => 'other'),
  ),
);

```

Here are some good examples to follow. Not exactly your case, but close.

# Answer
> 0 votes
**Snippet code:**

```
      $form['design']['#states'] = array(
        'visible' => array(
           array(':input[name="price"]' => array(
              'checked' => true,
              '!value' => 'other',
            )
          ),
        ),
      );

```

**This above solution make sure 'Design' field 'll display only if:**

* User select value from 'Price' field
* Value selected from price field is not 'other'.

---
Tags: 7, forms
---


# Question
Title: How can I handle race conditions in a headless setup?
I am currently trying to build an eCommerce site. The functionalities are quite basic; there are products with limited quantities and customers can purchase those products. I've decided to use Drupal 10 as my backend CMS headless to handle the products and orders. The frontend communicates with Drupal through REST APIs. This includes order creation. When a user checks out, an order gets created in the backend, and the quantity of the item purchased is decreased.

I have a potential issue arising with the above order creation. The order creation can be seen below... The code is a bit simplified but the point is there:

```
public function post($data) {
  if (!$this->loggedUser->hasPermission('access content')) {
    throw new AccessDeniedHttpException();
  }

  $productVariationStorage = \Drupal::entityTypeManager()->getStorage('commerce_product_variation');
  $productVariation = $productVariationStorage->load($data['id']);

  // potential check to make sure the product variation is available (quantity > 0)
  // Throw error message if not available
  $orderItems = array();
  $orderItem = OrderItem::create([
    'type' => 'example_order_item',
    'purchased_entity' => $data['id'],
    'quantity' => 1,
  ]);

  $orderItem->save();
  array_push($orderItems, $orderItem);

  $order = Order::create([
    'type' => 'example_order',
    'uid' => $this->loggedUser->id(),
    'store_id' => 1,
    'order_items' => $orderItems,
    'placed' => \Drupal::time()->getCurrentTime(),
    'state' => 'draft'
  ]);
  $order->save();

  $productVariation->field_quantity->value -= 1;
  $productVariation->save();

  $resultArray = array();
  $resultArray['order_id'] = $order->uuid();
  return new ResourceResponse($resultArray);
}

```

The purchased product ID is sent from the frontend in the request body. Drupal then loads the product variation and checks if the quantity is greater than zero (if it is available, this can only be seen written in comments). If it is available, it proceeds to create an order item type and an order, etc. The quantity is then reduced by one, and the product variation is saved.

Let's say customer one clicks checkout on the frontend and the order creation API is called resulting in the above PHP code running. However, very shortly after customer one clicks checkout, customer two also clicks checkout with the same product (quantity is one for the product). A problem arises if the order of execution is the following for the two requests:

1. Customer one check if available-\>it's available, continue
2. Customer two check if available-\>it's available, continue
3. Customer one create order, decrease quantity, save, etc.
4. Customer two create order, decrease quantity, save, etc.

Both customers are able to purchase a single product, and I need to refund someone. Can this scenario happen? If so, the solution would be to somehow lock the product variation entity until it is up to date. While it is locked nobody can read/write. Can this be done from PHP?

I appreciate the help in advance, and if anything is unclear, let me know, and I'll edit the post!

# Answer
> 3 votes
There are many ways to handle stock preventing overselling ... from a pattern standpoint, not necessarily from a contrib standpoint. However, our least favorite version is using a field on the product variation itself, as that results in a product update on every purchase. In a high-volume scenario, that's going to really hurt your database... and as you've seen, it's not great for concurrency issues.

Rather than using a field on the product, we'd typically recommend a custom table tracking the product variation ID and stock level. When a customer starts a purchase, you might use a separate table to place a hold and then only decrement the stock level once that order is placed. Thus, when you want to determine if a product is available for purchase, you're actually looking up how many holds are active against how many remaining stock for a given product.

Then, to solve for concurrency, you'll need an additional check in the checkout flow. Prior to payment, or at least between payment authorization and capture, you need to *confirm* the stock you thought was there is still there. If it isn't, you need to error out (and void any authorization if you went that route) ... if it is, you capture and carry on. This will almost always entail custom code, as we've yet to encounter the same set of rules twice, to be honest.

---
Tags: entities, commerce
---


title: why is index.php added to URLs?

text:
# Question
Title: why is index.php added to URLs?
Since I updated my site to Drupal 9.5.11, 'index.php/' is added to every URL: `http://mysite.org/index.php/` for the home page, for example.

On some page, I have a list with links to files and, because of this strange behavior, links lead to a 'Page not found' error. In this case, 'index.php/' is even added twice: `http://mysite.org/index.php/index.php/system/files/contracts/Contract-228-20231108.pdf`.

I found some posts about similar issues but the main difference with these posts is that in my case, the behavior occurs when the user is authenticated. No problem for anonymous visitors!

Other clue (maybe?): it occurs in my Production site and everything is OK on my local site (managed with MAMP).

Any idea what is going wrong?

# Answer
> 3 votes
It is floating core bug. See this issue

The answer which helps me:

Install redirect module and enable "Enforce clean and canonical URLs" then clear cache.

---
Tags: 9, uri
---


# Question
Title: Image field and links not showing in view block template
I have a CT `team_members` with the following fields.

```
field_team_member_image

field_team_member_name

field_member_designation

field_social_media_links(Multiple values with links to twitter, instagram, fb and linkedin)

```

I created a view block out of it and placed it in my desired region.

Now when I templated this,

in the block template(`block--theme-name-views-block--team-members-block-block-1.html.twig`), I gave the outline with the title and label as follows:

```
<section id="team" class="team">
    <div class="container" data-aos="fade-up">
        <div class="section-title">
            <h2>Team</h2>
            <p> {{ label }} </p>
        </div>
        <div class="row">
            {{ content }}
        </div>
    </div>
</section>

```

and for each repeating field(`views-view-fields--team-members-block.html.twig`) template:

```
<div class="col-lg-3 col-md-6 d-flex align-items-stretch">
    <div class="member" data-aos="fade-up" data-aos-delay="100">
        <div class="member-img">
            <img src="{{ fields.field_team_member_image.content }}" class="img-fluid" alt="">
            <div class="social">
                {% for item in fields.field_social_media_links %}
                    <a href="{{ item.url }}"><i class="bi bi- {{ item.title }}"></i></a>
                {% endfor %}
            </div>
        </div>
        <div class="member-info">
            <h4>{{ fields.field_team_member_name.content }}</h4>
            <span>{{ fields.field_member_designation.content }}</span>
        </div>
    </div>
</div>

```

But the **image is not displaying** at all (name and designation coming). I changed the `image` to `URL to image` in the view field formatter. Also, the social media links are not iterating and not displaying the links I need. Any help is appreciated.

# UPDATE

Image worked with directly given the field and applying the image style from the view settings.

Now the problem is with displaying the links

When I did the kint on the links field (

```
{{ kint(fields.field_social_media_links.content) }}

```

) I got it as follows:

```
protected string -> string (427) " <!-- THEME DEBUG --> <!-- THEME HOOK: 'views_view_field' --> <!-- BEGIN OUT...
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->
<a href="https://www.twitter.com">twitter</a>, <a href="https://www.facebook.com">facebook</a>, <a href="https://www.instagram.com">instagram</a>, <a href="https://www.linkedin.com">linkedIn</a>
<!-- END OUTPUT from 'core/modules/views/templates/views-view-field.html.twig' -->

```

Hope somebody got insight on this.

# Answer
Usually in the view twigs template you should be focus on view templates and not use "block" unless you really need.

Twig order for views are:

1. views-view--\[viewID\]--\[page/blockID\].html.twig
2. views-view--unformatted--\[viewID\]--\[page/blockID\].html.twig
3. views-view-fields--\[viewID\]--\[page/blockID\].html.twig

On the first level it's your wrapper, where you call header, footer, content and "high level" elements of your view

Second level is where you can create a wrapper for each group of fields

Third and last level is where you can call each fields.

About your problem with images, you have 2 type of fields, "image" and "media".

If you are using image field, in your view under the "formatter" you need to set "URL to image", then you ca use on your tag , it is also possible to choose an image style for your image.

If you are using "media" field, first you need to go to "manage display" of your media type "image" and create a new view mode, let's say "view url", activate view mode you just created and under "format" of your image field choose "URL to image" and an image style if needed.

Then, in your view you need to choose "rendered entity" under formatter and choose view mode you created "view url", with this way you will be able to output URL to your image and use tag .
> 1 votes

---
Tags: views, theming, blocks, 9
---


# Question
Title: Error when creating a custom Twig filter
I'm trying to create a custom Twig filter in Drupal 8. The goal is to use my custom filter in a template like so:

```
{{ a_variable|myfilter }}

```

I have created a custom module with 3 files:

```
MODULE.info.yml
MODULE.services.yml
src/TwigExtension/MyExtension.php

```

The `MODULE.info.yml` file contains the usual values.

The `MODULE.services.yml` file contains:

```
services:
  MODULE.twig_extension:
#   arguments: ['@renderer']  #  <-- Initial code (USELESS)
    class: Drupal\MODULE\TwigExtension\MyExtension
    tags:
      - { name: twig.extension }

```

The `src/TwigExtension/MyExtension.php` file contains:

```
namespace Drupal\MODULE\TwigExtension;

// use Drupal\Core\Template\TwigExtension;  // <-- Initial code (WRONG)

class MyExtension extends \Twig_Extension {
// class MyExtension extends TwigExtension {  // <-- Initial code (WRONG)

  /**
   * Generates a list of all Twig filters that this extension defines.
   */
  public function getFilters() {
    return [
      new \Twig_SimpleFilter('myfilter', array($this, 'myFilter')),
    ];
  }

  /**
   * Gets a unique identifier for this Twig extension.
   */
  public function getName() {
    return 'MODULE.twig_extension';
  }

  /**
   * Replaces all instances of "animal" in a string with "plant".
   */
  public static function myFilter($string) {
    return str_replace(array('animal'), array('plant'), $string);
  }

}

```

My initial code got following error: "Call to a member function generateFromRoute() on a non-object in /core/lib/Drupal/Core/Template/TwigExtension.php on line 224".

But I have now corrected the code following lauriii's answer and it works perfectly!

# Answer
> 8 votes
The problem in the code above is that your Twig extension class is extending the internal Drupal Twig extension class. That breaks the Twig extensions added by Drupal core and that's why you are getting the error.

To fix this, you should make your Twig extensions extend Twigs internal Twig extension class. Your class should be defined like this:

```
class MyExtension extends \Twig_Extension {

```

After making that change, you can also remove arguments set for that class from the `MODULE.services.yml`

# Answer
> 0 votes
the above sample is still off.. (ie: the 'arguments' clause in .services does seem to be needed)

take a look at /core/modules/system/tests/modules/twig\_extension\_test to model a twig filter and function from!

# Answer
> 0 votes
it seems we need to use \Twig\_Extension class more directly.

MODULE.services.yml `services:
 MODULE.twig.filters:
 arguments: ['@renderer']
 class: Drupal\MODULE\TwigExtension\HexToRgb
 tags:
 - { name: twig.extension }`

**/src/TwigExtension/HexToRgb.php**

```
/**
 * @file
 * Contains Drupal\MODULE\TwigExtension.
 */

namespace Drupal\MODULE\TwigExtension;

/**
 * A Twig extension (filter) converts hex color to rgb.
 */
class HexToRgb extends \Twig_Extension {

  /**
   * Generates a list of all Twig filters that this extension defines.
   */
  public function getFilters() {
    return array(
      new \Twig_SimpleFilter('hexToRGB', [$this, 'hexToRGB'], ['is_safe' => ['html']]),
      new \Twig_SimpleFilter('rangeToPercent', [$this, 'rangeToPercent'], ['is_safe' => ['html']]),
    );
  }

  /**
   * Gets a unique identifier for this Twig extension.
   */
  public function getName() {
    return 'MODULE.twig.filters';
  }

  /**
   * convert 3 or 6 char hex color to comma seperated RGB colors
   */
  public static function hexToRgb($hex=000000) {
    $r = $g = $b = FALSE;
    $hex = str_replace("#", "", $hex);

    if(strlen($hex) == 3) {
      $r = hexdec(substr($hex, 0, 1).substr($hex, 0, 1));
      $g = hexdec(substr($hex, 1, 1).substr($hex, 1, 1));
      $b = hexdec(substr($hex, 2, 1).substr($hex, 2, 1));
    } else {
      $r = hexdec(substr($hex, 0, 2));
      $g = hexdec(substr($hex, 2, 2));
      $b = hexdec(substr($hex, 4, 2));
    }

    $rgb = array($r, $g, $b);

    return implode(",", $rgb);
  }

  /**
   * convert range (0 to 100) to a percent with 2 decimals
   */
  public static function rangeToPercent($range=0) {
    return round(($range/100), 2);
  }

}

```

# Answer
> 0 votes
I was having a ton of issues with this on a site and I think I finally tracked down the problem: it was using twig/twig: ^3.

## Here is code for a twig FUNCTION that works with twig/twig 2

**my\_module/src/TwigExtension/MyModuleInputTwigExtension.php:**

```
<?php

namespace Drupal\my_module\TwigExtension;

/**
 * Custom Twig extension to format my field.
 */
class MyModuleInputTwigExtension extends \Twig_Extension {

  /**
   * {@inheritdoc}
   */
  public function getFunctions() {
    return [
      new \Twig_SimpleFunction('format_hours_msg', [$this, 'formatMsg'], ['is_safe' => ['html']]),
    ];
  }

  /**
   * Formats a string for proper output.
   *
   * @param string $string
   *   The input string.
   *
   * @return string
   *   The formatted string.
   */
  public function formatMsg($string) {
    // string formatting code  for $string
    return $string;
  }
}

```

**my\_module.services.yml:**

```
services:
  my_module.function:
    class: Drupal\my_module\TwigExtension\MyModuleInputTwigExtension
    tags:
      - { name: twig.extension }

```

But when I tried to use a similar method with /Twig\_SimpleFilter or even /Twig\_SimpleFunction and whatnot on the other site, it threw:

> Uncaught Error: Class "Twig\_Extension" not found in /var/www/docroot/modules/custom/my\_module/src/TwigExtension/MyModuleInputTwigExtension

When I removed the /TwigExtension/ from the routing file, it threw:

> Service 'my\_module.twig\_extension' for consumer 'twig' does not implement Twig\Extension\ExtensionInterface.

## Here is code for a twig FILTER that works with twig/twig 3:

**my\_module/src/TwigExtension/MyModuleInputTwigExtension.php:**

```
<?php

namespace Drupal\my_module\TwigExtension;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

class MyModuleTwigExtension extends AbstractExtension {

  public function getFilters() {
    return [
      new TwigFilter('to_https', [$this, 'toHttpsFilter']),
    ];
  }

  public function toHttpsFilter($url) {
    // Check if the URL starts with 'http:' or 'https:' and replace it with 'https:'
    $url = preg_replace('/^(http:|https:)?/', 'https:', $url);

    return $url;
  }
}

```

I've also see the return line for getFilters() look like this:

```
'to_https' => new TwigFilter('to_https', [$this, 'toHttpsFilter']),

```

**my\_module.services.yml:**

```
services:
  my_module.twig_extension:
    class: Drupal\my_module\TwigExtension\MyModuleTwigExtension
    tags:
      - { name: twig.extension }

```

# Answer
> -1 votes
Try https://www.drupal.org/project/twig\_extender . Add a plugin system for custom twig functions and filters

---
Tags: theming
---


# Question
Title: How do I render a Media Entity Reference image field in template_preprocess_node()?
I'm altering the way images are rendered in the node preprocess function, and it is working exactly as expected for images in "Image" fields:

```
$field_view = $fields['field_image']->view(['label' => 'hidden']);
$field_view['#view_mode'] = 'full';

```

This results in the regular image array, so when I add it to my twig template, it gets rendered as an image tag.

However, we'd like to start using Media fields instead, and I can't figure out how to get the render array to come back with an image instead of just a text link. If I use the same thing for a media field, I just get a link with the image title as the text of the link:

```
$field_view = $fields['field_media_image']->view([
  'label' => 'hidden',
]);

```

This is what the 'file' image render array looks like; it renders as an image, which is what I want to get for the media image field:

```
#theme => "field"
#title => "Image"
#label_display => "hidden"
#view_mode => "full"
#language => "und"
#field_name => "field_image"
#field_type => "image"
#field_translatable => true
#entity_type => "node"
#bundle => "page"
#object => Drupal\node\Entity\Node (29)
#items => Drupal\file\Plugin\Field\FieldType\FileFieldItemList (9)
#formatter => "image"
#is_multiple => false
#third_party_settings => array (0)
0 => array (6)
#cache => array (3)
#weight => 0

```

However, when I just use the same `view()` function on the media image field, I get this, which doesn't render as an image:

```
#theme => "field"
#title => "Media Image"
#label_display => "hidden"
#view_mode => "_custom"
#language => "und"
#field_name => "field_media_image"
#field_type => "entity_reference"
#field_translatable => false
#entity_type => "node"
#bundle => "page"
#object => Drupal\node\Entity\Node (29)
#items => Drupal\Core\Field\EntityReferenceFieldItemList (9)
#formatter => "entity_reference_label"
#is_multiple => false
#third_party_settings => array (0)
0 => array (5)
#cache => array (3)
#weight => 0

```

I would guess that the reason this renders as a textual link is because of `#formatter => "entity_reference_label"` but whenI change this value, I continue to get the same output.

# Answer
Try this:

```
if ($node->hasField('field_name') && $node->get('field_name')->entity) {

  // Set media entity.
  $mediaEntity = $node->get('field_name')->entity;

  // Get media image field.
  $mediaImage = $mediaEntity->get('field_media_image');

  // Get translated media image field.
  if ($mediaEntity->hasTranslation($langcode)) {
    $mediaImage = $mediaEntity->getTranslation($langcode)->get('field_media_image');
  }

  // Get media image entity.
  $mediaImageEntity = $mediaImage->entity;

  // Get image mime type.
  $mediaImageMimeType = $mediaImageEntity->getMimeType();

  // Get image file uri.
  $mediaImageEntityUri = $mediaImageEntity->getFileUri();

  // Set image url.
  $imageUrl = \Drupal::service('file_url_generator')->generateString($mediaImageEntityUri);

  // Set image style url.
  if ($mediaImageMimeType !== "image/svg+xml") {
    $imageUrl = \Drupal::entityTypeManager()->getStorage('image_style')->load('image_style_name')->buildUrl($mediaImageEntityUri);
  }

  $variables['imageUrl'] = $imageUrl;
}

```
> 1 votes

# Answer
Don't switch the field formatter, switch the entire entity view mode. I've done something similar with Paragraphs and media view modes, the following code is copy&paste from my project. It should be easy to adjust for nodes.

I just replaced the `#view_mode` key in the render array, but you have to do it for every single ER field value

```
function theme_preprocess_paragraph(array &$variables) {
  $paragraph = $variables['paragraph'];
  if ($paragraph->hasField('field_image_viewmode')) {
    $imageViewMode = $paragraph->field_image_viewmode->value;
    if (!$paragraph->field_gallery->isEmpty()) {
      $mediaEntities = $paragraph->field_gallery->referencedEntities();
      foreach ($mediaEntities as $idx => $mediaEntity) {
        // this is the key line
        $variables['content']['field_gallery'][$idx]['#view_mode'] = $imageViewMode;
        // this operation is not cache-safe
        unset($variables['content']['field_gallery'][$idx]['#cache']['keys']);
      }
    }
  }
}

```

But I recommend not doing this anymore. I'm now using view\_mode\_switch instead, which does the same thing with better code and with an UI (which basically means it is documented for editors)
> 0 votes

---
Tags: media, 9
---


title: JSON.API Failed to fetch

text:
# Question
Title: JSON.API Failed to fetch
I am trying to set up a React component that will fetch the JSON from my Drupal 9 site using JSON:API and JSON:API Views module.

I can see the JSON when I visit the URL, but get 'failed to fetch' from the React component.

What is the problem?

```
const endpoint = "http://my_site.com/jsonapi/views/job_listings/page_2";
const Job_Board = () => { const [users, setUsers] = useState([]);

useEffect(() => {
  (async () => {
    const data = await fetch(endpoint).then((res) => res.json());
    setUsers(data);
  })();
}, []);

```

# Answer
> 0 votes
I needed to set CORS headers for the Drupal site. I did this with https://www.drupal.org/project/cors\_ui

I just set allowed headers, methods, and origins to *

---
Tags: 9
---


# Question
Title: Resolve CORS issue without changing services.yml file
I have below in `routing.yml`

```
sample.post:
  path: '/sample/post'
  defaults:
    _controller: '\Drupal\sample\Controller\SampleController::postData'
  methods: [POST]
  requirements:
    _access: 'TRUE'
    _format: 'json'

```

In services.yml no change it will be same as default. I don't want to change in service.yml by enabling cors config.

When I call using jQuery.

```
  jQuery.ajax({
      url: 'http://localhost/sample/post',
      contentType: "application/json",
      type: 'POST',
      complete: function (data) {
        console.log(data);
      }
  });

```

It gives

> Failed to load http://localhost/sample/post: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

**Can I achieve w/o enabling cors config?** If I enable cors then it works fine.

# Answer
> Can I achieve w/o enabling cors config?

No. Without CORS configured, the server and browser will correctly conspire to reject the request.

You could implement it yourself, rather than using services.yml, but *something* needs to set the headers. And at the point where all you need to do is make a few simple edits to a configuration file, I'd question why you would want to write all that extra code yourself.
> 4 votes

# Answer
One workaround I've used in the past, when I've been unable to update the backend/server is to proxy the request through a "repeater" using an AWS API Gateway and a small Lambda function. It's not ideal, but in some cases, like when the API is not yours, or you cannot touch the code, it is necessary.

Obviously, it adds a little overhead/latency and I wouldn't recommend if you can update your service. And it doesn't really work in dev, if you're changing the response... However...

My Lambda function looks like this:

```
const https = require('https');
const { URL } = require('url');

exports.handler = async (event) => {
  return makeRequest(event).then(body => {
    return JSON.parse(body);
  }, (error) => {
    return { message: error.message, event };
  });
};

function makeRequest(event) {
  return new Promise((resolve, reject) => {
    let responseBody = '';
    const url = new URL(event.url);
    const options = {
      host: url.hostname,
      path: url.pathname,
      port: url.protocol === 'https:' ? 443 : 80,
      protocol: url.protocol,
      method: event.method,
      headers: {
        'Content-Type': 'application/json'
      }
    };
    const req = https.request(options, (res) => {
      res.on('data', (d) => {
        responseBody+=d;
      });
      res.on('end',function(){
        resolve(responseBody);
      });
    });
    req.on('error', (e) => {
      reject(Error(e.message));
    });
    req.write(JSON.stringify(event.data));
    req.end();
  });
}

```

I don't have any sort of CLI instructions, so here's a run down of the config in AWS web interface. You can configure security in many ways if needed including an API key:

1. Create a new Lambda function with the name of your choice using Node.js 8 and a new or existing role and entert he above script into the Function Code input area.
2. Go to the Amazon API Gateway section of the AWS Console and create a New API with the name of your choice.
3. From the Actions dropdown, select 'Create Method', choose 'POST' and save.
4. In the resulting endpoint config page, choose 'Lambda Function' as the integration type, leave 'Use Lambda Proxy integration' unchecked, select your Lambda function and save.
5. From the Actions dropdown, select 'Enable CORS' and then click the button to confirm
6. Unfortunately, this doesn't add all the CORS headers to the POST endpoint so from the menu on the left, click POST and then click the 'Method Response' box.
7. Click the toggle on the 200 response and add two more headers: Access-Control-Allow-Headers and Access-Control-Allow-Methods Go back to the Method Execution/POST screen and click the 'Integration Response' box.
8. Toggle the 200 response and then the Header Mappings and add 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' to the Access-Control-Allow-Headers header and 'POST,OPTIONS' to the Access-Control-Allow-Methods header.
9. From the Actions dropdown, select 'Deploy API', select 'New Stage' and give it a name (e.g. 'production' or 'beta').
10. This will give you an endpoint. Make a POST request to it with the following JSON body and you're done.

```
{
    "url": "https://some-non-cors-enabled-api.com/",
    "method": "POST",
    "data": {}
}

```

GitHub
> 0 votes

# Answer
The Advanced CORS module (https://www.drupal.org/project/advanced\_cors) promises to allow you to configure CORS without editing a services.yml
> 0 votes

---
Tags: 8
---


# Question
Title: How can we move Webform's progress bar from above the form to below it?
I can't find a way to move the progress bar to below the form. I've looked all through the UI options and also examined the Twig templates that are used to render the progress bar but there does not seem to be a way to move it. Is it being inserted through a process hook? Can't figure this one out.

# Answer
> 1 votes
You can do it in the `hook_webform_submission_form_alter`.

You need to unset `'#weight'` array key in the render element for the progress bar and move it to the appropriate place where you want it rendered.

Example:

```
function hook_webform_submission_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
  if ($form_id === 'your_webform_form_id') {
    if (
      array_key_exists('progress', $form)
      && array_key_exists('#weight', $form['progress'])
      && array_key_exists('#current_page', $form['progress'])
      && $form['progress']['#current_page'] === 'my_page'
    ) {
      unset($form['progress']['#weight']);
      $progress = $form['progress'];

      $index = array_search('element_to_be_placed_after', array_keys($form['elements']['my_page']));
      $changedArray = array_slice($form['elements']['my_page'], 0, $index, TRUE)
        + ['progress' => $progress]
        + array_slice($form['elements']['my_page'], $index, NULL, TRUE);
      $form['elements']['my_page'] = $changedArray;
    }
  }
}

```

---
Tags: webforms
---


title: How to hide the text formats help text?

text:
# Question
Title: How to hide the text formats help text?
I want to hide the description of the text format under the "Comment" box which says:

* No HTML tags allowed.
* Lines and paragraphs break automatically.

There are a variety of ways to do this on Drupal 7, but what about Drupal 8?

# Answer
AFAIK there is currently no core UI to control showing/hiding of those tips.

Th simplify module, one of the D7 choices you link to, has a D8 port that may still help with this.

The Allowed formats module is an incubator for future core improvements in the area of giving sitebuilder's UI control over text format and their help tips.

== UPDATE ==

A patch just committed to that module gives sitebuilders considerable control over help tips, using UI settings on the widgets.

== OLD ==

There are a couple of relevant issue in the issue queue for that module:

Allow to control if "About text formats" link should be shown or not

Allow to hide text format help text for Text(formatted)

The first of those issues contains this code from floretan, which points in the direction you would need to go to hide the help by custom code:

```
<?php
/**
 * Implements hook_field_widget_form_alter().
 */
function allowed_formats_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
  if ($context['widget'] instanceof \Drupal\text\Plugin\Field\FieldWidget\TextareaWidget) {
    $element['#after_build'][] = '_allowed_formats_remove_textarea_help';
  }
}

/**
 * #after_build callback.
 */
function _allowed_formats_remove_textarea_help($form_element, FormStateInterface $form_state) {
  if (isset($form_element['format'])) {
    // All this stuff is needed to hide the help text.
    unset($form_element['format']['guidelines']);
    unset($form_element['format']['help']);
    unset($form_element['format']['#type']);
    unset($form_element['format']['#theme_wrappers']);
  }

  return $form_element;
}
?>

```
> 15 votes

# Answer
This work for me in drupal 8, You have to change the field machine name

```
<?php

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_field_widget_form_alter().
 */
function YOURMODULENAME_form_alter(&$form, &$form_state, &$form_id) {
    $form['field_short_description']['widget']['#after_build'][] = '_allowed_formats_remove_textarea_help';
}

function _allowed_formats_remove_textarea_help($form_element, FormStateInterface $form_state) {

  if (isset($form_element[0]['format'])) {
    // All this stuff is needed to hide the help text.
    unset($form_element[0]['format']['guidelines']);
    unset($form_element[0]['format']['help']);
    unset($form_element[0]['format']['#type']);
    unset($form_element[0]['format']['#theme_wrappers']);
    $form_element[0]['format']['format']['#access'] = FALSE;
  }

  return $form_element;
}

```
> 15 votes

# Answer
As simple and general solution (for all fields) is to install a contributed theme outside core and use that as a administration theme and simply do something like

.filter-guidelines-item .tips { display:none; }

Or patch one of the themes inside core and make a note to repatch when you do an upgrade.
> 3 votes

# Answer
If you are wondering how to do this in Form API, so when you are creating form elements in a Form class instead of altering form elements afterwards:

Your form element:

```
$form['my_field'] = [
  '#type' => 'text_format',
  '#title' => 'My Title',
  '#allowed_formats' => ['basic_html'],
  '#after_build' => [[get_class($this), 'hideTextFormatHelpText'],],
];

```

Add this function to your class:

```
  public static function hideTextFormatHelpText(array $element, FormStateInterface $form_state) {
    if (isset($element['format']['help'])) {
      $element['format']['help']['#access'] = FALSE;
    }
    if (isset($element['format']['guidelines'])) {
      $element['format']['guidelines']['#access'] = FALSE;
    }
    if (isset($element['format']['#attributes']['class'])) {
      unset($element['format']['#attributes']['class']);
    }
    return $element;
  }

```

I specifically also removed the classes because you will otherwise see some padding and a border around something empty that you probably don't want.
> 1 votes

# Answer
There is a very simple way to do this. Filter tips are displayed within a block so you can go to appearance/settings and than go to theme customize css.

Add following:

.filter-wrapper { display: none; }

You can also add.

.description { display: none; }
> 0 votes

# Answer
After Drupal core 10 the allowed formats can be set as an option in text fields configuration.

See: https://www.drupal.org/node/3318572.
> 0 votes

---
Tags: 8, input-formats
---


title: Add link field in custom form

text:
# Question
Title: Add link field in custom form
I want add link field (label + url internal/external) in custom form

This not work:

```
$form['test_ink'] = array(
  '#type' => 'link',
  '#title' => $this->t('Link title'),
  '#url' => '',
);

```

# Answer
The `link` (Link) render element type is used to *render* an anchor element on a page, and not used to provide an input element in a form that is constrained for URLs.

As an example you may look at LinkWidget::formElement, which shows how that field widget creates form elements for a Link field. And the way it does this is to use the `url` (Url) form element, which will provide an input element that validates URLs. Make sure that the `#url` property is a valid (Url) object.

```
use Drupal\Core\Url;

$form['test_link'] = [
  '#type' => 'url',
  '#title' => $this->t('Link title'),
  // Example of a Url object from a route. See the documentation
  // for more methods that may help generate a Url object.
  '#url' => Url::fromRoute('entity.node.canonical', ['node' => 1]),
];

```

**Edit**:

1. Added @imclean's suggestion to the answer for readability
> 16 votes

# Answer
I liked @mpp's answer on how to create a linkit field if you have Linkit module enabled. His example was not code formatted, so this is just a repost using formatted code for better readability and to make it easier to copy paste this to use in your own projects. Create a linkit field with Drupal's form api:

```
$form['block_link'] = [
  '#type' => 'linkit',
  '#title' => $this->t('Select link target'),
  '#description' => $this->t('Start typing to see a list of results. Click to select.'),
  '#autocomplete_route_name' => 'linkit.autocomplete',
  '#autocomplete_route_parameters' => [
    'linkit_profile_id' => 'default',
  ],
  '#default_value' => isset($config['block_link']) ? $config['block_link'] : '',
];

```

Note that you can change 'default' to any linkit profile you might have in your project. Also note: my default value in this case comes from a block config form because I added this linkit field to a block's settings page. Remove #default\_value if it is not applicable to your case or change it depending on where you get your value from.
> 6 votes

# Answer
For anyone stumbling across this post looking at adding Linkit to a config form (thanks @mpp and @Flyke), there's been a slight change in the API: `'linkit_profile_id' => 'default',` should now be `'linkit_profile' => 'default',`

```
 $form['block_link'] = [
  '#type' => 'linkit',
  '#title' => $this->t('Select link target'),
  '#description' => $this->t('Start typing to see a list of results. Click to select.'),
  '#autocomplete_route_name' => 'linkit.autocomplete',
  '#autocomplete_route_parameters' => [
    'linkit_profile' => 'default',
  ],
  '#default_value' => isset($config['block_link']) ? $config['block_link'] : '',
];

```

Small point but worth knowing.
> 2 votes

# Answer
I was facing this problem when I needed to add a link (url+label) to the theme settings form. I didn't use the *url* field cause it has a bug if the user wants to add an internal link.

This is how it looked on the CMS:

This is the code:

```
/**
 * Implements hook_form_system_theme_settings_alter().
 **/
function francisco_form_system_theme_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface &$form_state, $form_id = NULL) {
  // Work-around for a core bug affecting admin themes. See issue #943212.
  if (isset($form_id)) {
    return;
  }

  $form['francisco_theme_option_sidebar'] = array(
    '#type' => 'details',
    '#title' => t('Sidebar'),
    '#description' => t('Lorem ipsum.'),
    '#open' => TRUE,
  );

  $form['francisco_theme_option_sidebar']['francisco_theme_option_sidebar_footer_cta_title'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Link Title'),
    '#default_value' => theme_get_setting('francisco_theme_option_sidebar_footer_cta_title'),
    '#description'   => t("Lorem ipsum."),
    '#maxlength' => 255
  );

  $form['francisco_theme_option_sidebar']['francisco_theme_option_sidebar_footer_cta_url'] = array(
    '#type'          => 'textfield',
    '#title'         => t('URL'),
    '#default_value' => theme_get_setting('francisco_theme_option_sidebar_footer_cta_url'),
    '#description'   => t("Lorem ipsum."),
    '#maxlength' => 2048,
  );

}

```
> 1 votes

# Answer
**To add link field (label + url internal/external) & core link widget's url field validation in custom form:**

```
$form['resource_fieldset']['design_tool_link'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
  '#title' => $this->t('Design Tool Link'),
  '#description' => $this->t('Select Design Tool Link'),
  '#required' => TRUE,
  '#element_validate' => [
    [
      'Drupal\link\Plugin\Field\FieldWidget\LinkWidget',
      'validateUriElement',
    ],
  ],
  '#attributes' => [
    'data-autocomplete-first-character-blacklist' => '/#?',
  ],
  '#process_default_value' => FALSE,
  '#default_value' => $design_tool_link ?? : '',
];

 $form['resource_fieldset']['title'] = [
  '#type' => 'textfield',
  '#title' => $this->t('Title'),
];

```

**Note: by adding #element\_validate attribute :**

* Custom Url field 'll accept external & internal links as default core link widget's URL field do
* Also validation of core link 'll applied instead of writing same validation again
> 1 votes

---
Tags: forms, 8
---


# Question
Title: Render a view in a given language in a custom command
I have written a Drupal Console command that creates a huge batch of HTML snippets. This is done by rendering a view programmatically (as in this StackExchange answer)

**The task**

Now I have to create these snippets in several languages.

**This works**

If I call the view in my browser I can easily chose the language with the respective path prefix:

http://www.example.com/de/path/to/the/view (german version)

http://www.example.com/en/path/to/the/view (english version)

**This does not work**

If I try to render the very same view from a Drupal Console command I am not able to set the target language. The rendered HTML is always in the default language.

At first I thought passing the langcode in the view() method should suffice:

```
// Now render the node as HTML
$viewBuilder = $this->entityTypeManager->getViewBuilder('node');
$build       = $viewBuilder->view($node, 'full', $langcode);
$html        = $this->renderer->renderPlain($build);

```

Then I tried setConfigOverrideLanguage():

```
$this->languageManager->setConfigOverrideLanguage($language);

// … render the view here …

$this->languageManager->setConfigOverrideLanguage($originalLanguage);

```

But this did not work either. So it tried:

```
$this->configFactory->getEditable('system.site')->set('langcode', $langcode)->save();

// … render the view here …

$this->configFactory->getEditable('system.site')->set('langcode', $originalLangcode)->save();

```

But I did not succeed. I even tried using a custom LanguageNegotiator, but I ran into a fatal error due to the fact that the service 'language\_manager' does not implement the ConfigurableLanguageManagerInterface, so it is missing the setNegotiator() and getNegotiator() methods.

Once again I am totally stuck and I don't know what I am missing (most likely just a tiny bit). How in the world is it possible to change the language of my rendered HTML???

**Edit 2017-01-05:**

I have to admit I am quite desperate atm. I even tried everything I ruled out above again. Guess what, it still does not work. Any ideas? I am so shure that I am missing only a tiny piece. But I don't have any idea where to search for :(

**Edit 2017-01-17:**

Obviously the console command is not aware of (parts of) the context, even if I set the language. Just to get it done I am considering putting together a request object which I would then have been handled by the kernel. If this should turn out to be too complicated I could still curl the respective pages, but I have a feeling that there should be another way of doing this.

**Edit 2017-03-14:**

First of all there there has to be a translation (even if the node data is in no way language specific). If you want the complete context you have to use the Kernel's `handle` method with a sub request.

# Answer
You should call:

```
Drupal::service("entity_field.manager")->clearCachedFieldDefinitions();

```

after language changes.
> 0 votes

# Answer
I'm not sure if you are referring to a view mode or a view (as in views module). If it's about a view mode:

> $ ddev drush si demo\_umami --yes

> $ ddev drush php:cli

```
$node = Node:load(2);
$langcode = 'es';
$translation = $node->getTranslation($langcode);
$build = \Drupal::entityTypeManager()->getViewBuilder('node')->view($translation, 'full', $langcode);
$html = \Drupal::service('renderer')->renderPlain($build);

```

Renders in Spanish:

```
[...]
<a href="/es/recipes/bizcochos-veganos-de-chocolate-y-nueces" rel="bookmark">\n
[...]

```
> 0 votes

---
Tags: 8, console
---


title: Aegir for Drupal 10

text:
# Question
Title: Aegir for Drupal 10
With Aegir being developed in Drupal 7 and the end of life looming for this November are there plans to migrate Aegir from Drupal 7 to 10? Or can anyone direct me to where I can find the migrated version.

# Answer
> 6 votes
At the moment, Aegir 3, the current stable major version, is minimally-maintained. Vendors offering support are Omega8, Consensus, ThinkDrop, and Symbiotic (who maintains some components at github.com/coopsymbiotic). Find them all at https://docs.aegirproject.org/community/services/.

For on-going support (as Debian packages are no longer maintained):

Aegir 5 is a complete rewrite in development (https://gitlab.com/aegir/aegir/), but progress is slow due to insufficient funding. Get in touch if you'd like to help with this initiative by providing funding, developer time, or anything else. Please see the blog posts on this topic.

# Answer
> 0 votes
According to today's update, you must upgrade to Aegis 5:

> Along with the offers of support, we’ve also heard a variety of concerns about the future of the Aegir system or Aegir 5 in particular. For example:
>
> 1. Can Aegir 3 support Drupal 10?
> 2. Will there be a migration path from Aegir 3 to Aegir 5?
> 3. Does Aegir 5 support multi-site environments?
> 4. Can Aegir 5 satisfy a SaaS use-case?
>
> The first 2 of these we can answer directly:
>
> 1. No. Fundamental divergence between PHP8, D10, and Drush make this effectively impossible.
> 2. Yes! Onboarding Aegir 3 sites to Aegir 5 is a key use-case on our radar.
>
> Questions 3 and 4 warrant more detailed answers, which we plan to post about shortly, but the short answers are “sort of” and “most definitely” respectively. The Aegir 5 architecture in general is a lot more flexible, intended to enable use-case-specific pluggability.

---
Tags: aegir
---


# Question
Title: Create tabs with paragraphs and Bootstrap tabs
I'm working on a project that consists of transferring a laravel website to drupal. One of the features that I'm having difficulty recreating is separating content information into tabs. This content already exists in Drupal and is grouped into a content type.

I need to create tabs in Drupal for a type of content that uses paragraphs to separate descriptions, this is the base model made in Laravel.

>

In the content there is a paragraph called "bloco de informações" where each description and its title are separated. Here is the paragraph in the content:

>

In the Drupal views I created a block and I am using the bootstrap tab in formats to create the tabs that separate the information from the content and using an identifier in the contextual filters to get the information relating to that content when it is on your page. This part more or less worked, the paragraphs were separated into tabs but when clicking on the tabs it does not change information, the page url changes but the tab remains static and is carrying all the paragraph information relating to that content in a single tab.

>

I tried to use the "Tokens in Views Filter Criteria" module in the filter criteria to separate the paragraphs into the tabs so that the transition occurs where, when clicking on a tab, it only brings me the content information relating to that paragraph, but when doing this , with the options I tested, it didn't load anything, it was blank, nor did the tabs option appear.

What I need is to know if it is possible to separate the content by tabs with the options I have, if anyone knows a better way to do this. I've been stuck with this problem for a few days and I still can't see the light at the end of the tunnel.

# Answer
> 0 votes
Have a look at the Field group module (https://www.drupal.org/project/field\_group). With that module, you can create horizontal and vertical tabs in a certain entity's view and form display (node, for example).

I hope it helps!

---
Tags: views, blocks, tokens, paragraphs, bootstrap-theme
---