diff options
-rw-r--r-- | Zotlabs/Module/Connedit.php | 53 | ||||
-rw-r--r-- | include/connections.php | 222 | ||||
-rwxr-xr-x | view/tpl/abook_edit.tpl | 279 |
3 files changed, 553 insertions, 1 deletions
diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 5968ccde6..3aaa2a874 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -86,6 +86,12 @@ class Connedit extends \Zotlabs\Web\Controller { call_hooks('contact_edit_post', $_POST); + $vc = get_abconfig(local_channel(),$orig_record['abook_xchan'],'system','vcard'); + $vcard = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); + $serialised_vcard = update_vcard($_REQUEST,$vcard); + if($serialised_vcard) + set_abconfig(local_channel(),$orig_record['abook_xchan'],'system','vcard',$serialised_vcard); + if(intval($orig_record[0]['abook_self'])) { $autoperms = intval($_POST['autoperms']); $is_self = true; @@ -647,6 +653,14 @@ class Connedit extends \Zotlabs\Web\Controller { $abook_prev = $abook_next = 0; } + $vc = get_abconfig(local_channel(),$contact['abook_xchan'],'system','vcard'); +logger('vc: ' . $vc); + + $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); + $vcard = (($vctmp) ? get_vcard_array($vctmp) : [] ); + +logger('vcard: ' . print_r($vcard,true)); + $tpl = get_markup_template("abook_edit.tpl"); if(feature_enabled(local_channel(),'affinity')) { @@ -781,6 +795,7 @@ class Connedit extends \Zotlabs\Web\Controller { '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no), '$addr' => $contact['xchan_addr'], '$section' => $section, + '$vcard' => $vcard, '$addr_text' => t('This connection\'s primary address is'), '$loc_text' => t('Available locations:'), '$locstr' => $locstr, @@ -823,7 +838,43 @@ class Connedit extends \Zotlabs\Web\Controller { '$contact_id' => $contact['abook_id'], '$name' => $contact['xchan_name'], '$abook_prev' => $abook_prev, - '$abook_next' => $abook_next + '$abook_next' => $abook_next, + '$vcard_label' => t('Details'), + '$displayname' => $displayname, + '$name_label' => t('Name'), + '$org_label' => t('Organisation'), + '$title_label' => t('Title'), + '$tel_label' => t('Phone'), + '$email_label' => t('Email'), + '$impp_label' => t('Instant messenger'), + '$url_label' => t('Website'), + '$adr_label' => t('Address'), + '$note_label' => t('Note'), + '$mobile' => t('Mobile'), + '$home' => t('Home'), + '$work' => t('Work'), + '$other' => t('Other'), + '$add_card' => t('Add Contact'), + '$add_field' => t('Add Field'), + '$create' => t('Create'), + '$update' => t('Update'), + '$delete' => t('Delete'), + '$cancel' => t('Cancel'), + '$po_box' => t('P.O. Box'), + '$extra' => t('Additional'), + '$street' => t('Street'), + '$locality' => t('Locality'), + '$region' => t('Region'), + '$zip_code' => t('ZIP Code'), + '$country' => t('Country') + + + + + + + + )); $arr = array('contact' => $contact,'output' => $o); diff --git a/include/connections.php b/include/connections.php index b08d046b3..3d52d1a48 100644 --- a/include/connections.php +++ b/include/connections.php @@ -630,3 +630,225 @@ function random_profile() { return ''; } +function update_vcard($arr,$vcard = null) { + + $fn = $arr['fn']; + + if(! $vcard) { + $vcard = new \Sabre\VObject\Component\VCard([ + 'FN' => $fn, + 'N' => array_reverse(explode(' ', $fn)) + ]); + } + $org = $arr['org']; + if($org) { + $vcard->ORG = $org; + } + + $title = $arr['title']; + if($title) { + $vcard->TITLE = $title; + } + + $tel = $arr['tel']; + $tel_type = $arr['tel_type']; + if($tel) { + $i = 0; + foreach($tel as $item) { + if($item) { + $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); + } + $i++; + } + } + + $email = $arr['email']; + $email_type = $arr['email_type']; + if($email) { + $i = 0; + foreach($email as $item) { + if($item) { + $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); + } + $i++; + } + } + + $impp = $arr['impp']; + $impp_type = $arr['impp_type']; + if($impp) { + $i = 0; + foreach($impp as $item) { + if($item) { + $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); + } + $i++; + } + } + + $url = $arr['url']; + $url_type = $arr['url_type']; + if($url) { + $i = 0; + foreach($url as $item) { + if($item) { + $vcard->add('URL', $item, ['type' => $url_type[$i]]); + } + $i++; + } + } + + $adr = $arr['adr']; + $adr_type = $arr['adr_type']; + + if($adr) { + $i = 0; + foreach($adr as $item) { + if($item) { + $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); + } + $i++; + } + } + + $note = $arr['note']; + if($note) { + $vcard->NOTE = $note; + } + + return $vcard->serialize(); + +} + +function get_vcard_array($vc) { + + $photo = ''; + if($vc->PHOTO) { + $photo_value = strtolower($vc->PHOTO->getValueType()); // binary or uri + if($photo_value === 'binary') { + $photo_type = strtolower($vc->PHOTO['TYPE']); // mime jpeg, png or gif + $photo = 'data:image/' . $photo_type . ';base64,' . base64_encode((string)$vc->PHOTO); + } + else { + $url = parse_url((string)$vc->PHOTO); + $photo = 'data:' . $url['path']; + } + } + + $fn = ''; + if($vc->FN) { + $fn = (string) escape_tags($vc->FN); + } + + $org = ''; + if($vc->ORG) { + $org = (string) escape_tags($vc->ORG); + } + + $title = ''; + if($vc->TITLE) { + $title = (string) escape_tags($vc->TITLE); + } + + $tels = []; + if($vc->TEL) { + foreach($vc->TEL as $tel) { + $type = (($tel['TYPE']) ? vcard_translate_type((string)$tel['TYPE']) : ''); + $tels[] = [ + 'type' => $type, + 'nr' => (string) escape_tags($tel) + ]; + } + } + $emails = []; + if($vc->EMAIL) { + foreach($vc->EMAIL as $email) { + $type = (($email['TYPE']) ? vcard_translate_type((string)$email['TYPE']) : ''); + $emails[] = [ + 'type' => $type, + 'address' => (string) escape_tags($email) + ]; + } + } + + $impps = []; + if($vc->IMPP) { + foreach($vc->IMPP as $impp) { + $type = (($impp['TYPE']) ? vcard_translate_type((string)$impp['TYPE']) : ''); + $impps[] = [ + 'type' => $type, + 'address' => (string) escape_tags($impp) + ]; + } + } + + $urls = []; + if($vc->URL) { + foreach($vc->URL as $url) { + $type = (($url['TYPE']) ? vcard_translate_type((string)$url['TYPE']) : ''); + $urls[] = [ + 'type' => $type, + 'address' => (string) escape_tags($url) + ]; + } + } + + $adrs = []; + if($vc->ADR) { + foreach($vc->ADR as $adr) { + $type = (($adr['TYPE']) ? vcard_translate_type((string)$adr['TYPE']) : ''); + $adrs[] = [ + 'type' => $type, + 'address' => escape_tags($adr->getParts()) + ]; + } + } + + $note = ''; + if($vc->NOTE) { + $note = (string) escape_tags($vc->NOTE); + } + + $card = [ + 'photo' => $photo, + 'fn' => $fn, + 'org' => $org, + 'title' => $title, + 'tels' => $tels, + 'emails' => $emails, + 'impps' => $impps, + 'urls' => $urls, + 'adrs' => $adrs, + 'note' => $note + ]; + + return $card; + +} + + +function vcard_translate_type($type) { + + if(!$type) + return; + + $type = strtoupper($type); + + $map = [ + 'CELL' => t('Mobile'), + 'HOME' => t('Home'), + 'HOME,VOICE' => t('Home, Voice'), + 'HOME,FAX' => t('Home, Fax'), + 'WORK' => t('Work'), + 'WORK,VOICE' => t('Work, Voice'), + 'WORK,FAX' => t('Work, Fax'), + 'OTHER' => t('Other') + ]; + + if (array_key_exists($type, $map)) { + return [$type, $map[$type]]; + } + else { + return [$type, t('Other') . ' (' . $type . ')']; + } +} diff --git a/view/tpl/abook_edit.tpl b/view/tpl/abook_edit.tpl index 2e02de33b..c36eca6ff 100755 --- a/view/tpl/abook_edit.tpl +++ b/view/tpl/abook_edit.tpl @@ -87,6 +87,285 @@ </div> </div> {{/if}} + <div class="panel"> + <div class="section-subtitle-wrapper" role="tab" id="vcard-tool"> + <h3> + <a data-toggle="collapse" data-parent="#contact-edit-tools" href="#vcard-tool-collapse" aria-expanded="true" aria-controls="vcard-tool-collapse"> + {{$vcard_label}} + </a> + </h3> + </div> + + <div id="vcard-tool-collapse" class="panel-collapse collapse{{if !$is_pending || $section == 'vcard'}} in{{/if}}" role="tabpanel" aria-labelledby="vcard-tool"> + +<script> +$(document).ready(function() { + + $(document).on('click', '.vcard-header, .vcard-cancel-btn', updateView); + $(document).on('click', '.add-field', doAdd); + $(document).on('click', '.remove-field', doRemove); + + function updateView() { + var id = $(this).data('id'); + var action = $(this).data('action'); + var header = $('#vcard-header-' + id); + var cancel = $('#vcard-cancel-' + id); + var addField = $('#vcard-add-field-' + id); + var info = $('#vcard-info-' + id); + var vcardPreview = $('#vcard-preview-' + id); + var fn = $('#vcard-fn-' + id); + + if(action === 'open') { + $(header).addClass('active'); + $(cancel).show(); + $(addField).show(); + $(info).show(); + $(fn).show(); + $(vcardPreview).hide(); + } + else { + $(header).removeClass('active'); + $(cancel).hide(); + $(addField).hide(); + $(info).hide(); + $(fn).hide(); + $(vcardPreview).show(); + } + } + + function doAdd() { + var what = $(this).data('add'); + var id = $(this).data('id'); + var element = '#template-form-' + what; + var where = '#card_form_' + id; + + $(element + ' .remove-field').attr('data-id', id) + + if(what === 'vcard-adr') { + var adrCount = $(where + ' .form-' + what).length; + var attrName = 'adr[' + adrCount + '][]'; + $(element + ' input').attr('name', attrName); + } + + if(what === 'vcard-org' || what === 'vcard-title' || what === 'vcard-note') { + $(where + ' .add-' + what).hide() + } + + $(element).clone().removeAttr('id').appendTo(where + ' .form-' + what + '-wrapper'); + } + + function doRemove() { + var what = $(this).data('remove'); + var element = $(this).parents('div.form-' + what); + var where = '#card_form_' + $(this).data('id'); + + if(what === 'vcard-org' || what === 'vcard-title' || what === 'vcard-note') { + $(where + ' .add-' + what).show() + } + + $(element).remove(); + } + +}); +</script> + + + + <div class="dropdown pull-right"> + <button data-toggle="dropdown" type="button" class="btn btn-default btn-sm dropdown-toggle"><i class="fa fa-plus"></i> {{$add_field}}</button> + <ul class="dropdown-menu"> + <li class="add-vcard-org" style="display: none"><a href="#" data-add="vcard-org" data-id="new" class="add-field" onclick="return false;">{{$org_label}}</a></li> + <li class="add-vcard-title" style="display: none"><a href="#" data-add="vcard-title" data-id="new" class="add-field" onclick="return false;">{{$title_label}}</a></li> + <li class="add-vcard-tel"><a href="#" data-add="vcard-tel" data-id="new" class="add-field" onclick="return false;">{{$tel_label}}</a></li> + <li class="add-vcard-email"><a href="#" data-add="vcard-email" data-id="new" class="add-field" onclick="return false;">{{$email_label}}</a></li> + <li class="add-vcard-impp"><a href="#" data-add="vcard-impp" data-id="new" class="add-field" onclick="return false;">{{$impp_label}}</a></li> + <li class="add-vcard-url"><a href="#" data-add="vcard-url" data-id="new" class="add-field" onclick="return false;">{{$url_label}}</a></li> + <li class="add-vcard-adr"><a href="#" data-add="vcard-adr" data-id="new" class="add-field" onclick="return false;">{{$adr_label}}</a></li> + <li class="add-vcard-note"><a href="#" data-add="vcard-note" data-id="new" class="add-field" onclick="return false;">{{$note_label}}</a></li> + </ul> + </div> + + <div class="vcard-fn-create form-group"> + <div class="form-vcard-fn-wrapper"> + <div class="form-group form-vcard-fn"> + <div class="vcard-nophoto"><i class="fa fa-user"></i></div><input type="text" name="fn" value="" placeholder="{{$name_label}}"> + </div> + </div> + </div> + + <div class="vcard-org form-group"> + <div class="form-vcard-org-wrapper"> + <div class="form-group form-vcard-org"> + <input type="text" name="org" value="" placeholder="{{$org_label}}"> + <i data-remove="vcard-org" data-id="new" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> + </div> + </div> + + <div class="vcard-title form-group"> + <div class="form-vcard-title-wrapper"> + <div class="form-group form-vcard-title"> + <input type="text" name="title" value="" placeholder="{{$title_label}}"> + <i data-remove="vcard-title" data-id="new" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> + </div> + </div> + + <div class="vcard-tel form-group"> + <div class="form-vcard-tel-wrapper"> + <div class="form-group form-vcard-tel"> + <select name="tel_type[]"> + <option value="CELL">{{$mobile}}</option> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <input type="text" name="tel[]" value="" placeholder="{{$tel_label}}"> + <i data-remove="vcard-tel" data-id="new" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> + </div> + </div> + + + <div class="vcard-email form-group"> + <div class="form-vcard-email-wrapper"> + <div class="form-group form-vcard-email"> + <select name="email_type[]"> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <input type="text" name="email[]" value="" placeholder="{{$email_label}}"> + <i data-remove="vcard-email" data-id="new" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> + </div> + </div> + + <div class="vcard-impp form-group"> + <div class="form-vcard-impp-wrapper"> + </div> + </div> + + <div class="vcard-url form-group"> + <div class="form-vcard-url-wrapper"> + </div> + </div> + + <div class="vcard-adr form-group"> + <div class="form-vcard-adr-wrapper"> + </div> + </div> + + <div class="vcard-note form-group"> + <div class="form-vcard-note-wrapper"> + </div> + </div> + + <div class="clear"></div> + + + +<div id="template-form-vcard-org" class="form-group form-vcard-org"> + <div class="form-group form-vcard-org"> + <input type="text" name="org" value="" placeholder="{{$org_label}}"> + <i data-remove="vcard-org" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> +</div> + +<div id="template-form-vcard-title" class="form-group form-vcard-title"> + <div class="form-group form-vcard-title"> + <input type="text" name="title" value="" placeholder="{{$title_label}}"> + <i data-remove="vcard-title" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> +</div> + +<div id="template-form-vcard-tel" class="form-group form-vcard-tel"> + <select name="tel_type[]"> + <option value="CELL">{{$mobile}}</option> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <input type="text" name="tel[]" value="" placeholder="{{$tel_label}}"> + <i data-remove="vcard-tel" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> +</div> + +<div id="template-form-vcard-email" class="form-group form-vcard-email"> + <select name="email_type[]"> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <input type="text" name="email[]" value="" placeholder="{{$email_label}}"> + <i data-remove="vcard-email" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> +</div> + +<div id="template-form-vcard-impp" class="form-group form-vcard-impp"> + <select name="impp_type[]"> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <input type="text" name="impp[]" value="" placeholder="{{$impp_label}}"> + <i data-remove="vcard-impp" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> +</div> + +<div id="template-form-vcard-url" class="form-group form-vcard-url"> + <select name="url_type[]"> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <input type="text" name="url[]" value="" placeholder="{{$url_label}}"> + <i data-remove="vcard-url" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> +</div> + +<div id="template-form-vcard-adr" class="form-group form-vcard-adr"> + <div class="form-group"> + <select name="adr_type[]"> + <option value="HOME">{{$home}}</option> + <option value="WORK">{{$work}}</option> + <option value="OTHER">{{$other}}</option> + </select> + <label>{{$adr_label}}</label> + <i data-remove="vcard-adr" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$po_box}}"> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$extra}}"> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$street}}"> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$locality}}"> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$region}}"> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$zip_code}}"> + </div> + <div class="form-group"> + <input type="text" name="" value="" placeholder="{{$country}}"> + </div> +</div> + +<div id="template-form-vcard-note" class="form-group form-vcard-note"> + <label>{{$note_label}}</label> + <i data-remove="vcard-note" data-id="" class="fa fa-trash-o remove-field drop-icons fakelink"></i> + <textarea name="note" class="form-control"></textarea> +</div> + + + </div> + </div> + + + + {{if $affinity }} <div class="panel"> |