Drupal StackExchange

Automatically trigger Acquia pipelines job when content is updated

3 days 10 hours ago

My team is fetching a large portion of our site's content at build time by using the i18n Gatsby plugin and downloading content from Drupal. The content we are fetching at build time rarely needs to be changed, but when it does, we now have to manually run an Acquia pipelines job and deploy the new artifact in order to display the updated content. This is inconvenient and time-consuming, especially since the content authors making these changes are typically not folks who have access to run a pipelines job or deploy a build.

Is there a straightforward way to automatically trigger a pipelines job when content is updated/added/deleted in Drupal? So far, the only solution my teammates and I have been able to think of is to use the Drupal Webhooks module to trigger a GitHub workflow, which would then do something like create a GitHub tag, which we could then configure to trigger a pipelines job. (We currently have our repo set up to start a pipelines job whenever a PR is opened in GitHub.)

Can we do this in a less roundabout way, for instance by using the Drupal Webhooks module to directly start a pipelines job in Acquia? From what we could tell, there isn't a way to do this, but it would be nice to avoid having to go through so many steps to set it up.

Also, is there a way to automatically deploy artifacts to a given environment? (I don't think we would want to do this in production, because it seems kind of risky, but might be nice to have it set up this way for one of our lower environments.)

Thank you in advance!

Amy

Minimum number of selections required

3 days 10 hours ago

Is it possible to require at least 5 out of 10 checkbox options to be selected in one web form field usung webform_validation module or built in custom properties?

I'm new to Drupal 10. In Drupal 7, I was using webform_validation and "Minimum number of selections required".

I could, but I don't want to use hooks nor custom functions.

Artur Śmigielski

Dynamic select lists in ajax configuration form [closed]

3 days 10 hours ago

I have a module in drupal 9 with a configuration form in the back office, I saw multiple answers on the web but none of them was optimized and compatible with drupal 9. In this form, the admin has to choose between two radio button options "Import" and "Export", and based on this choice, a select list called import_country_select or another completely different one called export_country_select, will be displayed. I will only put the code for the import_country_select case. Once import_country_select changes, the admin will choose two preferred cities which are two distinct select lists preferred_city_number_1 and preferred_city_number_2 listing different cities belonging to the previously selected country (I will only put the code for the "preferred_city_number_1").

1- Is my code correct or can it be optimized? I saw some posts stating that it's not recommended to return a form element in the ajax callback, it's better to return a response, but I didn't know what to write in my case.

2- My second concern is that I saw some examples where they do $form_state->setRebuild(TRUE); in the callback, why is that being used?

3- '#validated' => 'true', Is it correct to use to solve the "Illegal choice detected" error ?

4- In my method, I create the preferred_city_number_1 with an empty options array. Is there a way to add this form element on ajaxCallback instead of creating it first then only populating its options on callback?

5- And lastly, after some research I didn't quite understand whether or not we should use form_state inside the scope of buildForm.

/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state): array { $config = $this->config('mymodule.settings'); $form['first_section'] = [ '#type' => 'details', '#title' => $this->t('Export/Import Settings'), '#weight' => 1, '#collapsible' => TRUE, ]; $form['first_section']['export_or_import'] = [ '#type' => 'radios', '#title' => $this->t('Do you want to use this module for export or import?'), '#options' => [ 'option_import' => $this->t('Import'), 'option_export' => $this->t('Export'), ], ]; $form['first_section']['import_country_select'] = [ '#type' => 'select', '#title' => $this->t('Choose a country:'), '#empty_option'=> $this->t('-Select-'), '#options' => [ 'country_1' => $this->t('France'), 'country_2' => $this->t('Belgium'), 'country_3' => $this->t('Canada'), ], '#states' => [ 'visible' => [ ':input[name="export_or_import"]' => ['value' => 'option_import'], ], ], '#ajax' => [ 'callback' => '::selectUpdateAjaxCallback', 'event' => 'change', 'wrapper' => 'replace-select-div', 'progress' => [ 'type' => 'throbber', 'message' => $this->t('Loading...'), ], ] ]; $form['first_section']['import_preferred_cities'] = [ '#type' => 'details', '#title' => $this->t('Preferred cities (Import)'), '#weight' => 1, '#collapsible' => TRUE, '#states' => [ 'visible' => [ ':input[name="export_or_import"]' => ['value' => 'option_import'], ], ], ]; $form['first_section']['import_preferred_cities']['preferred_city_number_1'] = [ '#type' => 'select', '#title' => $this->t('Select your preferred city:'), '#empty_option'=> $this->t('-Select-'), '#options' => [], '#states' => [ 'visible' => [ ':input[name="export_or_import"]' => ['value' => 'option_import'], ], ], '#prefix' => '<div id="replace-select-div">', '#suffix' => '</div>', '#validated' => 'true', ]; return parent::buildForm($form, $form_state); } public function selectUpdateAjaxCallback(array &$form, FormStateInterface $form_state) { $citiesByCountry = [ 'country_1' => ['Paris', 'Lyon'], 'country_2' => ['Brussels', 'Leuven'], 'country_3' => ['Toronto', 'Ottawa'], ]; $selectedOption = $form_state->getValue("import_country_select"); $form['first_section']['import_preferred_cities']['preferred_city_number_1']['#options'] = $citiesByCountry[$selectedOption]; return $form['first_section']['import_preferred_cities']['preferred_city_number_1']; }
de2

How can I create a dynamic page? [closed]

3 days 10 hours ago

I'm a Drupal beginner. I want to create a page to list the tours and add a section that can contain some filters (price, destination, traveler rating, and date).

What is the best solution for this? Should I create a view?

Mohamed Ouhammou

Restrict translation and editing of node to one language

3 days 11 hours ago
Edit

I found this in Workbench Access issue queue: https://www.drupal.org/project/workbench_access/issues/2982941#comment-12670744

It seems as if I need to deactivate the translate *bundle* *node* permissions, because if those are set, the permission will be short circuited and no other access restrictions may apply, and create a hole bunch of new *translate *bundle* *node* *language* permissions on my own. In my case we have 15 node types and 6 languages. That would result in 90 new permissions. That is overwhelming.

Original Question

I'm trying to restrict the access to creating and editing of nodes in the Drupal admin section to only one language for a user. I didn't find a module which provides for this feature. Is there any module that does this?

I then tried to create my own module. I came up with this solution

File: custom_i18n_access.module <?php use Drupal\node\NodeInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Access\AccessResult; /** * Implements hook_node_access(). * * Prevent editor role to edit and/or delete fr/en nodes. Quick and dirty. */ function custom_i18n_access_node_access(NodeInterface $node, $op, AccountInterface $account) { $roles = $account->getRoles(); if (in_array('administrator', $roles)) { return AccessResult::neutral(); } if ($op !== 'update' && $op !== 'delete') { return AccessResult::neutral(); } // Access should be restricted only if this permission is set if (!$account->hasPermission('custom_i18n_access_restrict')) { return AccessResult::neutral(); } $current_language = \Drupal::languageManager()->getCurrentLanguage(); $lang = $current_language->getId(); if ($account->hasPermission("custom_i18n_access_{$lang}_allow")) { return AccessResult::neutral(); } return AccessResult::forbidden(); } File: custom_i18n_access.permissions.yml permission_callbacks: - Drupal\custom_i18n_access\Permissions::permissions File: src/Permissions.php <?php namespace Drupal\custom_i18n_access; class Permissions { public function permissions() { $languages = \Drupal::languageManager()->getLanguages(); $permissions["custom_i18n_access_restrict"] = [ 'title' => t("Restrict language access"), 'description' => 'Restrict the edit access of nodes', ]; foreach($languages as $lang) { $permissions["custom_i18n_access_{$lang->getId()}_allow"] = [ 'title' => t("Allow to edit @lang content", ['@lang' => $lang->getName()]), ]; } return $permissions; } }

This custom module successfully restricts the editing and deleting of existing content to only the language I specified in the permissions. But it does not prevent new translations of the content into other languages.

As I see it, the HOOK_node_access hook is not called for every language when on the translations subtask page. How can I achieve this? Is there a different hook for that? I didn't find any help online.

yunzen

Making File Field description required

3 days 14 hours ago

My users always skip adding the "description" to the file field because they can. I tried implementing the code posted here:

How do I make Drupal File Description Field Required?

(and thank you) -- but I have a question. My users now do see a red asterisk suggesting that the description is required ... but if they do not enter a description, they may still click save and create the node ... with no description entered in the box. Any ideas on how to get this to really force the issue and require the description?

drupal curious

Upgrade Status module reports PHPUnit\Framework\TestCase is not an interface

3 days 15 hours ago

Our site is running Drupal 8.8.13 and we want to move to Drupal 9. I've installed the Upgrade Status module v3.3. When I scan a module, like Admin Toolbar, it reports the problem:

web/modules/contrib/admin_toolbar/admin_toolbar_search/admin_toolbar_search.module Internal error: PHPUnit\Framework\TestCase is not an interface Run PHPStan with --debug option and post the stack trace to: https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md

Lots of other modules have the same problem.

Is this warning legit? or is there a problem with the configuration of Upgrade Status module?

bwaindwain

How to make a GET request to return Entity Registration form fields?

3 days 15 hours ago

I am using Drupal as a decoupled CMS with Entity Registration module, and would like to get the Registration Type form fields to display on my SPA.

I have enabled the REST resource:

/entity/entity_form_display/{entity_form_display}

I am making the GET request replacing entity_form_display with the ID of my Registration Type 'myform' showing in the URL here:

/admin/structure/registration-types/{type}/edit

Curl/ Postman URL:

http://mydomain.com/entity/entity_form_display/myform?_format=json

I get 404 Not Found:

"message": "The \"entity_form_display\" parameter was not converted for the path \"/entity/entity_form_display/{entity_form_display}\" (route name: \"rest.entity.entity_form_display.GET\")"

ChatGPT is suggesting " I specify {entity_form_display} as a parameter in the endpoint definition for a Drupal REST API resource by defining a custom route .."

I am hoping, and do not believe I need to do this, as the entity resource shows to be enabled in Drupal admin.

I have no trouble making REST requests to other resources.

Drupal 10.2.5 PHP 8.3.6 Entity Registration 3.1 Simple OAuth 5.2 Serialization

Thanks for your time.

Brownrice

Node Form Not submitting on ctool modal

3 days 16 hours ago

I have a custom form, on submission of which I am calling ctools modal with a node form(content type: turn).

Code for Custom Form.

function _my_module_name_files_listing_form($form, &$form_state) { $form = array(); $form_state['storage']['values'] = $files; $form['download_submit'] = array( '#type' => 'submit', '#value' => t('Download'), '#submit' => array('_my_module_name_files_download_submit'), ); $form['create_segment'] = array( '#type' => 'submit', '#value' => t('Create Segment'), '#attributes' => array('class' => array('ctools-use-modal')), '#ajax' => array( 'callback' => '_my_module_name_files_create_segment', ), ); $form['upload_content'] = array( '#type' => 'submit', '#value' => t('Upload Content'), '#submit' => array('_my_module_name_files_upload_content'), ); $form['delete_submit'] = array( '#type' => 'submit', '#value' => t('Delete'), '#submit' => array('_my_module_name_files_delete_submit'), ); return $form; }

Callback code for ajax submission rendering node form.

function _my_module_name_files_create_segment($form, &$form_state) { global $user; $form_id = 'turn_node_form'; ctools_include('node.pages', 'node', ''); ctools_include('ajax'); ctools_include('modal'); ctools_modal_add_js(); ctools_add_js('ajax-responder'); $destination = 'node/1'; $form_state = array( 'ajax' => TRUE, 'title' => t('Form Title'), ); $node = (object) array( 'uid' => $user->uid, 'name' => (isset($user->name) ? $user->name : ''), 'type' => 'turn', 'language' => LANGUAGE_NONE, 'status' => TRUE, ); $form_state['build_info']['args'] = array($node); $output = ctools_modal_form_wrapper($form_id, $form_state); if (!empty($form_state['ajax_commands'])) { $output = $form_state['ajax_commands']; } if (!empty($form_state['executed'])) { $output = array(); // Redirect to destination. $output[] = ctools_ajax_command_redirect('node/8', 0); } print ajax_render($output); drupal_exit(); }

Problem: Node Form is coming fine on modal and hitting save button triggers ajax call but node form does not submit. Am I missing something here?

arpitr