Search code examples
drupaldrupal-modulesdrupal-forms

How to add links task (tabs) on specific node (content) type through form submission?


I'm new to Drupal.
I created a custom module and made it to have link task on node type (likes View/Edit/Delete tab). It works fine and appear on every node type but now I want to exclude it on specific one that I select and submit through a form. Please tell me how can I achieve this.
mymodule.routing.yml:

mymodule.routname:
  path: '/node/{node}/custom-path'
  defaults:
   ...
  requirements:
    _custom_access: '\Drupal\mymodule\Controller\NodeAcess::access'


NodeAcess.php:

public function access(AccountInterface $account, $node) {
    $node = Node::load($node);
    $node_type = $node->bundle();
    $currentUser = \Drupal::currentUser();
    if ($currentUser->hasPermission('Bypass content access control') && $node_type != 'article') {
      $result = AccessResult::allowed();
    }
    else {
      $result = AccessResult::forbidden();
    }


    return $result;
  }


On the above function, I add the && $node_type != 'article' so the link task will not appear on the 'Article' nodes. But I want it to be dynamically when submitting form

Form


Solution

  • STEP 1

    In your case, I would create a config form for the module (src/Form/ModuleNameConfigForm.php), and I would list all the node bundles in a checkboxes render element like this in the buildForm() method:

    $nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple();
    

    The above will load all the nodes into the $nodes array, and then, you can iterate on that. (Please try to use dependency injection for the entity_type.manager service.)

    // Load the configuration of the form.
    $configSettings = \Drupal::configFactory()->get('modulename.settings');
    
    if (!empty($nodes)) {
      foreach ($nodes as $key => $node) {
        $options[$key] = $node->bundle();
      }
    }
    
    $form['disabled_node_links'] = [
        '#type' => 'checkboxes',
        '#default_value' => !empty($configSettings->get('disabled_node_links')) ? array_keys($configSettings->get('disabled_node_links'), TRUE) : [],
        '#options' => $options,
      ];
    

    Good, now we need to save the data to the configuration under the submitForm() method. To do so:

    $configSettings = \Drupal::configFactory()->get('modulename.settings');
    $configSettings
      ->set('disabled_node_links', $form_state->getValue('disabled_node_links'))
      ->save();
    

    The configuration under config/schema folder called modulename.schema.yml:

    modulename.settings:
      type: config_object
      label: 'ModuleName Settings'
      mapping:
        disabled_node_links:
          type: sequence
          label: 'Disabled links on nodes'
          sequence:
            type: boolean
    

    And the default values under config/install folder containing only 1 row without a value in modulename.settings.yml:

    disabled_node_links:
    

    STEP 2

    Create a routing for the config form where you can reach it in your Drupal (you should also create a permission for it.)

    Then, in your NodeAccess.php I would load the configuration, get the keys of it with array_keys(), and check each if the value of the configuration row is true or false. If the row is false, it means the checkbox has left empty, meaning you can return the AccessResult::allowed().


    Hope that helps, I didn't have time to create the whole module, but I hope this will guide you in a way where you can figure it out yourself what to do. Also check drupal.org on how to create config forms.