Drupal 7 ajax from ahah - php

i have this form:
function tax_assistant_form_alter(&$form, $form_state, $form_id) {
//questa funzione è usata per alterare la disposizione del form originale
//contenuto in un altro modulo (linkableobject)
if ($form_id == 'linkableobject_node_form') {
$vid=26;
$query=taxonomy_get_tree($vid);
//Creo funzione per array name vocabulary
foreach($query as $rec){
$form["prova"]= array(
'#type'=> 'select',
'#title'=> t($rec->name),
'#options'=>array(get_vid($vid)),
'#ajax' => array(
'callback'=>'get_synonyms',
'wrapper'=>'area_sinonimi',
'replace'=>'TRUE',
),
);
}
//form dei sinonimi
$form['sinonimi'] = array(
// '#type' => 'hidden',
'#title'=> t('Sinonimi'),
'#prefix' => '<div id="area_sinonimi">Qui andrebbero i sinonimi',
'#suffix' => '</div>',
);
}
and recall with ajax this function get_synonyms
function get_synonyms() {
$form_build_id = $_POST['form_build_id'];
$form_state = array('submitted' => FALSE);
$form = form_get_cache($form_build_id, $form_state);
$output="";
$synonyms = '';
$vid=26;
$tid = $_POST['prova'];
$result = db_query('SELECT name FROM {taxonomy_term_synonym} where tid=:tid', array(':tid'=>$tid));
//print_r($result);
$voc = get_vocabolario($vid);
if ($tid > 0)
$synonyms .= "<b>Synonyms for $voc:</b></br>";
foreach ($result as $rec) {
$synonyms.= "<i>'" . $rec->name . "';</i> ";
$keywords[$rec->name] = $rec->name;
}
$form['sinonimi'] = array(
'#type' => 'item',
'#description' => t("In order to facilitate the cataloging of your learning object,
try to make use of these terms for its description"),
'#value' => $synonyms,
);
$synonyms.='</br>';
form_set_cache($_POST['form_id'], $form, $form_state);
$form = form_builder($_POST['form_id'], $form, $form_state);
$output.=drupal_render($form['sinonimi']);
drupal_json_encode(array('status' => TRUE, 'data' => $output));
exit;
}
but give me this error Recoverable fatal error: Argument 1 passed to drupal_array_set_nested_value() must be of the type array, null given, called in /var/www/html/glorep/includes/form.inc on line 2532 and defined in drupal_array_set_nested_value() (line 6598 of /var/www/html/glorep/includes/common.inc).
I think the probles is ajax, i have upgrade this from D6 when there is D6, but i can understand how modify, can someone help me?

Please read this https://drupal.org/coding-standards and update your code.
You're adding form element ($form["prova"]) with the same name in loop. So each iteration will replace existing element with new one.
Check value of $tid = $_POST['prova']; because it depends from which options was set for this select box. I expect that you didn't set the keys for options.
Check arguments of drupal_array_set_nested_value() function.
Install and configure xdebug and will be able to find a bug in 1 minute.

Related

Drupal overriding modules's function into another module's function duplicating the form

I am at beginner level of drupal trying to Overriding the third party uc_cart_uc_cart_pane function into my own custom function custom_session_uc_cart_pane but it is duplicating the form or result
Here is sample functions
/**
* Implements hook_uc_cart_pane().
*/
function uc_cart_uc_cart_pane($items) {
$body = array();
if (!is_null($items)) {
$body = drupal_get_form('uc_cart_view_form', $items) + array(
'#prefix' => '<div id="cart-form-pane">',
'#suffix' => '</div>',
);
}
$panes['cart_form'] = array(
'title' => t('Default cart form'),
'enabled' => TRUE,
'weight' => 0,
'body' => $body,
);
return $panes;
}
function custom_session_uc_cart_pane($items){
$iframe = multi_domain_iframe();
// echo "<pre>";
// print_r($items);
// exit;
$pre_suf_fix = array(
'#prefix' => '<div id="cart-form-pane1">',
'#suffix' => '</div>'.$iframe,
);
$body = array() + $pre_suf_fix;
if (!is_null($items)) {
$body = drupal_get_form('custom_session_view_form', $items) + $pre_suf_fix;
}
$panes['cart_form'] = array(
'title' => t('Default cart form'),
'enabled' => TRUE,
'weight' => 0,
'body' => $body,
);
return $panes;
}
any thing which i am missing.
if you want to change some thing specifically for a form you can use
hook_form_alter
you do not need to override the function.
Thanks

Storing key value dictionary in Elgg

I am working on a plugin for Elgg that keeps track of device ids that are sent to the application when logging in from your mobile phone. For this, I would like to store these device ids in the database and would like to use ElggObjects for this.
This is what I do now:
function initialize() {
$androidTokens = elgg_get_entities(array(
'type' => 'object',
'subtype' => 'androidTokens',
'limit' => 0
));
$iosTokens = elgg_get_entities(array(
'type' => 'object',
'subtype' => 'iosTokens',
'limit' => 0
));
if ($androidTokens == 0) {
$tokenObject = new ElggObject();
$tokenObject->subtype = 'androidTokens';
$tokenObject->tags = array();
$tokenObject->save();
}
if ($iosTokens == 0) {
$tokenObject = new ElggObject();
$tokenObject->subtype = 'iosTokens';
$tokenObject->tags = array();
$tokenObject->save();
}
}
So this generates two ElggObjects that hold ids for android and for ios devices, stored in the metadata field tags. This array of tags can however not be retrieved anymore. When I do:
$tokenObject = elgg_get_entities(array(
'type' => 'object',
'subtype' => $os.'Tokens',
'limit' => 0
));
$tokens = $tokenObject->tags
tokens remains empty. Does someone know what I am doing wrong? Am I using the Elgg objects wrong?
I think the reason you're running into issues there is that elgg_get_entities returns an array of entities.
Am I correct in assuming that you'll only ever have one of each token object subtype? (One for iOS and one for Android?)
If so, I would modify your code as follows:
function initialize() {
$androidTokens = elgg_get_entities(array(
'type' => 'object',
'subtype' => 'androidTokens',
'limit' => 1 // only expecting one entity
));
$iosTokens = elgg_get_entities(array(
'type' => 'object',
'subtype' => 'iosTokens',
'limit' => 1 // only expecting one entity
));
if (count($androidTokens) == 0) {
$tokenObject = new ElggObject();
$tokenObject->subtype = 'androidTokens';
$tokenObject->tags = array();
$tokenObject->save();
}
if (count($iosTokens) == 0) {
$tokenObject = new ElggObject();
$tokenObject->subtype = 'iosTokens';
$tokenObject->tags = array();
$tokenObject->save();
}
}
Later, when grabbing the entity:
$tokenObject = elgg_get_entities(array(
'type' => 'object',
'subtype' => $os.'Tokens',
'limit' => 1 // only grab one
));
$tokens = $tokenObject[0]->tags; // get tag data for first (and only) entity

Prestashop error "invalid security token"

im creating a new module for prestashop 1.5.6 and im having some problems with it.
The module has to send sms to the costumers and it has to be an option of the back-Office menu.
I have created the module with the install and uninstall functions and added the tabs to the back-office menu, but im a newbie in prestashop so i don´t know how to make the AdminMyModuleController.php and when i try to click the tab of the module it says "INVALID SECURITY TOKEN", i don´t know how resolve this issue because i don´t know much of security.
If someone can add me on facebook or whatever to help me would be amazing.
Here is the code of the mymodule.php:
private function _createTab()
{
// Tab Raiz
$data = array(
'id_tab' => '',
'id_parent' => 0,
'class_name' => 'Empty',
'module' => 'mymodule',
'position' => 14, 'active' => 1
);
/* Insert the data to the tab table*/
$res = Db::getInstance()->insert('tab', $data);
//Get last insert id from db which will be the new tab id
$id_tabP = Db::getInstance()->Insert_ID();
//Define tab multi language data
$data_lang = array(
'id_tab' => $id_tabP,
'id_lang' => Configuration::get('PS_LANG_DEFAULT'),
'name' => 'SMS a clientes'
);
// Now insert the tab lang data
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
// Tab Configuracion
$data = array(
'id_tab' => '',
'id_parent' => $id_tabP,
'class_name' => 'AdminMymodule',
'module' => 'mymodule',
'position' => 1, 'active' => 1
);
$res = Db::getInstance()->insert('tab', $data);
$id_tab = Db::getInstance()->Insert_ID();
$data_lang = array(
'id_tab' => $id_tab,
'id_lang' => Configuration::get('PS_LANG_DEFAULT'),
'name' => 'Configuracion'
);
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
// Tab Enviar Sms
$data = array(
'id_tab' => '',
'id_parent' => $id_tabP,
'class_name' => 'AdminEnviar',
'module' => 'mymodule',
'position' => 1, 'active' => 1
);
$res = Db::getInstance()->insert('tab', $data);
$id_tab = Db::getInstance()->Insert_ID();
$data_lang = array(
'id_tab' => $id_tab,
'id_lang' => Configuration::get('PS_LANG_DEFAULT'),
'name' => 'Enviar SMS'
);
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
return true;
}
Thanks
As Lliw said, you must use InstallModuleTab function.
private function installModuleTab($tabClass, $tabName, $idTabParent)
{
$pass = true;
$tab = new Tab();
$tab->name = $tabName;
$tab->class_name = $tabClass;
$tab->module = $this->name; // defined in __construct() function
$tab->id_parent = $idTabParent;
$pass = $tab->save();
return($pass);
}
You can put all in your Install function. For example for your first tab:
public function install()
{
if(!parent::install()
|| !$this->installModuleTab('Empty', array(1 => 'SMS a clientes'), $idTabParent = 0))
return false;
return true;
}
You can set languages with the following array:
array(1 => 'SMS a clientes', 2 => 'Language 2', 3 => 'Language 3')
Then you must create the AdminMyModuleController.php file
It's the wrong way to create a module tab. You should use this function in your install() :
$this->installModuleTab('AdminMyModule', array(1 => 'Attribute description'), $idTabParent = 9);
Then create an AdminMyModuleController.php in your module folder/controllers/admin/AdminMyModuleController.php
But you will need to set some function to see something displayed, i'll make a tutorial for that but until i do it, you can look in another admincontroller from the prestashop core and do the same.

cannot submit ajax autocomplete form by enter key

I'm trying to add feature to our corporate website (this module called 'userpasswords2' searches database of local mailsystem passwords). I'm using AJAX autocomplete and modification of the form.
I cannot submit the form by enter key. AJAX autocomplete works fine, but when I choose the user, the form can only be submitted by submit button.
I would like it to work like here https://api.drupal.org/api/drupal - user enters for example 'hook', chooses for example hook_menu, hits enter, then hits enter again and get the result!
So again - clicking submit button works fine, hitting 'enter' key doesn't work.
Googled a lot, the workarounds I've found doesn't work for me. Please help.
function userpasswords2_menu() {
$items = array();
$items['userpasswords2'] = array(
'title' => 'User passwords',
'page callback' => 'drupal_get_form',
'page arguments' => array('userpasswords2_form'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['userpasswords2/ajax_username_autocomplete_callback2'] = array(
'page callback' => 'ajax_username_autocomplete_callback2',
'type' => MENU_CALLBACK,
'access callback' => TRUE,
);
return $items;
}
function userpasswords2_form($form, &$form_state) {
$form = array();
$form['user'] = array(
'#type' => 'textfield',
'#title' => t('Enter username'),
'#autocomplete_path' => 'userpasswords2/ajax_username_autocomplete_callback2',
'#executes_submit_callback' => 'TRUE',
);
$form['box'] = array(
'#type' => 'markup',
'#prefix' => '<div id="box">',
'#suffix' => '</div>',
'#markup' => '<br>',
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#ajax' => array(
'callback' => 'userpasswords2_callback',
'wrapper' => 'box',
),
'#value' => t('Submit'),
);
return $form;
}
function ajax_username_autocomplete_callback2($string = "") {
$matches = array();
if ($string) {
$result = db_select('my_domain_passwords')
->fields('my_domain_passwords',array('fullname','password'))
->condition('fullname', db_like($string) . '%', 'LIKE')
->range(0,10)
->execute();
foreach ($result as $user) {
$form['custom']['username'] = $matches[$user->fullname] = check_plain($user->fullname);
$form['custom']['password'] = check_plain($user->password);
}
}
drupal_json_output($matches);
}
function userpasswords2_form_validate($form, &$form_state) {
$username = $form_state['values']['user'];
$matches = array();
// select from database by fullname
$result = db_select('my_domain_passwords')
->fields('my_domain_passwords', array('fullname'))
->condition('fullname', db_like($username), 'LIKE')
->range(0,1)
->execute()
->fetchField();
if (!empty($username)) {
$form_state['custom']['username'] = $result;
$password = db_select('my_domain_passwords')
->fields('my_domain_passwords', array('password'))
->condition('fullname', db_like($username), 'LIKE')
->range(0,1)
->execute()
->fetchField();
$form_state['custom']['password'] = $password;
}
return $form;
}
function userpasswords2_callback($form, &$form_state) {
if ( (!empty($form_state['custom']['username'])) && (!empty($form_state['custom']['password'])) ) {
$output_string = $form_state['custom']['username'] . " : " . $form_state['custom']['password'];
} else {
$output_string = "No such user: " . $form_state['values']['user'];
}
$username = $form_state['custom']['username'];
$password = $form_state['custom']['password'];
$element = $form['box'];
$element['#markup'] = $output_string;
return $element;
}
If you remove your autocomplete, you can be able to submit by press enter. So the issue is in the autocomplete function. You need to patch the misc/autocomplte.js. Following is the patch, check out the link for more details.
case 13: // Enter.
case 27: // Esc.
this.hidePopup(e.keyCode);
if (e.keyCode == 13 && $(input).hasClass('auto_submit')) {
input.form.submit();
}
This could be help you https://www.drupal.org/project/drupal/issues/309088

In drupal 6, How to process uloaded file in more than one steps?

I am writing custom module in drupal.
Aim is to :
1. Upload a csv file
2. Display its content in a tabular layout.
3. On confirmation, save it in database.
Problem I am facing:
I am unable to upload any file. I am not getting any thing in $_FILES, even if I upload or not. >> SOLVED
How do I split the process ? Suppose I succeed in uploading file [with your help indeed ;) ], and I save the file, suppose in drupal6/uploaded_data directory. How do I redirect to next page where I can read from file and show tabular data for confirmation.
Codes :)
menu hooks and all
function productsadmin_menu() {
$items['admin/settings/product-administration'] = array(
'title' => 'Product Administration',
'description' => 'Upload products data',
'page callback' => 'productsadmin_form',
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function productsadmin_form() {
return drupal_get_form('productsadmin_my_form');
}
This function is passed to drupal_get_form()
function productsadmin_my_form() {
$form['#attributes'] = array('enctype' => "multipart/form-data");
$form['csv'] = array(
'#type' => 'file',
'#title' => 'Product Catalog',
'#description' => 'Product catalog in specified csv format',
'#required' => FALSE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
Validation (The part which is not working is commented)
function productsadmin_my_form_validate($form, &$form_state) {
if($form_state['values']['csv'] == "") {
form_set_error('csv', t('Please input product catalog csv data'));
}
/* // Check if file is uploaded (Not working)
if ($_FILES['files']['name']['csv'] == '') {
form_set_error('csv', t('Please upload product catalog' . $rahul_vals));
}
*/
}
Submit action
function productsadmin_my_form_submit($form, &$form_state) {
/*
1. Move File to uploaded_dir
2. Change the header so that it is redirected to new page
*/
}
you shouldn't use $_FILES in drupal,use drupal api
I made this example for you to explain how to work with cvs
/**
* Form function
*/
function _form_cvs_import($form_state) {
$form['#attributes'] = array('enctype' => "multipart/form-data");
$form['container'] = array(
'#type' => 'fieldset',
'#title' => t('CVS UPLOAD') ,
);
$form['container']['cvs_file'] = array(
'#type' => 'file' ,
'#title' => t('CVS FILE') ,
'#description' => t('insert your cvs file here') ,
) ;
$form['container']['submit'] = array(
'#type' => 'submit' ,
'#value' => t('SEND') ,
) ;
return $form ;
}
/**
* form validate
*/
function _form_cvs_import_validate($form, $form_state) {
$validators = array(
'file_validate_extensions' => array('cvs'),
);
if(!file_save_upload('cvs_file', $validators)) { // the file is not submitted
form_set_error('cvs_file', 'Please select the cvs file') ;
}else{ // the file is submitted another validation for extension
$file = file_save_upload('cvs_file', $validators, file_directory_path()) ;
if($file->filemime != 'application/octet-stream' ) {
form_set_error('cvs_file', 'Extensions Allowed : cvs') ;
}
}
}
/**
* form submit
*/
function _form_cvs_import_submit($form, $form_state) {
$file = file_save_upload('cvs_file', $validators, file_directory_path()) ; // this is the cvs file in the tmp directory
$file_handler = fopen($file->filepath, 'r') ; // open this cvs file
$line_num = 0 ;
$fields = array() ;
while(!feof($file_handler)) {
$line_num++ ;
$line = fgets($file_handler) ; // this is the line/row
$line_array = explode(",", $line); // array of row fields
$field_num = 0 ;
foreach($line_array as $field) {
$field_num++ ;
$fields[$line_num][$field_num] = str_replace('"', '', $field ); // E.g you can access second row and third field by $fields[2][3]
}
}
fclose($file_handler);
unlink($file->filepath);
}

Categories