Closed arukado-sama closed 9 years ago
Hello :-),
Unfortunately, there is no interface on-top of sabre/dav, this is just a server. What you're looking for is “clients”, to visualize address books, calendars, task lists and files.
If you feel brave, you can try sabre/katana, which is a ready-to-use sabre/dav server with an administration interface. You will find instructions inside this interface about how to connect a client easily.
Thanks for your answer! I saw sabre-katana before, is there any possibility to edit calendars/cards without implementing a client from scratch? Like a bundle for Symfony? I'll try katana now.
What's your use-case exactly? Could you just use an off-the-shelf client such as Thunderbird and Lightning? Or does it need to be integrated into a php web application?
I'm working on a company manager called Groupware. I can use thunderbird for calendars/addressbooks, but some table views in my application require access to addressbook contacts etc.
Here is my application:
For example the "Destinataire" column requires a company card to show the name of the associated company. The database is already built, it was used in the old Egroupware and my goal is too migrate the entire project on Symfony.
The old Egroupware:
You can also see that there is a calendar link, optional if we can use thunderbird but it would be great to have a calendar interface like baikal2. In any case my company wants calendar sync.
Hi @arukado-sama ,
So there's several different ways to interact with the data. I can't tell you which is the right one, and I don't have any tutorials.
Sabre\CalDAV\Backend\PDO
. Those classes all have pretty basic apis that are relatively easy to understand. This is definitely an option for you.From a pure architectural point of view we believe that option 3 is superior, but going for option 2 allows you to get started quickly and see results pretty fast. Option 3 requires from you that you learn the protocols, and if you want to add any custom extensions, it could be a lot of extra work.
@evert thanks again for helping me. How do I have to start with option 2? I mean, did I have to override some entities and controllers? Sadly I'm beginner at Symfony too, I implemented the current database into entities and used easy-admin bundle to show and edit them. I created some controller functions, twig views and javascripts but I don't know if I can understand how sabredav backends work. Do you think I should use sabre-katana to begin with?
Alright then I misunderstood the question. You already have a database, and now you want to expose that data via sabre/dav.
In that case, look at Sabre\CalDAV\Backend\PDO and in particular Sabre\CalDAV\Backend\AbstractBackend. You need to extend that class and then use your symfony entities to return the correct data.
Closing this ticket, but feel free to ask follow-up questions in this ticket. Stackoverflow might also be useful.
Thanks, I'll try this tomorrow and tell you if I encounter any problem!
Hi!
Today I'm trying to use the company address book in Symfony. I got a vcf file which contains other companies addresses and put it in addressbooks/admin/addressbook/ on sabredav (a default address book I created). Don't know if it's the right thing to do. I extended AbstractBackend and PDO but really don't know what to do next. Can I also synchronize this address book on Thunderbird?
Thanks in advance!
EDIT: I found this tutorial http://sabre.io/dav/building-a-carddav-client/, but I don't know how to use such a language in Symfony --> Nevermind, I think it's for "option 3".
EDIT2: I tried something like this
<?php
namespace Groupware\AddressBookBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Groupware\AddressBookBundle\Entity\Backend\PDO;
class HomeController extends Controller
{
public function indexAction()
{
$pdo = new PDO();
$cards = $pdo->getCards($pdo->getAddressBooksForUser("principals/admin"));
return $this->render('GroupwareAddressBookBundle:Home:index.html.twig', array('cards' => $cards));
}
}
Without success because the PDO class requires a \PDO argument.
Hey @arukado-sama ,
Without success because the PDO class requires a \PDO argument.
Give it the \PDO argument! What's stopping you?
I don't really know what do I have to give. I tried with "new \PDO" but \PDO requires the same arguments so it will create an infinite loop. It's new for me I'm sorry I can't understand very well how it works.
No, there's two classes:
Sabre\CardDAV\Backend\PDO
, which requires a \PDO
argument.
This is what Eclipse tells me about the PDO class:
Groupware\AddressBookBundle\Entity\Backend\PDO::__construct(PDO $pdo, string $addressBooksTableName, string $cardsTableName, $addressBookChangesTableName)
I really don't know what I'm supposed to place on "PDO $pdo".
new \PDO('...dsn to your database...')
Wow, I didn't understand that. How can I retrieve the "dsn"?
In your own example, it was:
$pdo = new \PDO('mysql:dbname=groupware; host=localhost','root','haruhi');
I understand now, thanks! Do you think my vcf file is correctly placed on the server?
I think this line is also wrong:
$cards = $globalpdo->getCards($globalpdo->getAddressBooksForUser("principals/admin"));
Because I got a conversion error. I'll search how to return the address book id.
Yes it sounds correct.
Hello!
Today I'm trying to retrieve cards with the address book id, here is my current function:
public function indexAction()
{
$pdo = new \PDO('mysql:dbname=groupware; host=localhost','root','haruhi');
$globalpdo = new PDO($pdo);
$addressbooks = $globalpdo->getAddressBooksForUser("principals/admin");
$addressbook = $addressbooks[0];
$cards = $globalpdo->getCards($addressbook->id);
return $this->render('GroupwareAddressBookBundle:Home:index.html.twig', array('cards' => $cards));
}
But it returns me an error at the moment because $addressbook isn't an object. I understood that getAddressBooksForUser() returns an array with all address books, or correct me if I'm wrong.
EDIT: I think I found a fix
$cards = $globalpdo->getCards($addressbook['id']);
I'll now try to show cardData for each card.
EDIT2: I got this error
Key "cardData" for array with keys "id, uri, lastmodified, etag, size" does not exist in GroupwareAddressBookBundle:Home:index.html.twig at line 19
When I try to show the uri of the card it works: addressbook.vcf
But I can't show the data. In fact this card I retrieve isn't a Card object, it's an array, so I can't use functions from Card entity.
Finally, I successfully retrieved card data:
public function indexAction()
{
$pdo = new \PDO('mysql:dbname=groupware; host=localhost','root','haruhi');
$globalpdo = new PDO($pdo);
$addressbooks = $globalpdo->getAddressBooksForUser("principals/admin");
$addressbook = $addressbooks[0];
$cards = $globalpdo->getCards($addressbook['id']);
$card = new Card($globalpdo, $addressbook, $cards[0]);
$data = $card->get();
return $this->render('GroupwareAddressBookBundle:Home:index.html.twig', array('data' => $data));
}
Unfortunately it shows the entire raw data, I need to retrieve each field of each card but don't know how to do it. Maybe by analyze the composition of the string, seems there is a function for that in the Card entity, I'll check out next week. Thanks for helping me about this, I was totally lost before that.
Hello!
I would like to use vobject to parse,show and edit the vcf file (which contains multiple vcards) I talked about. I tried to use the tutorial (http://sabre.io/vobject/usage/) but I don't understand how to correctly parse my file. My first goal is to show all vcards in a table with a column for each property.
My vcard data is currently showing like this:
BEGIN:VCARD VERSION:2.1 ADR;WORK;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;Technoparc de l'Aubini=C3=A8re;NANTES;;44338;FRANCE CATEGORIES:Fournisseurs EMAIL;INTERNET;WORK:jbiarrotte@aplus-sa.com N:Biarrotte;Josette;;; FN:Josette Biarrotte ORG:A PLUS SYSTEME; TEL;FAX;WORK:01 69 88 97 97 TEL;WORK:02 51 13 51 79 UID:addressbook-792-e4ed915a41244c230071b9bd4a5c023d END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK:;;38, rue de Panicale;LA VERRIERE;;78320; CATEGORIES:Clients N:LE BRAS;Syvie;;; FN:Syvie LE BRAS ORG:A2L; TEL;FAX;WORK:01 30 13 36 19 TEL;WORK:01 30 13 36 00 UID:addressbook-288-e4ed915a41244c230071b9bd4a5c023d END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;5, rue Caillardi=C3=A8re;BEAUCOUZE;;49070; CATEGORIES:Clients N:;;;; FN:A2POINTS ORG:A2POINTS; TEL;WORK:02 41 22 18 18 UID:addressbook-289-e4ed915a41244c230071b9bd4a5c023d END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK:;;Rue de Docteur Weys;SAUMUR Cedex;;49428; CATEGORIES:Clients N:;;;; FN:AAS ORG:AAS; TEL;FAX;WORK:02 41 53 04 50 TEL;WORK:02 41 53 04 30 UID:addressbook-290-e4ed915a41244c230071b9bd4a5c023d END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK:;;12 rue du champ de l'aire ZI des brunelleries;Bouchemaine;;49080;FRANCE CATEGORIES;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:Fournisseur M=C3=A9canique N:Plumelet;Estelle;;Mme; FN:Mme Estelle Plumelet ORG:AB CAOUTCHOUC; TEL;FAX;WORK:02 41 35 00 21 TEL;WORK:02 41 35 00 05 UID:addressbook-1240-ae182e169161504cd6086367f677b0e3 END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK:;;C/ Travessera de les corts 346;BARCELONA;;08029;ESPAGNE CATEGORIES;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:Fournisseur M=C3=A9canique EMAIL;INTERNET;WORK:luis.abad@abbot-vault.com N:ABAD jose R;;;M.; FN:M. ABAD jose R ORG:ABBOT & VAULT; TEL;WORK;TYPE=PREF:34 93 444 82 21 UID:addressbook-291-e4ed915a41244c230071b9bd4a5c023d END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK:;;ESPAGNE BARCELONA 08036;BARCELONA;;;ESPAGNE CATEGORIES:Fournisseurs N:;ABAD BARBARA;;ABBOT & VAULT; FN:ABBOT & VAULT ABAD BARBARA ORG:ABBOT&VAULT; TEL;FAX;WORK:34 93 217 03 50 TEL;WORK:34 93 237 18 40 UID:addressbook-773-e4ed915a41244c230071b9bd4a5c023d END:VCARD BEGIN:VCARD VERSION:2.1 ADR;WORK:;;BP 102;LOCHE;;37600;FRANCE CATEGORIES:Fournisseurs EMAIL;INTERNET;WORK:pascaldavignon@abe-transfo.com N:Davignon;Pascal;;M; FN:M Pascal Davignon ORG:ABE; TEL;CELL;WORK:06 75 02 22 43 TEL;FAX;WORK:02 47 92 10 23 TEL;WORK:02 47 92 10 22 UID:addressbook-1124-e4ed915a41244c230071b9bd4a5c023d END:VCARD
etc.
Thanks in advance!
You have to try better. What did you try, where did you faill?
Also, you should not ever have vCard version 2.1 files in the database, it will cause a lot of things to break. It needs to be 3.0 or 4.0.
I'm currently importing all cards in entities. As we only have one address book for the company I think it would be more useful to have this address book implemented in card entities. Moreover I'm using the easy-admin bundle which can show entities table easier. I'll use sabre to export the data from the vcf file to create all entities the first time. Do you think it's a good idea? I already started to implement entities and a function which parse the data to create them.
Hi!
Yes that sounds pretty reasonable to me.
Hi!
Thanks to your documentation my calendar sync is now working with Thunderbird and sabredav. Unfortunately with the same method I can't sync Tunderbird with my address book, I think it's a bug but not sure. For now I successfully created entities for vcards on Symfony and I can export them to .vcf files. Now I'm trying to retrieve all the data from the current 2.1 vcf file (the one on the sabredav server) to create associated vcard entities, then export them into 4.0 vcards on the server (to synchronize Symfony entities with the sabredav address book, I guess I'll need a Symfony sync service). I don't really know how to correctly retrieve all information, I will have to analyze all lines. Here is my current test function (to see how the data is retrieved):
public function saveToDatabase()
{
$pdo = new \PDO('mysql:dbname=groupware; host=localhost','root','haruhi');
$globalpdo = new PDO($pdo);
$addressbooks = $globalpdo->getAddressBooksForUser("principals/admin");
$addressbook = $addressbooks[0];
$cards = $globalpdo->getCards($addressbook['id']);
$card = new Card($globalpdo, $addressbook, $cards[0]);
$data = $card->get();
$i=0;
while(strlen($data) > 20)
// while($i<10)
{
$vcard = VObject\Reader::read($data, VObject\Reader::OPTION_FORGIVING);
$vcard->convert(VObject\Document::VCARD40);
echo "name :".$vcard->N."<br/>";
echo "name :".$vcard->FN."<br/>";
echo "title :".$vcard->TITLE."<br/>";
if(isset($vcard->TEL))
{
foreach($vcard->TEL as $tel)
{
//print_r($tel, false);
echo 'Phone number: ', $tel, "<br/>";
}
echo 'Phone number: ', $vcard->TEL, "<br/>";
}
$data = substr($data, strpos($data, "END:VCARD") + 10);
$i++;
}
return $card->get();
}
Don't know if the 4.0 conversion is really needed here. I understood that there are different types of phone numbers, home, work, voice, etc. I'll try to parse the data (to eliminate semicolons), right now I don't know how to do it because I only did it in java with the "scanner" class. I'll search alone for now but if you have time and want to help me a little I'll be very grateful. Anyway thanks again for your help, I should be totally lost without you but now I can see the light at the end of the tunnel.
Hello!
I successfully converted my huge 2.1 vcard in a 3.0 vcard, using a plugin on ThunderBird. I'm trying to retrieve parameters for each field of a vcard, without success. As you saw above I'm using $vcard->fieldname. I also tested with $vcard->__get("fieldname"). Unfortunately none of these commands can return parameters such as "WORK". For example I can retrieve all phone numbers with a foreach($vcard->TEL as $num) but without parameters I can't create vcard entities with it. Is it possible to retrieve parameters for each field? Is it also possible to parse address, name, etc?
Thanks in advance.
In fact I missed this documentation, I was looking in the CardDAV section. I'll try it today, thanks again!
I'm encountering a problem when I try to retrieve parameters from telephone numbers. Here is my function to implement a VCard entity (in my database) retrieving sabredav address book:
public function saveToDatabase()
{
$pdo = new \PDO('mysql:dbname=groupware; host=localhost','root','haruhi');
$globalpdo = new PDO($pdo);
$addressbooks = $globalpdo->getAddressBooksForUser("principals/admin");
$addressbook = $addressbooks[0];
$cards = $globalpdo->getCards($addressbook['id']);
$card = new Card($globalpdo, $addressbook, $cards[0]);
$data = $card->get();
$i=0;
while($i<1) // set to 1 to test with only 1 vcard from the remote address book
{
$newcard = new VCard();
$vcard = VObject\Reader::read($data, VObject\Reader::OPTION_FORGIVING);
$newcard->setFirstName("test2");
$newcard->setLastName("test2");
if($vcard->CATEGORIES)
{
$em = $this->getDoctrine()->getManager();
$categ = $em->getRepository('GroupwareAddressBookBundle:VCardCategorie');
$CAT = str_replace(";", "", (string)$vcard->CATEGORIES);
if(($CAT == "Clients")||($CAT == "Client"))
$newcard->setCat($categ->find(1));
if(($CAT == "Fournisseurs")||($CAT == "Fournisseur"))
$newcard->setCat($categ->find(2));
if(($CAT == "Clients/Fournisseurs")||($CAT == "Client / Fournisseur"))
$newcard->setCat($categ->find(3));
if(($CAT == "Fournisseur Mécanique")||($CAT == "Fournisseur mécanique"))
$newcard->setCat($categ->find(4));
}
if($vcard->EMAIL)
{
$EMAIL = str_replace(";", "", (string)$vcard->EMAIL);
$newcard->setMail($EMAIL);
}
if($vcard->ORG)
{
$ORG = str_replace(";", "", (string)$vcard->ORG);
$newcard->setOrg($ORG);
}
if($vcard->URL)
{
$URL = str_replace(";", "", (string)$vcard->URL);
$newcard->setUrl($URL);
}
if($vcard->NOTE)
{
$NOTE = str_replace(";", "", (string)$vcard->NOTE);
$newcard->setUrl($NOTE);
}
$em = $this->getDoctrine()->getManager();
$em->persist($newcard);
$em->flush();
if($vcard->TEL)
{
$ncard = $em->getRepository('GroupwareAddressBookBundle:VCard');
foreach($vcard->TEL as $tel)
{
$phone = new VCardTel();
$em = $this->getDoctrine()->getManager();
$type = $em->getRepository('GroupwareAddressBookBundle:VCardType');
$phone->setVCardId($ncard->find($newcard->getId()));
if($param = $tel['TYPE'])
{
foreach($param as $value)
{
if($value == "WORK") $phone->setType($type->find(1));
if($value == "HOME") $phone->setType($type->find(2));
if($value == "TEXT") $phone->setTypeText(true);
if($value == "VOICE") $phone->setTypeVoice(true);
if($value == "CELL") $phone->setTypeCell(true);
if($value == "FAX") $phone->setTypeFax(true);
if($value == "PAGER") $phone->setTypePager(true);
if($value == "VIDEO") $phone->setTypeVideo(true);
if($value == "TEXTPHONE") $phone->setTypeTextphone(true);
}
}
if(!$phone->getTypeText()) $phone->setTypeText(false);
if(!$phone->getTypeVoice()) $phone->setTypeVoice(false);
if(!$phone->getTypeCell()) $phone->setTypeCell(false);
if(!$phone->getTypeFax()) $phone->setTypeFax(false);
if(!$phone->getTypePager()) $phone->setTypePager(false);
if(!$phone->getTypeVideo()) $phone->setTypeVideo(false);
if(!$phone->getTypeTextphone()) $phone->setTypeTextphone(false);
$phone->setNumber((string)$tel);
$em->persist($phone);
$em->flush();
}
}
$data = substr($data, strpos($data, "END:VCARD") + 10);
$i++;
}
return $this->render('GroupwareAddressBookBundle:Home:index.html.twig');
}
It works but when the telephone number has more than 1 parameter, for example "WORK, VOICE", only the first is saved in the database, as if my foreach didn't work. VCardTel is the telephone number entity which is associated to a VCard with VCardId.
Here is an example of this error, the VOICE parameter isn't added in my entity, and strangely the second number gets the WORK (Travail) attribute but it only has the FAX attribute on the card:
I tried to echo $value and this it what it returned: FAX WORK WORK
Nevermind, I found the problem.
Here is the 2.1 vcard:
BEGIN:VCARD
VERSION:2.1
ADR;WORK;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;2 Avenue des Am=C3=A9thystes;NANTES;;44338;FRANCE
CATEGORIES:Fournisseurs
EMAIL;INTERNET;WORK:jbiarrotte@aplus-sa.com
N:Biarrotte;Josette;;;
FN:Josette Biarrotte
ORG:A PLUS SYSTEME;
TEL;FAX;WORK:01 69 88 97 97
TEL;WORK:02 51 13 51 79
END:VCARD
And here is the 3.0:
BEGIN:VCARD
VERSION:3.0
N;CHARSET=UTF-8:Biarrotte;Josette
FN;CHARSET=UTF-8:Josette Biarrotte
ORG;CHARSET=UTF-8:A PLUS SYSTEME;
ADR;TYPE=WORK,POSTAL;CHARSET=UTF-8:;;2 Avenue des Améthystes;NANTES;;44338;FRANCE
TEL;TYPE=WORK,VOICE:02 51 13 51 79
TEL;TYPE=FAX:01 69 88 97 97
EMAIL;TYPE=PREF,INTERNET:jbiarrotte@aplus-sa.com
CATEGORIES;CHARSET=UTF-8:Fournisseurs
END:VCARD
As you can see types are different, I have no idea what is causing this but I think the ThunderBird conversion isn't perfect at all. Problem resolved.
Hello!
I just installed sabredav on my Symfony project and I'm still a beginner. I wonder how can I add an interface for caldav/carddav (view/modify cards and calendars) in my application using sabredav. Is there any tutorial to create such an interface? I tested baikal but since the last update it doesn't work for me (error 403). I would like to directly show/modify calendars and address books in my application or in a pre-built interface.
Here is my sabredav serveur:
My server currently looks like this:
Thanks in advance!