Changeset 4230 in subversion
- Timestamp:
- Nov 17, 2010 7:50:33 AM (3 years ago)
- Location:
- branches/devel-addressbook
- Files:
-
- 9 edited
-
program/include/rcube_contacts.php (modified) (4 diffs)
-
program/include/rcube_vcard.php (modified) (4 diffs)
-
program/js/app.js (modified) (4 diffs)
-
program/localization/en_US/labels.inc (modified) (1 diff)
-
program/steps/addressbook/edit.inc (modified) (2 diffs)
-
program/steps/addressbook/func.inc (modified) (13 diffs)
-
program/steps/addressbook/save.inc (modified) (4 diffs)
-
program/steps/addressbook/show.inc (modified) (3 diffs)
-
skins/default/addressbook.css (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/devel-addressbook/program/include/rcube_contacts.php
r4227 r4230 346 346 347 347 if ($sql_arr = $this->db->fetch_assoc()) { 348 $ sql_arr['ID'] = $sql_arr[$this->primary_key];348 $record = $this->convert_db_data($sql_arr); 349 349 $this->result = new rcube_result_set(1); 350 $this->result->add($ sql_arr);351 } 352 353 return $assoc && $ sql_arr ? $sql_arr: $this->result;350 $this->result->add($record); 351 } 352 353 return $assoc && $record ? $record : $this->result; 354 354 } 355 355 … … 451 451 $updated = false; 452 452 $write_sql = array(); 453 $save_cols = $this->convert_save_data($save_cols); 453 $record = $this->get_record($id, true); 454 $save_cols = $this->convert_save_data($save_cols, $record); 454 455 455 456 foreach ($save_cols as $col => $value) { … … 473 474 return $updated; 474 475 } 475 476 477 private function convert_save_data($save_data) 476 477 478 private function convert_db_data($sql_arr) 479 { 480 $record = array(); 481 $record['ID'] = $sql_arr[$this->primary_key]; 482 483 if ($sql_arr['vcard']) { 484 $vcard = new rcube_vcard($sql_arr['vcard']); 485 $record += $vcard->get_assoc(); 486 } 487 else 488 $record += $sql_arr; 489 490 return $record; 491 } 492 493 494 private function convert_save_data($save_data, $record = array()) 478 495 { 479 496 $out = array(); 480 497 498 // copy values into vcard object 499 $vcard = new rcube_vcard($record['vcard']); 500 foreach ($save_data as $key => $values) { 501 list($field, $section) = explode(':', $key); 502 foreach ((array)$values as $value) { 503 if (strlen($value) || is_array($value)) 504 $vcard->set($field, $value, strtoupper($section)); 505 } 506 } 507 $out['vcard'] = $vcard->export(); 508 481 509 foreach ($this->table_cols as $col) { 482 510 $key = $col; … … 486 514 $out[$col] = is_array($save_data[$key]) ? join(',', $save_data[$key]) : $save_data[$key]; 487 515 } 488 489 // TODO: save all data into a vcard 490 516 491 517 return $out; 492 518 } -
branches/devel-addressbook/program/include/rcube_vcard.php
r4028 r4230 33 33 'N' => array(array('','','','','')), 34 34 ); 35 private $fieldmap = array('phone' => 'TEL', 'birthday' => 'BDAY', 'website' => 'URL', 'notes' => 'NOTE', 'email' => 'EMAIL', 'address' => 'ADR'); 35 36 36 37 public $business = false; … … 98 99 99 100 /** 101 * Return vCard data as associative array to be unsed in Roundcube address books 102 * 103 * @return array Hash array with key-value pairs 104 */ 105 public function get_assoc() 106 { 107 $out = array('name' => $this->displayname); 108 109 foreach (array('firstname','surname','middlename','nickname','organization') as $col) 110 $out[$col] = $this->$col; 111 112 foreach (array_flip($this->fieldmap) as $tag => $col) { 113 foreach ((array)$this->raw[$tag] as $i => $raw) { 114 if (is_array($raw)) { 115 $k = 0; 116 $key = $col; 117 $subtype = strtolower($raw['type'][$k++]); 118 while ($k < count($raw['type']) && ($subtype == 'internet' || $subtype == 'pref')) 119 $subtype = strtolower($raw['type'][$k++]); 120 if ($subtype) 121 $key .= ':' . $subtype; 122 123 if ($tag == 'ADR') { 124 list(,, $value['street'], $value['locality'], $value['region'], $value['zipcode'], $value['country']) = $raw; 125 $out[$key][] = $value; 126 } 127 else 128 $out[$key][] = $raw[0]; 129 } 130 else { 131 $out[$col][] = $raw; 132 } 133 } 134 } 135 136 return $out; 137 } 138 139 140 /** 100 141 * Convert the data structure into a vcard 3.0 string 101 142 */ … … 115 156 public function set($field, $value, $section = 'HOME') 116 157 { 158 static $touched = array(); 159 117 160 switch ($field) { 118 161 case 'name': … … 138 181 139 182 case 'email': 140 $index = $this->get_type_index('EMAIL', $section); 141 if (!is_array($this->raw['EMAIL'][$index])) { 142 $this->raw['EMAIL'][$index] = array(0 => $value, 'type' => array('INTERNET', $section, 'pref')); 143 } 144 else { 145 $this->raw['EMAIL'][$index][0] = $value; 183 if (!$touched['EMAIL']++) 184 $this->raw['EMAIL'] = array(); 185 $index = count($this->raw['EMAIL']); 186 $this->raw['EMAIL'][$index] = array(0 => $value, 'type' => array_filter(array('INTERNET', $section))); 187 break; 188 189 case 'address': 190 $value = $value[0] ? $value : array('', '', $value['street'], $value['locality'], $value['region'], $value['zipcode'], $value['country']); 191 // fall through 192 193 default: 194 if ($tag = $this->fieldmap[$field]) { 195 if (!$touched[$tag]++) 196 $this->raw[$tag] = array(); 197 $index = count($this->raw[$tag]); 198 $this->raw[$tag][$index] = (array)$value; 199 if ($section) 200 $this->raw[$tag][$index]['type'] = array($section); 146 201 } 147 202 break; -
branches/devel-addressbook/program/js/app.js
r4227 r4230 325 325 this.init_edit_field(col, null); 326 326 327 $(' #addfieldmenu').change(function(e){328 ref.insert_edit_field($(this).val(), $(this).attr('rel') );327 $('select.addfieldmenu').change(function(e){ 328 ref.insert_edit_field($(this).val(), $(this).attr('rel'), this); 329 329 this.selectedIndex = 0; 330 330 }); … … 3990 3990 }; 3991 3991 3992 this.insert_edit_field = function(col, section )3992 this.insert_edit_field = function(col, section, menu) 3993 3993 { 3994 3994 // just make pre-defined input field visible … … 3996 3996 if (elem.length) { 3997 3997 elem.show().focus(); 3998 $(menu).children('option[value="'+col+'"]').attr('disabled', true); 3998 3999 } 3999 4000 else { … … 4044 4045 row.append(label).append(cell).appendTo(appendcontainer); 4045 4046 input.first().focus(); 4047 4048 // disable option if limit reached 4049 if (!colprop.count) colprop.count = 0; 4050 if (colprop.limit && ++colprop.count == colprop.limit) 4051 $(menu).children('option[value="'+col+'"]').attr('disabled', true); 4046 4052 } 4047 4053 } -
branches/devel-addressbook/program/localization/en_US/labels.inc
r4184 r4230 276 276 $labels['newcontactgroup'] = 'Create new contact group'; 277 277 $labels['groupactions'] = 'Actions for contact groups...'; 278 279 $labels['addfield'] = 'Add field...'; 280 $labels['notes'] = 'Notes'; 278 281 279 282 $labels['previouspage'] = 'Show previous set'; -
branches/devel-addressbook/program/steps/addressbook/edit.inc
r4227 r4230 97 97 'phone' => array('size' => $i_size, 'visible' => true), 98 98 'address' => array('visible' => true), 99 'birthday' => array('size' => $i_size), 100 'website' => array('size' => $i_size), 101 'im' => array('size' => $i_size), 99 102 ), 100 103 ), … … 102 105 'name' => rcube_label('notes'), 103 106 'content' => array( 104 'notes' => array(' type' => 'textarea', 'size' => $t_cols, 'rows' => $t_rows, 'label' => false, 'visible' => true),107 'notes' => array('size' => $t_cols, 'rows' => $t_rows, 'label' => false, 'visible' => true, 'limit' => 1), 105 108 ), 106 109 'single' => true, -
branches/devel-addressbook/program/steps/addressbook/func.inc
r4227 r4230 57 57 58 58 59 // defaultcoltypes59 // TODO: let the $CONTACT object define the list of possible coltypes 60 60 $CONTACT_COLTYPES = array( 61 'name' => array('type' => 'text', 'size' => 40, 'l abel' => rcube_label('name')),62 'firstname' => array('type' => 'text', 'size' => 19, 'l abel' => rcube_label('firstname')),63 'surname' => array('type' => 'text', 'size' => 19, 'l abel' => rcube_label('surname')),64 'middlename' => array('type' => 'text', 'size' => 19, 'l abel' => rcube_label('middlename')),65 'nickname' => array('type' => 'text', 'size' => 40, 'l abel' => rcube_label('nickname')),66 'jobtitle' => array('type' => 'text', 'size' => 40, 'l abel' => rcube_label('jobtitle')),67 'organization' => array('type' => 'text', 'size' => 19, 'l abel' => rcube_label('organization')),68 'department' => array('type' => 'text', 'size' => 19, 'l abel' => rcube_label('department')),61 'name' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => rcube_label('name')), 62 'firstname' => array('type' => 'text', 'size' => 19, 'limit' => 1, 'label' => rcube_label('firstname')), 63 'surname' => array('type' => 'text', 'size' => 19, 'limit' => 1, 'label' => rcube_label('surname')), 64 'middlename' => array('type' => 'text', 'size' => 19, 'limit' => 1, 'label' => rcube_label('middlename')), 65 'nickname' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => rcube_label('nickname')), 66 'jobtitle' => array('type' => 'text', 'size' => 40, 'limit' => 1, 'label' => rcube_label('jobtitle')), 67 'organization' => array('type' => 'text', 'size' => 19, 'limit' => 1, 'label' => rcube_label('organization')), 68 'department' => array('type' => 'text', 'size' => 19, 'limit' => 1, 'label' => rcube_label('department')), 69 69 'email' => array('type' => 'text', 'size' => 40, 'label' => rcube_label('email'), 'subtypes' => array('home','work','other')), 70 70 'phone' => array('type' => 'text', 'size' => 40, 'label' => rcube_label('phone'), 'subtypes' => array('home','home2','work','work2','mobile','main','homefax','workfax','car','pager','assistant','other')), … … 75 75 'region' => array('type' => 'text', 'size' => 12, 'label' => rcube_label('region'), 'composite' => true), 76 76 'country' => array('type' => 'text', 'size' => 40, 'label' => rcube_label('country'), 'composite' => true), 77 'birthday' => array('type' => 'date', 'size' => 12, 'label' => rcube_label('birthday') ),77 'birthday' => array('type' => 'date', 'size' => 12, 'label' => rcube_label('birthday'), 'limit' => 1), 78 78 'website' => array('type' => 'text', 'size' => 40, 'label' => rcube_label('website'), 'subtypes' => array('home','work','blog','other')), 79 79 'im' => array('type' => 'text', 'size' => 40, 'label' => rcube_label('instantmessenger'), 'subtypes' => array('aim','icq','msn','yahoo','jabber','other')), 80 'notes' => array('type' => 'textarea', 'size' => 40, 'rows' => 15, 'label' => rcube_label('notes'), 'limit' => 1), 80 81 ); 81 82 … … 275 276 $coltypes = $GLOBALS['CONTACT_COLTYPES']; 276 277 277 $select_add = new html_select(array('id' => 'addfieldmenu'));278 $select_add->add(rcube_label('addfield'), '');279 $select_add->add($coltypes['middlename']['label'], 'middlename');280 278 foreach ($coltypes as $col => $prop) { 281 if (!$prop['composite'] && !$prop['default'])282 $select_add->add($prop['label'], $col);283 279 if ($prop['subtypes']) { 284 280 $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype')); … … 292 288 if (empty($fieldset['content'])) 293 289 continue; 290 291 $select_add = new html_select(array('class' => 'addfieldmenu', 'rel' => $section)); 292 $select_add->add(rcube_label('addfield'), ''); 294 293 295 294 // render head section with name fields (not a regular list of rows) … … 317 316 $colprop = (array)$fieldset['content'][$col] + (array)$coltypes[$col]; 318 317 $colprop['id'] = 'ff_'.$col; 319 if (empty($record[$col]) && !$colprop['visible']) 318 if (empty($record[$col]) && !$colprop['visible']) { 320 319 $colprop['style'] = 'display:none'; 320 $select_add->add($colprop['label'], $col); 321 } 321 322 $fields .= rcmail_get_edit_field($col, $record[$col], $colprop, $colprop['type']); 322 323 } … … 324 325 $content .= html::div($blockname, $fields); 325 326 } 327 328 if ($RCMAIL->action != 'show') 329 $content .= html::p('addfield', $select_add->show(null)); 326 330 327 331 $out .= html::tag('fieldset', $attrib, (!empty($fieldset['name']) ? html::tag('legend', null, Q($fieldset['name'])) : '') . $content) ."\n"; … … 338 342 $subtype = 'home'; 339 343 340 $fullkey = $col.' .'.$subtype;344 $fullkey = $col.':'.$subtype; 341 345 $label = isset($colprop['label']) ? $colprop['label'] : rcube_label($col); 342 346 … … 359 363 foreach ($colprop['subtypes'] as $i => $st) { 360 364 $newval = false; 361 if ($record[$field.' .'.$st]) {365 if ($record[$field.':'.$st]) { 362 366 $subtypes[count($values)] = $st; 363 $newval = $record[$field.' .'.$st];367 $newval = $record[$field.':'.$st]; 364 368 } 365 369 else if ($i == 0 && $record[$field]) { … … 387 391 foreach ((array)$values as $i => $val) { 388 392 if ($subtypes[$i]) 389 $subtype = $subtypes ;393 $subtype = $subtypes[$i]; 390 394 391 395 // render composite field … … 393 397 $composite = ''; 394 398 foreach ($colprop['childs'] as $j => $childcol) { 395 $childvalue = $val[$c oldcol] ? $val[$coldcol] : $val[$j];396 399 $childvalue = $val[$childcol] ? $val[$childcol] : $val[$j]; 400 397 401 if ($RCMAIL->action != 'show') { 398 402 $cp = $coltypes[$childcol]; … … 401 405 } 402 406 else 403 $composite .= html::span('data ', Q($childvalue)) . " ";407 $composite .= html::span('data ' . $childcol, Q($childvalue)) . " "; 404 408 } 405 409 … … 413 417 $colprop['array'] = true; 414 418 $val = rcmail_get_edit_field($col, $val, $colprop, $colprop['type']); 415 } 419 $coltypes[$field]['count']++; 420 } 421 else if (!$colprop['value']) 422 $val = Q($val); 416 423 417 424 if ($colprop['subtypes']) 418 425 $label = $subtype; 419 426 420 427 if ($label) { 421 428 $rows .= html::div('row', … … 427 434 } 428 435 436 // add option to the add-field menu 437 if (!$colprop['limit'] || $coltypes[$field]['count'] < $colprop['limit']) { 438 $select_add->add($colprop['label'], $col); 439 $select_add->_count++; 440 } 441 429 442 $content .= html::div('contactfieldgroup contactcontroller' . $col, $rows); 430 443 } 431 444 432 if ($RCMAIL->action != 'show' && !$fieldset['single'])433 $content .= html::p('addfield', $select_add->show(null , array('rel' => $section)));445 if ($RCMAIL->action != 'show' && $select_add->_count) 446 $content .= html::p('addfield', $select_add->show(null)); 434 447 435 448 $content = html::div(array('id' => 'contactsection' . $section), $content); -
branches/devel-addressbook/program/steps/addressbook/save.inc
r4227 r4230 37 37 if ($colprop['composite']) 38 38 continue; 39 // gather form data of composite fields 39 40 if ($colprop['childs']) { 40 41 $values = array(); … … 49 50 $a_record[$col.':'.$subtype][] = $values[$i]; 50 51 } 52 // assign values and subtypes 51 53 else if (is_array($_POST[$fname])) { 52 54 $values = get_input_value($fname, RCUBE_INPUT_POST); … … 67 69 #var_dump($a_record); 68 70 69 // Basic input checks 70 if (empty($a_record['name']) || empty($a_record['email'])) {71 // Basic input checks (TODO: delegate to $CONTACTS instance) 72 if (empty($a_record['name'])/* || empty($a_record['email'])*/) { 71 73 $OUTPUT->show_message('formincomplete', 'warning'); 72 74 rcmail_overwrite_action($return_action); … … 75 77 76 78 // Validity checks 77 foreach ((array)$a_record['email'] as $email) { 78 $_email = idn_to_ascii($email); 79 if (!check_email($_email, false)) { 80 $OUTPUT->show_message('emailformaterror', 'warning', array('email' => $_email)); 81 rcmail_overwrite_action($return_action); 82 return; 79 foreach ($a_record as $field => $values) { 80 if (strpos($field, 'email') === 0) { 81 foreach ((array)$values as $email) { 82 $_email = idn_to_ascii($email); 83 if (!check_email($_email, false)) { 84 $OUTPUT->show_message('emailformaterror', 'warning', array('email' => $email)); 85 rcmail_overwrite_action($return_action); 86 return; 87 } 88 } 83 89 } 84 90 } -
branches/devel-addressbook/program/steps/addressbook/show.inc
r4227 r4230 65 65 66 66 $i_size = !empty($attrib['size']) ? $attrib['size'] : 40; 67 $t_rows = !empty($attrib['textarearows']) ? $attrib['textarearows'] : 6;68 $t_cols = !empty($attrib['textareacols']) ? $attrib['textareacols'] : 40;69 67 70 68 $form = array( … … 72 70 'name' => rcube_label('contactproperties'), 73 71 'content' => array( 74 'email' => array('type' => 'text', 'size' => $i_size, 'value' => array()), 72 'email' => array('size' => $i_size, 'value' => array()), 73 'phone' => array('size' => $i_size), 74 'address' => array(), 75 'birthday' => array('size' => $i_size), 76 'website' => array('size' => $i_size), 77 'im' => array('size' => $i_size), 75 78 ), 76 79 ), … … 87 90 ); 88 91 89 foreach ((array)$record['email'] as $email) { 90 $form['info']['content']['email']['value'][] = html::a(array( 91 'href' => 'mailto:' . $email, 92 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($email)), 93 'title' => rcube_label('composeto'), 94 'class' => 'email', 95 ), Q($email)); 92 foreach ((array)$record as $field => $values) { 93 if (strpos($field, 'email') === 0) { 94 foreach ((array)$values as $email) { 95 $form['info']['content']['email']['value'][] = html::a(array( 96 'href' => 'mailto:' . $email, 97 'onclick' => sprintf("return %s.command('compose','%s',this)", JS_OBJECT_NAME, JQ($email)), 98 'title' => rcube_label('composeto'), 99 'class' => 'email', 100 ), Q($email)); 101 } 102 } 96 103 } 97 104 -
branches/devel-addressbook/skins/default/addressbook.css
r4227 r4230 267 267 .contactfieldgroup 268 268 { 269 margin: 1.2em 0; 269 margin: 0.8em 0; 270 } 271 272 form .contactfieldgroup 273 { 274 margin: 1.4em 0; 270 275 } 271 276 … … 310 315 margin-bottom: 0.1em; 311 316 } 317 318 .contactcontrolleraddress span.street, 319 .contactcontrolleraddress span.country { 320 display: block; 321 }
Note: See TracChangeset
for help on using the changeset viewer.
