/[drupal]/contributions/modules/dependent/dependent.module
ViewVC logotype

Contents of /contributions/modules/dependent/dependent.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Sat May 31 18:02:25 2008 UTC (17 months, 3 weeks ago) by levyofi
Branch: MAIN
CVS Tags: DRUPAL-5--1-4-BETA, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.4: +25 -25 lines
File MIME type: text/x-php
adding the possiblity to choose a selection field as a parent field.
fixing issues with link field and other fields without default 'form-item'.
1 <?php
2
3 /*
4 * Implementation of hook_form_alter()
5 */
6 function dependent_form_alter($form_id, &$form) {
7
8 if ($form_id == '_content_admin_field') {
9 //need to add our form element to the form where field types are created/updated
10
11 //get the names of the related content type and the field type
12 $content_type = content_types($form['type_name']['#value']);
13 $field_name=$form['field_name']['#value'];
14
15 //fill the options list in which the field type can be dependent on
16 //for now - thr list is filled with single on/off checkboxed and 2+ radio choices from the same content type only
17 $options=dependent_create_form_options(array('parent'=>$content_type['type'], 'child'=>$content_type['type']) ,$form, $field_name);
18 if ($options===FALSE){
19 return $form;
20 }else{
21 $form['#submit']['dependent_submition'] = array($options); //this is how we tell drupal that during submition the 'dependent_submition' function should be called
22 }
23 }
24 else if (strpos($form_id,'_node_form')){//this is a node form
25 $content_type = $form['type']['#value'];
26 $dependencies=db_query("SELECT * FROM {field_dependencies} WHERE parent_node_type_name='%s'", $content_type);
27 if (db_num_rows($dependencies)>0){
28 dependent_unset_required_before_validation($form_id, $form);
29 $form['#validate']['dependent_validate_required_fields']=array();
30 }
31 while ($field=db_fetch_array($dependencies)){ //the while loop is to support future development where a field can be dependent on many parents
32 if (isset($form[$field['child_field_name']])){
33 if (isset($form[$field['child_field_name']]['#theme'])){
34 $form[$field['child_field_name']]['#prefix']='<div class="form-item">'.$form[$field['child_field_name']]['#prefix'];
35 $form[$field['child_field_name']]['#suffix'].=$form[$field['child_field_name']]['#suffix'].'</div>';
36 }
37 $suffix=$form[$field['child_field_name']]['#suffix'].'<div class="child_of_'.$field['parent_field_name'].'" style="display: none">child of '.$field['parent_field_name'].($field['put_after_parent']?' put_after_parent':'').(($field['option_text']=='no_value_needed')?'':(' option_text='.$field['option_text'])).'</div>';//this string will help the javascript to hide/show this field
38 $form[$field['child_field_name']]['#suffix']=$suffix;
39 }
40 if ((isset($form[$field['parent_field_name']]))&&(strpos($form[$field['parent_field_name']]['#suffix'],"this_is_a_parent")===FALSE)){
41 $suffix=$form[$field['parent_field_name']]['#suffix'].'<div class="this_is_a_parent" style="display: none">'.$field['parent_field_name'].(($field['option_text']=='no_value_needed')?'':(' parent_text='.$field['option_text'])).'</div>';
42 //$suffix='<div class="this_is_a_parent" style="display: none">'.$field['parent_field_name'].(($field['option_text']=='no_value_needed')?'':(' parent_text='.$field['option_text'])).'</div>';
43 $form[$field['parent_field_name']]['#suffix']=$suffix;
44 }
45 }
46 foreach ($form as $key=>$value){
47 if (strpos($key,'field')!==FALSE){//this is a field
48 if (isset($value['key']['#options'])){
49 $index= array_search('N/A', $value['key']['#options']);
50 if ($index!==FALSE){
51 $len=strlen($index);
52 $flag=($len==0);
53 if ($len==0){
54 unset($form[$key]['key']['#options'][$index]);
55 }
56 }
57 }
58 }
59 }
60
61 drupal_add_css(drupal_get_path('module', 'dependent') .'/dependent.css');
62 drupal_add_js(drupal_get_path('module', 'dependent') .'/dependent.js');
63 }
64 else if ($form_id == '_content_admin_field_remove') { //a field removal page - need to update the database
65 $form['#submit']['dependent_content_admin_field_remove_submit'] = array();
66 }
67 }
68
69
70 /*
71 * this function is being called when the admin saves field settings
72 * $options - an array with all the options that this field can depend on.
73 */
74 function dependent_submition($form_id, $form_values, $options) {
75 if ($form_id == '_content_admin_field') {
76 //this is a submition of adding or editing a field type
77 if (isset($form_values['dependent_options'])){
78 //get the names of the content type and field type
79 $content_type = $form_values['type_name'];
80 $field_name=$form_values['field_name'];
81
82 //check if this is an update operation
83 $is_updatable=db_num_rows(db_query("SELECT * FROM {field_dependencies} WHERE child_field_name='%s' AND child_node_type_name='%s'", $field_name, $content_type));
84
85 //get the selected choice
86 $choice=strval($form_values['dependent_options']);
87 $option=explode(" option from ",$options[$choice]);
88 ($choice>0)?($selected_value=(count($option)>1)?$option[0]:'no_value_needed'):'';
89 ($choice>0)?$selected_field = ($option[1]?$option[1]:$options[$choice]): '';
90
91 //if this is an update delete previous database entries
92 if ($is_updatable){
93 db_query("DELETE FROM {field_dependencies} WHERE child_field_name='%s' AND child_node_type_name='%s'", $field_name, $content_type);
94 }
95 //enter the choice to the database
96 ($choice>0)?db_query("INSERT INTO {field_dependencies} VALUES ('%s','%s','%s','%s','%s',%s, %s)",$selected_field, $field_name, $content_type, $content_type, $selected_value, $form_values['put_after_parent'], $form_values['required']):'';
97 }
98 }
99 }
100
101 /*
102 * this function is being called when the admin removes a field
103 * $options - an array with all the options that this field can depend on.
104 */
105 function dependent_content_admin_field_remove_submit($form_id, $form_values) {
106 $content_type = $form_values['type_name'];
107 $field_name=$form_values['field_name'];
108 if ( $content_type && $field_name && $form_values['confirm']) {//remove this field dependencies data frm database
109 db_query("DELETE FROM {field_dependencies} WHERE (child_field_name='%s' OR parent_field_name='%s') AND child_node_type_name='%s'", $field_name, $field_name, $content_type);
110 }
111 }
112
113 /*
114 * Implementation of hook_form_alter()
115 */
116 function dependent_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
117 switch($op) {
118 case 'view'://hide the content of fields depends on the value of the parent field
119 $nodecopy=$node;
120 $result=db_query("SELECT * FROM {field_dependencies} WHERE child_node_type_name='%s'", $node->type);
121 while ($field=db_fetch_object($result)){
122 $value_needed=($field->option_text=='no_value_needed')?"1":$field->option_text;
123 $parent_field=$field->parent_field_name;
124 //check if $value_needed is in the array of $parent_field
125 $found=false;
126 $parent_content=$node->$parent_field;
127 for($index=0; $index<count($node->$parent_field); ++$index){
128 if ($parent_content[$index]['value']==$value_needed){
129 $found=true;
130 }
131 }
132 if ((!isset($node->content[$parent_field]))||((!$found)&&(isset($node->content[$field->child_field_name])))){
133 unset($node->content[$field->child_field_name]);
134 }
135 }
136 return $node;
137 break;
138 case 'validate':
139 $nodecopy=$node;
140 }
141 }
142
143 /*
144 * This function return an array of options in which a field can be depends on. it also adds the nessecery form elements to the form
145 * @param $content_types
146 * An array that represents the content types involved, with two keys 'parent' as the parent content type and 'child' as the dependent content type.
147 *
148 * @param $form
149 * The form to add the possible options that the admin should choose from
150 *
151 * $param $field_name
152 * The field name that this setting is for. Use null if this field is from another content tyoe
153 *
154 * @param $new_for_name
155 * The name of the fieldset item to add to $form
156 *
157 * @param $weight
158 * The weight that the form item will get in the form
159 *
160 * @param $form_value_name
161 * The initial for the form items in the fielset - this is useful when adding more than one fieldsets in other modules
162 */
163
164 function dependent_create_form_options($content_types, &$form, $field_name=NULL, $new_form_name='dependent', $weight=-5, $form_value_name=""){
165 if (isset($field_name)){
166 $onoff_field_instances=db_query('SELECT * FROM {node_field_instance} WHERE widget_type="options_onoff" and type_name="%s" and field_name<>"%s"', $content_types['parent'],$field_name );
167 $options_field_instances=db_query('SELECT nfi.field_name, nf.global_settings FROM {node_field_instance} nfi,{node_field} nf WHERE nfi.widget_type="options_buttons" and nfi.type_name="%s" and nfi.field_name=nf.field_name and nfi.field_name<>"%s"', $content_types['parent'], $field_name);
168 $selection_field_instances=db_query('SELECT nfi.field_name, nf.global_settings FROM {node_field_instance} nfi,{node_field} nf WHERE nfi.widget_type="options_select" and nfi.type_name="%s" and nfi.field_name=nf.field_name and nfi.field_name<>"%s"', $content_types['parent'], $field_name);
169 }else{
170 $onoff_field_instances=db_query('SELECT * FROM {node_field_instance} WHERE widget_type="options_onoff" and type_name="%s"', $content_types['parent']);
171 $options_field_instances=db_query('SELECT nfi.field_name, nf.global_settings FROM {node_field_instance} nfi,{node_field} nf WHERE nfi.widget_type="options_buttons" and nfi.type_name="%s" and nfi.field_name=nf.field_name', $content_types['parent']);
172 $selection_field_instances=db_query('SELECT nfi.field_name, nf.global_settings FROM {node_field_instance} nfi,{node_field} nf WHERE nfi.widget_type="options_select" and nfi.type_name="%s" and nfi.field_name=nf.field_name', $content_types['parent']);
173 }
174 $row=1;
175 if ((db_num_rows($onoff_field_instances)==0)&&(db_num_rows($options_field_instances)==0)&& (db_num_rows($selection_field_instances)==0)) //no field type can be selected
176 return FALSE;
177
178 //the first oprion is "no field"
179 $options[0]=t("no field");
180 //add the single on/off checkboxes to the options array
181 while($onoff_field=db_fetch_object($onoff_field_instances)){
182 $options[$row++]="$onoff_field->field_name";// in $onoff_field->type_name";
183 }
184 //add the options on each radio buttons field type. every single choice will be added as a separate choice which includes the choice text and the field type name
185 while($options_field=db_fetch_object($options_field_instances)){
186 $field_details=content_fields($options_field->field_name,$content_types['parent']);
187 $field_options_array=explode("\r\n", $field_details['allowed_values']);
188 //iterate through the array and put the options in $options together with the field name
189 foreach($field_options_array as $option){
190 $options[$row++]=$option.' '.t("option from").' '.$options_field->field_name;
191 //print_r($options);
192 }
193 }
194
195 //add the options on each radio buttons field type. every single choice will be added as a separate choice which includes the choice text and the field type name
196 while($options_field=db_fetch_object($selection_field_instances)){
197 $field_details=content_fields($options_field->field_name,$content_types['parent']);
198 $field_options_array=explode("\r\n", $field_details['allowed_values']);
199 //iterate through the array and put the options in $options together with the field name
200 foreach($field_options_array as $option){
201 $options[$row++]=$option.' '.t("option from").' '.$options_field->field_name;
202 //print_r($options);
203 }
204 }
205
206 //if this is an update operation we need to load the previously selected valued to the options list
207 $prev_result=db_query('SELECT * FROM {field_dependencies} WHERE child_field_name="%s" AND parent_node_type_name="%s" AND child_node_type_name="%s"', isset($field_name)?$field_name:"related", $content_types['parent'],$content_types['child']);
208 $is_updatable=db_num_rows($prev_result);
209 $prev_selected=array();
210 $put_after_parent_flag=FALSE;
211 while ($parent = db_fetch_array($prev_result)){
212 $selected_item=(($parent['option_text']=='no_value_needed')?'':($parent['option_text'].' '.t("option from").' ')).$parent['parent_field_name'] ;
213 $prev_selected[]=array_search($selected_item,$options);
214 $put_after_parent_flag=$parent['put_after_parent'];
215 }
216
217 $form[$new_form_name] = array(
218 '#type' => 'fieldset',
219 '#title' => t('Dependent options'),
220 '#weight' => $weight,
221 );
222
223 $form[$new_form_name][$form_value_name.'dependent_options'] = array(//the selection options for this field to depend on
224 '#type' => 'select',
225 '#title' => t('Field instances'),
226 '#default_value' => $is_updatable ? $prev_selected : array(0),
227 '#options' => $options,
228 '#multiple' => FALSE,
229 '#size' => min(count($options), 6),
230 '#description' => t('Choose the on/off checkbox field instances which the current field will depend on'),
231 );
232 $form[$new_form_name][$form_value_name.'put_after_parent']=array( //a checkbox to determine is this field should appear after the parent field
233 '#type' =>'checkbox',
234 '#title' => t('show this field right after its parent'),
235 '#default_value' => $put_after_parent_flag,
236 '#description' => t('check this option if you want this field to be shown right after the selected item'),
237 );
238 return $options;
239 }
240
241 /*
242 * This function look for dependent fields in the form and unset the required flag if exists
243 */
244 function dependent_unset_required_before_validation($form_id, &$form){
245 $dependencies=db_query("SELECT * FROM {field_dependencies} WHERE parent_node_type_name='%s' AND is_required=1", $form['type']['#value']);
246 while ($field=db_fetch_array($dependencies)){
247 //if (($form['#post'][$field['parent_field_name']]['key']!==$field['option_text'])||(($field['option_text']=='no_value_needed')&&($form_values[$field['paremt_field_name']]===0))){
248 dependent_find_and_destroy_required_flag($form[$field['child_field_name']], $field['child_field_name'] );
249 //}
250 }
251 }
252
253 /*
254 * This function get a form element and find it required flag and unsets it. It also adds the html recognition flag of a required field so this field will still looks as required
255 * This is done because the module validation functions are called after the default node_form_validate function
256 */
257 function dependent_find_and_destroy_required_flag(&$element, $field_name){
258 global $dependent_required_fields;
259 if (!isset($dependent_required_fields)){
260 $dependent_required_fields=array();
261 }
262 foreach ($element as $key=>$value) {
263 if (strval($key)=='#required') {
264 unset($element[$key]);
265 $dependent_required_fields[]=$field_name;
266 $element['#title'].= '<span class="form-required" title="'. t('This field is required.') .'">*</span>';
267
268 return;
269 }
270 if (is_array($value)){
271 dependent_find_and_destroy_required_flag($element[$key], $field_name);
272 }
273 }
274 }
275
276 /*
277 * This function is called as part of the form validation
278 * it looks for the required fields that the function 'dependent_find_and_destroy_required_flag' have set as not required.
279 * it then checks if this field was supposed to be filled. If yes, the function checks whether the field has a value and if not it calles 'form_set_error'
280 */
281 function dependent_validate_required_fields($form_id, $form_values){
282 $dependencies=db_query("SELECT * FROM {field_dependencies} WHERE parent_node_type_name='%s' AND is_required=1", $form_values['type']);
283 while ($field=db_fetch_array($dependencies)){
284 if (($form_values[$field['parent_field_name']]['key']===$field['option_text'])||(($field['option_text']=='no_value_needed')&&($form_values[$field['paremt_field_name']]===1))){//check if the parent field has the right value for the child field to be filled
285 if (((isset($form_values[$field['child_field_name']]['key']))&&($form_values[$field['child_field_name']]['key']===""))||((isset($form_values[$field['child_field_name']][0]))&&($form_values[$field['child_field_name']][0]['value']===""))){//check if the child field has a value
286 //the child field does not have a value
287 $field_data=content_fields($field['child_field_name'],$form_values['type']);
288 form_set_error('dependent',t('!name field is required.', array('!name' => $field_data['widget']['label'])));
289 }
290 }
291 }
292 }
293 ?>

  ViewVC Help
Powered by ViewVC 1.1.2