Drupal 7 Field Multiple value deletion and display - drupal-7

I have been stuck for days and I hope that somebody could help me out.
I am writing a module to link to different node (I understand that such module does exist however I would like to practice coding a module, I did tried to look at other module for reference, however, I cannot spot any problem).
After I added the module, I activate the field in a custom node type and select allow multiple value. When I added the content (of that content type) two of the field appears instead of one, and when I added extra field, I cannot delete. I hope that someone can give me some direction on how to fix it. I have included a screenshot of the problem below. I am also hoping to add a delete button / a way to delete an extra item. After research for days, I cannot find a drupal way to do it.
Below are the code I added for reference
for belong_to_relation.install, I added the following
function belong_to_relation_field_schema ($field) {
if ($field['type'] == 'belong_to_relation') {
// Declare fields in the db
$columns = array (
'to_node_type' => array (
'type' => 'varchar',
'length' => '64',
'not null' => FALSE,
'description' => 'The relation id from the belong_to_relation table',
),
'to_node_nid' => array (
'type' => 'int',
'not null' => FALSE,
'description' => 'the node id of the to node',
),
'extended_node_nid' => array (
'type' => 'int',
'not null' => FALSE,
'description' => 'the node id of the extended field node',
),
);
return array (
'columns' => $columns,
'indexes' => array(),
);
}
}
For belong_to_relation.module, I added the following
function belong_to_relation_field_info () {
return array (
'belong_to_relation_reference' => array (
'label' => t("Belong to Relation Node Reference"),
'description' => t('This field stores a node reference to a node of another content type'),
'default_widget' => 'belong_to_relation_reference_widget',
'default_formatter' => 'belong_to_relation_reference_formatter',
),
);
}
function belong_to_relation_field_widget_info () {
return array (
'belong_to_relation_reference_widget' => array (
'label' => t('Default'),
'field types' => array ('belong_to_relation_reference'),
),
);
}
function belong_to_relation_field_widget_form (&$form, &$form_state, $field,
$instance, $langcode, $items,
$delta, $element) {
$element += array(
'#type' => 'fieldset',
'#tree' => true
);
$element['to_node_type'] = array (
'#type' => 'select',
'#title' => t('Target Node Type'),
'#options' => array(),
'#default_value' => isset($item['to_node_type']) ? $item['to_node_type'] : NULL,
'#empty_option' => 'Select a Node type',
);
$element['to_node_nid'] = array (
'#type' => 'select',
'#title' => t('Target Node Type'),
'#options' => array(),
'#default_value' => isset($item['to_node_nid']) ? $item['to_node_nid'] : NULL,
'#empty_option' => 'Select a Node',
);
$element['extended_node_nid'] = array (
'#type' => 'select',
'#title' => t('Target Node Type'),
'#options' => array(),
'#default_value' => isset($item['extended_node_nid']) ? $item['extended_node_nid'] : NULL,
'#empty_option' => 'Select a Node type',
);
return $element;
}
function belong_to_relation_field_is_empty ($item, $field) {
return FALSE;
}
function belong_to_relation_field_formatter_info () {
return array (
'belong_to_relation_reference_formatter' => array (
'label' => t('Simple Belong To Relation Formatter'),
'field types' => array ('belong_to_relation_reference'),
),
);
}
I am currently running on drupal 7.7 on MAMP.

The OP wrote:
Solved, need to delete the if ($field['type'] == 'belong_to_relation') line in .install

Related

Drupal 7 programmatically create webform components

I've followed this great document which successfully creates a webform and associated components.
I am trying to adjust the code so it works for existing webforms instead of creating new ones.
My code is as follows:
$nid = 12;
$node = node_load(12);
// Create the webform components.
$components = array(
array(
'name' => 'Gender',
'form_key' => 'gender',
'type' => 'select',
'mandatory' => 1,
'weight' => 0,
'pid' => 0,
'extra' => array(
'title_display' => 'inline',
'private' => 0,
'items' => "Mrs|Mrs\nMiss|Miss\nMr|Mr",
'aslist' => 1,
),
),
);
// Setup notification email.
$emails = array(
array(
'email' => 'somebody#example.tld',
'subject' => 'default',
'from_name' => 'default',
'from_address' => 'default',
'template' => 'default',
'excluded_components' => array(),
),
);
// Attach the webform to the node.
$node->webform = array(
'confirmation' => '',
'confirmation_format' => NULL,
'redirect_url' => '<confirmation>',
'status' => '1',
'block' => '0',
'teaser' => '0',
'allow_draft' => '0',
'auto_save' => '0',
'submit_notice' => '1',
'submit_text' => '',
'submit_limit' => '-1', // User can submit more than once.
'submit_interval' => '-1',
'total_submit_limit' => '-1',
'total_submit_interval' => '-1',
'record_exists' => TRUE,
'roles' => array(
0 => '1', // Anonymous user can submit this webform.
),
'emails' => $emails,
'components' => $components,
);
// Save the node.
node_save($node);
When I attempt to execute my code I get the following error:
Error message SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'nid' cannot be null
First try to print all the available values of $node.
echo "<pre>";
print_r($node);
echo "</pre>"'
exit;
check that you are getting value for $node[nid] or not.

CakeDC Search and Tag plugin - search for multiple tags

Hopefully I'm missing something simple here. I'm using the CakeDC Search and Tags plugin for my cake (2.3.4) app.
Along with generic search by field functionality I want the user to be able to search by tags. I've almost got this working but the search will only display results if you search for a single tag not multiples. For example, if I add an article with the following tags - black, white, red. The article will only show in the search results if I search for a single tag (say, black) and not all 3, or even 2... What am I missing?
Heres my code:
Article.php model
class Article extends AppModel {
public $actsAs = array(
'Upload.Upload' => array(
'screenshot1' => array (
'fields' => array (
'dir' => 'dir'
),
'thumbnailMethod' => 'php',
'thumbnailSizes' => array(
'xvga' => '1024x768',
'vga' => '640x480',
'thumb' => '80x80'
),
),
),
'Search.Searchable',
'Tags.Taggable'
);
// Search plugin filters
public $filterArgs = array(
'title' => array('type' => 'like'),
'environment' => array('type' => 'like'),
'description' => array('type' => 'like'),
'error' => array('type' => 'like'),
'cause' => array('type' => 'like'),
'resolution' => array('type' => 'like'),
'live' => array('type' => 'value'),
'synced' => array('type' => 'value'),
'tags' => array('type' => 'subquery', 'method' => 'findByTags', 'field' => 'Article.id'),
array('name' => 'search', 'type' => 'query', 'method' => 'filterQuery'),
);
// This is the OR query that runs when the user uses the client side signle field search
public function filterQuery($data = array()) {
if(empty($data['search'])) { // search is the name of my search field
return array();
}
$query = '%'.$data['search'].'%';
return array(
'OR' => array(
'Article.title LIKE' => $query,
'Article.description LIKE' => $query,
'Article.error LIKE' => $query,
)
);
}
// Find by tags method
public function findByTags($data = array()) {
$this->Tagged->Behaviors->attach('Containable', array('autoFields' => false));
$this->Tagged->Behaviors->attach('Search.Searchable');
$query = $this->Tagged->getQuery('all', array(
'conditions' => array('Tag.name' => $data['tags']),
'fields' => array('foreign_key'),
'contain' => array('Tag')
));
return $query;
}
public $hasAndBelongsToMany = array(
'Category' => array(
'className' => 'Category',
'joinTable' => 'articles_categories',
'foreignKey' => 'article_id',
'associationForeignKey' => 'category_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
),
'Tag' => array('with' => 'Tagged')
);
Controller method
public function admin_advancedSearch() {
// Disable validation for this action
$this->Article->validate = array();
// For search plugin
$this->Prg->commonProcess();
// Set searched for details
$this->set('searchedFor', $this->passedArgs);
// If passed args are all empty
if ($this->passedArgs) {
if (empty($this->passedArgs['title']) AND
empty($this->passedArgs['environment']) AND
empty($this->passedArgs['description']) AND
empty($this->passedArgs['error']) AND
empty($this->passedArgs['cause']) AND
empty($this->passedArgs['resolution']) AND
empty($this->passedArgs['live']) AND
empty($this->passedArgs['synced']) AND
empty($this->passedArgs['tags'])) {
$this->Session->setFlash('Please enter at least one search criteria', 'flash_failure');
// Set this var for checks in view
$this->set('emptySeach', true);
} else {
$paginateConditions = $this->Article->parseCriteria($this->passedArgs);
$this->paginate = array('conditions' => array(
$paginateConditions),
'limit' => 10,
'order' => array('Article.modified' => 'DESC'));
$this->set('articles', $this->paginate());
// Count number of results
$count = 0;
foreach ($this->paginate() as $result) {
$count++;
}
$this->set('resultsCount', $count);
// Search was not empty - set flag for view
$this->set('emptySeach', false);
}
}
// Set layout
$this->layout = 'admin';
//debug($this->passedArgs);
}
All plugins are loaded successfully from bootstrap, searches work fine without tags. Searches with tags only work if one tag is entered....
*EDIT *
If I debug $query from the findByTags method I get this:
'SELECT `Tagged`.`foreign_key` FROM `knowledgebase`.`tagged` AS `Tagged` LEFT JOIN `knowledgebase`.`tags` AS `Tag` ON (`Tagged`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`name` = 'kia, rio, red''
So it looks like its trying to find a single tag with all the searched for tags in its name. How can I make the WHERE part an IN?
For example:
WHERE `Tag`.`name` IN ('kia', 'rio', 'red')
Thanks
Use the "method" https://github.com/cakedc/search#behavior-and-model-configuration key her to pass the search args to a customized method.
The example here shows you exactly how this works https://github.com/cakedc/search#full-example-for-modelcontroller-configuration-with-overriding
public $filterArgs = array(
'some_related_table_id' => array('type' => 'value'),
'search'=> array('type' => 'like', 'encode' => true, 'before' => false, 'after' => false, 'field' => array('ThisModel.name', 'OtherModel.name')),
'name'=> array('type' => 'query', 'method' => 'searchNameCondition')
);
public function searchNameCondition($data = array()) {
$filter = $data['name'];
$cond = array(
'OR' => array(
$this->alias . '.name LIKE' => '' . $this->formatLike($filter) . '',
$this->alias . '.invoice_number LIKE' => '' . $this->formatLike($filter) . '',
));
return $cond;
}
Inside your custom method explode() the tags and make them an array so that CakePHP is using them as IN() or better (in can become slow) make it a chain of AND or OR.

array_unshift - how to put array the top with key name

I have array element stored in $sal to put at the start of an array $fields['billing']. i am using array_unshift for this purpose.
$sal = array(
'label' => __('Tratamiento', 'woocommerce'),
'placeholder' => _x('', 'placeholder', ''),
'required' => 0,
'clear' => true,
'class' => array('form-row form-row-wide'),
'type' => 'select',
'options' => array(
'Señor' => __('Señor', 'woocommerce' ),
'Señora' => __('Señora', 'woocommerce' ),
'Señorita'=> __('Señorita', 'woocommerce')
)
);
array_unshift($fields['billing'] , $sal);
array_unshift adding element at the start of array at 0 key index. after print_r i see:
[0] => Array
(
[Label] => Treatment
[Placeholder] =>
[Required] => 0
[Clear] => 1
[Class] => Array
(
[0] => form-row-row-wide form
)
[Type] => select
[Options] => Array
(
[Lord] => Lord
[Lady] => Lady
[Ms.] => Miss
)
)
My problem is only that i just want to change the key value from [0] to ['saluation'], i can simply do that with:
$fields['billing']['saluation'] = $fields['billing'][0];
unset($fields['billing'][0]);
but i also want it at the start of array. i tried many techniques but still unable to figure this out.
this is actully woocommerce fields arrays which i am dealing with.
I just solved it by array_merge() function.
$fields['billing']= array_merge(array('saluation' => $sal), $fields['billing']);

Drupal 7 Forms API - AJAX Forms error: An illegal choice has been detected. Please contact the site administrator

I have a form set up where a users selects an item from a drop down. Once that item is selected another drop down is populated. Then depending on the value that is selected from the second drop down a fieldset may or may not be shown. If the field set is shown there is a field and a button. By clicking the button you add another copy of the same field. Once there is more than one a remove one button shows up as well. I got the basis for the code from here:
http://api.drupal.org/api/examples/ajax_example%21ajax_example_graceful_degradation.inc/function/ajax_example_add_more/7
The problem is when I click 'Add Another Survey Question' the first time it works fine and add a field. When I click it a second time or when I click remove now that there are two, I get this error: 'An illegal choice has been detected. Please contact the site administrator.'
What am I doing wrong?
Here's my code:
function touchpoints_addmetric_form($form, &$form_state, $tp_id) {
$selectedType = isset($form_state['values']['type']) ? $form_state['values']['type'] : FALSE;
$types = db_query('SELECT * FROM {touchpoints_metric_types}') -> fetchAllKeyed(0, 1);
$form['#tree'] = TRUE;
$form['type'] = array(
'#type' => 'select',
'#title' => t('Metric Type'),
'#options' => $types,
'#required'=>TRUE,
'#ajax' => array(
'event' => 'change',
'wrapper' => 'method-wrapper',
'callback' => 'touchpoints_method_callback'
)
);
$form['measurementmethod'] = array(
'#type' => 'select',
'#title' => t('Measurement Method'),
'#required'=>TRUE,
'#prefix' => '<div id="method-wrapper">',
'#suffix' => '</div>',
'#options' => _get_methods($selectedType)
);
$form['survey'] = array('
#type' => 'fieldset',
'#collapsible' => FALSE,
'#states' => array(
'visible' => array(
array(
array(':input[name="measurementmethod"]' => array('value' => '5')),
'xor',
array(':input[name="measurementmethod"]' => array('value' => '6')),
'xor',
array(':input[name="measurementmethod"]' => array('value' => '7'))
)
)
)
);
$form['survey']['contents'] = array(
'#type' => 'fieldset',
'#collapsible' => FALSE,
'#prefix' => '<div id="survey-div">',
'#suffix' => '</div>',
);
if (empty($form_state['num_surveys'])) {
$form_state['num_surveys'] = 1;
}
for ($i = 1; $i <= $form_state['num_surveys']; $i++) {
$form['survey']['contents']['survey_question'][$i] = array(
'#type' => 'textfield',
'#title' => t('Survey Question ' . $i),
'#size' => 70, '#maxlength' => 100,
);
}
$form['survey']['contents']['addsurvey'] = array(
'#type' => 'submit',
'#value' => t('Add Another Survey Question'),
'#submit' => array('touchpoints_metrics_survey_add_one'),
'#limit_validation_errors' => array(),
'#ajax' => array(
'callback' => 'touchpoints_metrics_survey_callback',
'wrapper' => 'survey-div',
),
);
if ($form_state['num_surveys'] > 1) {
$form['survey']['contents']['removesurvey'] = array(
'#type' => 'submit',
'#value' => t('Remove A Survey Question'),
'#submit' => array('touchpoints_metrics_survey_remove_one'),
'#limit_validation_errors' => array(),
'#ajax' => array(
'callback' => 'touchpoints_metrics_survey_callback',
'wrapper' => 'survey-div',
),
);
}
return $form;
}
function _get_methods($selected) {
if ($selected) {
$methods = db_query("SELECT * FROM {touchpoints_m_methods} WHERE mt_id=$selected") -> fetchAllKeyed(0, 2);
} else {
$methods = array();
}
return $methods;
}
function touchpoints_method_callback($form, &$form_state) {
return $form['measurementmethod'];
}
function touchpoints_metrics_survey_add_one($form, &$form_state) {
$form_state['num_surveys']++;
$form_state['rebuild'] = TRUE;
}
function touchpoints_metrics_survey_remove_one($form, &$form_state) {
if ($form_state['num_surveys'] > 1) {
$form_state['num_surveys']--;
}
$form_state['rebuild'] = TRUE;
}
function touchpoints_metrics_survey_callback($form, &$form_state) {
return $form['survey']['contents'];
}
I have encountered this error a few times, and this is what I found:
This is Drupal's way of saying "Hey, you tried to submit this form with a , checkbox or radio button option that wasn't included in the original form definition! That's not allowed." - See more at: http://proofgroup.com/blog/2008/jul/debugging_mysterious_illegal_choice_has_been_detected_please_contact_site_administrato#sthash.vDNmqslL.dpuf
Instead of custom code, maybe you should consider module Conditional Fields
Or a work around: '#validate' => TRUE source
Actually, it's '#validated' => TRUE.

drupal #default_value not applied in select option in drupal_render

I try to print a drupal 'select option' element in a form .I think drupal_render not applying #default_value.every thing is ok except #default_value not applied.
where is the problem?anybody know how i can do this?
do #default_value accept string value?
this is pseudo of my codes:
function test_menu(){
$items=array();
$items['admin/config/regional/test']=array(
'title' => 'test',
'description' => t('test'),
'page callback' =>'drupal_get_form',
'page arguments' => array('test_function'),
);
$items[]=array();
return $items;
}
function test_function(){
$header = array
(
'test1' => t('test1'),
'test2'=> t('test2'),
);
$a=(1,2,3);
$$options=array();
foreach($a as $i=>$v)
{
$f['type'] = array(
'#type' => 'select',
'#options' => array(1,2,3,4),
'#default_value'=>1,
);
$options += array($name=>array( 'test1' => $v,
'test2'=> drupal_render($f['type']) ,
}
$form['table'] = array
(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#multiple' => FALSE
//'#empty' => t('No users found'),
);
$form['submit'] = array
(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
I test textfield but its also not work and not accept #default_value in drupal_render
$f['test3']=array(
'#type'=>'textfield',
'#title'=>'test3',
'#default_value' =>'aaa',
);
I suppose this is beacuse using drupal_render .anybody have a solution?
In Drupal_render 's used in drupal_get_form , #default_value not set use must use #value instaed of it.
$f['type'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(array('1','2','3','4')),
'#value'=> '1',
);
The following code doesn`t work:
$form['title'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(array(t('opt1'), t('opt3'), t('opt4'), t('opt5'), t('opt6'))),
'#default_value' => array($default_value_key));
$form['title1'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(array(t('opt1'), t('opt3'), t('opt4'), t('opt5'), t('opt6'))),
'#default_value' => array($default_value_key));
return $form;
But then i did the following:
$form['group'] = array('#tree' => TRUE);
$form['group']['title'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(array(t('opt1'), t('opt3'), t('opt4'), t('opt5'), t('opt6'))),
'#default_value' => array($default_value_key));
$form['group']['title1'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(array(t('opt1'), t('opt3'), t('opt4'), t('opt5'), t('opt6'))),
'#default_value' => array($default_value_key));
return $form;
And default values now works.
I have the same problem. finally, i found one method. As you said, the default_value does not work. So make the default_value fixed as 0. and change the options array, put the default value on the top.
If you look at the example from Drupal's Form API, you'll see that the #options setting takes a key-value pair array and in the #default_value, you should specify the key of the default value, not the string value.
Also, according to documentation for the #options setting, #options is expecting String values. So your select should be more like:
$f['type'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(array('1','2','3','4')),
'#default_value'=> '1',
);

Resources