What's use of "#process" callback in drupal form api? - drupal

In drupal fapi there is an attribute "#process".what exactly does it?Why password field use it for field duplication instead of adding it with theming?
I want to use it for defining a new field type with hook_elements.
Edit:
here is my hook_elements:
function test_elemets() {
return array(
'test_field' => array(
'#input' => TRUE,
'#process' => array('test_field_process'),
)
);
}
and process callback:
function test_field_process($element, $edit, &$form_state, $complete_form) {
$element = array();
return $element;
}
as you see in process function I used $element=array() to see what happens.But the form is shown as it was before.why?

Read the Forms API documentation on the '#process' form element property.
It is an array of callback functions, each of which will be called with the the element definition array passed to it. The callback function can then act on the element definition array to turn it into a different (usually more complex) definition, like e.g. duplicating a password field while attaching an equality checking JavaScript file, or turning one combined 'radios' definition into an according amount of specific single 'radio' definitions, etc.
You will want to use it if you want to offer a complex form element (e.g. a combination of multiple 'standard' elements combined, or one with automatic addition of standard JavaScript helpers), but still keep the simple, declarative approach of the Forms API. (Look Ma - only one '#type' = 'myCrazyFormElement' array, that expands 'automagically' to something way more complex ;)
Doing this via the theming layer might be possible, depending on the use case, but would require more code, every time you need it.

api.drupal.org documentation on #process says:
An array of functions that are called
when an element is processed. Using
this callback, modules can "register"
further actions. For example the
"radios" form type is expanded to
multiple radio buttons using a
processing function.
Processing differs from theming in keeping within the form API. You can't alter a form array in the theme layer (at least not in D6). Password specifically, adds form_expand_ahah to #process. You could probably kludge most of that into the theme layer, but not this line:
$element['#cache'] = TRUE;
Because caching happens before the theme layer, that couldn't be done in the theme layer. More generally, while some of what happens in #process could happen in the theme layer, it couldn't all happen there because forms are more than front-end display; they're also back-end processing.

Related

How to strip/ignore unused attributes when saving a model object?

I am sending angular model objects to bookshelf to save, but it may carry extraneous attributes that aren't in the database. When I save, bookshelf will try to save all attributes and say it can't find these extra attributes.
What is the recommended way to handle this? I'm sure I can set out an array of whitelisted attributes, and strip the object manually, but is there another way?
IE, is there a built in way to ignore unused attributes? Or is there a way to query the DB to get the array of columns, then use that to strip my object?
You may use parse() in addition to an array of permitted attributes, like Ghost team did.
Mode = bookshelf.Model.extend({
permittedAttributes: [ 'field1', 'field2', 'field3' ],
parse: function (attrs) {
return _.pick(attrs, this.permittedAttributes)
}
})
If you define parse() in a base model, all models that extend it will behave the same way
Tooting my own horn here, but I encountered this problem so many times that I created a plugin for bookshelf. Didn't want to have to manually define permitted attributes every single time.
https://www.npmjs.com/package/bookshelf-strip-save

Buddypress plugin Group Hierarchy

Buddypress has a group functionality in which I combined with the plugin BP Group Hierarchy so that I can create an hierarchy of groups based on user role.
However, the plugin used an method as taught by Buddpress in group-extension-api> link.
The group steps are registered using the function bp_register_group_extension and add_action are called. I tried to remove the action by with no success. Because I not really understand how the array works i.e. array( &$extension, \'_register\' ), so I go search out and found this post.
There's a line stating that
The new format for the above object referenced method callbacks are always: class name, followed immediately by the method name, followed by the amount of previously added (classname+methodname). For classes, this allows you to add as many object referenced classes and add methods which don’t override each other.
However I can't seems to be able to remove the action.
I tried to remove the action by putting following lines of code in function.php
function remove_bp_hierarchy(){
if (has_action('bp_actions')) {
echo $extension = new BP_Groups_Hierarchy_Extension;
remove_action('bp_actions', array( &$extension, '_register' ), 999);
} else {
}
add_action('bp_init','remove_bp_hierarchy', 999);
Is it something wrong with my remove_action or I use wrong method? Thanks and regards.
## Update
Found a page in which let we see a list of hooks and also hooked function in the page. I see that there's a function with the name _register which is the function I'm looking for. However, class address always change. I was thinking using the function found to do a preg_match on it and remove it when it found. this is super heavy. So is there other way of removing it? Thanks and Regards.
CodingBabyDotCom -
Long story short: you will have to traverse the $wp_filter array to remove the action.
You need a reference to the SAME instance that was used to create the action in order to remove it with the remove_action function. So the function you posted doesn't work because it is using a new instance.
Unfortunately bp_register_group_extension() creates only a temporary instance, so it can't be referenced by later functions.
The code in your comment will remove ALL actions at level 8, which means all group extensions. To remove only the one you want, iterate over each filter and check its type with:
is_a( $wp_filter['bp_actions'][8][$key], 'BP_Groups_Hierarchy_Extension' )

Drupal 7 preprocess_views not working

I have the following code in my Drupal 7 template.php file:
function mytheme_preprocess_views_view__videos__videos(&$vars) {
drupal_add_css(drupal_get_path('theme', 'mytheme') . "/css/qwembed-jquery-1.0.css");
drupal_add_js(drupal_get_path('theme', 'mytheme').'/js/jquery.swfobject.1-1-1.min.js', array('type' => 'file', 'scope' => 'footer'));
drupal_add_js(drupal_get_path('theme', 'mytheme').'/js/qwembed-jquery-1.0.js', array('type' => 'file', 'scope' => 'footer'));
}
I need to load these css and js file only when this view is displayed.
the view display name is: Videos
the view Machine Name is: videos
and the override files are:
views-view--videos--videos.tpl.php
views-view-unformatted--videos--videos.tpl.php
views-view-fields--videos--videos.tpl.php
any ideas why this is not working?
The problem is likely that you try to implement a preprocess function based on the same naming pattern as used for template overrides. But preprocess functions are a bit different in that by default, they can only be implemented based on the name of the 'base' template, and do not have the same mechanism for 'specific' versions based on template suggestions. See my answer to a more generic question for details.
So you'd need to fall back to implementing the 'base' preprocess function, and check if it gets called for the desired view (and optionally display) within that function, roughly like so:
function [yourThemeName]_preprocess_views_view(&$vars) {
$view = $vars['view'];
if ('videos' == $view->name) {
// Add desired manipulations for all 'videos' views
if ('videos' == $view->current_display) {
// Add desired manipulations for the 'videos' display only
}
}
}
You could also add the behavior you expected by implementing a generic preprocess function that tries to call specific versions by checking for functions with the proper name - see the end of this article for an example - but this introduces quite some processing overhead and would only make sense, if you need specific preprocess functions for many views.
There are more 'base' preprocess functions per view type that you can implement directly - see the list of template_preprocess_views_view_* in 'views/theme/theme.inc' for the available options.
As a base rule, whenever there is a template_preprocess_* function for a template, you can implement a corresponding yourThemeOrModuleName_preprocess_* function as well. If you need to manipulate for templates based on template name suggestions, you need to find the 'base' preprocess function name, implement that and check for your specific case in that function (like for the specific view as in the example above).

How to update the value of a single field invoking appropriate validation

I'm making a module to allow users to update single fields on in this case, their user entity.
The code below is an example of the method I have initially been using to get it working and test other elements of the module
global $user;
$account = user_load($user->uid);
$edit = (array) $account;
$edit['field_lastname']['und'][0]['value'] = 'test';
user_save($account, $edit);
However this bypasses any field validation defined elsewhere in Drupal. I don't want to reproduce any validation written elsewhere - it's not the Drupal way!
My question is: Is there a function in Drupal 7 that can be called to update the value of a single field. I imagine such a function would clear the appropriate caches, invoke the fields validation etc.
I am aware the solution will be totally different to my current user object based one. I just can't for the life of me find the appropriate function in the API. I wander whether the fact I am looking for a save function alone is the problem - and that there are some other necessary steps that come before.
Any help gratefully appreciated.
Check out the drupal_form_submit function. It lets you submit forms from code. In this case, you could use it to the user edit form, which would then fire the appropriate validation.

Disable Drupal content creation message?

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

Resources