Drupal : Modify node - hook_node_insert / hook_node_insert - drupal

I have a problem with Drupal 7, I have a content type named "server", wich contains different fields :
hostname
CPU speed
...
The field hostname is entered manually. The others field must be entered progamatically.
So I specified a hostname and a function must search the information (CPU speed, ...) and fills the empty fields.
But I don't manage to update my node. I tried the functions hook_node_insert and hook_node_insert. When I print the node before (1) and after (2) the use of theses functions I can see the difference. But when I access the node http://localhost/drupal/?q=node/32 modifications have disappeared.
Here is a part of my function :
function module_node_presave($node) {
if ($node->type == 'server') {
dpm($node); //(1)
$node->field_server_cpu_speed[LANGUAGE_NONE][0]['value'] = 55;
dpm($node); //(2)
}
}
Can someone help me ?
Thanks in advance,
BDR

Try the Computed field module to create the dynamic fields or add the node_save($node); at the end of the codes to save the node:
function module_node_presave($node) {
if ($node->type == 'server') {
$node->field_server_cpu_speed[LANGUAGE_NONE][0]['value'] = 55;
node_save($node);
}
}

Related

How to override Doctrine #userAware annotion / filter on specific query?

I follow this instruction to create a #userAware annotation which automatically limits all queries on specific entities to the current user.
For example $todoRepo->findByTag("someTag") will automatically add WHERE user_id = 123 to the resulting query to make sure that only ToDo entities of the current user (id 123) can be accessed.
This works great but has one big downside: If for example the admin whats to know how many ToDo entities use the tag someTag he will only find his own entities...
Since using an #userAware annotation seems to be quite common, I wonder if there is any best practice on how to disable/bypass/override this filter/annotation on a specific query.
You can disable the filter. In your example, you must change the kernel request event, like that ...
public function onKernelRequest()
{
if ($user = $this->getUser()) {
if ($user->isAdmin() /* or whatever */) {
$this->em->getFilters()->disable('user_filter');
} else {
$filter = $this->em->getFilters()->enable('user_filter');
$filter->setParameter('id', $user->getId());
$filter->setAnnotationReader($this->reader);
}
}
}

Is there a suitable hook for intercepting all POSTs to an OpenACS/AOLServer system?

I'd like to disable all POSTs to an OpenACS/AOLServer installation. Is there an good singular place – a request-hook or wrapper/middleware – to do this?
(Bonus points if the intercept can let a few URI patterns or logged-in users through.)
Yes, this is straight forward to do. You have a choice here: you can register a proc to run instead of all POSTs, or can you register a filter to run before the POST and filter out certain users or whatever. I think the filter is a better choice.
To do this you register your proc or filter using ns_register_proc or ns_register_filter (with preauth). Put the following code in a .tcl file under the tcl folder of an OpenACS package or under the main AOLserver /web/servername/tcl directory.
Filter example:
ns_register_filter preauth POST / filter_posts
proc filter_posts {} {
set user_id [ad_verify_and_get_user_id]
set list_of_allowed_user_ids [21 567 8999]
if {[lsearch -exact $list_of_allowed_user_ids $user_id] == -1 } {
#this user isn't allowed - so redirect them
ns_returnredirect "/register/"
# tell AOLserver to abort this thread
return filter_return
} else {
# this user is allowed, tell AOLserver to continue
return filter_ok
}
}
Proc example:
ns_register_proc POST / handle_posts
proc handle_posts {} {
ns_returnredirect "http://someotherwebsite.com"
}

How do I add or remove collection document fields server side in Meteor?

I need to add or remove fields to a doc before insert or update in the allow or deny methods. I had presumed that the transform function would provide the needed functionality.
The meteor docs state
"An optional transformation function. Documents will be passed through
this function before being returned from fetch or findOne, and before
being passed to callbacks of observe, allow, and deny."
Whenever I tried to transform and return the doc from the function either from allow or deny the transformed version of the document was not what was inserted into the mongodb. I tried transforming via 2 strategies.
Strategy 1
var ts = new Date();
return _.extend(_.pick(doc, 'name', 'discounts', 'locations', 'url_map', 'client_updated_td', '_id'), { created_td:
ts, updated_td: ts, });
Strategy 2
// Discountsroutings.fields is in /lib/Discountroutings.js
Discountsroutings.fields = ['_id', 'created_td', 'updated_td', 'client_updated_td', 'name', 'discounts', 'locations', 'url_map'];
// this is in /server/discountsroutings.js var ts = new Date();
doc.created_td = ts; doc.updated_td = ts; return _.each(doc,function(value, key, list){
if(Discountsroutings.fields.indexOf(key) == -1 ){
delete doc[key];
}
});
Neither worked. In both cases fields were not removed though fields were added.
Interestingly, I tried the same two strategies from inside an insert allow and an insert deny and only Strategy #2 worked. So, for now I am just using Strategy #2 inside Deny insert/update methods. Works fine and isn't that difficult to wire up.
Am I doing this correctly? I want to add or remove fields from a collection server side the correct way.
Steeve have you tried my collection-hooks package? Sounds like what you need
you seem to know the list of fields you want to remove. So why don't you use $set and $unset to add and remove fields?
Recently needed to do the same thing and found no example here... thought I'd share how I did it:
Using
https://atmospherejs.com/matb33/collection-hooks
http://arasatasaygin.github.io/is.js/
Prospects.before.update(function (userId, doc, fieldNames, modifier, options) {
//check existence of other segment property and make sure to delete it if segment is updated from 'Other...' to something else
if (is.existy(doc.other_segment)) {
var segment = Segments.findOne({_id: modifier.$set.segment});
if (is.not.undefined(segment) && is.not.empty(segment)) {
if (is.not.equal(segment.name, 'Other...')) {
Prospects.update( {_id: doc._id} , {$unset: { other_segment : '' } } );
}
}
}});
Hope this helps! :)

New operation in hook_access()

Is it possible to define a new operation for a node access?
As I know, the operations for a node that are used in hook_access() are:
create
delete
update
view
I have a custom content type for which I need another operation, such as "suggest."
short answer is NO as node_access() who is responsible to call hook_access() does a check
on the $op parameter
if (!$node || !in_array($op,
array('view', 'update', 'delete',
'create'), TRUE)) {
return FALSE; }
you can attach some extra info to the node object in your suggest() function - hopefully called before node_access() - then check these extra informations in your hook_access() and return TRUE/FALSE according.
another option consists in hardcode permission checks into the suggest() action itself without messing around with hook_access.

Automatically refresh Drupal node after hook_view

I'm trying to show updated results for a CCK Computed Field.
The computation is based on fields in another node, so are not being automatically updated.
So: I'm calling node_save($node) in hook_view, which does make the adjustment but the results don't show until I refresh the page.
Is there a way to refresh the page automatically, or should I be approaching this from a different angle?
Edit: In response to Henrik's questions, here's more detail:
The hook_view and its node_save are below, the rest of the code is in a Computed Field in the 'project' content type, summing up values from another node. Without the node_save, I have to edit and save the 'project' node to get the result. With it, I just need to refresh the page.
Adding drupal_goto(drupal_get_destination()) in the hook_view gives a 'page not found', rather than the vicious loop I was expecting. Is there another place I could put it?
function mymodule_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'view':
if($node->type == 'project') {
project_view($node);
break;
}
}
}
function project_view($node) {
node_save($node);
return $node;
}
Edit 1: Given the newly posted code and additional explanations, I have three suggestions that might solve the problem without redirecting:
As project_view() does not take the node argument by reference, you might want to actually grab its (potentially updated) result in mymodule_nodeapi by writing
$node = project_view($node);
instead of just
project_view($node);
If that works, it should also work without the indirection via project_view() by just calling node_save($node) directly in mymodule_nodeapi. (node_save() takes the node argument by reference).
AFAIK, computed fields basically provide two working modes that you can switch via checkbox on the field configuration form:
Computing the field once on node_save(), storing the result in the database, updating only on new save operations.
Not storing the field at all, instead recomputing it every time the node is viewed.
Have you tried the 'always recompute' option already?
Edit 2: My original answer was flawed in two ways at once, as it used a completely wrong function to retrieve the current request URI and did not check for recursion (as lazysoundsystem pointed out very courteously ;)
So the following has been updated to an actually tested version of doing the redirection:
Is there a way to refresh the page
automatically
You could try:
if (!$_REQUEST['stop_redirect']) {
drupal_goto(request_uri(), array('stop_redirect' => true));
}
This will cause Drupal to send a redirect header to the client, causing a new request of the current page, making sure not to redirect again immediately.
If the value is only ever going to be computed, you could just add something to your node at load time.
function mymodule_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'load':
if($node->type == 'project') {
$node->content['myfield'] = array('#value' => mymodule_calculate_value(), '#weight' => 4, '#theme' => 'my_theme');
}
break;
}
}
}

Resources