Project

General

Profile

Download (95.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/**
3
 * This is the expertsdb_address module for use with CCK.
4
 *
5
 * <p>This file contains information on the expertsdb_address module. The module adds to
6
 * the field types available for inclusion in a content type definition. This field
7
 * is made up of several standard html form fields - street 1, street 2, apartment/suite
8
 * number, city, state, ZIP code, country and other.</p>
9
 * <p>Street 1, street 2, apartment/suite number, other and city can each have a maximum length
10
 * set by the admin. State is a dropdown list with values supplied via a database table
11
 * which is part of this module. ZIP is a 5 digit integer field.</p>
12
 * TODO add a hook that will allow field names to change via jquery or ajax when a country is
13
 * selected. ex. if CANADA is selected, 'State' could change to 'Province'.
14
 * TODO add an option in the admin settings that if some kind of geo-location module is enabled
15
 * that the address field defaults can be populated with data from them INSTEAD of the fields
16
 * that can be filled in now manually
17
 *
18
 * @version $Id: expertsdb_address.module,v 1.15.2.1 2007/12/14 20:16:15 rconstantine Exp $;
19
 * @package expertsdb_address
20
 * @category NeighborForge
21
 * @author Ryan Constantine
22
 * @filesource
23
 * @license http://www.gnu.org/licenses/gpl.txt GNU_GENERAL_PUBLIC_LICENSE
24
 * @link none yet
25
 */
26

    
27

    
28
/*
29
 * Definition of privacy levels
30
 */
31
define('PRIVACY_CONTACT_PRIVATE', 'ContactPrivate');
32
define('PRIVACY_PRIVATE', 'Private');
33
define('PRIVACY_PUBLIC', 'Public');
34

    
35
/**
36
 * Implementation of hook_menu
37
 *
38
 * Required for Activeselect's AJAX capabilities.
39
 * @return array An array of arrays, to add menu entries to the system menu.
40
 */
41
function expertsdb_address_menu($may_cache) {
42

    
43
	$items = array();
44
	if ($may_cache) {
45
		$items[] = array(
46
    'path' => 'expertsdb_address/activeselect',
47
    'title' => t('Activeselect CCK Address'),
48
    'callback' => 'drupal_get_form',
49
    'callback arguments' => array('expertsdb_address_activeselect'),
50
    'access' => user_access('access content'),
51
    'type' => MENU_CALLBACK,
52
		);
53

    
54
		$items[] = array(
55
    'path' => 'expertsdb_address/activeaddress1',
56
    'title' => t('Activeselect CCK Address of prestored addresses'),
57
    'callback' => 'drupal_get_form',
58
    'callback arguments' => array('expertsdb_address_activeaddress1'),
59
    'access' => user_access('administer content'),
60
    'type' => MENU_CALLBACK,
61
		);
62

    
63
		// implement js callback for more-addresses-button
64
		$items[] = array(
65
      'path' => 'expertsdb_address/widget/js',
66
      'callback' => 'expertsdb_address_widget_js',
67
      'access' => user_access('access content'),
68
      'type' => MENU_CALLBACK,
69
		);
70
	}
71

    
72
	return $items;
73
} // function expertsdb_address_menu()
74

    
75
/**
76
 * Implementation of hook_perm in order to restrict database access to bonafide site admins.
77
 * See note below in expertsdb_address_field_settings.
78
 */
79
function expertsdb_address_perm() {
80
	return array(
81
  		'administer databases',
82
    	'view private expertsdb_address fields',
83
	//TODO which else permission are required?
84
	);
85
}
86

    
87
/**
88
 * Implementation of hook_field_info().
89
 *
90
 * @return
91
 *   An array keyed by field type name. Each element of the array is an associative
92
 *   array with these keys and values:
93
 *   - "label": The human-readable label for the field type.
94
 */
95
function expertsdb_address_field_info() {
96
	return array(
97
  'expertsdb_address' => array('label' => 'Expertsdb Address'),
98
	);
99
} //function expertsdb_address_field_info()
100

    
101
/**
102
 * Implementation of hook_field_settings().
103
 *
104
 * See the README.txt for more info.
105
 *
106
 * @param $op
107
 *   The operation to be performed.
108
 * @param $field
109
 *   The field on which the operation is to be performed.
110
 * @return
111
 *   This varies depending on the operation.
112
 *   - "form": an array of form elements to add to
113
 *     the settings page.
114
 *   - "validate": no return value. Use form_set_error().
115
 *   - "save": an array of names of form elements to
116
 *     be saved in the database.
117
 *   - "database columns": an array keyed by column name, with arrays of column
118
 *     information as values.
119
 *   - "filters": an array whose values are 'filters'
120
 *     definitions as expected by views.module (see Views Documentation).
121
 *   - "callbacks": an array describing the field's behaviour regarding hook_field
122
 *     operations. The array is keyed by hook_field operations ('view', 'validate'...)
123
 *     and has the following possible values :
124
 *       CONTENT_CALLBACK_NONE     : do nothing for this operation
125
 *       CONTENT_CALLBACK_CUSTOM   : use the behaviour in hook_field(operation)
126
 *       CONTENT_CALLBACK_DEFAULT  : use content.module's default bahaviour
127
 *     Note : currently only the 'view' operation implements this feature.
128
 *     All other field operation implemented by the module _will_ be executed
129
 *     no matter what.
130
 */
131
function expertsdb_address_field_settings($op, $field) {
132
	switch ($op) {
133
		case 'form':
134
			$activeselect = module_exists('activeselect');
135
			$form = array();
136
			$form['state_abbrv'] = array(
137
        '#type' => 'select',
138
        '#title' => t('Display States/Provinces as'),
139
        '#description' => t('Be sure to check <em>Allow other countries?</em> below if you select Free-text.'),
140
        '#default_value' => isset($field['state_abbrv']) ? $field['state_abbrv'] : 0,
141
        '#options' => array('Select with full names', 'Select with abbreviations', 'Free-text entry'),
142
			);
143
			$form['country_abbrv'] = array(
144
        '#type' => 'checkbox',
145
        '#title' => t('Use abbreviations for display of Countries?'),
146
        '#default_value' => isset($field['country_abbrv']) ? $field['country_abbrv'] : 0,
147
        '#return_value' => 1,
148
			);
149
			$form['countries'] = array(
150
        '#type' => 'fieldset',
151
        '#title' => t('Allowed Countries'),
152
        '#description' => t('Check the countries from which you\'ll allow user addresses.'),
153
        '#collapsible' => TRUE,
154
        '#collapsed' => TRUE,
155
			);
156
			$all_countries = array();
157
			$sql = "SELECT cas.country_name, cas.country_code FROM {expertsdb_address_countries} cas ORDER BY cas.country_name ASC";
158
			$results = db_query($sql);
159
			while ($result = db_fetch_object($results)) {
160
				$all_countries[$result->country_code] = $result->country_name;
161
			}
162
			$state_options = expertsdb_address_get_states($all_countries);
163
			$form['countries']['other_countries'] = array(
164
        '#type' => 'checkbox',
165
        '#title' => t('Allow <em>other</em> countries?'),
166
        '#description' => t('Disable validation of state field against the state database. Admin users should validate the state field of sumitted addresses manually.'),
167
        '#default_value' => isset($field['other_countries']) ? $field['other_countries'] : 0,
168
        '#return_value' => 1,
169
			);
170
			$form['countries']['clist'] = array(
171
        '#type' => 'checkboxes',
172
        '#title' => t('Countries'),
173
        '#default_value' => isset($field['clist']) ? $field['clist'] : 1,
174
        '#options' => $all_countries,
175
			);
176

    
177
			//for selecting which fields to display
178
			$field_display_default = array();
179
			if (is_array($field['fielddisplay'])) {
180
				foreach ($field['fielddisplay'] as $part => $val) {
181
					if ($val) { $field_display_default[] = $part; }
182
				}
183
			}
184
			else {
185
				$field_display_default = array('field_display_preferred_address','field_display_street1', 'field_display_street2', 'field_display_apt', 'field_display_city', 'field_display_state', 'field_state_alternative', 'field_display_country', 'field_display_zip', 'field_display_other');
186
			}
187
			$form['field_display'] = array(
188
        '#type' => 'fieldset',
189
        '#title' => t('Customize fields to use'),
190
        '#collapsible' => TRUE,
191
        '#collapsed' => TRUE,
192
        '#description' => t('Here you can select which fields to use. Note: normally, the following fields are REQUIRED but will not be (naturally) when not used: Country, State, Zip, City, Address'),
193
			);
194
			$form['field_display']['fielddisplay'] = array(
195
        '#type' => 'checkboxes',
196
        '#required' => FALSE,
197
        '#default_value' => $field_display_default,
198
        '#options' => array(
199
					'field_display_preferred_address' => t("Preferred Address"),
200
          'field_display_street1' => t("Address"),
201
          'field_display_street2'  => t("Address continued"),
202
          'field_display_apt' => t("Apt/suite number"),
203
          'field_display_city'   => t("City"),
204
          'field_display_state' => t("State"),
205
      		'field_display_state_alternative' => t("State alternative"),
206
          'field_display_zip' => t("Zip"),
207
          'field_display_country' => t("Country"),
208
          'field_display_other' => t("Other"),
209
			),
210
			);
211

    
212
			//maximum lengths of fields
213
			$form['max_lengths'] = array(
214
        '#type' => 'fieldset',
215
        '#title' => t('Maximum field lengths'),
216
        '#collapsible' => TRUE,
217
        '#collapsed' => TRUE,
218
        '#description' => t('You may find that if you don\'t set values here that the placement of the form elements are funky. I designed the CSS file using
219
        30, 30, 7, 30, 30 as maximums. Feel free to adjust maximums as you see fit, but realize you may have to adjust the CSS file or override the CSS values
220
        in your theme\'s style.css file.'),
221
			);
222
			$form['max_lengths']['max_length_street1'] = array(
223
        '#type' => 'textfield',
224
        '#title' => t('Maximum length: address field'),
225
        '#size' => 6,
226
        '#default_value' => isset($field['max_length_street1']) ? $field['max_length_street1'] : '',
227
        '#required' => FALSE,
228
        '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
229
			);
230
			$form['max_lengths']['max_length_street2'] = array(
231
        '#type' => 'textfield',
232
        '#title' => t('Maximum length: address continued field'),
233
        '#size' => 6,
234
        '#default_value' => isset($field['max_length_street2']) ? $field['max_length_street2'] : '',
235
        '#required' => FALSE,
236
        '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
237
			);
238
			$form['max_lengths']['max_length_apt'] = array(
239
        '#type' => 'textfield',
240
        '#title' => t('Maximum length: apt field'),
241
        '#size' => 6,
242
        '#default_value' => isset($field['max_length_apt']) ? $field['max_length_apt'] : '',
243
        '#required' => FALSE,
244
        '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
245
			);
246
			$form['max_lengths']['max_length_city'] = array(
247
        '#type' => 'textfield',
248
        '#title' => t('Maximum length: city field'),
249
        '#size' => 6,
250
        '#default_value' => isset($field['max_length_city']) ? $field['max_length_city'] : '',
251
        '#required' => FALSE,
252
        '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
253
			);
254
			$form['max_lengths']['max_length_other'] = array(
255
        '#type' => 'textfield',
256
        '#title' => t('Maximum length: other field'),
257
        '#size' => 6,
258
        '#default_value' => isset($field['max_length_other']) ? $field['max_length_other'] : '',
259
        '#required' => FALSE,
260
        '#description' => t('The maximum length of the field in characters. Leave blank for an unlimited size.'),
261
			);
262

    
263
			//for customizing the field titles
264
			$form['field_names'] = array(
265
        '#type' => 'fieldset',
266
        '#title' => t('Customize field names'),
267
        '#collapsible' => TRUE,
268
        '#collapsed' => TRUE,
269
        '#description' => t('Here you can change the field name of any address field. This will aid in translating for other languages.'),
270
			);
271
			$form['field_names']['field_names_preferred_address'] = array(
272
        '#type' => 'textfield',
273
        '#title' => t('Preferred Address'),
274
        '#default_value' => isset($field['field_names_preferred_address']) && $field['field_names_preferred_address'] != '' ? $field['field_names_preferred_address'] : t('Preferred Address'),
275
        '#required' => FALSE,
276
			);
277
			$form['field_names']['field_names_street1'] = array(
278
        '#type' => 'textfield',
279
        '#title' => t('Address'),
280
        '#default_value' => isset($field['field_names_street1']) && $field['field_names_street1'] != '' ? $field['field_names_street1'] : t('Address'),
281
        '#required' => FALSE,
282
			);
283
			$form['field_names']['field_names_street2'] = array(
284
        '#type' => 'textfield',
285
        '#title' => t('Address continued'),
286
        '#default_value' => isset($field['field_names_street2']) && $field['field_names_street2'] != '' ? $field['field_names_street2'] : t('Address continued'),
287
        '#required' => FALSE,
288
			);
289
			$form['field_names']['field_names_apt'] = array(
290
        '#type' => 'textfield',
291
        '#title' => t('Apt/suite number'),
292
        '#default_value' => isset($field['field_names_apt']) && $field['field_names_apt'] != '' ? $field['field_names_apt'] : t('Apt/suite number'),
293
        '#required' => FALSE,
294
			);
295
			$form['field_names']['field_names_city'] = array(
296
        '#type' => 'textfield',
297
        '#title' => t('City'),
298
        '#default_value' => isset($field['field_names_city']) && $field['field_names_city'] != '' ? $field['field_names_city'] : t('City'),
299
        '#required' => FALSE,
300
			);
301
			$form['field_names']['field_names_state'] = array(
302
        '#type' => 'textfield',
303
        '#title' => t('State'),
304
        '#default_value' => isset($field['field_names_state']) && $field['field_names_state'] != '' ? $field['field_names_state'] : t('State'),
305
        '#required' => FALSE,
306
			);
307
			$form['field_names']['field_names_state_alternative'] = array(
308
        '#type' => 'textfield',
309
        '#title' => t('State'),
310
        '#default_value' => isset($field['field_names_state_alternative']) && $field['field_names_state_alternative'] != '' ? $field['field_names_state_alternative'] : t('State alternative'),
311
        '#required' => FALSE,
312
			);
313
			$form['field_names']['field_names_zip'] = array(
314
        '#type' => 'textfield',
315
        '#title' => t('ZIP'),
316
        '#default_value' => isset($field['field_names_zip']) && $field['field_names_zip'] != '' ? $field['field_names_zip'] : t('ZIP'),
317
        '#required' => FALSE,
318
			);
319
			$form['field_names']['field_names_country'] = array(
320
        '#type' => 'textfield',
321
        '#title' => t('Country'),
322
        '#default_value' => isset($field['field_names_country']) && $field['field_names_country'] != '' ? $field['field_names_country'] : t('Country'),
323
        '#required' => FALSE,
324
			);
325
			$form['field_names']['field_names_other'] = array(
326
        '#type' => 'textfield',
327
        '#title' => t('Other'),
328
        '#default_value' => isset($field['field_names_other']) && $field['field_names_other'] != '' ? $field['field_names_other'] : t('Other'),
329
        '#required' => FALSE,
330
			);
331

    
332
			//for customizing the field order
333
			$order_options = array(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10);
334
			$form['field_order'] = array(
335
        '#type' => 'fieldset',
336
        '#tree' => TRUE,
337
        '#title' => t('Customize field display order'),
338
        '#collapsible' => TRUE,
339
        '#collapsed' => TRUE,
340
        '#description' => t('Here you can order the address fields as you wish. This will affect both the form used for input and display on nodes.
341
        Be careful to not double up the numbers, there\'s no validation against duplicates here.'),
342
			);
343
			$form['field_order']['preferred_address'] = array(
344
        '#type' => 'select',
345
				'#title' => t('Preferred Address'),
346
				'#default_value' => isset($field['field_order']['preferred_address']) ? $field['field_order']['preferred_address'] : 1,
347
        '#options' => $order_options,
348
        '#required' => FALSE,
349
			);
350
			$form['field_order']['street1'] = array(
351
        '#type' => 'select',
352
        '#title' => t('Address'),
353
        '#default_value' => isset($field['field_order']['street1']) ? $field['field_order']['street1'] : 2,
354
        '#options' => $order_options,
355
        '#required' => FALSE,
356
			);
357
			$form['field_order']['street2'] = array(
358
        '#type' => 'select',
359
        '#title' => t('Address continued'),
360
        '#default_value' => isset($field['field_order']['street2']) ? $field['field_order']['street2'] : 3,
361
        '#options' => $order_options,
362
        '#required' => FALSE,
363
			);
364
			$form['field_order']['apt'] = array(
365
        '#type' => 'select',
366
        '#title' => t('Apt/suite number'),
367
        '#default_value' => isset($field['field_order']['apt']) ? $field['field_order']['apt'] : 4,
368
        '#options' => $order_options,
369
        '#required' => FALSE,
370
			);
371
			$form['field_order']['city'] = array(
372
        '#type' => 'select',
373
        '#title' => t('City'),
374
        '#default_value' => isset($field['field_order']['city']) ? $field['field_order']['city'] : 5,
375
        '#options' => $order_options,
376
        '#required' => FALSE,
377
			);
378
			$form['field_order']['state'] = array(
379
        '#type' => 'select',
380
        '#title' => t('State'),
381
        '#default_value' => isset($field['field_order']['state']) ? $field['field_order']['state'] : 6,
382
        '#options' => $order_options,
383
        '#required' => FALSE,
384
			);
385
			$form['field_order']['state_alternative'] = array(
386
        '#type' => 'select',
387
        '#title' => t('State alternative'),
388
        '#default_value' => isset($field['field_order']['state_alternative']) ? $field['field_order']['state_alternative'] : 7,
389
        '#options' => $order_options,
390
        '#required' => FALSE,
391
			);
392
			$form['field_order']['zip'] = array(
393
        '#type' => 'select',
394
        '#title' => t('ZIP'),
395
        '#default_value' => isset($field['field_order']['zip']) ? $field['field_order']['zip'] : 8,
396
        '#options' => $order_options,
397
        '#required' => FALSE,
398
			);
399
			$form['field_order']['country'] = array(
400
        '#type' => 'select',
401
        '#title' => t('Country'),
402
        '#default_value' => isset($field['field_order']['country']) ? $field['field_order']['country'] : 9,
403
        '#options' => $order_options,
404
        '#required' => FALSE,
405
			);
406
			$form['field_order']['other'] = array(
407
        '#type' => 'select',
408
        '#title' => t('Other'),
409
        '#default_value' => isset($field['field_order']['other']) ? $field['field_order']['other'] : 10,
410
        '#options' => $order_options,
411
        '#required' => FALSE,
412
			);
413

    
414
			//for customizing the field defaults
415
			$form['field_defaults'] = array(
416
        '#type' => 'fieldset',
417
        '#title' => t('Customize field defaults'),
418
        '#collapsible' => TRUE,
419
        '#collapsed' => TRUE,
420
        '#description' => t('Here you can set any defaults that should appear when a new address is to be entered.'),
421
			);
422
			$form['field_defaults']['field_defaults_street1'] = array(
423
        '#type' => 'textfield',
424
        '#title' => t('Address'),
425
        '#default_value' => isset($field['field_defaults_street1']) && $field['field_defaults_street1'] != '' ? $field['field_defaults_street1'] : '',
426
        '#required' => FALSE,
427
			);
428
			$form['field_defaults']['field_defaults_street2'] = array(
429
        '#type' => 'textfield',
430
        '#title' => t('Address continued'),
431
        '#default_value' => isset($field['field_defaults_street2']) && $field['field_defaults_street2'] != '' ? $field['field_defaults_street2'] : '',
432
        '#required' => FALSE,
433
			);
434
			$form['field_defaults']['field_defaults_apt'] = array(
435
        '#type' => 'textfield',
436
        '#title' => t('Apt/suite number'),
437
        '#default_value' => isset($field['field_defaults_apt']) && $field['field_defaults_apt'] != '' ? $field['field_defaults_apt'] : '',
438
        '#required' => FALSE,
439
			);
440
			$form['field_defaults']['field_defaults_city'] = array(
441
        '#type' => 'textfield',
442
        '#title' => t('City'),
443
        '#default_value' => isset($field['field_defaults_city']) && $field['field_defaults_city'] != '' ? $field['field_defaults_city'] : '',
444
        '#required' => FALSE,
445
			);
446
			if ($activeselect) {
447
				$form['field_defaults']['field_defaults_state'] = array(
448
          '#type' => 'select',
449
          '#title' => t('State'),
450
          '#multiple' => FALSE,
451
          '#default_value' => isset($field['field_defaults_state']) ? $field['field_defaults_state'] : '',
452
          '#required' => FALSE,
453
          '#options' => array(),
454
          '#DANGEROUS_SKIP_CHECK' => TRUE,
455
				);
456
			}
457
			else {
458
				$form['field_defaults']['field_defaults_state'] = array(
459
          '#type' => 'select',
460
          '#title' => t('State'),
461
          '#multiple' => FALSE,
462
          '#default_value' => isset($field['field_defaults_state']) && !empty($field['field_defaults_state']) ? $field['field_defaults_state'] : '',
463
          '#required' => FALSE,
464
          '#options' => $state_options,
465
				);
466
			}
467
			$form['field_defaults']['field_defaults_zip'] = array(
468
        '#type' => 'textfield',
469
        '#title' => t('ZIP'),
470
        '#default_value' => isset($field['field_defaults_zip']) && $field['field_defaults_zip'] != '' ? $field['field_defaults_zip'] : '',
471
        '#required' => FALSE,
472
			);
473
			if ($activeselect) {
474
				$form['field_defaults']['field_defaults_country'] = array(
475
          '#type' => 'activeselect',
476
          '#title' => t('Country'),
477
          '#multiple' => FALSE,
478
          '#default_value' => isset($field['field_defaults_country']) ? $field['field_defaults_country'] : '',
479
          '#required' => FALSE,
480
          '#options' => $all_countries,
481
          '#activeselect_path' => 'expertsdb_address/activeselect',
482
          '#activeselect_targets' => str_replace('_', '-', 'field_defaults_state'),
483
          '#activeselect_extra' => isset($field['field_defaults_state']) && !empty($field['field_defaults_state']) ? $field['field_defaults_state'] : '',
484
				);
485
			}
486
			else {
487
				$form['field_defaults']['field_defaults_country'] = array(
488
          '#type' => 'select',
489
          '#title' => t('Country'),
490
          '#multiple' => FALSE,
491
          '#default_value' => isset($field['field_defaults_country']) && !empty($field['field_defaults_country']) ? $field['field_defaults_country'] : '',
492
          '#required' => FALSE,
493
          '#options' => $all_countries,
494
				);
495
			}
496
			$form['field_defaults']['field_defaults_other'] = array(
497
        '#type' => 'textfield',
498
        '#title' => t('Other'),
499
        '#default_value' => isset($field['field_defaults_other']) && $field['field_defaults_other'] != '' ? $field['field_defaults_other'] : '',
500
        '#required' => FALSE,
501
			);
502

    
503
			//for validating addresses against a known database
504
			if ($activeselect && user_access('administer databases')) {
505
				$form['select_address_from_db'] = array(
506
          '#type' => 'fieldset',
507
          '#title' => t('Select from DB'),
508
          '#description' => t('Requires the activeselect module. This is for when you know all users\' addresses ahead of time, or you have a limited geography that you\'ve set up.'),
509
          '#collapsible' => TRUE,
510
          '#collapsed' => TRUE,
511
				);
512
				$form['select_address_from_db']['select_a_f_d'] = array(
513
          '#type' => 'checkbox',
514
          '#title' => t('Should users select addresses from a database?'),
515
          '#default_value' => isset($field['select_a_f_d']) ? $field['select_a_f_d'] : 0,
516
          '#return_value' => 1,
517
				);
518
				$all_tables = array();
519
				$sql = "SHOW tables";
520
				$results = db_query($sql);
521
				global $db_url;
522
				$db_name = substr(strrchr($db_url, "/"), 1);
523
				$db_tables = 'Tables_in_' .$db_name;
524
				while ($result = db_fetch_object($results)) {
525
					$all_tables[$result->$db_tables] = $result->$db_tables;
526
				}
527
				if (isset($field['select_streetcolumn']) && isset($field['select_street_numcolumn']) && isset($field['select_city']) && isset($field['select_zip'])) {
528
					$extra_street_num_city_zip = $field['select_streetcolumn']. ',' .$field['select_street_numcolumn']. ',' .$field['select_city']. ',' .$field['select_zip'];
529
				}
530
				else {
531
					$extra_street_num_city_zip = '';
532
				}
533
				$form['select_address_from_db']['select_table'] = array(
534
          '#type' => 'activeselect',
535
          '#title' => t('Select table to use for addresses'),
536
          '#default_value' => isset($field['select_table']) ? array($field['select_table']) : array(),
537
          '#multiple' => FALSE,
538
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
539
          '#options' => $all_tables,
540
          '#activeselect_path' => 'expertsdb_address/activeaddress1',
541
          '#activeselect_targets' => str_replace('_', '-', 'select_streetcolumn'). ',' .str_replace('_', '-', 'select_street_numcolumn'). ',' .str_replace('_', '-', 'select_city'). ',' .str_replace('_', '-', 'select_zip'),
542
          '#activeselect_extra' => $extra_street_num_city_zip,//should be string, not array or object
543
				);
544
				$form['select_address_from_db']['select_streetcolumn'] = array(
545
          '#type' => 'activeselect',
546
          '#title' => t('Select column for street'),
547
          '#default_value' => isset($field['select_streetcolumn']) ? array($field['select_streetcolumn']) : array(),
548
          '#multiple' => FALSE,
549
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
550
          '#options' => array(),
551
          '#DANGEROUS_SKIP_CHECK' => TRUE,
552
				);
553
				$form['select_address_from_db']['select_street_numcolumn'] = array(
554
          '#type' => 'select',
555
          '#title' => t('Select column for street number'),
556
          '#default_value' => isset($field['select_street_numcolumn']) ? array($field['select_street_numcolumn']) : array(),
557
          '#multiple' => FALSE,
558
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
559
          '#options' => array(),
560
          '#DANGEROUS_SKIP_CHECK' => TRUE,
561
				);
562
				$form['select_address_from_db']['select_city'] = array(
563
          '#type' => 'select',
564
          '#title' => t('Select column for city'),
565
          '#default_value' => isset($field['select_city']) ? array($field['select_city']) : array(),
566
          '#multiple' => FALSE,
567
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
568
          '#options' => array(),
569
          '#DANGEROUS_SKIP_CHECK' => TRUE,
570
				);
571
				$form['select_address_from_db']['select_zip'] = array(
572
          '#type' => 'select',
573
          '#title' => t('Select column for postal code'),
574
          '#default_value' => isset($field['select_zip']) ? array($field['select_zip']) : array(),
575
          '#multiple' => FALSE,
576
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
577
          '#options' => array(),
578
          '#DANGEROUS_SKIP_CHECK' => TRUE,
579
				);
580
				$form['select_address_from_db']['select_country'] = array(
581
          '#type' => 'activeselect',
582
          '#title' => t('Select a mandatory country'),
583
          '#description' => t('Be sure to select the right country in <em>Allowed Countries</em> above.'),
584
          '#default_value' => isset($field['select_country']) ? array($field['select_country']) : array(),
585
          '#multiple' => FALSE,
586
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
587
          '#options' => $all_countries,
588
          '#activeselect_path' => 'expertsdb_address/activeselect',
589
          '#activeselect_targets' => str_replace('_', '-', 'select_state'),
590
          '#activeselect_extra' => isset($field['select_state']) ? $field['select_state'] : '',
591
				);
592
				$form['select_address_from_db']['select_state'] = array(
593
          '#type' => 'select',
594
          '#title' => t('Select a mandatory state'),
595
          '#default_value' => isset($field['select_state']) ? array($field['select_state']) : array(),
596
          '#multiple' => FALSE,
597
          '#required' => isset($field['select_address_from_db']) ? $field['select_address_from_db'] : FALSE,
598
          '#options' => array(),
599
          '#DANGEROUS_SKIP_CHECK' => TRUE,
600
				);
601
			}
602

    
603
			/*
604
			 * implements a custom setting for multiple values,
605
			 * because the standard $form['multiple'] force db table normalization
606
			 */
607
			$form['allow_multiple'] = array(
608
          '#type' => 'checkbox',
609
          '#title' => t('Allow submission of multiple addresses'),
610
          '#default_value' => isset($field['allow_multiple']) ? $field['allow_multiple'] : 1,
611
          '#description' => t('Checking will allow the user to submit more than one address. Additionally, the user has to select one address as his preferred address.'),
612
			);
613

    
614
			// disable multiple
615
			$form['multiple'] = array('#type' => 'hidden','#value' => '0');
616

    
617
			return $form;
618

    
619
		case 'validate':
620
			if ($field['max_length_street1'] && !is_numeric($field['max_length_street1'])) {
621
				form_set_error('max_length_street1', t('"Maximum length: first street field" must be a number.'));
622
			}
623
			if ($field['max_length_street2'] && !is_numeric($field['max_length_street2'])) {
624
				form_set_error('max_length_street2', t('"Maximum length: second street field" must be a number.'));
625
			}
626
			if ($field['max_length_city'] && !is_numeric($field['max_length_city'])) {
627
				form_set_error('max_length_city', t('"Maximum length: city name" must be a number.'));
628
			}
629
			if ($field['max_length_other'] && !is_numeric($field['max_length_other'])) {
630
				form_set_error('max_length_other', t('"Maximum length: other" must be a number.'));
631
			}
632
			if (($field['other_countries'] == 0) && ($field['state_abbrv'] == 2)) {
633
				form_set_error('other_countries', t('"Allow <em>other</em> countries?" must be checked if you are using <em>Free-text entry</em> for states.'));
634
			}
635
			if (($field['other_countries'] == 1) && ($field['state_abbrv'] != 2)) {
636
				form_set_error('state_abbrv', t('You must use "<em>Free text entry</em>" for states if you "Allow <em>other</em> countries".'));
637
			}
638
			if (isset($field['multiple'])) {
639
				unset ($field['multiple']);
640
			}
641
			break;
642

    
643
		case 'save':
644
			return array('state_abbrv',
645
        'country_abbrv',
646
        'clist',
647
        'fielddisplay',
648
        'max_length_street1',
649
        'max_length_street2',
650
        'max_length_apt',
651
        'max_length_city',
652
        'max_length_other',
653
			  'field_names_preferred_address',
654
        'field_names_street1',
655
        'field_names_street2',
656
        'field_names_apt',
657
        'field_names_city',
658
        'field_names_state',
659
      	'field_names_state_alternative',
660
        'field_names_country',
661
        'field_names_zip',
662
        'field_names_other',
663
        'field_order',
664
        'field_defaults_street1',
665
        'field_defaults_street2',
666
        'field_defaults_apt',
667
        'field_defaults_city',
668
        'field_defaults_state',
669
      	'field_defaults_state_alternative',
670
        'field_defaults_country',
671
        'field_defaults_zip',
672
        'field_defaults_other',
673
        'select_a_f_d',
674
        'select_table',
675
        'select_streetcolumn',
676
        'select_street_numcolumn',
677
        'select_city',
678
        'select_zip',
679
        'select_country',
680
        'select_state',
681
        'other_countries',
682
      	'allow_multiple',
683
			);
684

    
685
		case 'database columns':
686
			$columns = array(
687
        'expertsdb_address' => array('type' => 'longtext', 'not null' => FALSE),
688
			);
689

    
690
			return $columns;
691

    
692
		case 'filters':
693
			return array(
694
          'default' => array(
695
            'operator' => 'views_handler_operator_like',
696
            'handler' => 'views_handler_filter_like',
697
			),
698
			);
699

    
700
		case 'callbacks'://pairs up with expertsdb_address_field::view
701
			return array(
702
      'view' => CONTENT_CALLBACK_CUSTOM,
703
			);
704
	}
705
} //function expertsdb_address_field_settings()
706

    
707
/**
708
 * Implementation of hook_field().
709
 *
710
 * <p>-Validate the user's input.</p>
711
 * <p>-Alternatively, present the data for viewing.</p>
712
 * @param $op
713
 *   What kind of action is being performed.
714
 * @param &$node
715
 *   The node the action is being performed on.
716
 * @param $field
717
 *   The field the action is being performed on.
718
 * @param &$node_field
719
 *   The contents of the field in this node. Changes to this variable will
720
 *   be saved back to the node object.
721
 * @return
722
 *   This varies depending on the operation.
723
 *   - The "load" operation should return an object containing extra values
724
 *     to be merged into the node object.
725
 *   - The "view" operation should return a string containing an HTML
726
 *     representation of the field data.
727
 *   - The "insert", "update", "delete", "validate", and "submit" operations
728
 *     have no return value.
729
 */
730
function expertsdb_address_field($op, &$node, $field, &$items, $teaser, $page) {
731
	switch ($op) {
732

    
733
		case 'view':
734
			$context = $teaser ? 'teaser' : 'full';
735
			$formatter = isset($field['display_settings'][$context]['format']) ? $field['display_settings'][$context]['format'] : 'default';
736
			$items = content_format($field, $items, $formatter, $node);
737
			if((!empty($items) && is_array($items) && count($items) > 0) || (!empty($items) && $formatter == 'table')){
738
				return theme('expertsdb_address_container', $node, $field, $items, $teaser, $page);
739
			}
740
	}
741
} //function expertsdb_address_field()
742

    
743
/**
744
 * Implementation of hook_validate_address_fields
745
 *
746
 * This hook is used by expertsdb_address and any supporting modules which add country-specific field validation.
747
 * The first argument is an array, passed in by reference in 'fieldname=>error string' pairs. The error string should remain empty
748
 * so long as there are no errors. If there is an error, the string should be replaced with an appropriate t-ified message. The
749
 * second argument is the country code of the address. The first thing an implementation of this hook should do is check to see if
750
 * the country code matches the country for which the module was made to support. If not, it should return immediately, without
751
 * modifying the $errors array. This will ensure that only the country which SHOULD validate, does the validation. The third argument
752
 * is the item containing the values of the form.
753
 *
754
 * @param array $errors
755
 * @param string $country_code
756
 * @param array $item
757
 * @param string $field_name
758
 */
759
function expertsdb_address_validate_address_fields(&$errors, $country_code, $item, $field_name) {
760
	if ($country_code != 'US' && $country_code != 'United States') {
761
		return;
762
	}
763
	if (($item['street1'] != '') && (!preg_match("/^[\.\'\-[:alpha:]0-9\/\s]+$/", $item['street1']))) {
764
		$errors['street1'] = t('Illegal value for %name\'s Street field. Only letters, numbers, \' and - are valid. No other special characters allowed.', array('%name' => $field_name));
765
	}
766
	if (($item['street2'] != '') && (!preg_match("/^[\.\'\-[:alpha:]0-9\/\s]+$/", $item['street2']))) {
767
		$errors['street2'] = t('Illegal value for %name\'s Street Continued field. Only letters, numbers, \' and - are valid. No other special characters allowed.', array('%name' => $field_name));
768
	}
769
	if (($item['apt'] != '') && (!preg_match("/^[\.\'\-[:alpha:]0-9\/]+$/", $item['apt']))) {
770
		$errors['apt'] = t('Illegal value for %name\'s Apt/Suite Number field. Only letters, numbers, \' and - are valid. No other special characters allowed.', array('%name' => $field_name));
771
	}
772
	if (($item['city'] != '') && (!preg_match("/^[\.\'\-[:alpha:]\s]+$/", $item['city']))) {
773
		$errors['city'] = t('Illegal value for %name\'s City field. Only letters, \' and - are valid. No numbers or other special characters allowed.', array('%name' => $field_name));
774
	}
775
	if (($item['zip'] != '') && (!preg_match("/^\d{5}(?:-\d{4})?$/", $item['zip']))) {
776
		$errors['zip'] = t('Illegal value for %name\'s ZIP field. No letters or special characters allowed.', array('%name' => $field_name));
777
	}
778
	if (($item['other'] != '') && (!preg_match("/^[\.\'\-[:alpha:]0-9\s]+$/", $item['other']))) {
779
		$errors['other'] = t('Illegal value for %name\'s Other field. Only letters, numbers, \' and - are valid. No other special characters allowed.', array('%name' => $field_name));
780
	}
781
	return;
782
} // expertsdb_address_validate_address_fields()
783

    
784
/**
785
 * Implementation of hook_widget_info().
786
 *
787
 * @return
788
 *   An array keyed by widget name. Each element of the array is an associative
789
 *   array with these keys and values:
790
 *   - "label": The human-readable label for the widget.
791
 *   - "field types": An array of field type names that can be edited using
792
 *     this widget.
793
 */
794
function expertsdb_address_widget_info() {
795
	return array(
796
    'expertsdb_address' => array(
797
      'label' => 'Expertsdb Address',
798
      'field types' => array('expertsdb_address'),
799
	),
800
	);
801
} //function expertsdb_address_widget_info()
802

    
803
/**
804
 * Implementation of hook_widget_settings().
805
 *
806
 * @param $op
807
 *   The operation to be performed.
808
 * @param $widget
809
 *   The widget on which the operation is to be performed.
810
 * @return
811
 *   This varies depending on the operation.
812
 *   - "form": an array of form elements to add to the settings page.
813
 *   - "validate": no return value. Use form_set_error().
814
 *   - "save": an array of names of form elements to be saved in the database.
815
 *   - "callbacks": an array describing the widget's behaviour regarding hook_widget
816
 *     operations. The array is keyed by hook_widget operations ('form', 'validate'...)
817
 *     and has the following possible values :
818
 *       CONTENT_CALLBACK_NONE     : do nothing for this operation
819
 *       CONTENT_CALLBACK_CUSTOM   : use the behaviour in hook_widget(operation)
820
 *       CONTENT_CALLBACK_DEFAULT  : use content.module's default bahaviour
821
 *     Note : currently only the 'default value' operation implements this feature.
822
 *     All other widget operation implemented by the module _will_ be executed
823
 *     no matter what.
824
 */
825
function expertsdb_address_widget_settings($op, $widget) {
826
	switch ($op) {
827
		case 'callbacks':
828
			return array(
829
        'default value' => CONTENT_CALLBACK_CUSTOM,
830
			);
831
	}
832
} //function expertsdb_address_widget_settings()
833

    
834

    
835
/**
836
 * Implementation of hook_widget().
837
 *
838
 * Presently, we don't allow multiple values as people should only have one name.
839
 * Also, we intercept the default value fields and unset() them as I couldn't think
840
 * of a use case for pre-setting a person's name. We also use a little bit of CSS
841
 * to render the form fields approximately the 'size' they've been specified in 'ems'
842
 * as the 'size' was not being rendered in 'ems' but as some fraction thereof; this
843
 * because a name with mostly wide letters wasn't all fitting in the display.
844
 * @param $op
845
 *   What kind of action is being performed.
846
 * @param &$node
847
 *   The node the action is being performed on.
848
 * @param $field
849
 *   The field the action is being performed on.
850
 * @param &$node_field
851
 *   The contents of the field in this node. Changes to this variable will
852
 *   be saved back to the node object.
853
 * @return
854
 *   This varies depending on the operation.
855
 *   - The "form" operation should return an array of form elements to display.
856
 *   - Other operations have no return value.
857
 */
858
function expertsdb_address_widget($op, &$node, $field, &$node_field) {
859
	drupal_add_css(drupal_get_path('module', 'expertsdb_address'). '/expertsdb_address_form.css', 'module', 'all', FALSE);
860

    
861
	switch ($op) {
862

    
863
		case 'prepare form values':
864
			// unserialize and prepare data
865
			_expertsdb_address_widget_prepare($node_field);
866

    
867
			// get posted values in both node edit and profile edit mode
868
			if ($_POST[$field['field_name']] || $_POST[$field['type_name'].'_node_form'][$field['field_name']]) {
869
				$node_field = ($_POST['form_id'] == 'user_edit') ?  $_POST[$field['type_name'].'_node_form'][$field['field_name']] : $_POST[$field['field_name']];
870
				unset($node_field['count'], $node_field['more-url'], $node_field['more']);
871
			}
872
			return;
873

    
874
		case 'form':
875
			$form = array();
876
			$form[$field['field_name']] = array(
877
        '#tree' => TRUE,
878
        '#theme' => 'expertsdb_address_widget_form',
879
        '#type' => 'fieldset',
880
        '#collapsible' => TRUE,
881
        '#collapsed' => FALSE,
882
        '#title' => t($field['widget']['label']),
883
        '#description' => t($field['widget']['description']),
884
        '#weight' => $field['widget']['weight'],
885
			);
886

    
887
			// render single or multiple values
888
			$delta = 0;
889
			// Render expertsdb_address fields for all the entered values
890
			if(is_array($node_field) && count($node_field) > 0){
891
				foreach ($node_field as $delta => $data) {
892
					if (is_array($data) && $data['country']) {
893
						_expertsdb_address_widget_form($form[$field['field_name']][$delta], $field, $data, $delta);
894
					}
895
				}
896
			}
897
			else{
898
				// Render one new expertsdb_address field
899
				_expertsdb_address_widget_form($form[$field['field_name']][$delta], $field, array(), $delta);
900
			}
901

    
902
			if($field['allow_multiple']){
903

    
904
				if(module_exists('jquery_plugin')){
905
					// pull in jquery checkbox plugin to make radioCheckboxes
906
					jquery_plugin_add('checkboxes');
907
				}
908
				// add javascript for 'more' button
909
				drupal_add_js(drupal_get_path('module', 'expertsdb_address') .'/expertsdb_address.js');
910

    
911
				// Create a wrapper for additional fields
912
				$form[$field['field_name']]['wrapper'] = array(
913
          '#type' => 'markup',
914
          '#value' => '<div id="' . str_replace('_', '-', $field['field_name']) . '-wrapper" class="clear-block"></div>',
915
				);
916

    
917
				// Add 'More' Javascript Callback
918
				$form[$field['field_name']]['more-url'] = array(
919
          '#type' => 'hidden',
920
          '#value' => url('expertsdb_address/widget/js/' . $field['type_name'] . '/' . $field['field_name'], NULL, NULL, TRUE),
921
          '#attributes' => array('class' => 'more-addresses'),
922
          '#id' => str_replace('_', '-', $field['field_name']) . '-more-url',
923
				);
924

    
925
				// Add Current Field Count
926
				$form[$field['field_name']]['count'] = array(
927
          '#type' => 'hidden',
928
          '#value' => $delta,
929
          '#id' => str_replace('_', '-', $field['field_name']) . '-count',
930
				);
931

    
932
				// Add More Button
933
				$form[$field['field_name']]['more'] = array(
934
	        '#name' => 'more',
935
	        '#id' => str_replace('_', '-', $field['field_name']) . '-more',
936
	        '#weight' => 10,
937
					'#type' => 'views_imagebutton',
938
					'#title' => t('More Addresses'),
939
	    		'#image' => drupal_get_path('module','expertsdb_email') . '/images/button_add_element.png',  // provide the path to your image here
940
	    		'#default_value' => t('More emails'), // original value of button text
941
				);
942
			}
943
			return $form;
944

    
945
		case 'validate':
946

    
947
			$preferred_counter = 0;
948

    
949
			if ($field['select_a_f_d'] == 1) {
950
				if (is_array($node_field)) {
951

    
952
					foreach ($node_field as $delta => $item) {
953
						if(!is_numeric($delta)) continue;
954

    
955
						// check for multiple preferred addresses
956
						if(is_numeric($delta) && $item['preferred_address']['preferred_address'] === 'preferred_address'){
957
							$preferred_counter ++;
958
						}
959

    
960
						//setup error handling fields
961
						$error_field_street1 = $field['field_name']. '][' .$delta. '][street1';
962
						$error_field_street2 = $field['field_name']. '][' .$delta. '][street2';
963
						$error_field_city = $field['field_name']. '][' .$delta. '][city';
964
						$error_field_state = $field['field_name']. '][' .$delta. '][state';
965
						$error_field_state = $field['field_name']. '][' .$delta. '][state_alternative';
966
						$error_field_zip = $field['field_name']. '][' .$delta. '][zip';
967
						$error_field_country = $field['field_name']. '][' .$delta. '][country';
968
						$errors = array(
969
                'street1' => '',
970
                'street2' => '',
971
                'city' => '',
972
                'state' => '',
973
            		'state_alternative' => '',
974
                'zip' => '',
975
                'country' => '',
976
						);
977

    
978
						//do the actual validation
979
						if (($item['country'] != '') && ($item['country'] == $field['country'])) {
980
							$errors['country'] = t('Illegal value for <em>Country</em>. It should have been set for you. Contact the site administrator.');
981
						}
982
						if (($item['state'] != '') && ($item['state'] == $field['state'])) {
983
							$errors['state'] = t('Illegal value for <em>State</em>. It should have been set for you. Contact the site administrator.');
984
						}
985
						$table = $field['select_table'];
986
						$column_city = $field['select_city'];
987
						$column_zip = $field['select_zip'];
988
						$sql = "SELECT %s FROM {%s} ORDER BY %s ASC";
989
						$results = db_query($sql, $column_city, $table, $column_city);
990
						while ($result = db_fetch_object($results)) {
991
							$all_cities[$result->$column_city] = $result->$column_city;
992
						}
993
						if (!array_key_exists($item['city'], $all_cities)) {
994
							$errors['city'] = t('Illegal value for <em>City</em>. You must select from the list.');
995
						}
996
						$results = db_query($sql, $column_zip, $table, $column_zip);
997
						while ($result = db_fetch_object($results)) {
998
							$all_zips[$result->$column_zip] = $result->$column_zip;
999
						}
1000
						if (!array_key_exists($item['zip'], $all_zips)) {
1001
							$errors['zip'] = t('Illegal value for <em>Zip Code</em>. You must select from the list.');
1002
						}
1003
						//switch the user's input to what is found in the DB
1004
						$sql1 = "SELECT %s FROM {%s} WHERE %s LIKE '%s'";
1005
						$results1 = db_fetch_object(db_query($sql1, $field['select_streetcolumn'], $table, $field['select_streetcolumn'], $item['street2']. '%'));
1006
						if (!$results1) {
1007
							$errors['street2'] = t('Illegal value for <em>Street Name</em>.');
1008
						}
1009
						else {
1010
							$node_field[$delta]['street2'] = $results1->$field['select_streetcolumn'];
1011
						}
1012
						$sql2 = "SELECT %s, %s FROM {%s} WHERE %s = %d AND %s LIKE '%s'";
1013
						$results2 = db_fetch_object(db_query($sql2, $field['select_street_numcolumn'], $field['select_streetcolumn'], $table, $field['select_street_numcolumn'], $item['street1'], $field['select_streetcolumn'], $item['street2']. '%'));
1014
						if (!$results2) {
1015
							$errors['street1'] = t('Possible illegal value for <em>Street Number</em>. This number was not found on the street you indicated.');
1016
							if ($errors['street2'] != '') {
1017
								$errors['street2'] = t('Possible illegal value for <em>Street Name</em>. This street was not found with the number you indicated.');
1018
							}
1019
						}
1020
						$sql3 = "SELECT * FROM {%s} WHERE %s = %d AND %s LIKE '%s' AND %s = '%s' AND %s = %d";
1021
						$values = array(
1022
						$table,
1023
						$field['select_street_numcolumn'], $item['street1'],
1024
						$field['select_streetcolumn'], $item['street2']. '%',
1025
						$field['select_city'], $item['city'],
1026
						$field['select_zip'], $item['zip'],
1027
						);
1028
						$result = db_fetch_object(db_query($sql3, $values));
1029
						if (!$result && ($errors['street1'] != '') && ($errors['street2'] != '') && ($errors['city'] != '') && ($errors['state'] != '') && ($errors['zip'] != '') && ($errors['country'] != '')) {
1030
							$errors['street1'] = t('Error. Cannot find this address in the database.');
1031
							$errors['street2'] = t('Error. Cannot find this address in the database.');
1032
							$errors['city'] = t('Error. Cannot find this address in the database.');
1033
							$errors['zip'] = t('Error. Cannot find this address in the database.');
1034
							$errors['state'] = t('Error. Cannot find this address in the database.');
1035
							$errors['country'] = t('Error. Cannot find this address in the database.');
1036
						}
1037

    
1038
						//report errors
1039
						if ($errors['street1'] != '') {
1040
							form_set_error($error_field_street1, $errors['street1']);
1041
						}
1042
						if ($errors['street2'] != '') {
1043
							form_set_error($error_field_street2, $errors['street2']);
1044
						}
1045
						if ($errors['city'] != '') {
1046
							form_set_error($error_field_city, $errors['city']);
1047
						}
1048
						if ($errors['state'] != '') {
1049
							form_set_error($error_field_state, $errors['state']);
1050
						}
1051
						if ($errors['zip'] != '') {
1052
							form_set_error($error_field_zip, $errors['zip']);
1053
						}
1054
						if ($errors['country'] != '') {
1055
							form_set_error($error_field_country, $errors['country']);
1056
						}
1057

    
1058
					}
1059
				}
1060
			}
1061
			else {
1062

    
1063
				$all_countries = array();
1064
				$sql = "SELECT cas.country_name, cas.country_code FROM {expertsdb_address_countries} cas ORDER BY cas.country_name ASC";
1065
				$results = db_query($sql);
1066
				while ($result = db_fetch_object($results)) {
1067
					$all_countries[$result->country_code] = $result->country_name;//master list of countries to check against
1068
				}
1069

    
1070
				if (isset($field['clist'])) {
1071
					$allowed_countries = $field['clist'];//just the country codes
1072
				}
1073
				else {
1074
					$allowed_countries = array();
1075
				}
1076
				$allowed_countries = array_filter($allowed_countries);//get rid of those not allowed
1077
				foreach ($allowed_countries as $code => $code2) {
1078
					$allowed_countries[$code] = $all_countries[$code];//add names to codes
1079
				}
1080

    
1081

    
1082
				if (is_array($node_field)) {
1083

    
1084
					// catch empty forms
1085
					$temp_field = $node_field;
1086
					foreach ($temp_field as $delta => $data) {
1087
						if(is_array($data)){
1088
							unset($data['country'],$data['state'],$data['preferred_address'],$data['field_order'],$data['fielddisplay']);
1089
							$input = implode('',$data);
1090
							if (strlen($input) == 0) return;
1091
						}
1092
					}
1093

    
1094
					foreach ($node_field as $delta => $item) {
1095
						if(!is_numeric($delta)) continue;
1096

    
1097
						// check for multiple preferred addresses
1098
						if($field['allow_multiple'] && is_numeric($delta) && $item['preferred_address']['preferred_address'] === 'preferred_address'){
1099
							$preferred_counter ++;
1100
						}
1101

    
1102
						$error_field_street1 = $field['field_name']. '][' .$delta. '][street1';
1103
						$error_field_street2 = $field['field_name']. '][' .$delta. '][street2';
1104
						$error_field_apt = $field['field_name']. '][' .$delta. '][apt';
1105
						$error_field_city = $field['field_name']. '][' .$delta. '][city';
1106
						$error_field_state = $field['field_name']. '][' .$delta. '][state';
1107
						$error_field_state = $field['field_name']. '][' .$delta. '][state_aternative';
1108
						$error_field_zip = $field['field_name']. '][' .$delta. '][zip';
1109
						$error_field_country = $field['field_name']. '][' .$delta. '][country';
1110
						$error_field_other = $field['field_name']. '][' .$delta. '][other';
1111

    
1112
						$errors = array(
1113
              'street1' => '',
1114
              'street2' => '',
1115
              'apt' => '',
1116
              'city' => '',
1117
              'state' => '',
1118
							'state_alternative' => '',
1119
              'zip' => '',
1120
              'country' => '',
1121
              'other' => ''
1122
              );
1123

    
1124
              //since states and countries come from drop-downs, we can validate them here
1125
              if (array_key_exists($item['country'], $allowed_countries)) {
1126
              	$selected_country[$item['country']] = $allowed_countries[$item['country']];
1127
              }
1128
              elseif (!$field['other_countries']) {
1129
              	$errors['country'] = t('Illegal value for %name\'s %type field. You must select a %type from the dropdown list.', array('%name' => t($field['widget']['label']), '%type' => $field['field_names_country']));
1130
              }
1131
              $state_options = expertsdb_address_get_states($selected_country);
1132
              if (count($state_options)>0 && $field['fielddisplay']['field_display_state'] && !$field['other_countries'] && !array_key_exists($item['state'], $state_options)) {
1133
              	$errors['state'] = t('Illegal value for %name\'s %type field. You must select a %type from the dropdown list.', array('%name' => t($field['widget']['label']), '%type' => $field['field_names_state']));
1134
              }
1135

    
1136
              //pass all other fields on to the various address modules for validation
1137
              foreach (module_implements('validate_address_fields') as $name) {
1138
              	$function = $name. '_validate_address_fields';
1139
              	$function($errors, $item['country'], $item, t($field['widget']['label']));
1140
              }
1141

    
1142
              if ($errors['street1'] != '') {
1143
              	form_set_error($error_field_street1, $errors['street1']);
1144
              }
1145
              if ($errors['street2'] != '') {
1146
              	form_set_error($error_field_street2, $errors['street2']);
1147
              }
1148
              if ($errors['apt'] != '') {
1149
              	form_set_error($error_field_apt, $errors['apt']);
1150
              }
1151
              if ($errors['city'] != '') {
1152
              	form_set_error($error_field_city, $errors['city']);
1153
              }
1154
              if ($errors['state'] != '') {
1155
              	form_set_error($error_field_state, $errors['state']);
1156
              }
1157
              if ($errors['state_alternative'] != '') {
1158
              	form_set_error($error_field_state, $errors['state']);
1159
              }
1160
              if ($errors['zip'] != '') {
1161
              	form_set_error($error_field_zip, $errors['zip']);
1162
              }
1163
              if ($errors['country'] != '') {
1164
              	form_set_error($error_field_country, $errors['country']);
1165
              }
1166
              if ($errors['other'] != '') {
1167
              	form_set_error($error_field_other, $errors['other']);
1168
              }
1169

    
1170
					}
1171
				}
1172

    
1173
				if ($field['max_lengths']['max_length_street1'] > 0) {
1174
					foreach ($node_field as $delta => $data) {//again, don't know if we'll ever need to deal with multiples, but leaving this in just in case
1175
						$error_field_street1 = $field['field_name']. '][' .$delta. '][street1';
1176
						if (strlen($data['street1']) > $field['max_lengths']['max_length_street1']) {
1177
							form_set_error($error_field_street1, t('%label\'s Street field is longer than %max characters.', array('%label' => $field['widget']['label'], '%max' => $field['max_lengths']['max_length_street1'])));
1178
						}
1179
					}
1180
				}
1181
				if ($field['max_lengths']['max_length_street2'] > 0) {
1182
					foreach ($node_field as $delta => $data) {//again, don't know if we'll ever need to deal with multiples, but leaving this in just in case
1183
						$error_field_street2 = $field['field_name']. '][' .$delta. '][street2';
1184
						if (strlen($data['street2']) > $field['max_lengths']['max_length_street2']) {
1185
							form_set_error($error_field_street2, t('%label\'s Street Continued field is longer than %max characters.', array('%label' => $field['widget']['label'], '%max' => $field['max_lengths']['max_length_street2'])));
1186
						}
1187
					}
1188
				}
1189
				if ($field['max_lengths']['max_length_city'] > 0) {
1190
					foreach ($node_field as $delta => $data) {//again, don't know if we'll ever need to deal with multiples, but leaving this in just in case
1191
						$error_field_city = $field['field_name']. '][' .$delta. '][city';
1192
						if (strlen($data['city']) > $field['max_lengths']['max_length_city']) {
1193
							form_set_error($error_field_city, t('%label\'s City field is longer than %max characters.', array('%label' => $field['widget']['label'], '%max' => $field['max_lengths']['max_length_city'])));
1194
						}
1195
					}
1196
				}
1197
				if ($field['max_lengths']['max_length_other'] > 0) {
1198
					foreach ($node_field as $delta => $data) {//again, don't know if we'll ever need to deal with multiples, but leaving this in just in case
1199
						$error_field_other = $field['field_name']. '][' .$delta. '][other';
1200
						if (strlen($data['other']) > $field['max_lengths']['max_length_other']) {
1201
							form_set_error($error_field_other, t('%label\'s Other field is longer than %max characters.', array('%label' => $field['widget']['label'], '%max' => $field['max_lengths']['max_length_other'])));
1202
						}
1203
					}
1204
				}
1205
			}
1206

    
1207
			// warn in case of multiple preferred email addresses
1208
			if($field['allow_multiple'] && $preferred_counter != 1){
1209
				form_set_error($field['field_name'] .']['. $delta. '][street1', t('Please select exactly one preferred address.'));
1210
			}
1211
			break;
1212

    
1213
		case 'process form values':
1214
			// run a cleanup cycle
1215
			if(!strstr($node_field[0]['expertsdb_address'],':{')){
1216
				_expertsdb_address_cleanup_and_sort($node_field,$field['field_name']);
1217
			}
1218
			break;
1219

    
1220
		case 'submit':
1221
			// do not save empty values and bring preferred email to the top
1222
			_expertsdb_address_cleanup_and_sort($node_field);
1223

    
1224
			// serialize data
1225
			_expertsdb_address_serialize($node_field);
1226
			break;
1227
	}
1228
} //function expertsdb_address_widget()
1229

    
1230
/**
1231
 * AHAH generation of additional form fields
1232
 *
1233
 * @param unknown_type $type_name
1234
 * @param unknown_type $field_name
1235
 */
1236
function expertsdb_address_widget_js($type_name, $field_name) {
1237
	$field = content_fields($field_name, $type_name);
1238
	$type = content_types($type_name);
1239
	// get the correct delta and field_name depending on being in node_form or user_edit
1240
	// $delta = ($_POST['form_id'] == 'user_edit') ? $_POST[$type['type'].'_node_form'][$field_name]['count']: $_POST[$field_name]['count'];
1241
	$delta = $_POST[$field_name]['count'];
1242
	$form = array();
1243

    
1244
	_expertsdb_address_widget_form($form, $field, $node_field, $delta);
1245

    
1246
	// Assign parents matching the original form
1247
	foreach (element_children($form) as $key) {
1248
		$form[$key]['#parents'] = array($field_name, $delta, $key);
1249
	}
1250

    
1251
	// Add names, ids, and other form properties
1252
	foreach (module_implements('form_alter') as $module) {
1253
		$function = $module .'_form_alter';
1254
		$function('expertsdb_address_widget_js', $form);
1255
	}
1256
	$form = form_builder('expertsdb_address_widget_js', $form);
1257

    
1258
	// if form is rendered as part of the user profile page, we need to alter name and id of newly generated form elements
1259
	/*	if($_POST['form_id'] == 'user_edit'){
1260
	foreach (element_children($form) as $key) {
1261
	$element_name = explode('[',$form[$key]['#name']);
1262
	array_walk($element_name,'_expertsdb_address_widget_alter_elements');
1263
	$form[$key]['#name'] = $type['type'] . '_node_form' . '[' . implode('][',$element_name).']';
1264
	}
1265
	}*/
1266

    
1267
	$output = drupal_render($form);
1268

    
1269
	print drupal_to_js(array('status' => TRUE, 'data' => $output));
1270

    
1271

    
1272
	exit;
1273
}
1274

    
1275
/**
1276
 * Connection to Active Server module.
1277
 *
1278
 * Here is where we fetch and format the options to push to the state dropdown.
1279
 */
1280
function expertsdb_address_activeselect($source, $targets, $string, $extra = NULL) {
1281
	if (empty($source) || empty($targets) || empty($string)) {
1282
		exit();
1283
	}
1284
	$targets = explode(',', $targets);
1285
	$output = array();
1286

    
1287
	$array = activeselect_explode_values($string);
1288

    
1289
	$state_options = expertsdb_address_get_states($array);
1290

    
1291
	foreach ($targets as $target) {
1292
		$options = array();
1293

    
1294
		if (isset($extra)) {
1295
			$first_element = FALSE;
1296
		}
1297
		else {
1298
			$first_element = TRUE;
1299
		}
1300
		foreach ($state_options as $key => $value) {
1301
			$options[$key]['value'] = $value;
1302

    
1303
			if ($first_element) {
1304
				$options[$key]['selected'] = TRUE;
1305
				$first_element = FALSE;
1306
			}
1307
			elseif ($key == $extra) {
1308
				$options[$key]['selected'] = TRUE;
1309
			}
1310
			else {
1311
				$options[$key]['selected'] = FALSE;
1312
			}
1313
		}
1314
		$multiple = FALSE;
1315

    
1316
		$output[$target] = array('options' => $options, 'multiple' => $multiple);
1317
	}
1318
	activeselect_set_header_nocache();
1319
	print drupal_to_js($output);
1320
	exit();
1321

    
1322
} // function expertsdb_address_activeselect()
1323

    
1324
/**
1325
 * Connection to Active Server module.
1326
 *
1327
 * Here is where we fetch and format the options to push to the street column dropdown.
1328
 */
1329
function expertsdb_address_activeaddress1($source, $targets, $string, $extra = NULL) {
1330
	if (empty($source) || empty($targets) || empty($string)) {
1331
		exit();
1332
	}
1333
	$targets = explode(',', $targets);
1334
	if ($extra != '') {
1335
		$extras = explode(',', $extra);
1336
	}
1337
	else {
1338
		$extras = NULL;
1339
	}
1340
	$output = array();
1341
	$array = activeselect_explode_values($string);
1342

    
1343
	$sql = "SHOW COLUMNS FROM {%s}";
1344
	$results = db_query($sql, $array);
1345
	while ($result = db_fetch_object($results)) {
1346
		$column_options[$result->Field] = $result->Field;
1347
	}
1348
	foreach ($targets as $target) {
1349
		$options = array();
1350
		if ($target == 'select-streetcolumn') {
1351
			$this_extra = $extras[0];
1352
		}
1353
		elseif ($target == 'select-street-numcolumn') {
1354
			$this_extra = $extras[1];
1355
		}
1356
		elseif ($target == 'select-city') {
1357
			$this_extra = $extras[2];
1358
		}
1359
		elseif ($target == 'select-zip') {
1360
			$this_extra = $extras[3];
1361
		}
1362
		if (isset($this_extra)) {
1363
			$first_element = FALSE;
1364
		}
1365
		else {
1366
			$first_element = TRUE;
1367
		}
1368
		foreach ($column_options as $key => $value) {
1369
			$options[$key]['value'] = $value;
1370

    
1371
			if ($first_element) {
1372
				$options[$key]['selected'] = TRUE;
1373
				$first_element = FALSE;
1374
			}
1375
			elseif ($key == $this_extra) {
1376
				$options[$key]['selected'] = TRUE;
1377
			}
1378
			else {
1379
				$options[$key]['selected'] = FALSE;
1380
			}
1381
		}
1382
		$multiple = FALSE;
1383

    
1384
		$output[$target] = array('options' => $options, 'multiple' => $multiple);
1385
	}
1386
	activeselect_set_header_nocache();
1387
	print drupal_to_js($output);
1388
	exit();
1389

    
1390
} // function expertsdb_address_activeselect()
1391

    
1392
/**
1393
 * Helper function renders the expertsdb_email widget only for multiple values.
1394
 *
1395
 * @param unknown_type $form_item
1396
 * @param unknown_type $field
1397
 * @param unknown_type $node_field
1398
 * @param integer $delta
1399
 */
1400
function _expertsdb_address_widget_form(&$form_item, $field, $node_field, $delta = 0) {
1401
	global $user;
1402

    
1403
	$activeselect = module_exists('activeselect');
1404

    
1405
	$form_item = array(
1406
    '#tree' => TRUE,
1407
    '#theme' => 'expertsdb_address_widget_form_row',
1408
	);
1409

    
1410
	// **********************************
1411

    
1412
	global $form_values, $_POST;
1413
	$all_countries = array();
1414
	$all_countries[] = t('Please select your country');
1415
	$sql = "SELECT cas.country_name, cas.country_code FROM {expertsdb_address_countries} cas ORDER BY cas.country_name ASC";
1416
	$results = db_query($sql);
1417
	while ($result = db_fetch_object($results)) {
1418
		$all_countries[$result->country_code] = $result->country_name;
1419
	}
1420

    
1421
	if (isset($field['clist'])) {
1422
		$allowed_countries = $field['clist'];
1423
	}
1424
	else {
1425
		$allowed_countries = array();
1426
	}
1427
	$allowed_countries = array_filter($allowed_countries);
1428
	foreach ($allowed_countries as $code => $code2) {
1429
		$allowed_countries[$code] = $all_countries[$code];
1430
	}
1431
	//if the user doesn't have activeselect, give a giant list of state/provinces to go with the country list
1432
	$state_options = expertsdb_address_get_states($allowed_countries);
1433
	$form_item = array();
1434
	//setup fieldset containing all address elements
1435
	$form_item = array('#tree' => TRUE);
1436
	$form_item['#type'] = 'fieldset';
1437
	$form_item['#attributes'] = array('class' => 'expertsdb-address-fieldset');
1438
	$form_item['#theme'] = 'expertsdb_address_display';
1439
	$form_item['#title'] = ($delta === 0) ? t('Address') : t('Additional Address');
1440
	$form_item['#description'] = NULL;
1441
	// $form_item['#weight'] = $delta;
1442

    
1443
	if($field['allow_multiple']){
1444
		// add preferred_address flag for multiple values; first item is always the preferred address
1445
		$form_item['preferred_address'] = array(
1446
  	'#type' => 'checkboxes',
1447
		'#title' => t('Preferred address'),
1448
   	'#description' => t("Check, if this address is your preferred address."),
1449
    '#default_value' => ($node_field['preferred_address']['preferred_address'] === 'preferred_address') ? 'preferred_address' : (($delta === 0) ? 'preferred_address' : NULL),
1450
		'#required' => $field['fielddisplay']['field_display_preferred_address'] == 'field_display_preferred_address' && $field['required'] == TRUE ? TRUE : FALSE,
1451
		'#attributes' => array(
1452
			'class' => 'preferred-address',
1453
		),
1454
    '#options' => array(
1455
    	'preferred_address' => t("Preferred address"),
1456
		),
1457
		);
1458
	}// add preferred option on single values
1459
	else{
1460
		// add preferred_address flag for multiple values; first item is always the preferred address
1461
		$form_item['preferred_address'] = array(
1462
  	'#type' => 'hidden',
1463
    '#required' => FALSE,
1464
    '#default_value' =>  'preferred_address',
1465
		'#required' => $field['fielddisplay']['field_display_preferred_address'] == 'field_display_preferred_address' && $field['required'] == TRUE ? TRUE : FALSE,
1466
		'#attributes' => array(
1467
			'class' => 'preferred-address',
1468
		),
1469
    '#options' => array(
1470
    	'preferred_address' => t("Preferred address"),
1471
		),
1472
		);
1473
	}
1474

    
1475

    
1476
	if ($field['select_a_f_d'] == 1) {
1477
		$table = $field['select_table'];
1478

    
1479
		$column_city = $field['select_city'];
1480
		$sql = "SELECT %s FROM {%s} ORDER BY %s ASC";
1481
		$results = db_query($sql, $column_city, $table, $column_city);
1482
		while ($result = db_fetch_object($results)) {
1483
			$all_cities[$result->$column_city] = $result->$column_city;
1484
		}
1485

    
1486
		$column_zip = $field['select_zip'];
1487
		$results = db_query($sql, $column_zip, $table, $column_zip);
1488
		while ($result = db_fetch_object($results)) {
1489
			$all_zips[$result->$column_zip] = $result->$column_zip;
1490
		}
1491

    
1492
		$mand_state = $field['select_state'];
1493
		$mand_country = $field['select_country'];
1494

    
1495
		$form_item['street1'] = array(
1496
          '#type' => 'textfield',
1497
          '#title' => t('Street number'),
1498
          '#default_value' => isset($node_field['street1']) ? $node_field['street1'] : '',
1499
          '#required' => $field['fielddisplay']['field_display_street1'] == 'field_display_street1' && $field['required'] == TRUE ? TRUE : FALSE,
1500
          '#size' => 10,
1501
          '#maxlength' => 10,
1502
		);
1503
		$form_item['street1']['#attributes'] = array('style' => 'width: 8.5em');
1504

    
1505
		$form_item['street2'] = array(
1506
          '#type' => 'textfield',
1507
          '#title' => t('Street name'),
1508
          '#description' => t('Leave off any street designators like Way, or Road, or Rd. Just use the name.'),
1509
          '#default_value' => isset($node_field['street2']) ? $node_field['street2'] : '',
1510
          '#required' => $field['fielddisplay']['field_display_street2'] == 'field_display_street2' && $field['required'] == TRUE ? TRUE : FALSE,
1511
          '#size' => 25,
1512
          '#maxlength' => 50,
1513
		);
1514
		$form_item['street2']['#attributes'] = array('style' => 'width: 21.25em');
1515

    
1516
		//$city = isset($_POST['city']) ? $_POST['city'] : $node_field['city'];
1517
		$form_item['city'] = array(
1518
          '#type' => 'select',
1519
          '#title' => t('City'),
1520
          '#default_value' => $city,
1521
          '#multiple' => FALSE,
1522
          '#required' => $field['fielddisplay']['field_display_city'] == 'field_display_city' && $field['required'] == TRUE ? TRUE : FALSE,
1523
          '#options' => $all_cities,
1524
		);
1525

    
1526
		//$zip = isset($_POST['zip']) ? $_POST['zip'] : $node_field['zip'];
1527
		$form_item['zip'] = array(
1528
          '#type' => 'select',
1529
          '#title' => t('Zip code'),
1530
          '#default_value' => $zip,
1531
          '#multiple' => FALSE,
1532
          '#required' => $field['fielddisplay']['field_display_zip'] == 'field_display_zip' && $field['required'] == TRUE ? TRUE : FALSE,
1533
          '#options' => $all_zips,
1534
		);
1535

    
1536
		$form_item['state'] = array(
1537
          '#type' => 'hidden',
1538
          '#title' => t('State'),
1539
          '#value' => $mand_state,
1540
		);
1541

    
1542
		$form_item['country'] = array(
1543
          '#type' => 'hidden',
1544
          '#title' => t('Country'),
1545
          '#value' => $mand_country,
1546
		);
1547
	}
1548
	else { //not using the pre-known address validation option
1549
		$form_item['street1'] = array(
1550
          '#type' => 'textfield',
1551
          '#title' => isset($field['field_names_street1']) ? $field['field_names_street1'] : t('Address'),
1552
          '#default_value' => isset($node_field['street1']) ? $node_field['street1'] : $field['field_defaults_street1'],
1553
          '#required' => $field['fielddisplay']['field_display_street1'] == 'field_display_street1' && $field['required'] == TRUE ? TRUE : FALSE,
1554
          '#size' => 20,
1555
          '#maxlength' => $field['max_length_street1'] ? $field['max_length_street1'] : NULL,
1556
          '#prefix' => '<div class="expertsdb-address-street1">',
1557
          '#suffix' => '</div>',
1558
		);
1559
		$form_item['street1']['#attributes'] = $field['max_length_street1'] ? array('style' => 'width:' .$field["max_length_street1"]*0.85. 'em') : array();
1560

    
1561
		$form_item['apt'] = array(
1562
          '#type' => 'textfield',
1563
          '#title' => isset($field['field_names_apt']) ? $field['field_names_apt'] : t('Apt/suite number'),
1564
          '#default_value' => isset($node_field['apt']) ? $node_field['apt'] : $field['field_defaults_apt'],
1565
          '#required' => FALSE,
1566
          '#size' => 7,
1567
          '#maxlength' => $field['max_length_apt'] ? $field['max_length_apt'] : NULL,
1568
          '#prefix' => '<div class="expertsdb-address-apt">',
1569
          '#suffix' => '</div>',
1570
		);
1571
		$form_item['apt']['#attributes'] = $field['max_length_apt'] ? array('style' => 'width:' .$field["max_length_apt"]*0.85. 'em') : array();
1572

    
1573
		$form_item['street2'] = array(
1574
          '#type' => 'textfield',
1575
          '#title' => isset($field['field_names_street2']) ? $field['field_names_street2'] : t('Address continued'),
1576
          '#default_value' => isset($node_field['street2']) ? $node_field['street2'] : $field['field_defaults_street2'],
1577
          '#required' => FALSE,
1578
          '#size' => 20,
1579
          '#maxlength' => $field['max_length_street2'] ? $field['max_length_street2'] : NULL,
1580
          '#prefix' => '<div class="expertsdb-address-street2">',
1581
          '#suffix' => '</div>',
1582
		);
1583
		$form_item['street2']['#attributes'] = $field['max_length_street2'] ? array('style' => 'width:' .$field["max_length_street2"]*0.85. 'em') : array();
1584

    
1585
		$form_item['city'] = array(
1586
          '#type' => 'textfield',
1587
          '#title' => isset($field['field_names_city']) ? $field['field_names_city'] : t('City'),
1588
          '#default_value' => isset($node_field['city']) ? $node_field['city'] : $field['field_defaults_city'],
1589
          '#required' => $field['fielddisplay']['field_display_city'] == 'field_display_city' && $field['required'] == TRUE ? TRUE : FALSE,
1590
          '#size' => 20,
1591
          '#maxlength' => $field['max_length_city'] ? $field['max_length_city'] : NULL,
1592
          '#prefix' => '<div class="expertsdb-address-city">',
1593
          '#suffix' => '</div>',
1594
		);
1595
		$form_item['city']['#attributes'] = $field['max_length_city'] ? array('style' => 'width:' .$field["max_length_city"]*0.85. 'em') : array();
1596

    
1597
		$state = (empty($node_field['state'])) ? (!empty($field['field_defaults_state'])) ? $field['field_defaults_state'] : '' :  $node_field['state'];
1598
		// squash tha t annoying array(0) value if that one comes in, activeselect will not work.
1599
		$state = (is_array($state) && count($state) == 0) ? '' : $state;
1600
		//$state = isset($_POST['state']) ? $_POST['state'] : $state_pre_default;
1601

    
1602
		if ($field['state_abbrv'] == 2) {
1603
			$form_item['state'] = array(
1604
            '#type' => 'textfield',
1605
            '#title' => isset($field['field_names_state']) ? $field['field_names_state'] : t('State'),
1606
            '#default_value' => $state,
1607
            '#required' => $field['fielddisplay']['field_display_state'] == 'field_display_state' && $field['required'] == TRUE ? TRUE : FALSE,
1608
            '#size' => 20,
1609
            '#maxlength' => $field['max_length_city'] ? $field['max_length_city'] : NULL,
1610
            '#prefix' => '<div class="expertsdb-address-state">',
1611
            '#suffix' => '</div>',
1612
			);
1613
			$form_item['state']['#attributes'] = $field['max_length_city'] ? array('style' => 'width:' .$field["max_length_city"]*0.85. 'em') : array();
1614
		}
1615
		else {
1616
			$form_item['state'] = array(
1617
            '#type' => 'select',
1618
            '#title' => isset($field['field_names_state']) ? $field['field_names_state'] : t('State'),
1619
            '#default_value' => $state,
1620
            '#multiple' => FALSE,
1621
            '#required' => $field['fielddisplay']['field_display_state'] == 'field_display_state' && $field['required'] == TRUE ? TRUE : FALSE,
1622
            '#options' => array(),
1623
            '#prefix' => '<div class="expertsdb-address-state">',
1624
            '#suffix' => '</div>',
1625
            '#DANGEROUS_SKIP_CHECK' => TRUE,
1626
			);
1627

    
1628
			// add a non-present state
1629
			$form_item['state_alternative'] = array(
1630
          '#type' => 'textfield',
1631
          '#title' => isset($field['field_names_state_alternative']) ? $field['field_names_state_alternative'] : t('Different State'),
1632
          '#default_value' => isset($node_field['state_alternative']) ? $node_field['state_alternative'] : $field['field_defaults_state_alternative'],
1633
          '#required' => FALSE, // $field['fielddisplay']['field_display_state_alternative'] == 'field_display_state_alternative' && $field['required'] == TRUE ? TRUE : FALSE,
1634
					'#size' => 20,
1635
          '#maxlength' => $field['max_length_city'] ? $field['max_length_city'] : NULL,
1636
          '#prefix' => '<div class="expertsdb-address-state-alternative">',
1637
          '#suffix' => '</div>',
1638
        	'#description' => t('If your !state is not listed, please enter it here. Make sure that you choose the correct country above.',array('!state' => $field['field_names_state'])),
1639
			);
1640
		}
1641

    
1642
		$form_item['zip'] = array(
1643
          '#type' => 'textfield',
1644
          '#title' => isset($field['field_names_zip']) ? $field['field_names_zip'] : t('ZIP'),
1645
          '#default_value' => isset($node_field['zip']) ? $node_field['zip'] : $field['field_defaults_zip'],
1646
          '#required' => $field['fielddisplay']['field_display_zip'] == 'field_display_zip' && $field['required'] == TRUE ? TRUE : FALSE,
1647
          '#size' => 10,
1648
          '#maxlength' => 10,
1649
          '#prefix' => '<div class="expertsdb-address-zip">',
1650
          '#suffix' => '</div>',
1651
		);
1652
		$form_item['zip']['#attributes'] = array('style' => 'width:8.5em', 'class' => 'number');
1653

    
1654
		if ($field['other_countries'] == 1) {
1655
			$form_item['country'] = array(
1656
            '#type' => 'textfield',
1657
            '#title' => isset($field['field_names_country']) ? $field['field_names_country'] : t('Country'),
1658
            '#default_value' => isset($node_field['country']) ? $node_field['country'] : '',
1659
            '#required' => $field['fielddisplay']['field_display_country'] == 'field_display_country' && $field['required'] == TRUE ? TRUE : FALSE,
1660
            '#size' => 20,
1661
            '#maxlength' => $field['max_length_city'] ? $field['max_length_city'] : NULL,
1662
            '#prefix' => '<div class="expertsdb-address-country">',
1663
            '#suffix' => '</div>',
1664
			);
1665
			$form_item['country']['#attributes'] = $field['max_length_city'] ? array('style' => 'width:' .$field["max_length_city"]*0.85. 'em') : array();
1666
		}
1667
		else {
1668
			$first_value = end($allowed_countries);
1669
			$first_key = array_keys($allowed_countries, $first_value);
1670
			$country_pre_default = isset($field['field_defaults_country']) ? $field['field_defaults_country'] : $first_key;
1671
			$form_item['country'] = array(
1672
            '#type' => 'select',
1673
            '#title' => isset($field['field_names_country']) ? $field['field_names_country'] : t('Country'),
1674
            '#default_value' => isset($node_field['country']) ? array($node_field['country']) : $country_pre_default,
1675
            '#multiple' => FALSE,
1676
            '#required' => $field['fielddisplay']['field_display_country'] == 'field_display_country' && $field['required'] == TRUE ? TRUE : FALSE,
1677
            '#options' => $allowed_countries,
1678
            '#prefix' => '<div class="expertsdb-address-country">',
1679
            '#suffix' => '</div>',
1680
			);
1681
			if ($activeselect && ($field['other_countries'] == 0)) {
1682
				$form_item['country']['#type'] = 'activeselect';
1683
				$form_item['country']['#activeselect_path'] = 'expertsdb_address/activeselect';
1684
				$form_item['country']['#activeselect_targets'] = str_replace('_', '-', $field['field_name']). '-' . $delta . '-state';
1685
				$form_item['country']['#activeselect_extra'] = !empty($state) ? $state : '';
1686
			}
1687
			else {
1688
				$form_item['state']['#options'] = $state_options;
1689
			}
1690
		}
1691
		$form_item['other'] = array(
1692
          '#type' => 'textfield',
1693
          '#title' => isset($field['field_names_other']) ? $field['field_names_other'] : t('Other'),
1694
          '#default_value' => isset($node_field['other']) ? $node_field['other'] : $field['field_defaults_other'],
1695
          '#required' => FALSE,
1696
          '#size' => 20,
1697
          '#maxlength' => $field['max_length_other'] ? $field['max_length_other'] : NULL,
1698
          '#prefix' => '<div class="expertsdb-address-other">',
1699
          '#suffix' => '</div>',
1700
					'#description' => t('If your !country is not listed, please enter it here.',array('!country' => $field['field_names_country'])),
1701
		);
1702
		$form_item['other']['#attributes'] = $field['max_length_other'] ? array('style' => 'width:' .$field["max_length_other"]*0.85. 'em') : array();
1703
	}
1704
	$form_item['field_order'] = array(
1705
        '#type' => 'value',
1706
        '#value' => $field['field_order'],
1707
	);
1708
	$form_item['fielddisplay'] = array(
1709
        '#type' => 'value',
1710
        '#value' => $field['fielddisplay'],
1711
	);
1712

    
1713
}
1714

    
1715
function _expertsdb_address_widget_alter_elements(&$element){
1716
	$element = preg_replace('@\]@', '', $element);
1717
}
1718

    
1719
/**
1720
 * Helper function to unserailize serialized data
1721
 *
1722
 * @param unknown_type $node_field
1723
 */
1724
function _expertsdb_address_widget_prepare(&$node_field){
1725
	// only prepare, if data is actually serialized
1726
	if(strstr($node_field[0]['expertsdb_address'],':{')){
1727
		$node_field[0] = unserialize($node_field[0]['expertsdb_address']);
1728
		if(count($node_field) > 0){
1729
			// return content of first array element
1730
			$node_field = $node_field[0];
1731
		}
1732
	}
1733
}
1734

    
1735
/**
1736
 * Helper function to serialize data
1737
 *
1738
 * @param unknown_type $node_field
1739
 */
1740
function _expertsdb_address_serialize(&$node_field){
1741
	$node_field = array(array('expertsdb_address' => serialize($node_field)));
1742
}
1743

    
1744
/**
1745
 * Function to remove unwanted elements from the node_field array
1746
 * and to move the preferred address to the top of the list
1747
 *
1748
 * @param array $node_field
1749
 */
1750
function _expertsdb_address_cleanup_and_sort(&$node_field){
1751
	$save_field = array();
1752
	//$registered_emails =array();
1753

    
1754
	// Remove the JS helper fields
1755
	unset($node_field['count'], $node_field['more-url'], $node_field['more']);
1756

    
1757
	// Don't save empty fields except the first value
1758
	if ($field['select_a_f_d'] != 1) {
1759
		foreach ($node_field as $delta => $item) {
1760
			unset($node_field[$delta]['field_order'],$node_field[$delta]['fielddisplay']);
1761
			if (!is_numeric($delta)) {
1762
				unset($node_field[$delta]);
1763
			}
1764
			elseif (($item['street1'] == '') && ($item['city'] == '') && ($item['zip'] == '') && ($item['other'] == '') && ($item['state_alternative'] == '')) {
1765
				unset($node_field[$delta]);
1766
				continue;
1767
			}
1768

    
1769
			// resort addresses; preferred address goes to top
1770
			if($node_field[$delta]['preferred_address'] && $node_field[$delta]['preferred_address']['preferred_address'] === 'preferred_address'){
1771
				// put email as first element into the list of emails to save
1772
				array_unshift($save_field,$node_field[$delta]);
1773
			}else{
1774
				$node_field[$delta]['preferred_address']['preferred_address'] = FALSE;
1775
				array_push($save_field,$node_field[$delta]);
1776
			}
1777
		}
1778
	}
1779
	else {
1780
		foreach ($node_field as $delta => $item) {
1781
			unset($node_field[$delta]['field_order'],$node_field[$delta]['fielddisplay']);
1782
			if (!is_numeric($delta)) {
1783
				unset($node_field[$delta]);
1784
			}
1785
			elseif (($item['street1'] == '') && ($item['city'] == '') && ($item['zip'] == '')) {
1786
				unset($node_field[$delta]);
1787
				continue;
1788
			}
1789

    
1790
			// resort addresses; preferred address goes to top
1791
			if($node_field[$delta]['preferred_address'] && $node_field[$delta]['preferred_address']['preferred_address'] === 'preferred_address'){
1792
				// put email as first element into the list of emails to save
1793
				array_unshift($save_field,$node_field[$delta]);
1794
			}else{
1795
				$node_field[$delta]['preferred_address']['preferred_address'] = FALSE;
1796
				array_push($save_field,$node_field[$delta]);
1797
			}
1798
		}
1799
	}
1800
	$node_field = $save_field;
1801
}
1802

    
1803
/**
1804
 * Get all locales supported on the server running Drupal.
1805
 */
1806
function expertsdb_address_get_all_locales() {
1807
	/*ob_start();
1808
	 system('locale -a');
1809
	 $str = ob_end_clean();
1810
	 return split("\\n", trim($str));*/
1811
	exec('locale -a', $output);
1812
	return $output;
1813
}
1814

    
1815
/**
1816
 * Set locale in a platform-independent way.
1817
 *
1818
 * Taken from: http://www.onphp5.com/article/22
1819
 *
1820
 * @param  string $locale  the locale name ('en_US', 'uk_UA', 'fr_FR' etc)
1821
 * @return  string  the encoding name used by locale-aware functions
1822
 * @throw  Exception  if the locale could not be set
1823
 */
1824
function expertsdb_address_setLocaleCP($locale) {
1825
	list($lang, $cty) = explode('_', $locale);
1826
	$locales = array($locale . '.UTF-8', $lang);
1827
	$result = setlocale(LC_ALL, $locales);
1828

    
1829
	if (!$result) {
1830
		drupal_set_message("Unknown Locale name $locale", "error");
1831
		return;
1832
	}
1833

    
1834
	// See if we have successfully set it to UTF-8
1835
	if (!strpos($result, 'UTF-8')) {
1836
		preg_match('~\.(\d+)$~', $result, $m);
1837
		$encoding = 'CP' . $m[1];
1838
	}
1839
	else {
1840
		$encoding = 'UTF-8';
1841
	}
1842

    
1843
	return $encoding;
1844
}
1845

    
1846
/**
1847
 * Query the DB for the allowed States/Provinces corresponding to the allowed Countries.
1848
 *
1849
 * If Activeselect is installed, this will be called dynamically to fill the state selector dynamically via AJAX.
1850
 * Expects an array of CountryCode => CountryName pairs.
1851
 * @param array $countries
1852
 * @return array $state_options
1853
 */
1854
function expertsdb_address_get_states($countries = NULL) {
1855
	$state_options = array();
1856
	$where = 'WHERE ';
1857
	if ($countries == NULL) {
1858
		$where = '';
1859
	}
1860
	else {
1861
		$countrynum = count($countries);
1862
		foreach ($countries as $code => $name) {
1863
			if ($countrynum > 1) {
1864
				$where .= 'cas.country_code = \'' .$code. '\' OR ';
1865
				$countrynum--;
1866
			}
1867
			else {
1868
				$where .= 'cas.country_code = \'' .$code. '\'';
1869
				$countrynum--;
1870
			}
1871
		}
1872
	}
1873
	$sql = "SELECT cas.state_id, cas.state_name, cas.state_abbrv, cas.country_code FROM {expertsdb_address_states} cas " .$where. " ORDER BY cas.country_code ASC, cas.state_name ASC";
1874
	$results = db_query($sql);
1875
	while ($result = db_fetch_object($results)) {
1876
		$state_options[$result->state_abbrv] = $result->state_name;
1877
	}
1878
	return $state_options;
1879
} // function expertsdb_address_get_states()
1880

    
1881
/**
1882
 * Theme the display of a single form row
1883
 *
1884
 * @param unknown_type $element
1885
 * @return unknown
1886
 */
1887
function theme_expertsdb_address_widget_form_row($element) {
1888
	$output = '';
1889
	$output .= '<div class="expertsdb-email-field-row clear-block"><div class="expertsdb-email-field-subrow clear-block">';
1890
	$output .= '<div class="expertsdb-email-field-preferred-email preferred-email-field-column">' . drupal_render($element['preferred_email']) . '</div>';
1891
	$output .= '<div class="expertsdb-email-field-expertsdb-email">' . drupal_render($element['email']) . '</div>';
1892
	$output .= '</div>';
1893
	$output .= '</div>';
1894
	return $output;
1895
}
1896

    
1897
/**
1898
 * Theme the display of the entire expertsdb_address set
1899
 *
1900
 * @param unknown_type $element
1901
 * @return unknown
1902
 */
1903
function theme_expertsdb_address_widget_form($element) {
1904
	// pull in the stylesheet
1905
	drupal_add_css(drupal_get_path('module', 'expertsdb_address') .'/expertsdb_address_form.css');
1906
	$output = drupal_render($element);
1907
	return $output;
1908
}
1909

    
1910
/**
1911
 * Theme to display a complete container with all email addresses in view mode
1912
 *
1913
 * @param unknown_type $node
1914
 * @param unknown_type $field
1915
 * @param unknown_type $items
1916
 * @param unknown_type $teaser
1917
 * @param unknown_type $page
1918
 * @return unknown
1919
 */
1920
function theme_expertsdb_address_container($node, $field, $items, $teaser, $page){
1921
	// pull in the stylesheet
1922
	drupal_add_css(drupal_get_path('module', 'expertsdb_address') .'/expertsdb_address_view.css');
1923
	$output = '';
1924
	$output .= '<div class="expertsdb-address-container">';
1925
	$output .= theme('field', $node, $field, $items, $teaser, $page);
1926
	$output .= '</div>';
1927
	return $output;
1928
}
1929

    
1930
/**
1931
 * Call drupal_render to get some output that is screen-ready.
1932
 *
1933
 * Was going to use this but haven't yet. Perhaps should do something here and eliminate CSS file?
1934
 *
1935
 * @param array $form
1936
 * 	The data to be rendered.
1937
 * @return string An HTML string ready for display.
1938
 */
1939
function theme_expertsdb_address_display($form) {
1940
	$output = '';
1941
	asort($form['field_order']['#value']);
1942
	foreach ($form['field_order']['#value'] as $field => $order) {
1943
		if ($form['fielddisplay']['#value']['field_display_'.$field] === 'field_display_'.$field) {
1944
			$output .= drupal_render($form[$field]);
1945
		}
1946
		else {
1947
			if ($field == 'country' || $field == 'state') { //make it so if activeselect isn't used that we do make #access FALSE instead of this
1948
				$form['#title'] = '';
1949
				$form['#attributes'] = array('style' => "display:none");
1950
			}
1951
			else {
1952
				$form['#access'] = FALSE;
1953
			}
1954
		}
1955
	}
1956
	$output .= drupal_render($form);
1957
	return $output;
1958
} //function theme_expertsdb_address_display()
1959

    
1960
/**
1961
 * Theme for address display as called from expertsdb_address_field_formatter().
1962
 */
1963
function theme_expertsdb_address($expertsdb_address, $field) {
1964
	//create the output
1965
	if ($expertsdb_address['afd'] == 1) {
1966
		$output = $expertsdb_address['street1']. ' ';
1967
		$output .= $expertsdb_address['street2']. '<br />';
1968
		$output .= $expertsdb_address['city']. ', ';
1969
		$output .= $expertsdb_address['state']. ' ';
1970
		$output .= $expertsdb_address['zip'];
1971
		$output .= '<br />';
1972
	}
1973
	else {
1974
		$output = '';
1975
		asort($field['field_order']);
1976
		foreach ($field['field_order'] as $field2 => $order) {
1977
			switch ($field2) {//TODO create more elaborate output based on $order; not I'm only now using it for display of other, assuming it will either be first or last
1978
				case 'street1':
1979
					if ($field['fielddisplay']['field_display_street1'] === 'field_display_street1' && isset($expertsdb_address['street1']) && $expertsdb_address['street1'] != '') {
1980
						$output .= $expertsdb_address['street1'] .' ';
1981
					}
1982
					break;
1983
				case 'street2':
1984
					if ($field['fielddisplay']['field_display_street2'] === 'field_display_street2' && isset($expertsdb_address['street2']) && $expertsdb_address['street2'] != '') {
1985
						$output .= '<br />'. $expertsdb_address['street2'];
1986
					}
1987
					break;
1988
				case 'apt':
1989
					if ($field['fielddisplay']['field_display_apt'] === 'field_display_apt' && isset($expertsdb_address['apt']) && $expertsdb_address['apt'] != '') {
1990
						$output .= '#'. $expertsdb_address['apt'];
1991
					}
1992
					break;
1993
				case 'city':
1994
					if ($field['fielddisplay']['field_display_city'] === 'field_display_city' && isset($expertsdb_address['city']) && $expertsdb_address['city'] != '') {
1995
						$output .= '<br />'. $expertsdb_address['city'] .', ';
1996
					}
1997
					break;
1998
				case 'state':
1999
					if ($field['fielddisplay']['field_display_state'] === 'field_display_state' && isset($expertsdb_address['state']) && $expertsdb_address['state'] != '') {
2000
						$output .= $expertsdb_address['state'] .' ';
2001
					}
2002
					break;
2003
				case 'zip':
2004
					if ($field['fielddisplay']['field_display_zip'] === 'field_display_zip' && isset($expertsdb_address['zip']) && $expertsdb_address['zip'] != '') {
2005
						$output .= $expertsdb_address['zip'];
2006
					}
2007
					break;
2008
				case 'country':
2009
					if ($field['fielddisplay']['field_display_country'] === 'field_display_country' && isset($expertsdb_address['country']) && $expertsdb_address['country'] != '') {
2010
						$output .= ' '. $expertsdb_address['country'];
2011
					}
2012
					break;
2013
				case 'other':
2014
					if ($field['fielddisplay']['field_display_other'] !== 0 && isset($expertsdb_address['other']) && $expertsdb_address['other'] != '') {
2015
						if ($order > 1) {
2016
							$output .= '<br />'. $expertsdb_address['other'] .'<br />';
2017
						}
2018
						else {
2019
							$output .= $expertsdb_address['other'] .'<br />';
2020
						}
2021
					}
2022
					break;
2023
			}
2024
		}
2025
		$output .= '<br /><br />';
2026
	}
2027
	return $output;
2028
} // function theme_expertsdb_address()
2029

    
2030
/**
2031
 * Implementation of hook_field_formatter_info().
2032
 */
2033
function expertsdb_address_field_formatter_info() {
2034
	return array(
2035
    'default' => array(
2036
      'label' => t('Default: show all values'),
2037
      'field types' => array('expertsdb_address'),
2038
	),
2039
  'country_specific' => array(
2040
      'label' => t('Country specific, dependig on contry formatter'),
2041
      'field types' => array('expertsdb_address'),
2042
	),
2043
  'table' => array(
2044
      'label' => t('Show addresses as table'),
2045
      'field types' => array('expertsdb_address'),
2046
	),
2047
	);
2048
}
2049

    
2050
/**
2051
 * Implementation of hook_field_formatter().
2052
 *
2053
 * <p>Here we format the data for display and make sure it is plain text. It should be as
2054
 * elsewhere it was validated as alphanumeric characters only.</p>
2055
 * <p>The $node argument is necessary so that filter access can be checked on
2056
 * node preview.</p>
2057
 * @param $field
2058
 *   The field the action is being performed on.
2059
 * @param $item
2060
 *   An array, keyed by column, of the data stored for this item in this field.
2061
 * @param $formatter
2062
 *   The name of the formatter being used to display the field. In our case, we name
2063
 *   it directly, rather than send it through content_format() and therefore we don't
2064
 *   use hook_field_formatter_info either.
2065
 * @param $node
2066
 *   The node object, for context. Will be NULL in some cases.
2067
 *   Warning : when displaying field retrieved by Views, $node will not
2068
 *   be a "full-fledged" node object, but an object containg the data returned
2069
 *   by the Views query (at least nid, vid, changed)
2070
 * @return
2071
 *   An HTML string containing the formatted item.
2072
 */
2073
function expertsdb_address_field_formatter($field, $item, $formatter, $node) {
2074
	// item comes in as either serialized or unserilaized item
2075
	if (empty($item[0]['expertsdb_address']) && empty($item[0]['city'])) {
2076
		return array();
2077
	}
2078
	if(strstr($item[0]['expertsdb_address'],':{')){
2079
		$items = unserialize($item[0]['expertsdb_address']);
2080
	}else{
2081
		unset($item['count'], $item['more-url'], $item['more']);
2082
		$items = $item;
2083
	}
2084

    
2085
	if(empty($items)) return;
2086
	/*
2087
	 * React on privacy settings
2088
	 */
2089
	if($node->field_privacy){
2090
		global $user;
2091
		$term = taxonomy_get_term($node->field_privacy[0]['tid']);
2092
		switch($term->name){
2093

    
2094
			case PRIVACY_CONTACT_PRIVATE:
2095
			case PRIVACY_PRIVATE:
2096
				// show information only to roles with access and node author
2097
				if($user->uid != $node->uid && !user_access('view private expertsdb_address fields',$user)){
2098
					return;
2099
				}
2100
				break;
2101

    
2102
			case PRIVACY_PUBLIC:
2103
				// allow everybody to view aliases as configured in the field formatter (display field)
2104
				break;
2105

    
2106
		}
2107
	}
2108

    
2109
	// pull in the stylesheet
2110
	drupal_add_css(drupal_get_path('module', 'expertsdb_address') .'/expertsdb_address_view.css');
2111

    
2112
	switch ($formatter) {
2113

    
2114
		case 'table':
2115
			// invoke the table formatter
2116
			// and: yes, we use the serialized item here. The table formatter will take care of displaying all addresses.
2117
			$item[0]['view'] = _expertsdb_address_list_table_formatter($node, $field, $items);
2118
			return $item;
2119
			break;
2120

    
2121
		case 'country_specific':
2122
			foreach ($items as $delta => $item) {
2123
				if (empty($item['city'])) {
2124
					// don't stop on empty values
2125
					continue;
2126
				}
2127

    
2128
				$expertsdb_address = _expertsdb_address_prepare_view_data($item,$field);
2129
				if(function_exists('theme_expertsdb_address_').strtolower($expertsdb_address['country'])){
2130
					$items[$delta]['view'] = theme('expertsdb_address_'.strtolower($expertsdb_address['country']), $expertsdb_address, $field);
2131
				} // fall back to default
2132
				else{
2133
					$items[$delta]['view'] = theme('expertsdb_address', $expertsdb_address, $field);
2134
				}
2135
			}
2136
			break;
2137

    
2138
		case 'default':
2139
			foreach ($items as $delta => $item) {
2140
				if (empty($item['city'])) {
2141
					// don't stop on empty values
2142
					continue;
2143
				}
2144

    
2145
				$expertsdb_address = _expertsdb_address_prepare_view_data($item,$field);
2146
				$items[$delta]['view'] = theme('expertsdb_address', $expertsdb_address, $field);
2147
			}
2148

    
2149
	}
2150

    
2151
	return $items;
2152
} //function expertsdb_address_format()
2153

    
2154
function _expertsdb_address_prepare_view_data($item,$field){
2155
	$expertsdb_address = array();
2156
	// prepare dataset
2157
	if ($field['select_a_f_d'] == 1) {
2158
		$expertsdb_address['afd'] = 1;
2159
		$expertsdb_address['street1'] = strip_tags($item['street1']);
2160
		$expertsdb_address['street2'] = strip_tags($item['street2']);
2161
		$expertsdb_address['city'] = strip_tags($item['city']);
2162
		$expertsdb_address['state'] = strip_tags($item['state']);
2163
		$expertsdb_address['state_alternative'] = strip_tags($item['state_alternative']);
2164
		$expertsdb_address['zip'] = strip_tags($item['zip']);
2165
		$expertsdb_address['country'] = strip_tags($item['country']);
2166
	}
2167
	else {
2168
		//if no field typically in an address is set, return. if at least one field is set, continue.
2169
		if (!isset($item['street1']) && !isset($item['city']) && !isset($item['state']) && !isset($item['zip']) && !isset($item['country'])) {
2170
			return '';
2171
		}
2172
		//get some values to use later
2173
		$expertsdb_address['afd'] = 0;
2174
		$all_countries = array();
2175
		$all_countries[] = t('Please select your country');
2176
		$sql = "SELECT cas.country_name, cas.country_code FROM {expertsdb_address_countries} cas ORDER BY cas.country_name ASC";
2177
		$results = db_query($sql);
2178
		while ($result = db_fetch_object($results)) {
2179
			$all_countries[$result->country_code] = $result->country_name;
2180
		}
2181
		if (isset($field['clist'])) {
2182
			$allowed_countries = $field['clist'];
2183
		}
2184
		else {
2185
			$allowed_countries = array();
2186
		}
2187
		$allowed_countries = array_filter($allowed_countries);
2188
		foreach ($allowed_countries as $code => $code2) {
2189
			$allowed_countries[$code] = $all_countries[$code];
2190
		}
2191

    
2192
		if ($field['other_countries']) {
2193
			$country[$item['country']] = $item['country'];
2194
		}
2195
		else {
2196
			$country[$item['country']] = $all_countries[$item['country']];
2197
		}
2198

    
2199
		if ($field['state_abbrv'] == 2) {
2200
			$expertsdb_address_state = strip_tags($item['state']);
2201
		}
2202
		else {
2203
			$states = expertsdb_address_get_states($country);
2204
		}
2205

    
2206
		//check the values
2207
		$expertsdb_address['street1'] = strip_tags($item['street1']);
2208
		$expertsdb_address['street2'] = strip_tags($item['street2']);
2209
		$expertsdb_address['apt'] = strip_tags($item['apt']);
2210
		$expertsdb_address['city'] = strip_tags($item['city']);
2211
		$expertsdb_address['state'] = strip_tags($item['state']);
2212
		$expertsdb_address['state_alternative'] = strip_tags($item['state_alternative']);
2213
		$expertsdb_address['zip'] = strip_tags($item['zip']);
2214
		$expertsdb_address['country'] = strip_tags($item['country']);
2215
		$expertsdb_address['other'] = strip_tags($item['other']);
2216

    
2217
		//are we using state abbreviations for display?
2218
		if ($field['state_abbrv'] == 0) {
2219
			$expertsdb_address['state'] = ($expertsdb_address['state_alternative']) ? $expertsdb_address['state_aternative'] : $states[$expertsdb_address['state']];
2220
		}
2221

    
2222
		//are we using country abbreviations for display?
2223
		if ($field['country_abbrv'] == 0) {
2224
			$expertsdb_address['country'] = ($expertsdb_address['other']) ? $expertsdb_address['other'] : $country[$expertsdb_address['country']];
2225
		}
2226
	}
2227

    
2228
	// always keep the preferred flag
2229
	$expertsdb_address['preferred_address'] = $item['preferred_address'];
2230

    
2231
	return $expertsdb_address;
2232
}
2233

    
2234
function _expertsdb_address_list_table_formatter($node, $field, $items) {
2235

    
2236
	if(empty($items) || count($items[0]) < 2) return;
2237
	// Format the header
2238
	$header = array();
2239
	// make sure, that the number of cells matches the number of headers
2240
	$registered_items = array();
2241
	// items not to display in the table
2242
	$omitted_items = array('other','state_alternative');
2243

    
2244
	$force_preferred = count($items) == 1 ? TRUE :FALSE;
2245

    
2246
	foreach($field['field_order'] as $key => $parts){
2247
		if (!in_array($key,$omitted_items) && $field['fielddisplay']['field_display_'.$key]){
2248
			$registered_items[] = $key;
2249
		}// skip item
2250
		else{
2251
			continue;
2252
		}
2253
		switch($key){
2254
			case 'preferred_address':
2255
				$cell['data'] = t('Pref.');
2256
				$cell['class'] = _expertsdb_address_create_stylename($field['field_names_'.$key]);
2257
				$header[$field['field_order']['$key']] = $cell;
2258
				break;
2259

    
2260
			default:
2261
				$cell['data'] = $field['field_names_'.$key];
2262
				$cell['class'] = _expertsdb_address_create_stylename($field['field_names_'.$key]);
2263
				$header[$field['field_order'][$key]] = $cell;
2264
		}
2265
	}
2266

    
2267
	// sort header like field_order
2268
	ksort($header);
2269
	$preferred_style = '';
2270
	foreach ($items as $dalta => $item) {
2271
		$row = array();
2272
		// transpose values, like country and region
2273
		$item = _expertsdb_address_prepare_view_data($item,$field);
2274

    
2275
		$preferred_style = (isset($item['preferred_address']) && $item['preferred_address']['preferred_address'] === 'preferred_address' || $force_preferred == TRUE) ? ' preferred' : '';
2276

    
2277
		// step out if item is empty
2278
		if(empty($item)) continue;
2279

    
2280
		foreach($item as $key => $parts){
2281

    
2282
			// do not use fields, that are not in the header
2283
			if(!in_array($key,$registered_items)) continue;
2284

    
2285
			switch($key){
2286
				case 'preferred_address':
2287
					$cell['data'] = ($item[$key]['preferred_address'] === 'preferred_address' || $force_preferred == TRUE) ? '<strong>*</strong>' : '&nbsp;';
2288
					$cell['class'] = _expertsdb_address_create_stylename($key).$preferred_style;
2289
					$row[$field['field_order'][$key]] = $cell;
2290
					break;
2291

    
2292
				case 'state':
2293
					$cell['data'] = (!empty($item[$key])) ? $item[$key] : (!empty($item['state_alternative']) ? $item['state_alternative'] : '');
2294
					$cell['class'] = _expertsdb_address_create_stylename($key).$preferred_style;
2295
					$row[$field['field_order'][$key]] = $cell;
2296
					break;
2297

    
2298
				case 'country':
2299
					$cell['data'] = (!empty($item['other'])) ? $item['other'] : $item['country'];
2300
					$cell['class'] = _expertsdb_address_create_stylename($key).$preferred_style;
2301
					$row[$field['field_order'][$key]] = $cell;
2302
					break;
2303

    
2304
				default:
2305
					$cell['data'] = (!empty($item[$key])) ? $item[$key] : '';
2306
					$cell['class'] = _expertsdb_address_create_stylename($key).$preferred_style;
2307
					$row[$field['field_order'][$key]] = $cell;
2308
			}
2309
		}
2310

    
2311
		// sort row like field_order
2312
		ksort($row);
2313
		$rows[] = $row;
2314
	}
2315

    
2316
	return theme('table', $header, $rows, array('class' => 'expertsdb-address-table'));
2317
}
2318

    
2319
function _expertsdb_address_create_stylename($fieldname){
2320
	if(!$fieldname) return;
2321
	return views_css_safe('field-'. strtolower(preg_replace('@\s@','-',$fieldname)));
2322
}
2323
/**
2324
 * Implementation of hook_diff()
2325
 */
2326
function expertsdb_address_diff(&$old_node, &$new_node) {
2327
	$result = array();
2328
	$cck_info = content_types($new_node->type);
2329
	if ($cck_info) {
2330
		foreach ($cck_info['fields'] as $field) {
2331
			if ($field['type'] == 'expertsdb_address') {
2332
				$old_values = array();
2333
				$new_values = array();
2334
				if (isset($old_node->$field['field_name'])) {
2335
					$old_values = expertsdb_address_diff_values($old_node, $field);
2336
				}
2337
				if (isset($new_node->$field['field_name'])) {
2338
					$new_values = expertsdb_address_diff_values($new_node, $field);
2339
				}
2340
				$result[] = array(
2341
          'name' => $field['widget']['label'],
2342
          'old' => $old_values,
2343
          'new' => $new_values,
2344
          'format' => array(
2345
            'show_header' => true,
2346
				),
2347
				);
2348
			}
2349
		}
2350
	}
2351
	return $result;
2352
}
2353

    
2354
function expertsdb_address_diff_values(&$node, &$field) {
2355
	foreach ($node->$field['field_name'] as $item => $value) {
2356
		foreach ($value as $i) {
2357
			$result[] = $i;
2358
		}
2359
	}
2360
	return $result;
2361
}
(12-12/47)