//i would like to use a Drupal function named field_attach_update() for certain nodeids
$node = node_load($nid);
$node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'some value';
field_attach_update('node', $node);
I need to create a function, and place it in drupal folder, and run it for thousands of nodes. I have the node ids i want to change their subfields value.
How the above code should be altered so as to change only the subfields value, and give as parameter all nodes that i need the change to be done?
I would like to use drush to run the function
And for sure something like is not a good solution...(perhaps i should add some timer between each save? i need to update 20k nodes, and not crash our server that hosts drupal)
$node = node_load(123);
$node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'some value';
field_attach_update('node', $node);
$node = node_load(124);
$node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'some value';
field_attach_update('node', $node);
...
In my opinion, BatchApi will be the better solution for this. I prefer VBO only under 1k nodes for bulk updates.
Here is a helpful post for Batch on a custom drush command:
https://www.metaltoad.com/blog/using-drupal-batch-api
Related
I have a content type "about" created in Drupal 7. I have a field collection named "field_usf_projects" which is set to unlimited and contains 2 fields, "usf_title" and "usf_description". Now I want to run a for loop which retrieves the field_usf_projects and then displays 2 fields namely ("usf_title" and "usf_description") inside a ul - li structure.
I have gone through many links but cannot find a working solution. Please help me with this.
Thanks in advance.
Here is my solution, on hook_node_view you can use the entity wrapper to get the fields
function mymodule_node_view($node, $view_mode, $langcode) {
// Check if the node is type 'about'.
if ($node->type != 'about') {
return;
}
// Get the contents of the node using entity wrapper.
$node_wrapper = entity_metadata_wrapper('node', $node);
// Get the contents of the field collection.
$values = $node_wrapper->field_usf_projects;
// Loop field_usf_projects.
foreach ($values as $item) {
// Print the values of the fields.
var_dump($item->usf_title->value());
var_dump($item->usf_description->value());
}
}
Instead of dumping, you can add the markup for your
A nicer thing to do would be use the hook_preprocess_node to add the markup straight into the $variables, and print them via template.
https://api.drupal.org/api/drupal/modules!node!node.module/function/template_preprocess_node/7
I can tell you how I'm handling this, event it's a bit dirty and I'm risking to be crucified, but it works for me. If you are inside node template you have $node object. Print it with print_r or similar way and just follow the structure of output to get to your data. It will probably be something like:
$node->field_usf_title['und']...
If you don't have that $node object find node id and load the node with
$node = node_load($nid);
first.
I was finally fed up with Field collection. I cannot get any data. I have used Multifield which is way too much better than Field collection. Please see it at https://www.drupal.org/project/multifield
Let me know what is better multi field or Field Collection.
Thanks!
I'm new to Drupal. I looked here and on google for a while before asking, but I'm sure I can't find the answer because I don't know how to ask the question.
Here is what's going on. I'm using a custom module to load certain entities and then output them in a specific format for an application to access. The problem is that the NODE BODY contains special information and media files that should be converted. My goal is to obtain the HTML output that would normally be used on this field.
// Execute an EntityFieldQuery
$result = $query->execute();
if (isset($result['node'])) {
$article_items_nids = array_keys($result['node']);
$article_items = entity_load('node', $news_items_nids);
}
// Loop through each article
foreach ($article_items as $article) {
return $article->body[LANGUAGE_NONE]['0']['value'];
}
All of this works great. The only problem is that I get things like this in the output:
[[{"type":"media","view_mode":"media_original","fid":"283","attributes":{"alt":"","class":"media-image","data-thmr":"thmr_32","height":"400","width":"580"}}]]
or
*protoss_icon*
My goal is to find a way that these items are converted just like they are when these articles are viewed normally.
I've tried doing things such as:
render(field_view_field('node', $article, 'body'));
or
render($article->body[LANGUAGE_NONE]['0']['value']);
without success. Thanks for any help, I'm learning so I don't have a complete grasp of the process drupal uses to build output.
You can try something like this (this works only with nodes not with other custom entity types):
$node = node_load($nid);
$field = field_get_items('node', $node, 'your_field_name');
$output = field_view_value('node', $node, 'your_field_name', $field[$delta]);
the field_view_value returns a renderable array for a single field value. (from drupal api documentation)
I'm using Drupal 7 + Rules. I would like to create a rule that unpublishes all nodes authored by a user when they have been given a particular role.
EVENT - After updating an existing user account
CONDITION - User has role(s): SelectedRole
ACTION - ???
BONUS: If this could be limited to nodes of a certain type, that would be even better.
If there is a better way outside of Rules to do this, I'm open to other ideas.
Thanks so much!
You can create a custom ruleset to loop through the nodes or a Views Bulk Operation action.
An easiest option is to add a custom PHP function on your rule (PHP > Execute custom PHP code). Of course you have to enable the php filter core module if you didn't already.
In the PHP action you have to get all the nids of the published nodes the current user and loop through them to unpublish them. I will use the EntityFieldQuery API class but you can use the database functions also.
// Get updated user id
$uid = $account -> uid;
// Get all nodes from user that are of NODE_TYPE and are published
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'NODE_TYPE')
->propertyCondition('status', 1)
->propertyCondition('uid', $uid);
$result = $query->execute();
$nids = array_keys($result['node']);
// Load all nodes in one go for better performance.
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
// set status property to 0 (unpublished)
$node->status = 0;
// re-save the node
node_save($node);
}
I would also suggest to add one more Condition for the user before the one you are using: User Has Roles: (NOT) SelectedRole so that the action do not run everytime the user profile is updated.
References:
Use Rules to Unpublish content based on Author's role
Publish unpublished node programmatically
Find nodes created by user (more programmatically)
I have a content type that has unlimited filefield fields in addition to other fields. At node save/submit I would like to create an additional node for each file in the field, and assign that filefield to it. I'm fine with the nodeapi hooks and progmatically creating the node, but I can't access the content of the filefield from the node. When I print the filefield contents from within hook_node_insert I get:
...
(
[fid] => 38
[display] => 1
[description] =>
[upload_button] => Upload
[remove_button] => Remove
[upload] =>
)
....
Not the formatted and proceed field I would normally see. My suspicion is that I can access this somehow from the form and do a form submit after modifying it, but I'm not sure how to do this and it may not the best way. Let me know if you have any tips on this, greatly appreciated.
since we have [fid] populated we can use file_load($fid) to load the file object. Then you can cast this file object to array and then attach it to the file field of newly created node.
Loop through the array and for each $fid you encounter..
$file = file_load($fid);
$new_node= new StdClass();
$new_node->type = 'image';
$new_node->language = LANGUAGE_NONE;
node_object_prepare($new_node);
// add additional data about new node.
$new_node->field_custom_files[LANGUAGE_NONE][] = array($file);
node_submit($new_node);
node_save($new_node);
I have not tested this, but do let me know if you face any issues.
I have a Drupal content type which contains a number of computed fields. Some (but not all) items are being added to this content type via a cron-triggered RSS feed importer. I'm trying to trigger computed field generation for new items in hook_cron. The following code grabs all items that haven't been tagged as 'submitted', loads and re-saves the node, and then marks the node as 'submitted'.
$query = db_select('node', 'n');
$query->fields('n', array('nid'));
$table_alias = $query->join('field_data_field_submitted', 'r', 'n.nid = r.entity_id AND r.field_submitted_value = 0');
$result = $query->execute();
foreach ($result as $record){
$q = $record->nid;
$n = node_load($q);
node_save($n);
$query = db_update('field_data_field_submitted')
->fields(array('field_submitted_value' => 1))
->condition('entity_id', $q)
->execute();
}
This code works the way I expect it to if I call it from a module-generated page (created using hook_menu with a page callback function). Nodes are resubmitted, and the computed field data is generated. When I put this code in my hook_cron function, the query works, it loops through the records and updates the 'submitted' value, but the computed fields are not computed. I'm confused as to why this would not get triggered in cron. Any help?
Doh! Finally realized that this was completely my own doing. Due to the nature of this content type, where we allow anonymous users to create new content, but explicitly do not trigger the computed fields when they create the content (long story, but short form is that authenticated users then verify & enhance this content, which is where the computed fields come in). So, as I was setting up the initial content, I disabled the computed fields for anonymous users (if $user->uid > 0), and completely forgot about that. Once I tweaked that logic to allow computed fields to be processed on import (triggering it with a field that has a value for the imported content, but not for other content), the problem was solved.
The cron run has access to the full bootstrap so there's no logical reason why your code would produce different results in that context.
That said, you're only updating the field_data_field_submitted table when you also need to update the field_revision_field_submitted table, so that might somehow account for the discrepancy.
Drupal provides an API for the field system so that these sorts of problems can be avoided completely. The same code you've used, rewritten the 'Drupal' way, would be:
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
->fieldCondition('field_submitted', 'value', 0);
$results = $query->execute();
if (!empty($results['node'])) {
$nodes = node_load_multiple(array_keys($results['node']));
foreach ($nodes as $node) {
$node->field_submitted[$node->language][0]['value'] = 1;
node_save($node);
}
}
I can't think of a good reason why the above code would fail on cron either so it might be worth giving it a whirl.