Hi all

Thanks for the stable release of Rules 2! :) It's much appreciated!

I have a content type that tracks the membership of a user in a group. Initially the start date is populated and the end date will be populated at a later date. I would like to automatically populate the end date of the old node when a new node is created with a start date. (old node end date = new node start date)

I've created a view that filters the applicable nodes and added the VBO field so I can use the view in rules.

I've created a rule with the following parameters:

Event: When content is created
Condition: Content is of type
Action: Load VBO list
Action: Loop through VBO list
Action: Set a data value (this is where I'm stuck)

The list item doesn't have a type, thus I cannot update the field_end_date of the item, despite the content type being set during the condition.

How to I assign a type to a list item so I can update the field?

Comments

gillarf’s picture

Component: Rules Core » Rules Engine

I have a similar issue - i can't access the variable set in the loop, as it is not available in the data selector.

I want to set access permissions to a set of users provided by the view. Export below (without loop variable as it is not available).

I can't use "condition 'entity has field' (or 'content is of type')"

{ "rules_allow_acces_to_friends" : {
"LABEL" : "Allow access to friends",
"PLUGIN" : "reaction rule",
"REQUIRES" : [ "views_bulk_operations", "content_access_rules", "rules" ],
"ON" : [ "node_insert" ],
"DO" : [
{ "views_bulk_operations_action_load_id_list" : {
"USING" : { "view" : "all_users|default" },
"PROVIDE" : { "entity_id_list" : { "entity_id_list" : "A list of entity ids" } }
}
},
{ "LOOP" : {
"USING" : { "list" : [ "entity-id-list" ] },
"ITEM" : { "friend" : "Current list item" },
"DO" : [
{ "content_access_action_user_grant" : {
"node" : [ "node" ],
"content_access_user_view" : [ "" ],
"content_access_user_update" : [ "" ],
"content_access_user_delete" : [ "" ]
}
}
]
}
}
]
}
}

gillarf’s picture

Category: support » bug

should probably be a bug i think - does not work as expected

fago’s picture

Category: bug » support

use components

mbouchard58’s picture

Sorry, but I don't see how using Components helps (at least it doesn't help me). I've added a boolean field called "Active" to a custom content type (I've also tried this with Taxonomy). There will be multiple pieces of content of this type but only one can be Active. When the user sets one to Active I want to fire a rule which makes the previously Active content inactive. I created a view which selects the current active content and added a VBO field to the view.

My rule checks for my custom content type and that the entity has the Active field. My Active field appears in the Conditions sections when I choose Data Comparison -- so far so good. In the Action section, however, it doesn't. I create a loop through my VBO view. I attempt to Set a Data Value, but the Active field is not one of the choices in the Data Selector.

I have the same problem with Components, only more so. I am sure I am thinking about this the wrong way, i.e., the non-Drupal way. I've looked at screen casts and read documentation but everything is either too generic or using built in functionality (like "Promote to Front Page").

I am open to suggestion and will appreciate any advice.

Thanks

mbouchard58’s picture

OK, so I got my rule to work using components as fago suggested (was there ever a doubt?) but I don't understand why I had to. I document what I did just in case someone else has this problem and finds this thread.

I created the rule as mentioned in #4 except that now I'm working with taxonomy terms which is what I wanted in the first place.
I created a Component of type Rule which accepts one Taxonomy term as a parameter (called Active Semester but you can call it anything you want). For conditions it has:
Entity is of Type: Taxonomy Term
Entity has Field: field_tax_sem_active
The Action of the rule is to Set Data Value of field_tax_sem_active to 0 (i.e., No; it's a boolean).

Then in my main rule (i.e., not the component), I call this Component from within the Loop I created under the VBO view passing in the taxonomy term to the component from the view.

It works, but I don't understand why I need to create a Component Rule when the View already has the criteria I want. I am "Loading a list of entity objects from a VBO View" not just the entity id's. It seems to me since my custom field is on the view and it's mentioned on the conditions for the main rule, I should be able to use it in actions without using a component. What am I missing?

Main Rule:
{ "rules_one_active_semester" : {
"LABEL" : "One Active Semester",
"PLUGIN" : "reaction rule",
"REQUIRES" : [ "rules", "views_bulk_operations", "taxonomy" ],
"ON" : [ "taxonomy_term_presave" ],
"IF" : [
{ "entity_is_of_type" : { "entity" : [ "term" ], "type" : "taxonomy_term" } },
{ "entity_has_field" : { "entity" : [ "term" ], "field" : "field_tax_sem_active" } },
{ "data_is" : { "data" : [ "term:field-tax-sem-active" ], "value" : 1 } }
],
"DO" : [
{ "views_bulk_operations_action_load_list" : {
"USING" : { "view" : "semesters|default" },
"PROVIDE" : { "entity_list" : { "semester_list" : "Semester list" } }
}
},
{ "LOOP" : {
"USING" : { "list" : [ "semester-list" ] },
"ITEM" : { "active_semester" : "Active Semester" },
"DO" : [
{ "component_rules_deactivate_semesters" : { "active_semester" : [ "active_semester" ] } }
]
}
}
]
}
}

Component:
{ "rules_deactivate_semesters" : {
"LABEL" : "DeActivate Semesters",
"PLUGIN" : "rule",
"REQUIRES" : [ "rules" ],
"USES VARIABLES" : { "active_semester" : { "label" : "Active Semester", "type" : "taxonomy_term" } },
"IF" : [
{ "entity_is_of_type" : { "entity" : [ "active-semester" ], "type" : "taxonomy_term" } },
{ "entity_has_field" : { "entity" : [ "active-semester" ], "field" : "field_tax_sem_active" } }
],
"DO" : [
{ "data_set" : { "data" : [ "active-semester:field-tax-sem-active" ], "value" : 0 } }
]
}
}

Thanks very much to Johan Falk and NodeOne for providing such excellent training!

nicodv’s picture

same problem here

nicodv’s picture

@fago: can you be more specific?

For what I see, if I load any VBO list of users (not content) I have access to all the fields of the users in that view from rules, no conditions, no extra effort required. But in the moment I use a VBO view of content, no field is available from rules... yes if I provide a parameter and act on it from rules, but if the vbo list is independent from the parameter provided: i get no access to its fields (hope I explained myself)

I hope I'm missing something, because it's been 5 hours trying all variants I could think of, even the craziest.

Any extra help will be really appreciated.

Thanks in advance

nico

nicodv’s picture

Well, I found a correct workaround (for me at least) At a first glance it is only useful for checkbox/radio button-type of problem.
Instead of trying to get the field out of the VBO list, to later set a data value from rules, the idea is to use the flag module, and after loading the VBO and looping in it, flag or unflag the resulting node-item brought by the loop. It works great!!

I can imagine you can later do some 'magic' creating a rule with an event based on A node has been flagged or unflagged and an action like populating a field of that node... but I haven't tried that.

Hope this works for you.

PS: I really think rules needs a new feature in this case...but I still love rules very much :) (very!)

nico

cliff98109’s picture

Component: Rules Engine » Rules Core

I seem to be having the same problem, inside of an event action I can't access the fields of the content type retrieved by the VBO operation, has anybody figured out a way of doing this?

gillarf’s picture

@cliff98109 Are you using components? I did this yesterday on a VBO and as Fago says, you need to use components.

All fields for the content type were available for me to operate on.

gillarf’s picture

Here's a great video from Johann Falk that I have to refer back to every time I do this :-)

http://nodeone.se/en/using-rules-components-with-vbo

Anonymous’s picture

I agree the video is helpful. However, there is a trick required to access the fields. Below is an email excerpt from Johan Falk that enabled me to solve this issue.

To be able to manipulate fields in Rules, you must first run the
"entity has field" condition (or any equivalent, such as "entity is of
bundle"). Unfortunately, you cannot add conditions inside loops, so
this is a bit tricky.

The workaround is to create a *component* that runs the condition
check, and then sets any field values. Then this component can be
called from within the loop. //Johan Falk, Sweden

I did exactly what Johan told me to do. For a little background I am using VBO to loop through a list of nodes and need to change one of my custom fields (a select list) in that node. So I created a component (rule set) , for simplicity let's call it "sub component A" and included in variable: data type = node, label = node, machine name= input_node. These last two you could name them whatever you want.

Then I added a rule, call it what you want. Next, add a condition and select entity has a field. As for the data selector you need to use the machine name from earlier - input_node, don't drill down. And then under "FIELD" select the value of the field you are looking for... "field_customname".

Finally I added in my action - in my case "set a data value" and for the data selector I drilled down to input_node:field_customname (it was the very last entry). From there I just set the value , saved and then went back to my loop and "add action" within the loop (see Johans video mentoined in the prior post #11 if you're lost), The action is components and I selected "Rule set:sub component A". Next , the selector to choose is the one for the current list item, no drill down needed as you just pass in that current node.

I executed my component and ba-da-bing, it worked - after 3 days of banging my head against a wall. Hope this helps someone else!

soulston’s picture

One thing that can make a difference as to what elements are available to use in your data selector is the nesting of the action i.e. have you moved it out to the right within the loop. Sadly for setting data values you can't go back and alter the data selector after adding it like you can with say adding a flag.

For example when you initially add a new action to flag a user, the only option available is "entity-list", however, if you save this, then nest the action within the loop and go back in to edit it you can then choose "list-item", or whatever variable you decided to loop over.

j.johnson.bbt’s picture

For three days I've been trying to get this to work.

My goal is simple. Add all the prices of a particular node using rules loops and VBO list import. After I've got my crap pile, I want to insert that into my newly created node. Great for autobilling, but this is the only part that isn't working for me!

I'm validating just fine, but the data isn't going through. I almost wonder if it's that loops is broken on my website. Here are my components:

{ "rules_create_monthly_invoice" : {
    "LABEL" : "Create monthly Invoice",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "views_bulk_operations" ],
    "USES VARIABLES" : {
      "user" : { "label" : "Hotel Affiliate", "type" : "user" },
      "crap_pile" : { "label" : "crap pile", "type" : "decimal", "parameter" : false }
    },
    "IF" : [
      { "user_has_role" : { "account" : [ "user" ], "roles" : { "value" : { "4" : "4" } } } }
    ],
    "DO" : [
      { "data_set" : { "data" : [ "crap-pile" ], "value" : "0" } },
      { "views_bulk_operations_action_load_list" : {
          "USING" : { "view" : "list_of_billing_items_for_month|default", "args" : [ "" ] },
          "PROVIDE" : { "entity_list" : { "list_of_billing_items" : "list of billing items" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "list-of-billing-items" ] },
          "ITEM" : { "current_billing_item" : "Current billing item" },
          "DO" : [
            { "component_rules_validate_list_of_billing_items" : { "current_billing_item" : [ "current_billing_item" ] } }
          ]
        }
      },
      { "entity_create" : {
          "USING" : {
            "type" : "node",
            "param_type" : "hotel_affiliate_invoice",
            "param_title" : "Test title[site:current-date]",
            "param_author" : [ "user" ]
          },
          "PROVIDE" : { "entity_created" : { "entity_created_invoice" : "Invoice" } }
        }
      },
      { "data_set" : {
          "data" : [ "entity-created-invoice:field-total-due:amount" ],
          "value" : [ "crap-pile" ]
        }
      }
    ],
    "PROVIDES VARIABLES" : [ "crap_pile" ]
  }
}

{ "rules_validate_list_of_billing_items" : {
    "LABEL" : "validate list of billing items",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : {
      "current_billing_item" : { "label" : "current billing item", "type" : "entity" },
      "crap_pile" : { "label" : "crap pile", "type" : "decimal" }
    },
    "IF" : [
      { "entity_has_field" : {
          "entity" : [ "current-billing-item" ],
          "field" : "field_total_add_bill"
        }
      },
      { "entity_has_field" : { "entity" : [ "current-billing-item" ], "field" : "field_year_month" } }
    ],
    "DO" : [
      { "data_calc" : {
          "USING" : {
            "input_1" : [ "current-billing-item:field-total-add-bill:amount-decimal" ],
            "op" : "+",
            "input_2" : [ "crap-pile" ]
          },
          "PROVIDE" : { "result" : { "shovel" : "Calculation result" } }
        }
      },
      { "data_set" : { "data" : [ "crap-pile" ], "value" : [ "shovel" ] } }
    ]
  }
}

When I run it, I'm getting the node created. But my value keeps coming up as zero or just doesn't show up at all. What am I doing wrong? Can anyone explain the difference between amount and amount decimal? Where is the data value stored for "price" fields? I've tried both ways but this looping business is stubborn. Thanks in advance!

gatorjoe’s picture

Issue summary: View changes

#12, emag thank you so much! This was the solution to the problem for me.

kasiawaka’s picture

Thanks for all the posts here, that helped me understand how to change a field value on a node that is provided by VBO. Here is my interpretation and working example if that helps anyone.

If you want to have a Rule that will loop through the list of entities provided by VBO view and set a value on one of the fields of that entity, we need to do the following:

1. Create VBO view

VBO view is a regular View but with VBO bulk operations as one of the fields. Set any conditions and fields on the view to generate a list of results (for example nodes) that the Rule is suppose to loop though later.

2. Create the main rule.

  • Set the event you want to execute the rule on. In my case, the event is "Content is viewed of type Page", I want some actions to be done on other content type on the site.
  • Set the conditions. In my case, the only condition was to check the number of results from VBO view (created in #1) and if that view has at least one result, proceed with actions.
  • Create actions. This is where all the fun and magic happens.
  1. First, we need to have entities to operate on, so the first action will be "Load a list of entity objects from a VBO View." and pick a view and display to use (from #1). I left the variable name "entity_list"
  2. Loop through the results of the view. Because the results of the view are loaded to "entity_list" (as the machine name selected above), so loop though Data Selector = entity-list and "save" the results in a variable called "list_item" (of course, change that to whatever you want, but keep it consistent later on, when referring to it)
  3. Now, you can for each item from the list perform some actions. But, if I want to change the fields on a node, you may noticed that those fields are not available here. To access them and change their value (using "Set a data value"), we need to have a rules component where we will manipulate that field value. The component will manipulate the one entity that is passed to it from the list_item. Follow #3.

3. Create the rule component

Go to Rules Component: /admin/config/workflow/rules/components. That component that will let us set the data value on a field.

  1. Component type: Rule
  2. Name: important only to you so that you know what component to pick back in the main Rule later
  3. Variables. Data type = Node, Label = Input node, Machine name: input_node, Type: Parameter. You can chose anything for Label and Machine name but remember what you are using to refer to it later on in this component
  4. Conditions. You will need one condition "Content is of type" (to pull all the fields from that content type), with Data selector = input-node and Content Type = your content type you are manipulating. This can also be a user entity etc. Second condition will check for that particular field we want to manipulate, so it will be "Entity has field" with Data selector = input-node and Field value = the field you want to manipulate in actions
  5. Actions. This is the part we could not do in the main Rule because the field wasn't available to us. Now, we can access that field and change its value. The action will be "Set a data value" and Data selector: input-node:field-your-field-name and under Value: select the value (if it's a radio button or checkbox) or enter manually
  6. Save the component

4. Tell the main rule from #2 that in the loop, we want to use that component from #3.

Under the Loop, select "Add action", pick the component you want to do the action (component name from #3) and set Date selector: list-item because we want the component to perform an action (change field value) for every node from the list (which is a list of nodes from VBO view from #1). To tell if this is going to work, under that Component item in the main rule, you should "rule: Name of your component" and Parameter: Input node: [list-item] - the last one basically says that we are taking list-item from the Loop and send it to the Component which is listening for it under the variable "Input node".

It took me several days to process all the pieces and understand how this works so hopefully this lengthy explanation will save someone else some time. Good luck!

kasiawaka’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

charly71’s picture

Hi kasiawaka,

I've followed your process but something goes wrong: in my case I would like to "Set a data value" AND publish the content node. Well, the rule works fine on already published nodes, but it completly ignores unpublished nodes in the VBO...
There is some issue with VBO and rule's permission? Does the rule get both unpublished and published content? There is any permission setting to add?

Thanks

leoklein’s picture

#16 Hats off to kasiawaka!

My goal: Find nodes past an expiration date and change workflow to 'expired'.

I haven't got the thing to properly loop -- it only does one node per cron -- but there's light at the end of this painfully long tunnel.

Thanks!

LEO

leoklein’s picture

Re: #16 Hats off to kasiawaka!

Bingo! Put the loop in the component and voila!

LEO

florin_yonescat’s picture

#16 This works well if you have hard coded values, but what if I want to update the content from VBO with content from the node that is being updated or created now (Event: After updating existing content of type)?