r64168 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r64167‎ | r64168 | r64169 >
Date:19:06, 25 March 2010
Author:yaron
Status:deferred
Tags:
Comment:
Changed handling of day-of-week-based monthly events - 'dayofweekinmonth' unit replaced by regular 'month' unit with new 'week number' parameter, and some bugs fixed; also some minor changes elsewhere
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_ParserExtensions.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/SMW_ParserExtensions.php
@@ -274,10 +274,10 @@
275275 array_shift( $params ); // We already know the $parser ...
276276
277277 // Use first parameter as concept (query) string.
278 - $concept_input = str_replace( array( '&gt;', '&lt;' ), array( '>', '<' ), array_shift( $params ) );
 278+ $concept_input = str_replace( array( '&gt;', '&lt;' ), array( '>', '<' ), array_shift( $params ) );
279279
280280 // second parameter, if any, might be a description
281 - $concept_docu = array_shift( $params );
 281+ $concept_docu = array_shift( $params );
282282
283283 // NOTE: the str_replace above is required in MediaWiki 1.11, but not in MediaWiki 1.14
284284 $query = SMWQueryProcessor::createQuery( $concept_input, array( 'limit' => 20, 'format' => 'list' ), SMWQueryProcessor::CONCEPT_DESC );
@@ -340,7 +340,7 @@
341341 $params = func_get_args();
342342 array_shift( $params ); // We already know the $parser ...
343343
344 - foreach ( $params as $p )
 344+ foreach ( $params as $p ) {
345345 if ( trim( $p ) != '' ) {
346346 $parts = explode( '=', trim( $p ), 2 );
347347
@@ -351,143 +351,191 @@
352352 SMWParseData::addProperty( $property, $object, false, $parser, true );
353353 }
354354 }
355 -
 355+ }
 356+
356357 SMWOutputs::commitToParser( $parser ); // not obviously required, but let us be sure
357358 return '';
358359 }
359360
360 - /**
361 - * Function for handling the {{\#set_recurring_event }} parser function.
362 - * This is used for defining a set of date values for a page that
363 - * represents a recurring event.
364 - * Like with the #set function, all annotations happen silently.
365 - *
366 - * Usage:
367 - * {{\#set_recurring_event:
368 - * property = Has date
369 - * | start = January 4, 2010
370 - * | end = June 7, 2010
371 - * | unit = week
372 - * | period = 1
373 - * | include = March 16, 2010;March 23, 2010
374 - * | exclude = March 15, 2010;March 22, 2010
375 - * }}
376 - * This sets a "Has date" value for every Monday within the specified
377 - * six-month period, except for two Mondays which are excluded and
378 - * two Tuesdays that are saved in their place.
379 - *
380 - * @param[in] &$parser Parser The current parser
381 - * @return nothing
382 - */
383 - static public function doSetRecurringEvent( &$parser ) {
384 - $params = func_get_args();
385 - array_shift( $params ); // we already know the $parser ...
386 - // initialize variables
387 - $property_name = $start_date = $end_date = $unit = $period = null;
388 - $included_dates = array();
389 - $excluded_dates_jd = array();
390 - // set values from the parameters
391 - foreach ( $params as $p ) {
392 - if ( trim( $p ) != "" ) {
393 - $parts = explode( "=", trim( $p ) );
394 - if ( count( $parts ) == 2 ) {
395 - list( $arg, $value ) = $parts;
396 - if ( $arg === 'property' ) {
397 - $property_name = $value;
398 - } elseif ( $arg === 'start' ) {
399 - $start_date = SMWDataValueFactory::newTypeIDValue( '_dat', $value );
400 - } elseif ( $arg === 'end' ) {
401 - $end_date = SMWDataValueFactory::newTypeIDValue( '_dat', $value );
402 - } elseif ( $arg === 'unit' ) {
403 - $unit = $value;
404 - } elseif ( $arg === 'period' ) {
405 - $period = (int)$value;
406 - } elseif ( $arg === 'include' ) {
407 - $included_dates = explode( ';', $value );
408 - } elseif ( $arg === 'exclude' ) {
409 - $excluded_dates = explode( ';', $value );
410 - foreach ( $excluded_dates as $date_str ) {
411 - $date = SMWDataValueFactory::newTypeIDValue( '_dat', $date_str );
412 - $excluded_dates_jd[] = $date->getValueKey();
413 - }
414 - }
415 - }
416 - }
417 - }
418 - // we need at least a property and start date - if either one
419 - // is null, exit here
420 - if ( is_null( $property_name ) || is_null( $start_date ) )
421 - return;
422 -
423 - // if the period is null, or outside of normal bounds, set it to 1
424 - if ( is_null( $period ) || $period < 1 || $period > 500 )
425 - $period = 1;
426 - // get the Julian day value for both the start and end date
427 - $start_date_jd = $start_date->getValueKey();
428 - if ( ! is_null( $end_date ) )
429 - $end_date_jd = $end_date->getValueKey();
430 - $cur_date = $start_date;
431 - $cur_date_jd = $start_date->getValueKey();
432 - $i = 0;
433 - $reached_end_date = false;
434 - do {
435 - $i++;
436 - $exclude_date = ( in_array( $cur_date_jd, $excluded_dates_jd ) );
437 - if ( ! $exclude_date ) {
438 - $cur_date_str = $cur_date->getLongWikiText();
439 - SMWParseData::addProperty( $property_name, $cur_date_str, false, $parser, true );
440 - }
441 - // now get the next date
442 - // handling is different depending on whether it's
443 - // month/year or week/day, since the latter is a
444 - // set number of days while the former isn't
445 - if ( $unit === 'year' || $unit == 'month' ) {
446 - $cur_year = $cur_date->getYear();
447 - $cur_month = $cur_date->getMonth();
448 - $cur_day = $cur_date->getDay();
449 - $cur_time = $cur_date->getTimeString();
450 - if ( $unit == 'year' ) {
451 - $cur_year += $period;
452 - } else { // $unit === 'month'
453 - $cur_month += $period;
454 - $cur_year += (int)( ( $cur_month - 1 ) / 12 );
455 - $cur_month %= 12;
456 - $display_month = ( $cur_month == 0 ) ? 12 : $cur_month;
457 - }
458 - $date_str = "$cur_year-$display_month-$cur_day $cur_time";
459 - $cur_date = SMWDataValueFactory::newTypeIDValue( '_dat', $date_str );
460 - $cur_date_jd = $cur_date->getValueKey();
461 - } elseif($unit == 'dayofweekinmonth') {
462 - // e.g., "3rd Monday of every month"
463 - $check_month = $cur_date->getMonth();
464 - $cur_date_jd += 28 * $period;
465 - $cur_date = SMWDataValueFactory::newTypeIDValue('_dat', $cur_date_jd);
466 - if ($cur_date->getMonth() != (($check_month + $period) % 12 )){
467 - $cur_date_jd += 7; // add another week
468 - $cur_date = SMWDataValueFactory::newTypeIDValue('_dat', $cur_date_jd);
 361+ /**
 362+ * Function for handling the {{\#set_recurring_event }} parser function.
 363+ * This is used for defining a set of date values for a page that
 364+ * represents a recurring event.
 365+ * Like with the #set function, all annotations happen silently.
 366+ *
 367+ * Usage:
 368+ * {{\#set_recurring_event:
 369+ * property = Has date
 370+ * | start = January 4, 2010
 371+ * | end = June 7, 2010
 372+ * | unit = week
 373+ * | period = 1
 374+ * | include = March 16, 2010;March 23, 2010
 375+ * | exclude = March 15, 2010;March 22, 2010
 376+ * }}
 377+ * This sets a "Has date" value for every Monday within the specified
 378+ * six-month period, except for two Mondays which are excluded and
 379+ * two Tuesdays that are saved in their place.
 380+ *
 381+ * There's also a 'week number' parameter, which is only valid when
 382+ * the 'unit' parameter is set to 'month'. This one dictates that the
 383+ * event should always happen on the n-th week of each month, instead
 384+ * of a specific numbered date. Negative values for 'week number'
 385+ * indicate the n-th last week of a month instead.
 386+ *
 387+ * @param[in] &$parser Parser The current parser
 388+ * @return nothing
 389+ */
 390+ static public function doSetRecurringEvent( &$parser ) {
 391+ $params = func_get_args();
 392+ array_shift( $params ); // We already know the $parser ...
 393+
 394+ // Initialize variables
 395+ $property_name = $start_date = $end_date = $unit = $period = $week_num = null;
 396+ $included_dates = array();
 397+ $excluded_dates_jd = array();
 398+ // Set values from the parameters
 399+ foreach ( $params as $p ) {
 400+ if ( trim( $p ) != '' ) {
 401+ $parts = explode( '=', trim( $p ) );
 402+ if ( count( $parts ) == 2 ) {
 403+ list( $arg, $value ) = $parts;
 404+ if ( $arg === 'property' ) {
 405+ $property_name = $value;
 406+ } elseif ( $arg === 'start' ) {
 407+ $start_date = SMWDataValueFactory::newTypeIDValue( '_dat', $value );
 408+ } elseif ( $arg === 'end' ) {
 409+ $end_date = SMWDataValueFactory::newTypeIDValue( '_dat', $value );
 410+ } elseif ( $arg === 'unit' ) {
 411+ $unit = $value;
 412+ } elseif ( $arg === 'period' ) {
 413+ $period = (int)$value;
 414+ } elseif ( $arg === 'week number' ) {
 415+ $week_num = (int)$value;
 416+ } elseif ( $arg === 'include' ) {
 417+ $included_dates = explode( ';', $value );
 418+ } elseif ( $arg === 'exclude' ) {
 419+ $excluded_dates = explode( ';', $value );
 420+ foreach ( $excluded_dates as $date_str ) {
 421+ $date = SMWDataValueFactory::newTypeIDValue( '_dat', $date_str );
 422+ $excluded_dates_jd[] = $date->getValueKey();
 423+ }
 424+ }
469425 }
470 - } else { // $unit == 'day' or 'week'
471 - // assume 'day' if it's none of the above
472 - $cur_date_jd += ( $unit === 'week' ) ? 7 * $period : $period;
473 - $cur_date = SMWDataValueFactory::newTypeIDValue( '_dat', $cur_date_jd );
474 - }
 426+ }
 427+ }
 428+ // We need at least a property and start date - if either one
 429+ // is null, exit here
 430+ if ( is_null( $property_name ) || is_null( $start_date ) )
 431+ return;
475432
476 - // should we stop?
477 - if ( is_null( $end_date ) ) {
478 - global $smwgDefaultNumRecurringEvents;
479 - $reached_end_date = $i > $smwgDefaultNumRecurringEvents;
480 - } else {
481 - global $smwgMaxNumRecurringEvents;
482 - $reached_end_date = ( $cur_date_jd > $end_date_jd ) || ( $i > $smwgMaxNumRecurringEvents );
483 - }
484 - } while ( ! $reached_end_date );
 433+ // If the period is null, or outside of normal bounds, set it to 1
 434+ if ( is_null( $period ) || $period < 1 || $period > 500 )
 435+ $period = 1;
485436
486 - // handle the 'include' dates as well
487 - foreach ( $included_dates as $date_str )
488 - SMWParseData::addProperty( $property_name, $date_str, false, $parser, true );
489 - SMWOutputs::commitToParser( $parser ); // not obviously required, but let us be sure
490 - }
 437+ // Handle 'week number', but only if it's of unit 'month'
 438+ if ( $unit == 'month' && ! is_null( $week_num ) ) {
 439+ $unit = 'dayofweekinmonth';
 440+ if ( $week_num < -4 || $week_num > 5 || $week_num == 0 ) {
 441+ $week_num = null;
 442+ }
 443+ }
 444+ if ( $unit == 'dayofweekinmonth' && is_null( $week_num ) )
 445+ $week_num = ceil($start_date->getDay() / 7);
491446
 447+ // Get the Julian day value for both the start and end date
 448+ $start_date_jd = $start_date->getValueKey();
 449+ if ( ! is_null( $end_date ) )
 450+ $end_date_jd = $end_date->getValueKey();
 451+ $cur_date = $start_date;
 452+ $cur_date_jd = $start_date->getValueKey();
 453+ $i = 0;
 454+ $reached_end_date = false;
 455+ do {
 456+ $i++;
 457+ $exclude_date = ( in_array( $cur_date_jd, $excluded_dates_jd ) );
 458+ if ( ! $exclude_date ) {
 459+ $cur_date_str = $cur_date->getLongWikiText();
 460+ SMWParseData::addProperty( $property_name, $cur_date_str, false, $parser, true );
 461+ }
 462+ // now get the next date
 463+ // handling is different depending on whether it's
 464+ // month/year or week/day, since the latter is a
 465+ // set number of days while the former isn't
 466+ if ( $unit === 'year' || $unit == 'month' ) {
 467+ $cur_year = $cur_date->getYear();
 468+ $cur_month = $cur_date->getMonth();
 469+ $cur_day = $cur_date->getDay();
 470+ $cur_time = $cur_date->getTimeString();
 471+ if ( $unit == 'year' ) {
 472+ $cur_year += $period;
 473+ $display_month = $cur_month;
 474+ } else { // $unit === 'month'
 475+ $cur_month += $period;
 476+ $cur_year += (int)( ( $cur_month - 1 ) / 12 );
 477+ $cur_month %= 12;
 478+ $display_month = ( $cur_month == 0 ) ? 12 : $cur_month;
 479+ }
 480+ $date_str = "$cur_year-$display_month-$cur_day $cur_time";
 481+ $cur_date = SMWDataValueFactory::newTypeIDValue( '_dat', $date_str );
 482+ $cur_date_jd = $cur_date->getValueKey();
 483+ } elseif ( $unit == 'dayofweekinmonth' ) {
 484+ // e.g., "3rd Monday of every month"
 485+ $prev_month = $cur_date->getMonth();
 486+ $prev_year = $cur_date->getYear();
 487+ $new_month = ( $prev_month + $period ) % 12;
 488+ if ( $new_month == 0 ) $new_month = 12;
 489+ $new_year = $prev_year + floor( ( $prev_month + $period - 1 ) / 12 );
 490+ $cur_date_jd += ( 28 * $period ) - 7;
 491+ // we're sometime before the actual date now -
 492+ // keep incrementing by a week, until we get
 493+ // there
 494+ do {
 495+ $cur_date_jd += 7;
 496+ $cur_date = SMWDataValueFactory::newTypeIDValue('_dat', $cur_date_jd);
 497+ $right_month = ($cur_date->getMonth() == $new_month);
 498+ if ( $week_num < 0 ) {
 499+ $next_week_jd = $cur_date_jd;
 500+ do {
 501+ $next_week_jd += 7;
 502+ $next_week_date = SMWDataValueFactory::newTypeIDValue( '_dat', $next_week_jd );
 503+ $right_week = ($next_week_date->getMonth() != $new_month) || ($next_week_date->getYear() != $new_year);
 504+ } while ( ! $right_week );
 505+ $cur_date_jd = $next_week_jd + ( 7 * $week_num );
 506+ $cur_date = SMWDataValueFactory::newTypeIDValue( '_dat', $cur_date_jd );
 507+ } else {
 508+ $cur_week_num = ceil( $cur_date->getDay() / 7 );
 509+ $right_week = ( $cur_week_num == $week_num );
 510+ if ($week_num == 5 && ( $cur_date->getMonth() % 12 == ( $new_month + 1 ) % 12 ) ) {
 511+ $cur_date_jd -= 7;
 512+ $cur_date = SMWDataValueFactory::newTypeIDValue( '_dat', $cur_date_jd );
 513+ $right_month = $right_week = true;
 514+ }
 515+ }
 516+ } while (! $right_month || ! $right_week);
 517+ } else { // $unit == 'day' or 'week'
 518+ // assume 'day' if it's none of the above
 519+ $cur_date_jd += ( $unit === 'week' ) ? 7 * $period : $period;
 520+ $cur_date = SMWDataValueFactory::newTypeIDValue( '_dat', $cur_date_jd );
 521+ }
 522+
 523+ // should we stop?
 524+ if ( is_null( $end_date ) ) {
 525+ global $smwgDefaultNumRecurringEvents;
 526+ $reached_end_date = $i > $smwgDefaultNumRecurringEvents;
 527+ } else {
 528+ global $smwgMaxNumRecurringEvents;
 529+ $reached_end_date = ( $cur_date_jd > $end_date_jd ) || ( $i > $smwgMaxNumRecurringEvents );
 530+ }
 531+ } while ( ! $reached_end_date );
 532+
 533+ // handle the 'include' dates as well
 534+ foreach ( $included_dates as $date_str )
 535+ SMWParseData::addProperty( $property_name, $date_str, false, $parser, true );
 536+
 537+ SMWOutputs::commitToParser( $parser ); // not obviously required, but let us be sure
 538+ }
 539+
492540 /**
493541 * Function for handling the {{\#declare }} parser function. It is used for declaring template parameters
494542 * that should automagically be annotated when the template is used.

Status & tagging log