I have an insert hook that catches nodes whenever the user adds a node.
So here's my code:
function blah_insert($node){
$record = array(
'nid' => (int) $node->nid
);
drupal_write_record('table_name', $record);
}
schema::
table_name(
nid int primary key not null
)
Performing a check on the return value of drupal_write_record results in FALSE. db_query doesn't work either. var_dump confirms that all the fields are where they're supposed to be.
The nodes are properly being inserted into the node tables but not the table that is defined by the schema in my install file (not written like the schema that I have above of course - nid is defined as an int and all other relevant fields).
Does anyone have any idea as to what's going on?
Make sure your module is installed and enabled
Make sure your module name is definitely named blah (or whatever you're putting before _insert
Make sure that you're using the right hook...if your module is not responsible for defining a content type (i.e. a 'node' module) then you're using the wrong one. From the docs of hook_insert: "This hook is invoked only on the module that defines the node's content type". It may be that you're looking for hook_node_insert() instead, which responds to the insertion of a node of any type.
When you implement any hooks in your module make sure you clear caches afterwards, depending on what version of Drupal you're using these implementations may be cached for quicker access and won't be picked up until that cache is cleared.
Check that your custom table actually exists in the database! If not grab the devel module, install it and visit /devel/reinstall where you can invoke a full re-install of your module.
Once you've checked those if is still doesn't work it's symptomatic of a larger problem with your Drupal installation...if your schema is as you've said it is above then there's no reason drupal_write_record() wouldn't work if the function is indeed being run.
Related
How do I get a collection of files that are in 'checked-in' status at any point of time? Using plone 4.1. Checked-in is not a workflow status. It is a file that has been locked by a user while editing so that the other user cannot access the latest copy before the former has unlocked the file by 'check-in'. I want to know if I can have a collection to display a list of all the files that have been locked i.e 'check-out' or have 'check-in' status at any point of time.
Since checked-in objects are indistinguishable from "normal" published objects, there is probably no easy way to create such a collection.
A few workarounds come to mind:
Look for checked out objects by searching for objects in the private state whose ids begin with "copy_of"
Check for "published" objects.
Create a custom workflow that contains an additional "checked-in" state and (somehow) use the checked in state for objects that have been checked out and checked back in at least once.
None of these are particularly attractive so a catalog search for published items is probably your best bet:
>>> [brain.getObject().getId() for brain in portal.portal_catalog(
review_state="published")]
['front-page', 'news', 'aggregator', 'events', 'aggregator', 'Members']
Which you can compare with a list of all objects if you like:
>>> [brain.getObject().getId() for brain in portal.portal_catalog()]
['front-page', 'news', 'aggregator', 'events', 'aggregator', 'Members',
'copy_of_front-page']
You don't need to do this programmatically, just wanted to demonstrate the difference between searching for published objects vs all objects. The latter returns an additional checked out object (in the private state).
It's possible with this approach:
Add a new field 'Has workingcopy' to all ATCT's via the famous schemaextender.
Register the field in the catalog, to make it available to collections.
Listen to eventhandlers to set the field to true, when a workingcopy is created and to False when it's chekced-out or canceled.
I wrote a package for this, because I need it anyway for a project soon: adi.workingcopyflag
Since the checked-in/checked-out state is not indexed in portal_catalog there is no way to make the information available to a collection.
Okay lets say I have a basic demographic content type (Client) that I am saving as a node.
I need to make a key for an external database that we occasionally need to work with.
I want Drupal to take the fragments of three fields being collected in the Client content type and join them into a single field to be saved within the Client content type. Ideally this should be done when I create a new (Client) node.
The new field should contain the following
First 3 letters of firstname
First 3 letters of lastname
and last 4 digits of Social Security Number.
For example
firstname: John
lastname: Doe
SSN: 123-45-6789
A new field should be created, let’s call it fk_database. Using the example above the field >created would be -> johdoe6789
Can this be done via Rules module, or should I approach this in a different way? If I need to do this via a PHP script where exactly should that be added in the Drupal structure?
The easiest way would probably be to use the Computed Field module, it's pretty much built for exactly what you want to do:
Computed Field is a very powerful CCK field module that lets you add a custom "computed fields" to your content types. These computed fields are populated with values that you define via PHP code. You may draw on anything available to Drupal, including other fields, the current user, database tables, you name it.
If you do need to do it in code though, have a look into hook_entity_presave() which would probably be the best place to run your code from.
I personally would build a custom module to handle this and make use of the node API to handle the custom fields if you want to build them on the fly?
Modules could be created either in the modules directory on the 'root' or really they should be in sites > all > modules
You'll have to switch it on in the backend under site building > modules to enable it
You will be able to hook into the API and handle requests via the case statements e.g.
function hook_node_load($node, $types) {
//do something on node load
}
function hook_node_update($node) {
//do something on node update
}
function hook_node_insert($node) {
//do something on node insert
}
I'm creating a module wich provides a separate node overview page for each content type.
My problem lies in trying to recreate the node operations dropdown.
In the node module this is done by calling the module_invoke_all function with the 'node_operations' hook.
This returns an array of all modules that implement the 'node_operations' hook.
In my case the following two modules: 'node' and 'nodewords'.
When I call module_invoke_all('node_operations') in my module, it returns only the 'nodewords' module, not the 'node' module.
This is because the 'node_node_operations' function does not exist.
Can anyone explain this behavior?
It looks like the hook is in node.admin.inc, which is not automatically included. See http://api.drupal.org/api/drupal/modules--node--node.admin.inc/function/node_node_operations/7
This is imho a bug, you should look if there already is an issue and if not, create a new one.
Anyway, as a workaround, you can include the node.admin.inc file like this before calling the hook:
<?php
module_load_include('inc', 'node', 'node.admin');
?>
(Yeah, weird syntax ;))
I'm developing an Action in Drupal which is supposed to activate after saving a node, exporting content to XML (which includes data from the node that was just saved), using the "Trigger: After saving an updated post" trigger.
Unfortunately this action actually happens right before the information from the recently saved post is saved to the database. ie. when looking at the XML later, I find that the most recent change I made was not included. Saving after editing a different node will restore the previously missing data.
How can I get my action to fire after the saving process is complete?
There is a common pitfall in this context, regardless of whether you use a trigger or Mike Munroes suggestion via hook_nodeapi() (+1):
As long as your export logic runs on the same page cycle that processed the update, and it uses node_load() to get the nodes data, node_load()might return a statically cached version of the node from before the update that does not contain the changes yet. If this is the problem in your case, you can work around it in two ways:
Force a reset of the static node cache by passing TRUE as the third parameter to node_load(). This would ensure that the node gets populated freshly from the database (at the price of some additional db queries, so be aware of a potential performance impact).
If you are going the hook_nodeapi() route, you could avoid the need to call node_load() altogether if you pass the $node object available there directly to your export function, as it will be a representation of the updated state.
You should use hook_nodeapi and invoke your action on insert and update. Look over the documenation for hook_nodeapi for other instances where you could call your export logic.
example where module name = 'export_to_xml':
/**
* Implementation of hook_nodeapi().
*/
function export_to_xml_nodeapi(&$node, $op, $a3, $a4) {
if ($op == 'update' || $op == 'insert') {
export_logic_function();
}
}
Whenever a content item is created, a message is displayed like this:
[Content Type] [Name] has been created.
Is there any way to disable this message for specific users? Or for all users would be fine too.
I think the best practice would be to use hook_nodeapi() and drupal_get_messages('status'). The $op for hook_nodeapi() would be insert. Ex:
mymodule_nodeapi(&$node, $op) {
if ($node->type == 'content_type_to_check_for' && $op == 'insert') {
drupal_get_messages('status');
}
}
It's node_form_submit that is creating those messages. You could pretty easily use hook_form_alter on the node form and use your own version of node_form_submit instead. All you would need to do, would be to copy the function and add an user_access('whatever') check before that message is created.
Alternatively, you could in preprocess_page function, check which messages is being served, and remove unwanted ones, but that would be a bit more tricky. Should be possible with some regex. On the other hand, this method would be a bit more upgrade friendly, since you could remain using the node_form_submit function and would get future changes if any.
Best way would be to user Disable Messages module.
There are many kind of messages that can be disabled by this module:
Filter out messages that match a full text string exactly.
Filter out messages that match a regular expression.
Permissions to specifically hide all messages of a given type from any role.
Disable all filtering for specific users.
Disable all filtering for specific paths.
Apply filtering only for specific paths.
Debug system to get messages in the HTML without showing it to the end users.
Here is the way I discovered to hide such messages for specific content types (the node type is 'request'):
// specific node type form alteration hook (implements [hook_form_FORM_ID_alter][1]())
function MYCUSTOMMODULE_form_request_node_form_alter(&$form, &$form_state) {
// ...
// custom validation function
$form['#validate'][] = '_custom_request_node_form_validate';
// ...
}
function _custom_request_node_form_validate($form, &$form_state) {
//...
// here we can set a submit handler that is executed before
// node_form_submit which sets the messages we are trying to hide
$form_state['submit_handlers'][] = '_custom_request_node_disable_msg';
//...
}
function _custom_request_node_disable_msg($form, &$form_state) {
//...
// clear status messages
drupal_get_messages('status');
}
If you want to use the Rules module, then you can use the new module I created called "Better Rules Message".
By using this you can setup a rule that will delete all of the messages after a node is being created...
Hopefully this will be added to the main Rules module in the near future.
googletorp is right (about the submit function). But unfortunately you can't decouple the message from the node submit function and duplicating the functionality (without the message) is going to mean your site might break when a security release is issued. You'd have to maintain your own version of that function. It's probably not a big deal but it's a good idea to follow best practice.
You'll need to write your own submit hook either before or after node_form_submit gets called.
With a submit hook after the node save, you could remove the message from $_SESSION['messages'] if the messages array was easy enough to work with. I imagine that would be simple enough. See drupal_set_message
OR
You could write some class in CSS in your body tag and set the display to none when status messages are returned on the page that the node form submits to. But that might put your business logic in your theme layer which should be avoided.
You can use stringoverrides module in drupal ! :)
You could try using the following module to disable specific messages in Drupal - http://drupal.org/project/disable_messages