0

I am creating a Rules Action that will update the node title after it is created.

Here is my code, but when I try to create new content using Postman, it keeps loading. I dont get response in Drupal logs.

...
class ContentTitle extends RulesActionBase {

  protected function doExecute(EntityInterface $entity) {

    $entity_id = $entity->id(); // Getting dynamic entity ID
    $controller = \Drupal::entityManager()->getStorage('node');
    $node = $controller->load($entity_id);

    $title = $entity->label();
    $item = $node->get('field_xyz')->value;
    $new_title = "Title is " . $title . $item;

    \Drupal::logger('custom_rules')->notice('new_title: ' . $new_title);

    $data = array(
      'type' => 'custom_content',
      'title' => [
        'value' => $new_title,
      ]
    );
    $node = Drupal::entityManager()
      ->getStorage('node')
      ->create($data);
    $node->save();
  }
}

Im getting the expected output in the logger.

I dont think I am setting the title in $data properly. Any suggestion is greatly appreciated. Thanks!

3 Answers 3

0

You can set a node's title with the "Set a data value" action - you don't need to write your own action. I'm going to assume that you're putting this into your own action because there are other things you want to do that you haven't mentioned or because you are learning how to write an action - if this is ONLY about setting the title then I don't see the point of a custom action.

Problems with the approach and the partial solution given in the initial post:

  1. You don't need to get the entity ID then load the entity from storage, because Rules is already passing you the loaded entity.

  2. You're using entity instead of node, which wrong - Nodes have titles, Entities in general DON'T.

  3. You're hardwiring in a title taken from a specific field 'field_xyz'. Instead, you should pass in a string variable which holds the title. That way the Rule configuration can get the value out of 'field_xyz' or out of 'field_nlm' or from a thousand other places - writing the action with a string parameter will make it far more useful.

  4. The EntityManager has been deprecated since Drupal 8.0 and should not be used. You should be using EntityTypeManager instead. But as I said in #1, this isn't even needed.

  5. You don't have to save the node, Rules will handle the saving automatically.

This really only requires one line of code (plus some boilerplate code, like all plugins...). Here's a complete solution that takes two context variables:

  1. The node to change.
  2. The title to use.

namespace Drupal\my_module\Plugin\RulesAction;

use Drupal\node\NodeInterface;
use Drupal\rules\Core\RulesActionBase;

/**
 * Sets the title of a content item.
 *
 * @RulesAction(
 *   id = "rules_node_set_title",
 *   label = @Translation("Sets the title of the selected content item"),
 *   category = @Translation("Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node",
 *       label = @Translation("Node"),
 *       description = @Translation("Specifies the content item to change."),
 *       assignment_restriction = "selector"
 *     ),
 *     "title" = @ContextDefinition("string",
 *       label = @Translation("Title"),
 *       description = @Translation("The new title.")
 *     ),
 *   }
 * )
 */
class NodeSetTitle extends RulesActionBase {

  /**
   * Executes the action with the given context.
   *
   * @param \Drupal\node\NodeInterface $node
   *   The node to modify.
   * @param string $title
   *   The new title.
   */
  protected function doExecute(NodeInterface $node, $title) {
    $node->setTitle($title);
  }

  /**
   * {@inheritdoc}
   */
  public function autoSaveContext() {
    // The node should be auto-saved after the execution.
    return ['node'];
  }

}
-1

You can create node like below also:

use \Drupal\node\Entity\Node;

class ContentTitle extends RulesActionBase {

  protected function doExecute(EntityInterface $entity) {
    $entity_id = $entity->id(); // Getting dynamic entity ID
    $controller = \Drupal::entityManager()->getStorage('node');
    $node = $controller->load($entity_id);
    $title = $entity->label();
    $item = $node->get('field_xyz')->value;
    $new_title = "Title is " . $title . $item;
    \Drupal::logger('custom_rules')->notice('new_title: ' . $new_title);
    $node = Node::create([
      'type' => 'content_type',
      'title' => $new_title,
    ]);
    $node->save();
  }
}

In your code "title" should be only $new_title not in the array as value. Even your code also looks fine except that title. I didn't any try of your code but I am suggesting to use above one.

2
  • Thanks for your reply. Im getting 172.18.0.1 - - [19/Jun/2018:10:11:13 +0000] "-" 408 - "-" "-" in my access log Jun 19, 2018 at 10:15
  • This answer has all the same problems as the origin post, and doesn't provide any significant help or guidance on how to properly write a RulesAction.
    – anonymous
    Sep 24, 2020 at 0:49
-1

Simple answer from https://drupal.stackexchange.com/a/249771/70281 did the trick for me.

$node->set('title', $new_title);
$node->save();
1
  • This is not good, because if the "entity" you pass in doesn't have a 'title' property, this will fail. Entities do not in general have a title.
    – anonymous
    Sep 24, 2020 at 0:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.