1<?php 2 3namespace Sabre\VObject\Component; 4 5use Sabre\VObject; 6 7class VCardTest extends \PHPUnit_Framework_TestCase { 8 9 /** 10 * @dataProvider validateData 11 */ 12 function testValidate($input, $expectedWarnings, $expectedRepairedOutput) { 13 14 $vcard = VObject\Reader::read($input); 15 16 $warnings = $vcard->validate(); 17 18 $warnMsg = array(); 19 foreach($warnings as $warning) { 20 $warnMsg[] = $warning['message']; 21 } 22 23 $this->assertEquals($expectedWarnings, $warnMsg); 24 25 $vcard->validate(VObject\Component::REPAIR); 26 27 $this->assertEquals( 28 $expectedRepairedOutput, 29 $vcard->serialize() 30 ); 31 32 } 33 34 public function validateData() { 35 36 $tests = array(); 37 38 // Correct 39 $tests[] = array( 40 "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n", 41 array(), 42 "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n", 43 ); 44 45 // No VERSION 46 $tests[] = array( 47 "BEGIN:VCARD\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n", 48 array( 49 'VERSION MUST appear exactly once in a VCARD component', 50 ), 51 "BEGIN:VCARD\r\nVERSION:3.0\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n", 52 ); 53 54 // Unknown version 55 $tests[] = array( 56 "BEGIN:VCARD\r\nVERSION:2.2\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n", 57 array( 58 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.', 59 ), 60 "BEGIN:VCARD\r\nVERSION:2.1\r\nFN:John Doe\r\nUID:foo\r\nEND:VCARD\r\n", 61 ); 62 63 // No FN 64 $tests[] = array( 65 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nEND:VCARD\r\n", 66 array( 67 'The FN property must appear in the VCARD component exactly 1 time', 68 ), 69 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nEND:VCARD\r\n", 70 ); 71 // No FN, N fallback 72 $tests[] = array( 73 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;John;;;;;\r\nEND:VCARD\r\n", 74 array( 75 'The FN property must appear in the VCARD component exactly 1 time', 76 ), 77 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;John;;;;;\r\nFN:John Doe\r\nEND:VCARD\r\n", 78 ); 79 // No FN, N fallback, no first name 80 $tests[] = array( 81 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;;;;;;\r\nEND:VCARD\r\n", 82 array( 83 'The FN property must appear in the VCARD component exactly 1 time', 84 ), 85 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nN:Doe;;;;;;\r\nFN:Doe\r\nEND:VCARD\r\n", 86 ); 87 88 // No FN, ORG fallback 89 $tests[] = array( 90 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nORG:Acme Co.\r\nEND:VCARD\r\n", 91 array( 92 'The FN property must appear in the VCARD component exactly 1 time', 93 ), 94 "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:foo\r\nORG:Acme Co.\r\nFN:Acme Co.\r\nEND:VCARD\r\n", 95 ); 96 return $tests; 97 98 } 99 100 function testGetDocumentType() { 101 102 $vcard = new VCard(array(), false); 103 $vcard->VERSION = '2.1'; 104 $this->assertEquals(VCard::VCARD21, $vcard->getDocumentType()); 105 106 $vcard = new VCard(array(), false); 107 $vcard->VERSION = '3.0'; 108 $this->assertEquals(VCard::VCARD30, $vcard->getDocumentType()); 109 110 $vcard = new VCard(array(), false); 111 $vcard->VERSION = '4.0'; 112 $this->assertEquals(VCard::VCARD40, $vcard->getDocumentType()); 113 114 $vcard = new VCard(array(), false); 115 $this->assertEquals(VCard::UNKNOWN, $vcard->getDocumentType()); 116 } 117 118 function testPreferredNoPref() { 119 120 $vcard = <<<VCF 121BEGIN:VCARD 122VERSION:3.0 123EMAIL:1@example.org 124EMAIL:2@example.org 125END:VCARD 126VCF; 127 128 $vcard = VObject\Reader::read($vcard); 129 $this->assertEquals('1@example.org', $vcard->preferred('EMAIL')->getValue()); 130 131 } 132 133 function testPreferredWithPref() { 134 135 $vcard = <<<VCF 136BEGIN:VCARD 137VERSION:3.0 138EMAIL:1@example.org 139EMAIL;TYPE=PREF:2@example.org 140END:VCARD 141VCF; 142 143 $vcard = VObject\Reader::read($vcard); 144 $this->assertEquals('2@example.org', $vcard->preferred('EMAIL')->getValue()); 145 146 } 147 148 function testPreferredWith40Pref() { 149 150 $vcard = <<<VCF 151BEGIN:VCARD 152VERSION:4.0 153EMAIL:1@example.org 154EMAIL;PREF=3:2@example.org 155EMAIL;PREF=2:3@example.org 156END:VCARD 157VCF; 158 159 $vcard = VObject\Reader::read($vcard); 160 $this->assertEquals('3@example.org', $vcard->preferred('EMAIL')->getValue()); 161 162 } 163 164 function testPreferredNotFound() { 165 166 $vcard = <<<VCF 167BEGIN:VCARD 168VERSION:4.0 169END:VCARD 170VCF; 171 172 $vcard = VObject\Reader::read($vcard); 173 $this->assertNull($vcard->preferred('EMAIL')); 174 175 } 176 177 function testNoUIDCardDAV() { 178 179 $vcard = <<<VCF 180BEGIN:VCARD 181VERSION:4.0 182FN:John Doe 183END:VCARD 184VCF; 185 $this->assertValidate( 186 $vcard, 187 VCARD::PROFILE_CARDDAV, 188 3, 189 'vCards on CardDAV servers MUST have a UID property.' 190 ); 191 192 } 193 194 function testNoUIDNoCardDAV() { 195 196 $vcard = <<<VCF 197BEGIN:VCARD 198VERSION:4.0 199FN:John Doe 200END:VCARD 201VCF; 202 $this->assertValidate( 203 $vcard, 204 0, 205 2, 206 'Adding a UID to a vCard property is recommended.' 207 ); 208 209 } 210 function testNoUIDNoCardDAVRepair() { 211 212 $vcard = <<<VCF 213BEGIN:VCARD 214VERSION:4.0 215FN:John Doe 216END:VCARD 217VCF; 218 $this->assertValidate( 219 $vcard, 220 VCARD::REPAIR, 221 1, 222 'Adding a UID to a vCard property is recommended.' 223 ); 224 225 } 226 227 function testVCard21CardDAV() { 228 229 $vcard = <<<VCF 230BEGIN:VCARD 231VERSION:2.1 232FN:John Doe 233UID:foo 234END:VCARD 235VCF; 236 $this->assertValidate( 237 $vcard, 238 VCARD::PROFILE_CARDDAV, 239 3, 240 'CardDAV servers are not allowed to accept vCard 2.1.' 241 ); 242 243 } 244 245 function testVCard21NoCardDAV() { 246 247 $vcard = <<<VCF 248BEGIN:VCARD 249VERSION:2.1 250FN:John Doe 251UID:foo 252END:VCARD 253VCF; 254 $this->assertValidate( 255 $vcard, 256 0, 257 0 258 ); 259 260 } 261 262 function assertValidate($vcf, $options, $expectedLevel, $expectedMessage = null) { 263 264 $vcal = VObject\Reader::read($vcf); 265 $result = $vcal->validate($options); 266 267 $this->assertValidateResult($result, $expectedLevel, $expectedMessage); 268 269 } 270 271 function assertValidateResult($input, $expectedLevel, $expectedMessage = null) { 272 273 $messages = array(); 274 foreach($input as $warning) { 275 $messages[] = $warning['message']; 276 } 277 278 if ($expectedLevel === 0) { 279 $this->assertEquals(0, count($input), 'No validation messages were expected. We got: ' . implode(', ', $messages)); 280 } else { 281 $this->assertEquals(1, count($input), 'We expected exactly 1 validation message, We got: ' . implode(', ', $messages)); 282 283 $this->assertEquals($expectedMessage, $input[0]['message']); 284 $this->assertEquals($expectedLevel, $input[0]['level']); 285 } 286 287 } 288} 289