vobject icon indicating copy to clipboard operation
vobject copied to clipboard

Updating a telefone number with specific type

Open christophdb opened this issue 7 years ago • 4 comments

Hi everybody,

I have a vcard with: TEL;TYPE=work:+49 123 TEL;TYPE=home:+49 234 TEL;TYPE=cell:+49 345

I know that I can delete the object with: unset($vcard->TEL);

I know that I can walk through the elements with: foreach($vcard->TEL as $tel) echo $tel['TYPE'] .": ". $tel;

But how can I update for example only the telefonenumber with type="home". I checked the functions in the Component.php but I can not figure out how it works...

Is it necessary to save all elements, unset the complete TEL Object and then to recreate it with the other objects? Is there a simpler way?

Can anybody help me? Best regards Christoph

christophdb avatar Jun 19 '17 13:06 christophdb

Hi again, I made some progress, but I am still not happy with it. So please give me feedback if my code could be simplified.

Here is my vcard:

BEGIN:VCARD VERSION:3.0 PRODID:-//Inverse inc.//SOGo Connector 1.0//EN UID:C790FF67-B850-0001-36F9-11D11E30E490.vcf N:adfadf;ABCDE;;; FN:ABCDE adfadf ORG:Company XYZ;Abteilung TEL;TYPE=work:123 TEL;TYPE=home:234 TEL;TYPE=cell:34 END:VCARD

Now I want to update only the TEL;TYPE=home Number. As Evert Pot writes in the docs it is never a good idea to delete entries and to recreate because it could delete customer data. So how can I update this single value?

First I thought it would be simple as: $vcard->{'TEL;TYPE=home'} but unfortunately that is not working.

Adding like $vcard->add('TEL', '234234234', ['TYPE' => 'home']) is also not working because it adds another entry without deleting the old one.

Now I use the following code:

   <?php
   // check if there is a TEL-entry. If not, just add it.
if ( !isset($vcard->TEL ) ){
	$vcard->add('TEL', '234234234', ['type' => 'home']);
}
else{
	
	// load old values
	foreach($vcard->TEL as $tel)
		$tmp['tel'][(string)$tel['TYPE']] = $tel;
	
	// write my values
	$tmp['tel']['work'] = "234234234";

            // delete all TEL-entries
	unset($vcard->TEL);

            // write new tel-entries
	foreach($tmp['tel'] as $key => $value)
		$vcard->add('TEL', $value, ['type' => $key]);
}

is there no simpler way? If I even think further to vcard->ADR it gets even more complecated because I have multiple parts as value... Is there no simpler way? Best regards Christoph

christophdb avatar Jun 20 '17 14:06 christophdb

Hi Christoph,

Here's a simple way using loops:

foreach($vcard->TEL as $tel) {
  if (!$tel['TYPE']->has('home')) {
    continue;
  }
  $tel->setValue('234234234');
}

This ensures this works correctly if home is uppercase (HOME) but also if there's more than one TYPE on a single property. Note that if there's more than 1 phone number that has TYPE=HOME, all of them will be updated.

This can be simplified further using:

$vcard->getByType('TEL','HOME')->setValue('234234234');

Note that getByType will only return 1 item. If there's more than one phone numbers with TYPE=HOME, only the first will be returned.

evert avatar Jun 20 '17 14:06 evert

Here's a simple way using loops:

I guess the IF is missing negation.

staabm avatar Jun 20 '17 14:06 staabm

Fixed!

evert avatar Jun 20 '17 14:06 evert