Mercurial > hg > rc1
comparison vendor/sabre/vobject/tests/VObject/Component/VCalendarTest.php @ 7:430dbd5346f7
vendor sabre as distributed
author | Charlie Root |
---|---|
date | Sat, 13 Jan 2018 09:06:10 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
6:cec75ba50afc | 7:430dbd5346f7 |
---|---|
1 <?php | |
2 | |
3 namespace Sabre\VObject\Component; | |
4 | |
5 use DateTimeZone; | |
6 use Sabre\VObject; | |
7 | |
8 class VCalendarTest extends \PHPUnit_Framework_TestCase { | |
9 | |
10 /** | |
11 * @dataProvider expandData | |
12 */ | |
13 public function testExpand($input, $output, $timeZone = 'UTC', $start = '2011-12-01', $end = '2011-12-31') { | |
14 | |
15 $vcal = VObject\Reader::read($input); | |
16 | |
17 $timeZone = new DateTimeZone($timeZone); | |
18 | |
19 $vcal->expand( | |
20 new \DateTime($start), | |
21 new \DateTime($end), | |
22 $timeZone | |
23 ); | |
24 | |
25 // This will normalize the output | |
26 $output = VObject\Reader::read($output)->serialize(); | |
27 | |
28 $this->assertEquals($output, $vcal->serialize()); | |
29 | |
30 } | |
31 | |
32 public function expandData() { | |
33 | |
34 $tests = array(); | |
35 | |
36 // No data | |
37 $input = 'BEGIN:VCALENDAR | |
38 CALSCALE:GREGORIAN | |
39 VERSION:2.0 | |
40 END:VCALENDAR | |
41 '; | |
42 | |
43 $output = $input; | |
44 $tests[] = array($input,$output); | |
45 | |
46 | |
47 // Simple events | |
48 $input = 'BEGIN:VCALENDAR | |
49 CALSCALE:GREGORIAN | |
50 VERSION:2.0 | |
51 BEGIN:VEVENT | |
52 UID:bla | |
53 SUMMARY:InExpand | |
54 DTSTART;VALUE=DATE:20111202 | |
55 END:VEVENT | |
56 BEGIN:VEVENT | |
57 UID:bla2 | |
58 SUMMARY:NotInExpand | |
59 DTSTART;VALUE=DATE:20120101 | |
60 END:VEVENT | |
61 END:VCALENDAR | |
62 '; | |
63 | |
64 $output = 'BEGIN:VCALENDAR | |
65 CALSCALE:GREGORIAN | |
66 VERSION:2.0 | |
67 BEGIN:VEVENT | |
68 UID:bla | |
69 SUMMARY:InExpand | |
70 DTSTART;VALUE=DATE:20111202 | |
71 END:VEVENT | |
72 END:VCALENDAR | |
73 '; | |
74 | |
75 $tests[] = array($input, $output); | |
76 | |
77 // Removing timezone info | |
78 $input = 'BEGIN:VCALENDAR | |
79 CALSCALE:GREGORIAN | |
80 VERSION:2.0 | |
81 BEGIN:VTIMEZONE | |
82 TZID:Europe/Paris | |
83 END:VTIMEZONE | |
84 BEGIN:VEVENT | |
85 UID:bla4 | |
86 SUMMARY:RemoveTZ info | |
87 DTSTART;TZID=Europe/Paris:20111203T130102 | |
88 END:VEVENT | |
89 END:VCALENDAR | |
90 '; | |
91 | |
92 $output = 'BEGIN:VCALENDAR | |
93 CALSCALE:GREGORIAN | |
94 VERSION:2.0 | |
95 BEGIN:VEVENT | |
96 UID:bla4 | |
97 SUMMARY:RemoveTZ info | |
98 DTSTART:20111203T120102Z | |
99 END:VEVENT | |
100 END:VCALENDAR | |
101 '; | |
102 | |
103 $tests[] = array($input, $output); | |
104 | |
105 // Recurrence rule | |
106 $input = 'BEGIN:VCALENDAR | |
107 CALSCALE:GREGORIAN | |
108 VERSION:2.0 | |
109 BEGIN:VEVENT | |
110 UID:bla6 | |
111 SUMMARY:Testing RRule | |
112 DTSTART:20111125T120000Z | |
113 DTEND:20111125T130000Z | |
114 RRULE:FREQ=WEEKLY | |
115 END:VEVENT | |
116 END:VCALENDAR | |
117 '; | |
118 | |
119 $output = 'BEGIN:VCALENDAR | |
120 CALSCALE:GREGORIAN | |
121 VERSION:2.0 | |
122 BEGIN:VEVENT | |
123 UID:bla6 | |
124 SUMMARY:Testing RRule | |
125 DTSTART:20111202T120000Z | |
126 DTEND:20111202T130000Z | |
127 RECURRENCE-ID:20111202T120000Z | |
128 END:VEVENT | |
129 BEGIN:VEVENT | |
130 UID:bla6 | |
131 SUMMARY:Testing RRule | |
132 DTSTART:20111209T120000Z | |
133 DTEND:20111209T130000Z | |
134 RECURRENCE-ID:20111209T120000Z | |
135 END:VEVENT | |
136 BEGIN:VEVENT | |
137 UID:bla6 | |
138 SUMMARY:Testing RRule | |
139 DTSTART:20111216T120000Z | |
140 DTEND:20111216T130000Z | |
141 RECURRENCE-ID:20111216T120000Z | |
142 END:VEVENT | |
143 BEGIN:VEVENT | |
144 UID:bla6 | |
145 SUMMARY:Testing RRule | |
146 DTSTART:20111223T120000Z | |
147 DTEND:20111223T130000Z | |
148 RECURRENCE-ID:20111223T120000Z | |
149 END:VEVENT | |
150 BEGIN:VEVENT | |
151 UID:bla6 | |
152 SUMMARY:Testing RRule | |
153 DTSTART:20111230T120000Z | |
154 DTEND:20111230T130000Z | |
155 RECURRENCE-ID:20111230T120000Z | |
156 END:VEVENT | |
157 END:VCALENDAR | |
158 '; | |
159 | |
160 $tests[] = array($input, $output); | |
161 | |
162 // Recurrence rule + override | |
163 $input = 'BEGIN:VCALENDAR | |
164 CALSCALE:GREGORIAN | |
165 VERSION:2.0 | |
166 BEGIN:VEVENT | |
167 UID:bla6 | |
168 SUMMARY:Testing RRule2 | |
169 DTSTART:20111125T120000Z | |
170 DTEND:20111125T130000Z | |
171 RRULE:FREQ=WEEKLY | |
172 END:VEVENT | |
173 BEGIN:VEVENT | |
174 UID:bla6 | |
175 RECURRENCE-ID:20111209T120000Z | |
176 DTSTART:20111209T140000Z | |
177 DTEND:20111209T150000Z | |
178 SUMMARY:Override! | |
179 END:VEVENT | |
180 END:VCALENDAR | |
181 '; | |
182 | |
183 $output = 'BEGIN:VCALENDAR | |
184 CALSCALE:GREGORIAN | |
185 VERSION:2.0 | |
186 BEGIN:VEVENT | |
187 UID:bla6 | |
188 SUMMARY:Testing RRule2 | |
189 DTSTART:20111202T120000Z | |
190 DTEND:20111202T130000Z | |
191 RECURRENCE-ID:20111202T120000Z | |
192 END:VEVENT | |
193 BEGIN:VEVENT | |
194 UID:bla6 | |
195 RECURRENCE-ID:20111209T120000Z | |
196 DTSTART:20111209T140000Z | |
197 DTEND:20111209T150000Z | |
198 SUMMARY:Override! | |
199 END:VEVENT | |
200 BEGIN:VEVENT | |
201 UID:bla6 | |
202 SUMMARY:Testing RRule2 | |
203 DTSTART:20111216T120000Z | |
204 DTEND:20111216T130000Z | |
205 RECURRENCE-ID:20111216T120000Z | |
206 END:VEVENT | |
207 BEGIN:VEVENT | |
208 UID:bla6 | |
209 SUMMARY:Testing RRule2 | |
210 DTSTART:20111223T120000Z | |
211 DTEND:20111223T130000Z | |
212 RECURRENCE-ID:20111223T120000Z | |
213 END:VEVENT | |
214 BEGIN:VEVENT | |
215 UID:bla6 | |
216 SUMMARY:Testing RRule2 | |
217 DTSTART:20111230T120000Z | |
218 DTEND:20111230T130000Z | |
219 RECURRENCE-ID:20111230T120000Z | |
220 END:VEVENT | |
221 END:VCALENDAR | |
222 '; | |
223 | |
224 $tests[] = array($input, $output); | |
225 | |
226 // Floating dates and times. | |
227 $input = <<<ICS | |
228 BEGIN:VCALENDAR | |
229 VERSION:2.0 | |
230 BEGIN:VEVENT | |
231 UID:bla1 | |
232 DTSTART:20141112T195000 | |
233 END:VEVENT | |
234 BEGIN:VEVENT | |
235 UID:bla2 | |
236 DTSTART;VALUE=DATE:20141112 | |
237 END:VEVENT | |
238 BEGIN:VEVENT | |
239 UID:bla3 | |
240 DTSTART;VALUE=DATE:20141112 | |
241 RRULE:FREQ=DAILY;COUNT=2 | |
242 END:VEVENT | |
243 END:VCALENDAR | |
244 ICS; | |
245 | |
246 $output = <<<ICS | |
247 BEGIN:VCALENDAR | |
248 VERSION:2.0 | |
249 BEGIN:VEVENT | |
250 UID:bla1 | |
251 DTSTART:20141112T225000Z | |
252 END:VEVENT | |
253 BEGIN:VEVENT | |
254 UID:bla2 | |
255 DTSTART;VALUE=DATE:20141112 | |
256 END:VEVENT | |
257 BEGIN:VEVENT | |
258 UID:bla3 | |
259 DTSTART;VALUE=DATE:20141112 | |
260 END:VEVENT | |
261 BEGIN:VEVENT | |
262 UID:bla3 | |
263 DTSTART;VALUE=DATE:20141113 | |
264 RECURRENCE-ID;VALUE=DATE:20141113 | |
265 END:VEVENT | |
266 END:VCALENDAR | |
267 ICS; | |
268 | |
269 $tests[] = array($input, $output, 'America/Argentina/Buenos_Aires', '2014-01-01', '2015-01-01'); | |
270 | |
271 // Recurrence rule with no valid instances | |
272 $input = 'BEGIN:VCALENDAR | |
273 CALSCALE:GREGORIAN | |
274 VERSION:2.0 | |
275 BEGIN:VEVENT | |
276 UID:bla6 | |
277 SUMMARY:Testing RRule3 | |
278 DTSTART:20111125T120000Z | |
279 DTEND:20111125T130000Z | |
280 RRULE:FREQ=WEEKLY;COUNT=1 | |
281 EXDATE:20111125T120000Z | |
282 END:VEVENT | |
283 END:VCALENDAR | |
284 '; | |
285 | |
286 $output = 'BEGIN:VCALENDAR | |
287 CALSCALE:GREGORIAN | |
288 VERSION:2.0 | |
289 END:VCALENDAR | |
290 '; | |
291 | |
292 $tests[] = array($input, $output); | |
293 return $tests; | |
294 | |
295 } | |
296 | |
297 /** | |
298 * @expectedException LogicException | |
299 */ | |
300 public function testBrokenEventExpand() { | |
301 | |
302 $input = 'BEGIN:VCALENDAR | |
303 CALSCALE:GREGORIAN | |
304 VERSION:2.0 | |
305 BEGIN:VEVENT | |
306 RRULE:FREQ=WEEKLY | |
307 DTSTART;VALUE=DATE:20111202 | |
308 END:VEVENT | |
309 END:VCALENDAR | |
310 '; | |
311 $vcal = VObject\Reader::read($input); | |
312 $vcal->expand( | |
313 new \DateTime('2011-12-01'), | |
314 new \DateTime('2011-12-31') | |
315 ); | |
316 | |
317 } | |
318 | |
319 function testGetDocumentType() { | |
320 | |
321 $vcard = new VCalendar(); | |
322 $vcard->VERSION = '2.0'; | |
323 $this->assertEquals(VCalendar::ICALENDAR20, $vcard->getDocumentType()); | |
324 | |
325 } | |
326 | |
327 function testValidateCorrect() { | |
328 | |
329 $input = 'BEGIN:VCALENDAR | |
330 CALSCALE:GREGORIAN | |
331 VERSION:2.0 | |
332 PRODID:foo | |
333 BEGIN:VEVENT | |
334 DTSTART;VALUE=DATE:20111202 | |
335 DTSTAMP:20140122T233226Z | |
336 UID:foo | |
337 END:VEVENT | |
338 END:VCALENDAR | |
339 '; | |
340 | |
341 $vcal = VObject\Reader::read($input); | |
342 $this->assertEquals(array(), $vcal->validate(), 'Got an error'); | |
343 | |
344 } | |
345 | |
346 function testValidateNoVersion() { | |
347 | |
348 $input = 'BEGIN:VCALENDAR | |
349 CALSCALE:GREGORIAN | |
350 PRODID:foo | |
351 BEGIN:VEVENT | |
352 DTSTART;VALUE=DATE:20111202 | |
353 UID:foo | |
354 DTSTAMP:20140122T234434Z | |
355 END:VEVENT | |
356 END:VCALENDAR | |
357 '; | |
358 | |
359 $vcal = VObject\Reader::read($input); | |
360 $this->assertEquals(1, count($vcal->validate())); | |
361 | |
362 } | |
363 | |
364 function testValidateWrongVersion() { | |
365 | |
366 $input = 'BEGIN:VCALENDAR | |
367 CALSCALE:GREGORIAN | |
368 VERSION:3.0 | |
369 PRODID:foo | |
370 BEGIN:VEVENT | |
371 DTSTART;VALUE=DATE:20111202 | |
372 UID:foo | |
373 DTSTAMP:20140122T234434Z | |
374 END:VEVENT | |
375 END:VCALENDAR | |
376 '; | |
377 | |
378 $vcal = VObject\Reader::read($input); | |
379 $this->assertEquals(1, count($vcal->validate())); | |
380 | |
381 } | |
382 | |
383 function testValidateNoProdId() { | |
384 | |
385 $input = 'BEGIN:VCALENDAR | |
386 CALSCALE:GREGORIAN | |
387 VERSION:2.0 | |
388 BEGIN:VEVENT | |
389 DTSTART;VALUE=DATE:20111202 | |
390 UID:foo | |
391 DTSTAMP:20140122T234434Z | |
392 END:VEVENT | |
393 END:VCALENDAR | |
394 '; | |
395 | |
396 $vcal = VObject\Reader::read($input); | |
397 $this->assertEquals(1, count($vcal->validate())); | |
398 | |
399 } | |
400 | |
401 function testValidateDoubleCalScale() { | |
402 | |
403 $input = 'BEGIN:VCALENDAR | |
404 VERSION:2.0 | |
405 PRODID:foo | |
406 CALSCALE:GREGORIAN | |
407 CALSCALE:GREGORIAN | |
408 BEGIN:VEVENT | |
409 DTSTART;VALUE=DATE:20111202 | |
410 UID:foo | |
411 DTSTAMP:20140122T234434Z | |
412 END:VEVENT | |
413 END:VCALENDAR | |
414 '; | |
415 | |
416 $vcal = VObject\Reader::read($input); | |
417 $this->assertEquals(1, count($vcal->validate())); | |
418 | |
419 } | |
420 | |
421 function testValidateDoubleMethod() { | |
422 | |
423 $input = 'BEGIN:VCALENDAR | |
424 VERSION:2.0 | |
425 PRODID:foo | |
426 METHOD:REQUEST | |
427 METHOD:REQUEST | |
428 BEGIN:VEVENT | |
429 DTSTART;VALUE=DATE:20111202 | |
430 UID:foo | |
431 DTSTAMP:20140122T234434Z | |
432 END:VEVENT | |
433 END:VCALENDAR | |
434 '; | |
435 | |
436 $vcal = VObject\Reader::read($input); | |
437 $this->assertEquals(1, count($vcal->validate())); | |
438 | |
439 } | |
440 | |
441 function testValidateTwoMasterEvents() { | |
442 | |
443 $input = 'BEGIN:VCALENDAR | |
444 VERSION:2.0 | |
445 PRODID:foo | |
446 METHOD:REQUEST | |
447 BEGIN:VEVENT | |
448 DTSTART;VALUE=DATE:20111202 | |
449 UID:foo | |
450 DTSTAMP:20140122T234434Z | |
451 END:VEVENT | |
452 BEGIN:VEVENT | |
453 DTSTART;VALUE=DATE:20111202 | |
454 UID:foo | |
455 DTSTAMP:20140122T234434Z | |
456 END:VEVENT | |
457 END:VCALENDAR | |
458 '; | |
459 | |
460 $vcal = VObject\Reader::read($input); | |
461 $this->assertEquals(1, count($vcal->validate())); | |
462 | |
463 } | |
464 | |
465 function testValidateOneMasterEvent() { | |
466 | |
467 $input = 'BEGIN:VCALENDAR | |
468 VERSION:2.0 | |
469 PRODID:foo | |
470 METHOD:REQUEST | |
471 BEGIN:VEVENT | |
472 DTSTART;VALUE=DATE:20111202 | |
473 UID:foo | |
474 DTSTAMP:20140122T234434Z | |
475 END:VEVENT | |
476 BEGIN:VEVENT | |
477 DTSTART;VALUE=DATE:20111202 | |
478 UID:foo | |
479 DTSTAMP:20140122T234434Z | |
480 RECURRENCE-ID;VALUE=DATE:20111202 | |
481 END:VEVENT | |
482 END:VCALENDAR | |
483 '; | |
484 | |
485 $vcal = VObject\Reader::read($input); | |
486 $this->assertEquals(0, count($vcal->validate())); | |
487 | |
488 } | |
489 | |
490 function testGetBaseComponent() { | |
491 | |
492 $input = 'BEGIN:VCALENDAR | |
493 VERSION:2.0 | |
494 PRODID:foo | |
495 METHOD:REQUEST | |
496 BEGIN:VEVENT | |
497 SUMMARY:test | |
498 DTSTART;VALUE=DATE:20111202 | |
499 UID:foo | |
500 DTSTAMP:20140122T234434Z | |
501 END:VEVENT | |
502 BEGIN:VEVENT | |
503 DTSTART;VALUE=DATE:20111202 | |
504 UID:foo | |
505 DTSTAMP:20140122T234434Z | |
506 RECURRENCE-ID;VALUE=DATE:20111202 | |
507 END:VEVENT | |
508 END:VCALENDAR | |
509 '; | |
510 | |
511 $vcal = VObject\Reader::read($input); | |
512 | |
513 $result = $vcal->getBaseComponent(); | |
514 $this->assertEquals('test', $result->SUMMARY->getValue()); | |
515 | |
516 } | |
517 | |
518 function testGetBaseComponentNoResult() { | |
519 | |
520 $input = 'BEGIN:VCALENDAR | |
521 VERSION:2.0 | |
522 PRODID:foo | |
523 METHOD:REQUEST | |
524 BEGIN:VEVENT | |
525 SUMMARY:test | |
526 RECURRENCE-ID;VALUE=DATE:20111202 | |
527 DTSTART;VALUE=DATE:20111202 | |
528 UID:foo | |
529 DTSTAMP:20140122T234434Z | |
530 END:VEVENT | |
531 BEGIN:VEVENT | |
532 DTSTART;VALUE=DATE:20111202 | |
533 UID:foo | |
534 DTSTAMP:20140122T234434Z | |
535 RECURRENCE-ID;VALUE=DATE:20111202 | |
536 END:VEVENT | |
537 END:VCALENDAR | |
538 '; | |
539 | |
540 $vcal = VObject\Reader::read($input); | |
541 | |
542 $result = $vcal->getBaseComponent(); | |
543 $this->assertNull($result); | |
544 | |
545 } | |
546 | |
547 function testNoComponents() { | |
548 | |
549 $input = <<<ICS | |
550 BEGIN:VCALENDAR | |
551 VERSION:2.0 | |
552 PRODID:vobject | |
553 END:VCALENDAR | |
554 ICS; | |
555 | |
556 $this->assertValidate( | |
557 $input, | |
558 0, | |
559 3, | |
560 "An iCalendar object must have at least 1 component." | |
561 ); | |
562 | |
563 } | |
564 | |
565 function testCalDAVNoComponents() { | |
566 | |
567 $input = <<<ICS | |
568 BEGIN:VCALENDAR | |
569 VERSION:2.0 | |
570 PRODID:vobject | |
571 BEGIN:VTIMEZONE | |
572 TZID:America/Toronto | |
573 END:VTIMEZONE | |
574 END:VCALENDAR | |
575 ICS; | |
576 | |
577 $this->assertValidate( | |
578 $input, | |
579 VCalendar::PROFILE_CALDAV, | |
580 3, | |
581 "A calendar object on a CalDAV server must have at least 1 component (VTODO, VEVENT, VJOURNAL)." | |
582 ); | |
583 | |
584 } | |
585 | |
586 function testCalDAVMultiUID() { | |
587 | |
588 $input = <<<ICS | |
589 BEGIN:VCALENDAR | |
590 VERSION:2.0 | |
591 PRODID:vobject | |
592 BEGIN:VEVENT | |
593 UID:foo | |
594 DTSTAMP:20150109T184500Z | |
595 DTSTART:20150109T184500Z | |
596 END:VEVENT | |
597 BEGIN:VEVENT | |
598 UID:bar | |
599 DTSTAMP:20150109T184500Z | |
600 DTSTART:20150109T184500Z | |
601 END:VEVENT | |
602 END:VCALENDAR | |
603 ICS; | |
604 | |
605 $this->assertValidate( | |
606 $input, | |
607 VCalendar::PROFILE_CALDAV, | |
608 3, | |
609 "A calendar object on a CalDAV server may only have components with the same UID." | |
610 ); | |
611 | |
612 } | |
613 | |
614 function testCalDAVMultiComponent() { | |
615 | |
616 $input = <<<ICS | |
617 BEGIN:VCALENDAR | |
618 VERSION:2.0 | |
619 PRODID:vobject | |
620 BEGIN:VEVENT | |
621 UID:foo | |
622 RECURRENCE-ID:20150109T185200Z | |
623 DTSTAMP:20150109T184500Z | |
624 DTSTART:20150109T184500Z | |
625 END:VEVENT | |
626 BEGIN:VTODO | |
627 UID:foo | |
628 DTSTAMP:20150109T184500Z | |
629 DTSTART:20150109T184500Z | |
630 END:VTODO | |
631 END:VCALENDAR | |
632 ICS; | |
633 | |
634 $this->assertValidate( | |
635 $input, | |
636 VCalendar::PROFILE_CALDAV, | |
637 3, | |
638 "A calendar object on a CalDAV server may only have 1 type of component (VEVENT, VTODO or VJOURNAL)." | |
639 ); | |
640 | |
641 } | |
642 | |
643 function testCalDAVMETHOD() { | |
644 | |
645 $input = <<<ICS | |
646 BEGIN:VCALENDAR | |
647 VERSION:2.0 | |
648 METHOD:PUBLISH | |
649 PRODID:vobject | |
650 BEGIN:VEVENT | |
651 UID:foo | |
652 RECURRENCE-ID:20150109T185200Z | |
653 DTSTAMP:20150109T184500Z | |
654 DTSTART:20150109T184500Z | |
655 END:VEVENT | |
656 END:VCALENDAR | |
657 ICS; | |
658 | |
659 $this->assertValidate( | |
660 $input, | |
661 VCalendar::PROFILE_CALDAV, | |
662 3, | |
663 "A calendar object on a CalDAV server MUST NOT have a METHOD property." | |
664 ); | |
665 | |
666 } | |
667 | |
668 function assertValidate($ics, $options, $expectedLevel, $expectedMessage = null) { | |
669 | |
670 $vcal = VObject\Reader::read($ics); | |
671 $result = $vcal->validate($options); | |
672 | |
673 $this->assertValidateResult($result, $expectedLevel, $expectedMessage); | |
674 | |
675 } | |
676 | |
677 function assertValidateResult($input, $expectedLevel, $expectedMessage = null) { | |
678 | |
679 $messages = array(); | |
680 foreach($input as $warning) { | |
681 $messages[] = $warning['message']; | |
682 } | |
683 | |
684 if ($expectedLevel === 0) { | |
685 $this->assertEquals(0, count($input), 'No validation messages were expected. We got: ' . implode(', ', $messages)); | |
686 } else { | |
687 $this->assertEquals(1, count($input), 'We expected exactly 1 validation message, We got: ' . implode(', ', $messages)); | |
688 | |
689 $this->assertEquals($expectedMessage, $input[0]['message']); | |
690 $this->assertEquals($expectedLevel, $input[0]['level']); | |
691 } | |
692 | |
693 } | |
694 | |
695 | |
696 } |