1<?php 2 3namespace Sabre\VObject\Property\ICalendar; 4 5use Sabre\VObject\Component\VCalendar; 6use Sabre\VObject\Node; 7use Sabre\VObject\Reader; 8 9class RecurTest extends \PHPUnit_Framework_TestCase { 10 11 use \Sabre\VObject\PHPUnitAssertions; 12 13 function testParts() { 14 15 $vcal = new VCalendar(); 16 $recur = $vcal->add('RRULE', 'FREQ=Daily'); 17 18 $this->assertInstanceOf('Sabre\VObject\Property\ICalendar\Recur', $recur); 19 20 $this->assertEquals(['FREQ' => 'DAILY'], $recur->getParts()); 21 $recur->setParts(['freq' => 'MONTHLY']); 22 23 $this->assertEquals(['FREQ' => 'MONTHLY'], $recur->getParts()); 24 25 } 26 27 /** 28 * @expectedException \InvalidArgumentException 29 */ 30 function testSetValueBadVal() { 31 32 $vcal = new VCalendar(); 33 $recur = $vcal->add('RRULE', 'FREQ=Daily'); 34 $recur->setValue(new \Exception()); 35 36 } 37 38 function testSetValueWithCount() { 39 $vcal = new VCalendar(); 40 $recur = $vcal->add('RRULE', 'FREQ=Daily'); 41 $recur->setValue(['COUNT' => 3]); 42 $this->assertEquals($recur->getParts()['COUNT'], 3); 43 } 44 45 function testGetJSONWithCount() { 46 $input = 'BEGIN:VCALENDAR 47BEGIN:VEVENT 48UID:908d53c0-e1a3-4883-b69f-530954d6bd62 49TRANSP:OPAQUE 50DTSTART;TZID=Europe/Berlin:20160301T150000 51DTEND;TZID=Europe/Berlin:20160301T170000 52SUMMARY:test 53RRULE:FREQ=DAILY;COUNT=3 54ORGANIZER;CN=robert pipo:mailto:robert@example.org 55END:VEVENT 56END:VCALENDAR 57'; 58 59 $vcal = Reader::read($input); 60 $rrule = $vcal->VEVENT->RRULE; 61 $count = $rrule->getJsonValue()[0]['count']; 62 $this->assertTrue(is_int($count)); 63 $this->assertEquals(3, $count); 64 } 65 66 function testSetSubParts() { 67 68 $vcal = new VCalendar(); 69 $recur = $vcal->add('RRULE', ['FREQ' => 'DAILY', 'BYDAY' => 'mo,tu', 'BYMONTH' => [0, 1]]); 70 71 $this->assertEquals([ 72 'FREQ' => 'DAILY', 73 'BYDAY' => ['MO', 'TU'], 74 'BYMONTH' => [0, 1], 75 ], $recur->getParts()); 76 77 } 78 79 function testGetJSONWithUntil() { 80 $input = 'BEGIN:VCALENDAR 81BEGIN:VEVENT 82UID:908d53c0-e1a3-4883-b69f-530954d6bd62 83TRANSP:OPAQUE 84DTSTART;TZID=Europe/Berlin:20160301T150000 85DTEND;TZID=Europe/Berlin:20160301T170000 86SUMMARY:test 87RRULE:FREQ=DAILY;UNTIL=20160305T230000Z 88ORGANIZER;CN=robert pipo:mailto:robert@example.org 89END:VEVENT 90END:VCALENDAR 91'; 92 93 $vcal = Reader::read($input); 94 $rrule = $vcal->VEVENT->RRULE; 95 $untilJsonString = $rrule->getJsonValue()[0]['until']; 96 $this->assertEquals('2016-03-05T23:00:00Z', $untilJsonString); 97 } 98 99 100 function testValidateStripEmpties() { 101 102 $input = 'BEGIN:VCALENDAR 103VERSION:2.0 104PRODID:foobar 105BEGIN:VEVENT 106UID:908d53c0-e1a3-4883-b69f-530954d6bd62 107TRANSP:OPAQUE 108DTSTART;TZID=Europe/Berlin:20160301T150000 109DTEND;TZID=Europe/Berlin:20160301T170000 110SUMMARY:test 111RRULE:FREQ=DAILY;BYMONTH=;UNTIL=20160305T230000Z 112ORGANIZER;CN=robert pipo:mailto:robert@example.org 113DTSTAMP:20160312T183800Z 114END:VEVENT 115END:VCALENDAR 116'; 117 118 $vcal = Reader::read($input); 119 $this->assertEquals( 120 1, 121 count($vcal->validate()) 122 ); 123 $this->assertEquals( 124 1, 125 count($vcal->validate($vcal::REPAIR)) 126 ); 127 128 $expected = 'BEGIN:VCALENDAR 129VERSION:2.0 130PRODID:foobar 131BEGIN:VEVENT 132UID:908d53c0-e1a3-4883-b69f-530954d6bd62 133TRANSP:OPAQUE 134DTSTART;TZID=Europe/Berlin:20160301T150000 135DTEND;TZID=Europe/Berlin:20160301T170000 136SUMMARY:test 137RRULE:FREQ=DAILY;UNTIL=20160305T230000Z 138ORGANIZER;CN=robert pipo:mailto:robert@example.org 139DTSTAMP:20160312T183800Z 140END:VEVENT 141END:VCALENDAR 142'; 143 144 $this->assertVObjectEqualsVObject( 145 $expected, 146 $vcal 147 ); 148 149 } 150 151 function testValidateStripNoFreq() { 152 153 $input = 'BEGIN:VCALENDAR 154VERSION:2.0 155PRODID:foobar 156BEGIN:VEVENT 157UID:908d53c0-e1a3-4883-b69f-530954d6bd62 158TRANSP:OPAQUE 159DTSTART;TZID=Europe/Berlin:20160301T150000 160DTEND;TZID=Europe/Berlin:20160301T170000 161SUMMARY:test 162RRULE:UNTIL=20160305T230000Z 163ORGANIZER;CN=robert pipo:mailto:robert@example.org 164DTSTAMP:20160312T183800Z 165END:VEVENT 166END:VCALENDAR 167'; 168 169 $vcal = Reader::read($input); 170 $this->assertEquals( 171 1, 172 count($vcal->validate()) 173 ); 174 $this->assertEquals( 175 1, 176 count($vcal->validate($vcal::REPAIR)) 177 ); 178 179 $expected = 'BEGIN:VCALENDAR 180VERSION:2.0 181PRODID:foobar 182BEGIN:VEVENT 183UID:908d53c0-e1a3-4883-b69f-530954d6bd62 184TRANSP:OPAQUE 185DTSTART;TZID=Europe/Berlin:20160301T150000 186DTEND;TZID=Europe/Berlin:20160301T170000 187SUMMARY:test 188ORGANIZER;CN=robert pipo:mailto:robert@example.org 189DTSTAMP:20160312T183800Z 190END:VEVENT 191END:VCALENDAR 192'; 193 194 $this->assertVObjectEqualsVObject( 195 $expected, 196 $vcal 197 ); 198 199 } 200 201 function testValidateInvalidByMonthRruleWithRepair() { 202 203 $calendar = new VCalendar(); 204 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=0'); 205 $result = $property->validate(Node::REPAIR); 206 207 $this->assertCount(1, $result); 208 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 209 $this->assertEquals(1, $result[0]['level']); 210 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24', $property->getValue()); 211 212 } 213 214 function testValidateInvalidByMonthRruleWithoutRepair() { 215 216 $calendar = new VCalendar(); 217 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=0'); 218 $result = $property->validate(); 219 220 $this->assertCount(1, $result); 221 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 222 $this->assertEquals(3, $result[0]['level']); 223 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=0', $property->getValue()); 224 225 } 226 227 function testValidateInvalidByMonthRruleWithRepair2() { 228 229 $calendar = new VCalendar(); 230 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=bla'); 231 $result = $property->validate(Node::REPAIR); 232 233 $this->assertCount(1, $result); 234 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 235 $this->assertEquals(1, $result[0]['level']); 236 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24', $property->getValue()); 237 238 } 239 240 function testValidateInvalidByMonthRruleWithoutRepair2() { 241 242 $calendar = new VCalendar(); 243 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=bla'); 244 $result = $property->validate(); 245 246 $this->assertCount(1, $result); 247 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 248 $this->assertEquals(3, $result[0]['level']); 249 // Without repair the invalid BYMONTH is still there, but the value is changed to uppercase 250 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=BLA', $property->getValue()); 251 252 } 253 254 function testValidateInvalidByMonthRruleValue14WithRepair() { 255 256 $calendar = new VCalendar(); 257 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=14'); 258 $result = $property->validate(Node::REPAIR); 259 260 $this->assertCount(1, $result); 261 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 262 $this->assertEquals(1, $result[0]['level']); 263 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24', $property->getValue()); 264 265 } 266 267 function testValidateInvalidByMonthRruleMultipleWithRepair() { 268 269 $calendar = new VCalendar(); 270 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=0,1,2,3,4,14'); 271 $result = $property->validate(Node::REPAIR); 272 273 $this->assertCount(2, $result); 274 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 275 $this->assertEquals(1, $result[0]['level']); 276 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[1]['message']); 277 $this->assertEquals(1, $result[1]['level']); 278 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=1,2,3,4', $property->getValue()); 279 280 } 281 282 function testValidateOneOfManyInvalidByMonthRruleWithRepair() { 283 284 $calendar = new VCalendar(); 285 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=bla,3,foo'); 286 $result = $property->validate(Node::REPAIR); 287 288 $this->assertCount(2, $result); 289 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[0]['message']); 290 $this->assertEquals(1, $result[0]['level']); 291 $this->assertEquals('BYMONTH in RRULE must have value(s) between 1 and 12!', $result[1]['message']); 292 $this->assertEquals(1, $result[1]['level']); 293 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=3', $property->getValue()); 294 295 } 296 297 function testValidateValidByMonthRrule() { 298 299 $calendar = new VCalendar(); 300 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=2,3'); 301 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYMONTHDAY=24;BYMONTH=2,3', $property->getValue()); 302 303 } 304 305 /** 306 * test for issue #336 307 */ 308 function testValidateRruleBySecondZero() { 309 310 $calendar = new VCalendar(); 311 $property = $calendar->createProperty('RRULE', 'FREQ=DAILY;BYHOUR=10;BYMINUTE=30;BYSECOND=0;UNTIL=20150616T153000Z'); 312 $result = $property->validate(Node::REPAIR); 313 314 // There should be 0 warnings and the value should be unchanged 315 $this->assertEmpty($result); 316 $this->assertEquals('FREQ=DAILY;BYHOUR=10;BYMINUTE=30;BYSECOND=0;UNTIL=20150616T153000Z', $property->getValue()); 317 318 } 319 320 function testValidateValidByWeekNoWithRepair() { 321 322 $calendar = new VCalendar(); 323 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYWEEKNO=11'); 324 $result = $property->validate(Node::REPAIR); 325 326 $this->assertCount(0, $result); 327 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYWEEKNO=11', $property->getValue()); 328 329 } 330 331 function testValidateInvalidByWeekNoWithRepair() { 332 333 $calendar = new VCalendar(); 334 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYWEEKNO=55;BYDAY=WE'); 335 $result = $property->validate(Node::REPAIR); 336 337 $this->assertCount(1, $result); 338 $this->assertEquals('BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', $result[0]['message']); 339 $this->assertEquals(1, $result[0]['level']); 340 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYDAY=WE', $property->getValue()); 341 342 } 343 344 function testValidateMultipleInvalidByWeekNoWithRepair() { 345 346 $calendar = new VCalendar(); 347 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYWEEKNO=55,2,-80;BYDAY=WE'); 348 $result = $property->validate(Node::REPAIR); 349 350 $this->assertCount(2, $result); 351 $this->assertEquals('BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', $result[0]['message']); 352 $this->assertEquals(1, $result[0]['level']); 353 $this->assertEquals('BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', $result[1]['message']); 354 $this->assertEquals(1, $result[1]['level']); 355 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYWEEKNO=2;BYDAY=WE', $property->getValue()); 356 357 } 358 359 function testValidateAllInvalidByWeekNoWithRepair() { 360 361 $calendar = new VCalendar(); 362 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYWEEKNO=55,-80;BYDAY=WE'); 363 $result = $property->validate(Node::REPAIR); 364 365 $this->assertCount(2, $result); 366 $this->assertEquals('BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', $result[0]['message']); 367 $this->assertEquals(1, $result[0]['level']); 368 $this->assertEquals('BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', $result[1]['message']); 369 $this->assertEquals(1, $result[1]['level']); 370 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYDAY=WE', $property->getValue()); 371 372 } 373 374 function testValidateInvalidByWeekNoWithoutRepair() { 375 376 $calendar = new VCalendar(); 377 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYWEEKNO=55;BYDAY=WE'); 378 $result = $property->validate(); 379 380 $this->assertCount(1, $result); 381 $this->assertEquals('BYWEEKNO in RRULE must have value(s) from -53 to -1, or 1 to 53!', $result[0]['message']); 382 $this->assertEquals(3, $result[0]['level']); 383 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYWEEKNO=55;BYDAY=WE', $property->getValue()); 384 385 } 386 387 function testValidateValidByYearDayWithRepair() { 388 389 $calendar = new VCalendar(); 390 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYYEARDAY=119'); 391 $result = $property->validate(Node::REPAIR); 392 393 $this->assertCount(0, $result); 394 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYYEARDAY=119', $property->getValue()); 395 396 } 397 398 function testValidateInvalidByYearDayWithRepair() { 399 400 $calendar = new VCalendar(); 401 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYYEARDAY=367;BYDAY=WE'); 402 $result = $property->validate(Node::REPAIR); 403 404 $this->assertCount(1, $result); 405 $this->assertEquals('BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', $result[0]['message']); 406 $this->assertEquals(1, $result[0]['level']); 407 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYDAY=WE', $property->getValue()); 408 409 } 410 411 function testValidateMultipleInvalidByYearDayWithRepair() { 412 413 $calendar = new VCalendar(); 414 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYYEARDAY=380,2,-390;BYDAY=WE'); 415 $result = $property->validate(Node::REPAIR); 416 417 $this->assertCount(2, $result); 418 $this->assertEquals('BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', $result[0]['message']); 419 $this->assertEquals(1, $result[0]['level']); 420 $this->assertEquals('BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', $result[1]['message']); 421 $this->assertEquals(1, $result[1]['level']); 422 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYYEARDAY=2;BYDAY=WE', $property->getValue()); 423 424 } 425 426 function testValidateAllInvalidByYearDayWithRepair() { 427 428 $calendar = new VCalendar(); 429 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYYEARDAY=455,-480;BYDAY=WE'); 430 $result = $property->validate(Node::REPAIR); 431 432 $this->assertCount(2, $result); 433 $this->assertEquals('BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', $result[0]['message']); 434 $this->assertEquals(1, $result[0]['level']); 435 $this->assertEquals('BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', $result[1]['message']); 436 $this->assertEquals(1, $result[1]['level']); 437 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYDAY=WE', $property->getValue()); 438 439 } 440 441 function testValidateInvalidByYearDayWithoutRepair() { 442 443 $calendar = new VCalendar(); 444 $property = $calendar->createProperty('RRULE', 'FREQ=YEARLY;COUNT=6;BYYEARDAY=380;BYDAY=WE'); 445 $result = $property->validate(); 446 447 $this->assertCount(1, $result); 448 $this->assertEquals('BYYEARDAY in RRULE must have value(s) from -366 to -1, or 1 to 366!', $result[0]['message']); 449 $this->assertEquals(3, $result[0]['level']); 450 $this->assertEquals('FREQ=YEARLY;COUNT=6;BYYEARDAY=380;BYDAY=WE', $property->getValue()); 451 452 } 453} 454