From b3ad574ddfd8697b6342356fb23e756ba8cabb0f Mon Sep 17 00:00:00 2001 From: Pascal Corpet Date: Sat, 5 Jun 2010 00:20:40 +0200 Subject: [PATCH] Adds Outlook CSV format for birthdays and contacts (Closes #670) --- ChangeLog | 1 + htdocs/images/icons/outlook.gif | Bin 0 -> 1091 bytes modules/carnet.php | 51 ++++++++++++ modules/carnet/outlook.inc.php | 142 ++++++++++++++++++++++++++++++++++ templates/carnet/calendar.outlook.tpl | 32 ++++++++ templates/carnet/mescontacts.tpl | 18 +++-- 6 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 htdocs/images/icons/outlook.gif create mode 100644 modules/carnet/outlook.inc.php create mode 100644 templates/carnet/calendar.outlook.tpl diff --git a/ChangeLog b/ChangeLog index 6df167f..2f7f1f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ Bug/Wish: - #386: Adds the possibility to fill in multiple nationalities -JAC - #443: Adds concept of ordinary firstname -JAC - #450: Adds marital name, thus ordinary name can be any name -JAC + - #670: Adds Outlook CSV format for birthdays and contacts -Car - #891: Improves education display -JAC * XnetLists: diff --git a/htdocs/images/icons/outlook.gif b/htdocs/images/icons/outlook.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4c0ad0a0bdd780f8cc432804c20b4cac12d9efa GIT binary patch literal 1091 zcmcJO=}*%K9EX4DC9pX=rx{`b$bw>#jv;J1wxo*6G2#@=LdYgmX*oioSI!q@c zWW<6XAWj3F09~nt*$QyjK-&gmNuVqTa4gkOUKH*GNhTQOAWqfyC-&!gW0pl&dOCr`8{k#F zsv}EM841ejM@#}tU1>=mtkn5owgs?i1~W*Yx{KMD4Sh`5;J+&O0{aGFcFey1XHWW@ zv0uTW8ORR+c`=x0hOQknJ^NSVb)*nGl8Kt0G)d*@`L0~pTvD{A!^;xGKoZJlSa}RP zp8=+Mn92eDFy=6Ir4Z4zW?oT%X}TWl>oY&^p1y{%@*_4rLtDLXS>9$EyCAKJQTG*sAnA{0#(JawP}UaP+EgjKfNA`DTwU&^x#K-i{jL1^uKRKL##7|?T$BhEklDKMP=E-;&4QxxG_{Cv*afS?Vt5o&)Kn zsoL*gp$Sj}7^EW?oduj=uxgj<{GMf!dRe6YbP}j5&C4=C_1t)ZL6kS&$x?P-m6y0; z4kIs%v@pzp%~cREdvhtE6WL#u+BB{3oDDKIh>{zqlKtvXUdVxg};~^P-~J(RkO=Ncrl)y%7|TLJo^o zMnBo=w*RZ&$XZ|71L`R%d6$rf_?^L1Zub_22)Psi_43^3N2Jd7qAGm@ZZ9W)BH6uDKXUAN!@f|@9m$m;ialxD zsCs9lkXZcn^no+}0R=ds`}d=Sy3fvkSWEmg@UWN{U*P-YD9+PG<5~SNf^-IYhB5P{ i9o|g0AEGt+6TZPiO!}PHQ3;t`Tp $this->make_hook('pdf', AUTH_COOKIE), 'carnet/contacts/vcard' => $this->make_hook('vcard', AUTH_COOKIE), 'carnet/contacts/ical' => $this->make_hook('ical', AUTH_PUBLIC, 'user', NO_HTTPS), + 'carnet/contacts/csv' => $this->make_hook('csv', AUTH_PUBLIC, 'user', NO_HTTPS), + 'carnet/contacts/csv/birthday' => $this->make_hook('csv_birthday', AUTH_PUBLIC, 'user', NO_HTTPS), 'carnet/rss' => $this->make_hook('rss', AUTH_PUBLIC, 'user', NO_HTTPS), ); @@ -357,6 +359,38 @@ class CarnetModule extends PLModule ); } + function handler_csv_birthday(&$page, $alias = null, $hash = null) + { + $user = Platal::session()->tokenAuth($alias, $hash); + if (is_null($user)) { + if (S::logged()) { + $user == S::user(); + } else { + return PL_FORBIDDEN; + } + } + + $page->changeTpl('carnet/calendar.outlook.tpl', NO_SKIN); + $filter = new UserFilter(new UFC_Contact($user)); + $profiles = $filter->iterProfiles(); + $page->assign('events', PlIteratorUtils::map($profiles, array($this, 'buildBirthRef'))); + $years = array(date("Y")); + for ($i = 1; $i <= 10; ++$i) { + $years[] = $years[0] + $i; + } + $page->assign('years', $years); + $lang = 'fr'; + if (preg_match('/([a-zA-Z]{2,8})($|[^a-zA-Z])/', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches)) { + $lang = strtolower($matches[1]); + } + $page->assign('lang', $lang); + if ($lang == 'fr') { + $encoding = 'iso8859-15'; + } else { + $encoding = 'utf-8'; + } + pl_content_headers("text/comma-separated-values;charset=".$encoding); + } function handler_ical(&$page, $alias = null, $hash = null) { @@ -387,6 +421,23 @@ class CarnetModule extends PLModule $vcard->addProfiles($pf->getProfiles()); $vcard->show(); } + + function handler_csv(&$page, $alias = null, $hash = null) + { + $user = Platal::session()->tokenAuth($alias, $hash); + if (is_null($user)) { + if (S::logged()) { + $user == S::user(); + } else { + return PL_FORBIDDEN; + } + } + + $page->changeTpl('carnet/mescontacts.outlook.tpl', NO_SKIN); + $pf = new ProfileFilter(new UFC_Contact($user)); + require_once 'carnet/outlook.inc.php'; + Outlook::output_profiles($pf->getProfiles(), 'fr'); + } } // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: diff --git a/modules/carnet/outlook.inc.php b/modules/carnet/outlook.inc.php new file mode 100644 index 0000000..791b15c --- /dev/null +++ b/modules/carnet/outlook.inc.php @@ -0,0 +1,142 @@ + array("Nom","Titre","Prénom","Deuxième prénom","Nom","Suffixe","Surnom","Société ","Service ","Titre","Rue (bureau)","Rue (bureau) 2","Rue (bureau) 3","Ville (bureau)","Dép/Région (bureau)","Code postal (bureau)","Pays (bureau)","Rue (domicile)","Rue (domicile) 2","Rue (domicile) 3","Ville (domicile)","Dép/Région (domicile)","Code postal (domicile)","Pays (domicile)","Rue (autre)","Rue (autre) 2","Rue (autre) 3","Ville (autre)","Dép/Région (autre)","Code postal (autre)","Pays (autre)","Téléphone de l'assistant(e)","Télécopie (bureau)","Téléphone (bureau)","Téléphone 2 (bureau)","Rappel","Téléphone (voiture)","Téléphone société","Télécopie (domicile)","Téléphone (domicile)","Téléphone 2 (domicile)","RNIS","Tél. mobile","Télécopie (autre)","Téléphone (autre)","Récepteur de radiomessagerie","Téléphone principal","Radio téléphone","Téléphone TDD/TTY","Télex","Adresse de messagerie","Type de messagerie","Nom complet de l'adresse de messagerie","Adresse de messagerie 2","Type de messagerie 2","Nom complet de l'adresse de messagerie 2","Adresse de messagerie 3","Type de messagerie 3","Nom complet de l'adresse de messagerie 3","Anniversaire","Anniversaire de mariage ou fête","Autre boîte postale","B.P. professionnelle","Boîte postale du domicile","Bureau","Catégories","Code gouvernement","Compte","Conjoint(e)","Critère de diffusion","Disponibilité Internet","Emplacement","Enfants","Informations facturation","Initiales","Kilométrage","Langue","Mots clés","Nom de l'assistant(e)","Notes","Numéro d'identification de l'organisation","Page Web","Passe-temps","Priorité","Privé","Profession","Recommandé par","Responsable","Serveur d'annuaire","Sexe","Utilisateur 1","Utilisateur 2","Utilisateur 3","Utilisateur 4"), + ); + + private static function add_address(&$adr, &$contact, $adr_type = 'autre') { + $contact['Rue ('.$adr_type.')'] = $adr->text; + $contact['Code postal ('.$adr_type.')'] = $adr->postalCode; + $contact['Ville ('.$adr_type.')'] = $adr->locality; + $contact['Dép/Région ('.$adr_type.')'] = $adr->administrativeArea; + $contact['Pays ('.$adr_type.')'] = $adr->country; + $contact['Téléphone ('.$adr_type.')'] = $adr->fixed_tel; + $contact['Télécopie ('.$adr_type.')'] = $adr->fax_tel; + } + + private static function profile_to_contact(&$p) { + $contact = array( + 'Prénom' => $p->firstName(), + 'Nom' => $p->lastName(), + 'Notes' => '('.$p->promo.')', + 'Tél. mobile' => $p->mobile, + 'Anniversaire' => $p->birthdate, + 'Surnom' => $p->nickname, + ); + // Homes + $adrs = $p->iterAddresses(Profile::ADDRESS_PERSO); + if ($adr = $adrs->next()) { + Outlook::add_address(&$adr, &$contact, 'domicile'); + } + if ($adr = $adrs->next()) { + Outlook::add_address(&$adr, &$contact, 'autre'); + } + // Pro + $adrs = $p->iterAddresses(Profile::ADDRESS_PRO); + if ($adr = $adrs->next()) { + Outlook::add_address(&$adr, &$contact, 'bureau'); + } + $mainjob = $p->getMainJob(); + if ($mainjob && $mainjob->company) { + $contact['Société '] = $mainjob->company->name; + } + if (!empty($p->section)) { + $contact['Utilisateur 2'] = 'Section : '. $p->section; + } + if ($p->isFemale()) { + $contact['Sexe'] = 'Féminin'; + } else { + $contact['Sexe'] = 'Masculin'; + } + $binets = $p->getBinets(); + if (count($binets)) { + $bn = DirEnum::getOptions(DirEnum::BINETS); + $bns = array(); + foreach (array_keys($binets) as $bid) if (!empty($bn[$bid])) { + $bns[$bid] = $bn[$bid]; + } + if (count($bns) > 0) { + $contact['Utilisateur 3'] = 'Binets : '.join(', ', $bns); + } + } + $user = $p->owner(); + if ($user) { + $contact['Adresse de messagerie'] = $user->bestalias; + $contact['Nom complet de l\'adresse de messagerie'] = $p->fullName().' <'.$user->bestalias.'>'; + $contact['Adresse de messagerie 2'] = $user->bestalias_alternate; + $contact['Nom complet de l\'adresse de messagerie 2'] = $p->fullName().' <'.$user->bestalias_alternate.'>'; + if ($user->bestalias != $user->forlife) { + $contact['Adresse de messagerie 3'] = $user->forlife; + $contact['Nom complet de l\'adresse de messagerie 3'] = $p->fullName().' <'.$user->forlife.'>'; + } + $groups = $user->groups(); + if (count($groups)) { + $gn = DirEnum::getOptions(DirEnum::GROUPESX); + $gns = array(); + foreach (array_keys($groups) as $gid) if (!empty($gn[$gid])) { + $gns[$gid] = $gn[$gid]; + } + if (count($gns) > 0) { + $contact['Utilisateur 1'] = 'Groupes X : '. join(', ', $gns); + } + } + } + return $contact; + } + + private static function protect($t) { + if (empty($t)) { + return '""'; + } + $t = preg_replace("/\r?\n/", ", ", $t); + return '"'.strtr(utf8_decode($t),'"', '\\"').'"'; + } + + public static function output_profiles(&$profiles, $lang) { + header("Content-Type: text/plain;charset=iso8859-15"); + $fields =& Outlook::$contact_fields[$lang]; + foreach ($fields as $i => $k) { + if ($i != 0) { + echo ','; + } + echo Outlook::protect($k); + } + echo "\r\n"; + foreach ($profiles as &$p) { + $values = Outlook::profile_to_contact(&$p); + foreach ($fields as $i => $k) { + if ($i != 0) { + echo ','; + echo Outlook::protect($values[$k]); + } else { + // HACK to fix fullname + echo Outlook::protect($p->firstName()." ".$p->lastName()); + } + } + echo "\r\n"; + } + } +} +// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: +?> diff --git a/templates/carnet/calendar.outlook.tpl b/templates/carnet/calendar.outlook.tpl new file mode 100644 index 0000000..815c6fb --- /dev/null +++ b/templates/carnet/calendar.outlook.tpl @@ -0,0 +1,32 @@ +{**************************************************************************} +{* *} +{* Copyright (C) 2003-2010 Polytechnique.org *} +{* http://opensource.polytechnique.org/ *} +{* *} +{* This program is free software; you can redistribute it and/or modify *} +{* it under the terms of the GNU General Public License as published by *} +{* the Free Software Foundation; either version 2 of the License, or *} +{* (at your option) any later version. *} +{* *} +{* This program is distributed in the hope that it will be useful, *} +{* but WITHOUT ANY WARRANTY; without even the implied warranty of *} +{* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} +{* GNU General Public License for more details. *} +{* *} +{* You should have received a copy of the GNU General Public License *} +{* along with this program; if not, write to the Free Software *} +{* Foundation, Inc., *} +{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *} +{* *} +{**************************************************************************} +{if $lang eq "en"} +"Subject","Start Date","End Date","All day event","Categories","Description","Private" +{else} +"Objet","{"Début"|utf8_decode}","Fin","{"Journée entière"|utf8_decode}","{"Catégories"|utf8_decode}","{"Privé"|utf8_decode}" +{/if} +{iterate from=$events item=e} +{foreach from=$years item=year} +"{$e.summary|addslashes|utf8_decode}","{$e.timestamp|date_format:"%m/%d/"}{$year}","{$e.timestamp|date_format:"%m/%d/"}{$year}","True","{if $lang eq +"en"}Birthday{else}Anniversaire{/if}","False" +{/foreach} +{/iterate} diff --git a/templates/carnet/mescontacts.tpl b/templates/carnet/mescontacts.tpl index 167bdcc..77a9bde 100644 --- a/templates/carnet/mescontacts.tpl +++ b/templates/carnet/mescontacts.tpl @@ -61,15 +61,23 @@ [tri par noms]
  • - {icon name=calendar_view_day title='Anniversaires'} - - Le calendrier des anniversaires + Le calendrier des anniversaires : + + {icon name=calendar_view_day title='Anniversaires au format iCal'} + + + {icon name=outlook title='Anniversaires au format Outlook'}
  • - {icon name=vcard title='Carte de visite'} - La carte de visite électronique + La carte de visite électronique : + + {icon name=vcard title='Carte de visite au format vCard'} + (sans les photos) + + {icon name=outlook title='Contacts au format Outlook'} +
  • -- 2.1.4