1<?php
2
3namespace Sabre\VObject;
4
5use Sabre\VObject\Component\VCalendar;
6use Sabre\VObject\Component\VCard;
7
8class ComponentTest extends \PHPUnit_Framework_TestCase {
9
10    function testIterate() {
11
12        $comp = new VCalendar([], false);
13
14        $sub = $comp->createComponent('VEVENT');
15        $comp->add($sub);
16
17        $sub = $comp->createComponent('VTODO');
18        $comp->add($sub);
19
20        $count = 0;
21        foreach ($comp->children() as $key => $subcomponent) {
22
23           $count++;
24           $this->assertInstanceOf('Sabre\\VObject\\Component', $subcomponent);
25
26        }
27        $this->assertEquals(2, $count);
28        $this->assertEquals(1, $key);
29
30    }
31
32    function testMagicGet() {
33
34        $comp = new VCalendar([], false);
35
36        $sub = $comp->createComponent('VEVENT');
37        $comp->add($sub);
38
39        $sub = $comp->createComponent('VTODO');
40        $comp->add($sub);
41
42        $event = $comp->vevent;
43        $this->assertInstanceOf('Sabre\\VObject\\Component', $event);
44        $this->assertEquals('VEVENT', $event->name);
45
46        $this->assertInternalType('null', $comp->vjournal);
47
48    }
49
50    function testMagicGetGroups() {
51
52        $comp = new VCard();
53
54        $sub = $comp->createProperty('GROUP1.EMAIL', '1@1.com');
55        $comp->add($sub);
56
57        $sub = $comp->createProperty('GROUP2.EMAIL', '2@2.com');
58        $comp->add($sub);
59
60        $sub = $comp->createProperty('EMAIL', '3@3.com');
61        $comp->add($sub);
62
63        $emails = $comp->email;
64        $this->assertEquals(3, count($emails));
65
66        $email1 = $comp->{"group1.email"};
67        $this->assertEquals('EMAIL', $email1[0]->name);
68        $this->assertEquals('GROUP1', $email1[0]->group);
69
70        $email3 = $comp->{".email"};
71        $this->assertEquals('EMAIL', $email3[0]->name);
72        $this->assertEquals(null, $email3[0]->group);
73
74    }
75
76    function testMagicIsset() {
77
78        $comp = new VCalendar();
79
80        $sub = $comp->createComponent('VEVENT');
81        $comp->add($sub);
82
83        $sub = $comp->createComponent('VTODO');
84        $comp->add($sub);
85
86        $this->assertTrue(isset($comp->vevent));
87        $this->assertTrue(isset($comp->vtodo));
88        $this->assertFalse(isset($comp->vjournal));
89
90    }
91
92    function testMagicSetScalar() {
93
94        $comp = new VCalendar();
95        $comp->myProp = 'myValue';
96
97        $this->assertInstanceOf('Sabre\\VObject\\Property', $comp->MYPROP);
98        $this->assertEquals('myValue', (string)$comp->MYPROP);
99
100
101    }
102
103    function testMagicSetScalarTwice() {
104
105        $comp = new VCalendar([], false);
106        $comp->myProp = 'myValue';
107        $comp->myProp = 'myValue';
108
109        $this->assertEquals(1, count($comp->children()));
110        $this->assertInstanceOf('Sabre\\VObject\\Property', $comp->MYPROP);
111        $this->assertEquals('myValue', (string)$comp->MYPROP);
112
113    }
114
115    function testMagicSetArray() {
116
117        $comp = new VCalendar();
118        $comp->ORG = ['Acme Inc', 'Section 9'];
119
120        $this->assertInstanceOf('Sabre\\VObject\\Property', $comp->ORG);
121        $this->assertEquals(['Acme Inc', 'Section 9'], $comp->ORG->getParts());
122
123    }
124
125    function testMagicSetComponent() {
126
127        $comp = new VCalendar();
128
129        // Note that 'myProp' is ignored here.
130        $comp->myProp = $comp->createComponent('VEVENT');
131
132        $this->assertEquals(1, count($comp));
133
134        $this->assertEquals('VEVENT', $comp->VEVENT->name);
135
136    }
137
138    function testMagicSetTwice() {
139
140        $comp = new VCalendar([], false);
141
142        $comp->VEVENT = $comp->createComponent('VEVENT');
143        $comp->VEVENT = $comp->createComponent('VEVENT');
144
145        $this->assertEquals(1, count($comp->children()));
146
147        $this->assertEquals('VEVENT', $comp->VEVENT->name);
148
149    }
150
151    function testArrayAccessGet() {
152
153        $comp = new VCalendar([], false);
154
155        $event = $comp->createComponent('VEVENT');
156        $event->summary = 'Event 1';
157
158        $comp->add($event);
159
160        $event2 = clone $event;
161        $event2->summary = 'Event 2';
162
163        $comp->add($event2);
164
165        $this->assertEquals(2, count($comp->children()));
166        $this->assertTrue($comp->vevent[1] instanceof Component);
167        $this->assertEquals('Event 2', (string)$comp->vevent[1]->summary);
168
169    }
170
171    function testArrayAccessExists() {
172
173        $comp = new VCalendar();
174
175        $event = $comp->createComponent('VEVENT');
176        $event->summary = 'Event 1';
177
178        $comp->add($event);
179
180        $event2 = clone $event;
181        $event2->summary = 'Event 2';
182
183        $comp->add($event2);
184
185        $this->assertTrue(isset($comp->vevent[0]));
186        $this->assertTrue(isset($comp->vevent[1]));
187
188    }
189
190    /**
191     * @expectedException LogicException
192     */
193    function testArrayAccessSet() {
194
195        $comp = new VCalendar();
196        $comp['hey'] = 'hi there';
197
198    }
199    /**
200     * @expectedException LogicException
201     */
202    function testArrayAccessUnset() {
203
204        $comp = new VCalendar();
205        unset($comp[0]);
206
207    }
208
209    function testAddScalar() {
210
211        $comp = new VCalendar([], false);
212
213        $comp->add('myprop', 'value');
214
215        $this->assertEquals(1, count($comp->children()));
216
217        $bla = $comp->children()[0];
218
219        $this->assertTrue($bla instanceof Property);
220        $this->assertEquals('MYPROP', $bla->name);
221        $this->assertEquals('value', (string)$bla);
222
223    }
224
225    function testAddScalarParams() {
226
227        $comp = new VCalendar([], false);
228
229        $comp->add('myprop', 'value', ['param1' => 'value1']);
230
231        $this->assertEquals(1, count($comp->children()));
232
233        $bla = $comp->children()[0];
234
235        $this->assertInstanceOf('Sabre\\VObject\\Property', $bla);
236        $this->assertEquals('MYPROP', $bla->name);
237        $this->assertEquals('value', (string)$bla);
238
239        $this->assertEquals(1, count($bla->parameters()));
240
241        $this->assertEquals('PARAM1', $bla->parameters['PARAM1']->name);
242        $this->assertEquals('value1', $bla->parameters['PARAM1']->getValue());
243
244    }
245
246
247    function testAddComponent() {
248
249        $comp = new VCalendar([], false);
250
251        $comp->add($comp->createComponent('VEVENT'));
252
253        $this->assertEquals(1, count($comp->children()));
254
255        $this->assertEquals('VEVENT', $comp->VEVENT->name);
256
257    }
258
259    function testAddComponentTwice() {
260
261        $comp = new VCalendar([], false);
262
263        $comp->add($comp->createComponent('VEVENT'));
264        $comp->add($comp->createComponent('VEVENT'));
265
266        $this->assertEquals(2, count($comp->children()));
267
268        $this->assertEquals('VEVENT', $comp->VEVENT->name);
269
270    }
271
272    /**
273     * @expectedException InvalidArgumentException
274     */
275    function testAddArgFail() {
276
277        $comp = new VCalendar();
278        $comp->add($comp->createComponent('VEVENT'), 'hello');
279
280    }
281
282    /**
283     * @expectedException InvalidArgumentException
284     */
285    function testAddArgFail2() {
286
287        $comp = new VCalendar();
288        $comp->add([]);
289
290    }
291
292    function testMagicUnset() {
293
294        $comp = new VCalendar([], false);
295        $comp->add($comp->createComponent('VEVENT'));
296
297        unset($comp->vevent);
298
299        $this->assertEquals(0, count($comp->children()));
300
301    }
302
303
304    function testCount() {
305
306        $comp = new VCalendar();
307        $this->assertEquals(1, $comp->count());
308
309    }
310
311    function testChildren() {
312
313        $comp = new VCalendar([], false);
314
315        // Note that 'myProp' is ignored here.
316        $comp->add($comp->createComponent('VEVENT'));
317        $comp->add($comp->createComponent('VTODO'));
318
319        $r = $comp->children();
320        $this->assertInternalType('array', $r);
321        $this->assertEquals(2, count($r));
322    }
323
324    function testGetComponents() {
325
326        $comp = new VCalendar();
327
328        $comp->add($comp->createProperty('FOO', 'BAR'));
329        $comp->add($comp->createComponent('VTODO'));
330
331        $r = $comp->getComponents();
332        $this->assertInternalType('array', $r);
333        $this->assertEquals(1, count($r));
334        $this->assertEquals('VTODO', $r[0]->name);
335    }
336
337    function testSerialize() {
338
339        $comp = new VCalendar([], false);
340        $this->assertEquals("BEGIN:VCALENDAR\r\nEND:VCALENDAR\r\n", $comp->serialize());
341
342    }
343
344    function testSerializeChildren() {
345
346        $comp = new VCalendar([], false);
347        $event = $comp->add($comp->createComponent('VEVENT'));
348        unset($event->DTSTAMP, $event->UID);
349        $todo = $comp->add($comp->createComponent('VTODO'));
350        unset($todo->DTSTAMP, $todo->UID);
351
352        $str = $comp->serialize();
353
354        $this->assertEquals("BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nBEGIN:VTODO\r\nEND:VTODO\r\nEND:VCALENDAR\r\n", $str);
355
356    }
357
358    function testSerializeOrderCompAndProp() {
359
360        $comp = new VCalendar([], false);
361        $comp->add($event = $comp->createComponent('VEVENT'));
362        $comp->add('PROP1', 'BLABLA');
363        $comp->add('VERSION', '2.0');
364        $comp->add($comp->createComponent('VTIMEZONE'));
365
366        unset($event->DTSTAMP, $event->UID);
367        $str = $comp->serialize();
368
369        $this->assertEquals("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPROP1:BLABLA\r\nBEGIN:VTIMEZONE\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", $str);
370
371    }
372
373    function testAnotherSerializeOrderProp() {
374
375        $prop4s = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
376
377        $comp = new VCard([], false);
378
379        $comp->__set('SOMEPROP', 'FOO');
380        $comp->__set('ANOTHERPROP', 'FOO');
381        $comp->__set('THIRDPROP', 'FOO');
382        foreach ($prop4s as $prop4) {
383            $comp->add('PROP4', 'FOO ' . $prop4);
384        }
385        $comp->__set('PROPNUMBERFIVE', 'FOO');
386        $comp->__set('PROPNUMBERSIX', 'FOO');
387        $comp->__set('PROPNUMBERSEVEN', 'FOO');
388        $comp->__set('PROPNUMBEREIGHT', 'FOO');
389        $comp->__set('PROPNUMBERNINE', 'FOO');
390        $comp->__set('PROPNUMBERTEN', 'FOO');
391        $comp->__set('VERSION', '2.0');
392        $comp->__set('UID', 'FOO');
393
394        $str = $comp->serialize();
395
396        $this->assertEquals("BEGIN:VCARD\r\nVERSION:2.0\r\nSOMEPROP:FOO\r\nANOTHERPROP:FOO\r\nTHIRDPROP:FOO\r\nPROP4:FOO 1\r\nPROP4:FOO 2\r\nPROP4:FOO 3\r\nPROP4:FOO 4\r\nPROP4:FOO 5\r\nPROP4:FOO 6\r\nPROP4:FOO 7\r\nPROP4:FOO 8\r\nPROP4:FOO 9\r\nPROP4:FOO 10\r\nPROPNUMBERFIVE:FOO\r\nPROPNUMBERSIX:FOO\r\nPROPNUMBERSEVEN:FOO\r\nPROPNUMBEREIGHT:FOO\r\nPROPNUMBERNINE:FOO\r\nPROPNUMBERTEN:FOO\r\nUID:FOO\r\nEND:VCARD\r\n", $str);
397
398    }
399
400    function testInstantiateWithChildren() {
401
402        $comp = new VCard([
403            'ORG' => ['Acme Inc.', 'Section 9'],
404            'FN'  => 'Finn The Human',
405        ]);
406
407        $this->assertEquals(['Acme Inc.', 'Section 9'], $comp->ORG->getParts());
408        $this->assertEquals('Finn The Human', $comp->FN->getValue());
409
410    }
411
412    function testInstantiateSubComponent() {
413
414        $comp = new VCalendar();
415        $event = $comp->createComponent('VEVENT', [
416            $comp->createProperty('UID', '12345'),
417        ]);
418        $comp->add($event);
419
420        $this->assertEquals('12345', $comp->VEVENT->UID->getValue());
421
422    }
423
424    function testRemoveByName() {
425
426        $comp = new VCalendar([], false);
427        $comp->add('prop1', 'val1');
428        $comp->add('prop2', 'val2');
429        $comp->add('prop2', 'val2');
430
431        $comp->remove('prop2');
432        $this->assertFalse(isset($comp->prop2));
433        $this->assertTrue(isset($comp->prop1));
434
435    }
436
437    function testRemoveByObj() {
438
439        $comp = new VCalendar([], false);
440        $comp->add('prop1', 'val1');
441        $prop = $comp->add('prop2', 'val2');
442
443        $comp->remove($prop);
444        $this->assertFalse(isset($comp->prop2));
445        $this->assertTrue(isset($comp->prop1));
446
447    }
448
449    /**
450     * @expectedException InvalidArgumentException
451     */
452    function testRemoveNotFound() {
453
454        $comp = new VCalendar([], false);
455        $prop = $comp->createProperty('A', 'B');
456        $comp->remove($prop);
457
458    }
459
460    /**
461     * @dataProvider ruleData
462     */
463    function testValidateRules($componentList, $errorCount) {
464
465        $vcard = new Component\VCard();
466
467        $component = new FakeComponent($vcard, 'Hi', [], $defaults = false);
468        foreach ($componentList as $v) {
469            $component->add($v, 'Hello.');
470        }
471
472        $this->assertEquals($errorCount, count($component->validate()));
473
474    }
475
476    function testValidateRepair() {
477
478        $vcard = new Component\VCard();
479
480        $component = new FakeComponent($vcard, 'Hi', [], $defaults = false);
481        $component->validate(Component::REPAIR);
482        $this->assertEquals('yow', $component->BAR->getValue());
483
484    }
485
486    function ruleData() {
487
488        return [
489
490            [[], 2],
491            [['FOO'], 3],
492            [['BAR'], 1],
493            [['BAZ'], 1],
494            [['BAR','BAZ'], 0],
495            [['BAR','BAZ','ZIM',], 0],
496            [['BAR','BAZ','ZIM','GIR'], 0],
497            [['BAR','BAZ','ZIM','GIR','GIR'], 1],
498
499        ];
500
501    }
502
503}
504
505class FakeComponent extends Component {
506
507    function getValidationRules() {
508
509        return [
510            'FOO' => '0',
511            'BAR' => '1',
512            'BAZ' => '+',
513            'ZIM' => '*',
514            'GIR' => '?',
515        ];
516
517    }
518
519    function getDefaults() {
520
521        return [
522            'BAR' => 'yow',
523        ];
524
525    }
526
527}
528