redirection on custom submit handler - drupal-7

so basically this is my 2nd day in this problem.
i have my module send_xml.module
function send_xml_form_user_register_form_alter(&$form, &$form_state) {
$form['#submit'][] = 'send_xml_submit_function';
}
function send_xml_submit_function($form, &$form_state){
$email = $form_state['values']['mail'];
$password = $form_state['values']['pass'];
$form_state['redirect'] = array(
'mylink', array(
'query' => array(
'email' => $email,
'password' => $password,
),
),
);
but it does not redirect after the process in mylink, it just refreshes the page.

Use hook_form_alter like this:
function send_xml_form_alter(&$form, &$form_state, $form_id) {
switch ($form_id) {
case 'user_register_form':
$form['#submit'] = array('send_xml_submit_function');
break;
default:
# code...
break;
}
}
function send_xml_submit_function($form, &$form_state){
// call default submit -- this is default submit action for register form
user_register_submit($form, $form_state);
// if you use profile2 to create fields in register form then call this function too
profile2_form_submit_handler($form, $form_state);
$email = $form_state['values']['mail'];
$password = $form_state['values']['pass'];
$form_state['redirect'] = array(
'mylink', array(
'query' => array(
'email' => $email,
'password' => $password,
),
),
);
}
I had same problem weeks ago and this is way I solved it, actually I have no clear idea why this work and why appending #submit don't work.
I checked drupal user_register_submit code and seems like it clear $form_state['redirect'] to redirect user to <front>.

You can also use drupal_goto function:
function send_xml_submit_function($form, &$form_state){
$email = $form_state['values']['mail'];
$password = $form_state['values']['pass'];
drupal_goto('REDIRECT_pATH', array('query' => array('email' => $email, 'password' => $password)));
}

Related

How to pass dynamic file location in Form API?

my requirement is to upload files to specific folders. How can I achieve this by using form api.
How can I modify below code such that upload_location should be dynamic. Uploaded file should save into the Folder name provided by the user.
#submit element is not calling custom_document_submit function.
$form['folder_name'] = array(
'#type' => 'textfield',
'#title' => t('Folder Name'),
);
$form['document'] = array(
'#type' => 'managed_file',
'#upload_validators' => array('file_validate_extensions' => array('xml')),
'#upload_location' => 'public://',
'#submit' => array('custom_document_submit'),
);
function custom_document_submit($form, &$form_state){
$destination = $form_state['values']['folder_name'];
$validators = array();
$file = file_save_upload('document', $validators, 'public://'.$destination);
}
The #submit property cannot be declare on a managed_file form object...
Instead, you have to add or to modify a submit action on your form (or button).
$form['#submit'][] = 'custom_document_submit';
If you don't want to modify the submit method of your form, you can also simply add a validator (with the #validate property), witch will modify the '#upload_location' property of your document depending on the folder_name value.
Both, #submit and #validate properties have to be added to the form itself.
<?php
define('IMPORT_DIRECTORY_PATH', 'public://import');
$form['folder_name'] = array(
'#type' => 'textfield',
'#title' => t('Folder Name'),
);
form['document'] = array(
'#title' => t('Upload .xml'),
'#type' => 'managed_file',
'#upload_validators' => array(
'file_validate_extensions' => array('xml'),
),
'#process' => array('import_document_element_process'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Upload'),
'#submit' => array('custom_document_submit'),
);
function custom_document_submit($form, &$form_state){
// Validate extensions.
$validators = array(
'file_validate_extensions' => array('xml'),
);
$file = file_save_upload('document', $validators, FALSE, FILE_EXISTS_RENAME);
// If the file passed validation.
if ($file) {
// Rename uploaded file to prevent cache from remembering name file.
$directory = SCHEDULES_IMPORT_DIRECTORY_PATH;
if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
$uri = $directory . '/xml_' . $file->uid . '_' . $file->timestamp . '.xml';
if ($file = file_move($file, $uri)) {
$form_state['values']['document'] = $file;
}
else {
form_set_error('document', t('The file could not be uploaded.'));
}
}
else {
form_set_error('document', t('The directory is not writable.'));
}
}
else {
form_set_error('document', t('The file extension is not correct.'));
}
// dpm($form_state['values']['document']);
// var_dump( $form_state['values']['document']);
}
/**
* Removing the upload button in managed files.
*/
function import_document_element_process($element, &$form_state, $form) {
$element = file_managed_file_process($element, $form_state, $form);
$element['upload_button']['#access'] = FALSE;
return $element;
}

cakephp 2.2 Using contain with Auth not working

I have a working example of Auth set up with Users & Groups, based on the cookbook tutorial. I have an additional Locations table, which is associated with my Groups.
Location hasMany Group. Group belongsTo Locations. In 2.2 I think I should be able to get location data back for a User, but am not able to.
// App controller
public function beforeFilter() {
$this->Auth->authenticate = array(
'all' => array (
'scope' => array('User.status' => 1)
),
'Form' => array(
'contain' => array('Group', 'Location'),
'fields' => array('Location.name')
)
);
The above code only works if I create a direct association between User and Location. Is it possible to use contain here with a Group to Location association?
Problem of BaseAuthenticate is how it returns user info: return $result[$model];.
So when I need contains I'm using alternative component placed in app/Controller/Auth:
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class FormAndContainableAuthenticate extends FormAuthenticate {
protected function _findUser($username, $password) {
if (empty($this->settings['contain'])) { //< deafult
$userData = parent::_findUser($username, $password);
} else { //< with contains
$userModel = $this->settings['userModel'];
list($plugin, $model) = pluginSplit($userModel);
$fields = $this->settings['fields'];
$conditions = array(
$model . '.' . $fields['username'] => $username,
$model . '.' . $fields['password'] => $this->_password($password),
);
if (!empty($this->settings['scope'])) {
$conditions = array_merge($conditions, $this->settings['scope']);
}
$modelObj = ClassRegistry::init($userModel);
$modelObj->contain($this->settings['contain']);
$result = $modelObj->find('first', array(
'conditions' => $conditions
));
if (empty($result) || empty($result[$model])) {
return false;
}
foreach($result as $modelName => $modelData) {
if ($modelName !== $model) {
$result[$model][$modelName] = $modelData;
}
}
$userData = $result[$model];
}
// remove dangerous fields like password
unset($userData[$this->settings['fields']['password']]);
if (!empty($this->settings['exclude'])) {
foreach ($this->settings['exclude'] as $fieldName) {
unset($userData[$fieldName]);
}
}
return $userData;
}
}
As you can see - it uses parent Component when no contains provided.
Also some bonus: you can provide a set of fields to remove from resulting array. Just pass field names via 'exclude' key
How to use Component:
public $components = array(
'Auth' => array(
'authenticate' => array(
'FormAndContainable' => array(
'fields' => array(
'username' => 'username',
'password' => 'password',
),
'userModel' => 'Staff',
'contain' => array('StaffPermission'),
'exclude' => array('plain_password')
)
),
),
);
If User is not linked to Location, but Group is, you should try this:
'contain' => array('Group' => array('Location')),

How to pass parameters with testAction in CakePHP2.0

I want to test a function with this header:
public function includeNumComments($posts){
Where $post is an array of data.
I wonder how can i test the method passing it an array of posts.
I have tried things like this, but it doesn't work:
$result = $this->testAction("/comments/includeNumComments/", array('data' => $posts));
$result = $this->testAction("/comments/includeNumComments/", array($posts));
Thanks
Here's the correct case, it worked for me. Hope it helps:
public function testAddUser() {
$data = array(
'User' => array(
'id' => 12,
'username' => 'testname1',
'password' => 'Pass#123!',
'email' => 'test#example.com'
)
);
$result = $this->testAction(
'/users/add',
array('data' => $data, 'method' => 'post')
);
debug($result);
}
That's not really using testAction then, because you can't pass an array via HTTP. There'd be no way to do this via a form or link on a website.
You can just test it as a normal function:
$result = $this->CommentsController->includeNumComments($posts);

Can I create a Drupal autocomplete textfield in a block?

I want to create an auto-complete form in my custom module that will be loaded in a block. Drupal doesn't seem to be loading the necessary Javascript libraries to work properly. How do I know what needs to be loaded and how/where do I tell Drupal to load these libraries?
hook_block_view:
function my_module_block_view($delta = '') {
//The $delta parameter tells us which block is being reqested.
switch ($delta) {
case 'my_module_my_block':
$block['subject'] = t('Block Subject');
$block['content'] = drupal_get_form('my_module_my_form');
break;
}
return $block;
}
Form code:
function my_module_my_form($form, &$form_state) {
$form = array();
$form['term'] = array(
'#type' => 'textfield',
'#autocomplete_path' => 'my-module-autocomplete'
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Add',
);
return $form;
}
The form loads, the field is there, but auto-complete isn't working :(
If I call the my-module-autocomplete path I do get a valid response back when compared with a Content Type edit form. The ajax spinner in the input field never appears so the ajax isn't being called. Realistically all I want is the autocomplete field...the submit will be handled manually.
It's probably because you're reseting $form to an empty array at the beginning of the function. In Drupal 7 there's a bunch of stuff added to that element before it's passed through to your form function (that's why $form is passed to your function whereas in Drupal 6 it wasn't).
Just remove $form = array(); and it should work, other than that your code looks perfect.
the following should work;
function mymodule_block_info() {
$blocks['mymodule'] = array(
// The name that will appear in the block list.
'info' => t('My Module'),
// Default setting.
'cache' => DRUPAL_NO_CACHE,
);
return $blocks;
}
function mymodule_block_view($delta = ''){
switch($delta){
case 'mymodule':
if(user_access('access content')){ //good idea to check user perms here
$block['subject'] = t('My Module');
$block['content'] = 'Hi :)';
$block['content'] = drupal_get_form('mymodule_form');
return $block;
}
break;
}
}
function mydmodule_menu() {
$items['module/autocomplete'] = array(
'page callback' => 'mymodule_autocomplete',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK
);
return $items;
}
function mymodule_form($form, &$form_state) {
$form['greenentry'] = array(
'#type' => 'textfield',
'#title' => t('Enter'),
'#autocomplete_path' => 'mymodule/autocomplete',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
function mymodule_autocomplete($string) {
$matches = array();
// Some fantasy DB table which holds cities
$query = db_select('cities', 'c');
// Select rows that match the string
$return = $query
->fields('c', array('city'))
->condition('c.city', '%' . db_like($string) . '%', 'LIKE')
->range(0, 10)
->execute();
// add matches to $matches
foreach ($return as $row) {
$matches[$row->url] = check_plain($row->url);
}
// return for JS
drupal_json_output($matches);
}
this code is so pretty to add an auto-complete filed in block. But i just found a tiny notice here. if someone get an error
An ajax error occurred. http result code 200
then just add
exit();
after the line
drupal_json_output($matches);
hence fix the issue.

CakePHP $this->Auth->login() not working

The web app is working great except for auth manual calls. I've been struggling with this for days. In my sample code I have temporarily rewritten the cookie to narrow down the cause. Here is my app controller snip:
App::import('Sanitize');
//uses('sanitize');
class AppController extends Controller {
var $components = array('Clean','Acl', 'Auth', 'Session', 'RequestHandler', 'Cookie', /* 'DebugKit.Toolbar' */);
var $helpers = array('uiNav','Flash','Html', 'Form', 'Session','Javascript','Ajax','Js' => array('Jquery'), 'Time','Js');
function beforeFilter() {
//Configure AuthComponent
$this->Auth->authorize = 'actions';
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'view');
$this->Auth->actionPath = 'controllers/';
$this->Auth->autoRedirect = false;
$this->Auth->allowedActions = array('display');
if(!$this->Auth->user()){
//$cookie = $this->Cookie->read('Auth.User');
$cookie = array('username' => 'chris22', 'password' => 'stuff');
if (!is_null($cookie)) {
$this->set('checking_cookie',$cookie);
if ($this->Auth->login($cookie)) {
$this->set('cookie_message','cookie validates!');
// Clear auth message, just in case we use it.
$this->Session->delete('Message.auth');
/* $this->redirect($this->Auth->redirect()); */
}
}
}
}
}
As you can see I'm just plugging the user name and password into $this->Auth->login and it's not working!!
I don't know if my user controller is relevent, but here is the login function for that too:
function login() {
if ($this->Auth->user()) {
if (!empty($this->data) && $this->data['User']['remember_me'] && isset($this->data['User']['password'])) {
$cookie = array();
$cookie['username'] = $this->data['User']['username'];
$cookie['password'] = $this->data['User']['password'];
$this->Cookie->write('Auth.User', $cookie, true, '+1 month');
//unset($this->data['User']['remember_me']);
$this->set('cookie-00', 'setting cookie.');
}else{ $this->set('cookie_message', 'not setting cookie.');}
$this->redirect($this->Auth->redirect());
}
}
Thanks!
EDIT - 1 - I think I know why this is not working for you.
Reason 1: $this->Auth->login takes data in the form of
array(
'User'=>array(
'username'=>'myusername',
'password'=>'mypassword'
)
)
Reason 2: $this->Auth->login does NOT hash the password.
You must send the password exactly as it appears in the database.
EVERYTHING BELOW THIS LINE IS POSSIBLE BUT NOT LIKELY IN THIS CASE:
Are you sure that when you originally created the username and password, the hashes were setup?
To check that your hashes match look at your users table with phpmyadmin or mysql workbench and find the password field for the user chris22
Compare that entry to your current hashing. To check your current hash, put the code below somewhere in a controller function (index) and navigate there.
debug(Security::hash('stuff'));
exit;
I hope this helps!
Make sure the fields are correctly assigned in the Auth component.
if you use different field names than username & password to connect, you must declare them in your controller like this way :
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email', 'password' => 'mot_de_passe')
)
)
)

Resources