API: Adding wlshow parameter to list=watchlist to allow for filtering (non-)minor...
[lhc/web/wiklou.git] / languages / Language.php
index 9cbe943..d9aa5f5 100644 (file)
@@ -171,6 +171,7 @@ class Language {
         * @return array
         */
        function getDefaultUserOptions() {
+               trigger_error( 'Use of ' . __METHOD__ . ' is deprecated', E_USER_NOTICE );
                return User::getDefaultOptions();
        }
 
@@ -509,6 +510,7 @@ class Language {
         *
         *    xjj  j (day number) in Hebrew calendar
         *    xjF  F (month name) in Hebrew calendar
+        *    xjt  t (days in month) in Hebrew calendar
         *    xjx  xg (genitive month name) in Hebrew calendar
         *    xjn  n (month number) in Hebrew calendar
         *    xjY  Y (full year) in Hebrew calendar
@@ -648,6 +650,10 @@ class Language {
                                        if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
                                        $num = gmdate( 't', $unix );
                                        break;
+                               case 'xjt':
+                                       if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
+                                       $num = $hebrew[3];
+                                       break;
                                case 'L':
                                        if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
                                        $num = gmdate( 'L', $unix );
@@ -826,130 +832,141 @@ class Language {
                $month = substr( $ts, 4, 2 );
                $day = substr( $ts, 6, 2 );
 
-               # Month number when March = 1, February = 12
-               $month -= 2;
-               if( $month <= 0 ) {
-                       # January of February
-                       $month += 12;
-                       $year--;
+               # Calculate Hebrew year
+               $hebrewYear = $year + 3760;
+
+               # Month number when September = 1, August = 12
+               $month += 4;
+               if( $month > 12 ) {
+                       # Next year
+                       $month -= 12;
+                       $year++;
+                       $hebrewYear++;
                }
 
-               # Days since 1 March - calculating 30 days a month,
-               # and then adding the missing number of days
-               $day += intval( 7 * $month / 12 + 30 * ( $month - 1 ) );
-               # Calculate Hebrew year for days after 1 Nisan
-               $hebrewYear = $year + 3760;
-               # Passover date for this year (as days since 1 March)
-               $passover = self::passoverDate( $hebrewYear );
-               if( $day <= $passover - 15 ) {
-                       # Day is before 1 Nisan (passover is 15 Nisan) - it is the previous year
-                       # Next year's passover (as days since 1 March)
-                       $anchor = $passover;
-                       # Add days since previous year's 1 March
-                       $day += 365;
-                       if( ( $year % 400 == 0 ) || ( $year % 100 != 0 && $year % 4 == 0 ) ) {
-                               # Leap year
-                               $day++;
+               # Calculate day of year from 1 September
+               $dayOfYear = $day;
+               for( $i = 1; $i < $month; $i++ ) {
+                       if( $i == 6 ) {
+                               # February
+                               $dayOfYear += 28;
+                               # Check if the year is leap
+                               if( $year % 400 == 0 || ( $year % 4 == 0 && $year % 100 > 0 ) ) {
+                                       $dayOfYear++;
+                               }
+                       } elseif( $i == 8 || $i == 10 || $i == 1 || $i == 3 ) {
+                               $dayOfYear += 30;
+                       } else {
+                               $dayOfYear += 31;
                        }
+               }
+
+               # Calculate the start of the Hebrew year
+               $start = self::hebrewYearStart( $hebrewYear );
+
+               # Calculate next year's start
+               if( $dayOfYear <= $start ) {
+                       # Day is before the start of the year - it is the previous year
+                       # Next year's start
+                       $nextStart = $start;
                        # Previous year
                        $year--;
                        $hebrewYear--;
-                       # Passover date for the new year (as days since 1 March)
-                       $passover = self::passoverDate( $hebrewYear );
+                       # Add days since previous year's 1 September
+                       $dayOfYear += 365;
+                       if( ( $year % 400 == 0 ) || ( $year % 100 != 0 && $year % 4 == 0 ) ) {
+                               # Leap year
+                               $dayOfYear++;
+                       }
+                       # Start of the new (previous) year
+                       $start = self::hebrewYearStart( $hebrewYear );
+               } else {
+                       # Next year's start
+                       $nextStart = self::hebrewYearStart( $hebrewYear + 1 );
+               }
+
+               # Calculate Hebrew day of year
+               $hebrewDayOfYear = $dayOfYear - $start;
+
+               # Difference between year's days
+               $diff = $nextStart - $start;
+               # Add 12 (or 13 for leap years) days to ignore the difference between
+               # Hebrew and Gregorian year (353 at least vs. 365/6) - now the
+               # difference is only about the year type
+               if( ( $year % 400 == 0 ) || ( $year % 100 != 0 && $year % 4 == 0 ) ) {
+                       $diff += 13;
                } else {
-                       # Next year's passover (as days since 1 March)
-                       $anchor = self::passoverDate( $hebrewYear + 1 );
-               }
-
-               # Days since 1 Nisan
-               $day -= $passover - 15;
-               # Difference between this year's passover date by gregorian calendar,
-               # and the next year's one + 12 days. This should be 1 days for a regular year,
-               # but 0 for incomplete one, 2 for complete, and those + 30 days of Adar I
-               # for a leap year.
-               $anchor -= $passover - 12;
-               $nextYear = $year + 1;
-               if( ( $nextYear % 400 == 0 ) || ( $nextYear % 100 != 0 && $nextYear % 4 == 0 ) ) {
-                       # Next year is a leap year - difference is growing
-                       $anchor++;
-               }
-
-               # Calculate day in the month from number of days sine 1 Nisan
-               # Don't check Adar - if the day is not in adar, we will stop before;
-               # if it is in adar, we will use it to check if it is Adar I or Adar II
-               for( $month = 0; $month < 11; $month++ ) {
+                       $diff += 12;
+               }
+
+               # Check the year pattern, and is leap year
+               # 0 means an incomplete year, 1 means a regular year, 2 means a complete year
+               # This is mod 30, to work on both leap years (which add 30 days of Adar I)
+               # and non-leap years
+               $yearPattern = $diff % 30;
+               # Check if leap year
+               $isLeap = $diff >= 30;
+
+               # Calculate day in the month from number of day in the Hebrew year
+               # Don't check Adar - if the day is not in Adar, we will stop before;
+               # if it is in Adar, we will use it to check if it is Adar I or Adar II
+               $hebrewDay = $hebrewDayOfYear;
+               $hebrewMonth = 1;
+               $days = 0;
+               while( $hebrewMonth <= 12 ) {
                        # Calculate days in this month
-                       if( $month == 7 && $anchor % 30 == 2 ) {
+                       if( $isLeap && $hebrewMonth == 6 ) {
+                               # Adar in a leap year
+                               if( $isLeap ) {
+                                       # Leap year - has Adar I, with 30 days, and Adar II, with 29 days
+                                       $days = 30;
+                                       if( $hebrewDay <= $days ) {
+                                               # Day in Adar I
+                                               $hebrewMonth = 13;
+                                       } else {
+                                               # Subtract the days of Adar I
+                                               $hebrewDay -= $days;
+                                               # Try Adar II
+                                               $days = 29;
+                                               if( $hebrewDay <= $days ) {
+                                                       # Day in Adar II
+                                                       $hebrewMonth = 14;
+                                               }
+                                       }
+                               }
+                       } elseif( $hebrewMonth == 2 && $yearPattern == 2 ) {
                                # Cheshvan in a complete year (otherwise as the rule below)
                                $days = 30;
-                       } else if( $month == 8 && $anchor % 30 == 0 ) {
+                       } elseif( $hebrewMonth == 3 && $yearPattern == 0 ) {
                                # Kislev in an incomplete year (otherwise as the rule below)
                                $days = 29;
                        } else {
-                               # Even months have 30 days, odd have 29
-                               $days = 30 - $month % 2;
+                               # Odd months have 30 days, even have 29
+                               $days = 30 - ( $hebrewMonth - 1 ) % 2;
                        }
-                       if( $day <= $days ) {
-                               # In this month
+                       if( $hebrewDay <= $days ) {
+                               # In the current month
                                break;
-                       }
-                       # Try in next months
-                       $day -= $days;
-               }
-
-               # Now we move to a year from Tishrei
-               if( $month >= 6 ) {
-                       # After Tishrei, use next year
-                       $hebrewYear++;
-               }
-               # Recalculate month number so that we start from Tishrei
-               $month = ( $month + 6 ) % 12 + 1;
-
-               # Fix Adar
-               if( $month == 6 && $anchor >= 30 ) {
-                       # This *is* adar, and this year is leap
-                       if( $day > 30 ) {
-                               # Adar II
-                               $month = 14;
-                               $day -= 30;
                        } else {
-                               # Adar I
-                               $month = 13;
+                               # Subtract the days of the current month
+                               $hebrewDay -= $days;
+                               # Try in the next month
+                               $hebrewMonth++;
                        }
                }
 
-               return array( $hebrewYear, $month, $day );
-       }
-
-       /**
-        * Algorithm to convert Gregorian dates to Thai solar dates.
-        *
-        * Link: http://en.wikipedia.org/wiki/Thai_solar_calendar
-        *
-        * @param string $ts 14-character timestamp
-        * @return array converted year, month, day
-        */
-       private static function tsToThai( $ts ) {
-               $gy = substr( $ts, 0, 4 );
-               $gm = substr( $ts, 4, 2 );
-               $gd = substr( $ts, 6, 2 );
-
-               # Add 543 years to the Gregorian calendar
-               # Months and days are identical
-               $gy_thai = $gy + 543;
-
-               return array( $gy_thai, $gm, $gd );
+               return array( $hebrewYear, $hebrewMonth, $hebrewDay, $days );
        }
 
-
        /**
+        * This calculates the Hebrew year start, as days since 1 September.
         * Based on Carl Friedrich Gauss algorithm for finding Easter date.
         * Used for Hebrew date.
         */
-       private static function passoverDate( $year ) {
-               $a = intval( ( 12 * $year + 17 ) % 19 );
-               $b = intval( $year % 4 );
-               $m = 32.044093161144 + 1.5542417966212 * $a +  $b / 4.0 - 0.0031777940220923 * $year;
+       private static function hebrewYearStart( $year ) {
+               $a = intval( ( 12 * ( $year - 1 ) + 17 ) % 19 );
+               $b = intval( ( $year - 1 ) % 4 );
+               $m = 32.044093161144 + 1.5542417966212 * $a +  $b / 4.0 - 0.0031777940220923 * ( $year - 1 );
                if( $m < 0 ) {
                        $m--;
                }
@@ -959,7 +976,7 @@ class Language {
                }
                $m -= $Mar;
 
-               $c = intval( ( $Mar + 3 * $year + 5 * $b + 5 ) % 7);
+               $c = intval( ( $Mar + 3 * ( $year - 1 ) + 5 * $b + 5 ) % 7);
                if( $c == 0 && $a > 11 && $m >= 0.89772376543210 ) {
                        $Mar++;
                } else if( $c == 1 && $a > 6 && $m >= 0.63287037037037 ) {
@@ -968,10 +985,31 @@ class Language {
                        $Mar++;
                }
 
-               $Mar += intval( ( $year - 3760 ) / 100 ) - intval( ( $year - 3760 ) / 400 ) - 2;
+               $Mar += intval( ( $year - 3761 ) / 100 ) - intval( ( $year - 3761 ) / 400 ) - 24;
                return $Mar;
        }
 
+       /**
+        * Algorithm to convert Gregorian dates to Thai solar dates.
+        *
+        * Link: http://en.wikipedia.org/wiki/Thai_solar_calendar
+        *
+        * @param string $ts 14-character timestamp
+        * @return array converted year, month, day
+        */
+       private static function tsToThai( $ts ) {
+               $gy = substr( $ts, 0, 4 );
+               $gm = substr( $ts, 4, 2 );
+               $gd = substr( $ts, 6, 2 );
+
+               # Add 543 years to the Gregorian calendar
+               # Months and days are identical
+               $gy_thai = $gy + 543;
+
+               return array( $gy_thai, $gm, $gd );
+       }
+
+
        /**
         * Roman number formatting up to 3000
         */
@@ -1532,9 +1570,10 @@ class Language {
 
                if( !is_array( $rawEntry ) ) {
                        error_log( "\"$rawEntry\" is not a valid magic thingie for \"$mw->mId\"" );
+               } else {
+                       $mw->mCaseSensitive = $rawEntry[0];
+                       $mw->mSynonyms = array_slice( $rawEntry, 1 );
                }
-               $mw->mCaseSensitive = $rawEntry[0];
-               $mw->mSynonyms = array_slice( $rawEntry, 1 );
        }
 
        /**
@@ -1734,8 +1773,8 @@ class Language {
         */
        function convertGrammar( $word, $case ) {
                global $wgGrammarForms;
-               if ( isset($wgGrammarForms['en'][$case][$word]) ) {
-                       return $wgGrammarForms['en'][$case][$word];
+               if ( isset($wgGrammarForms[$this->getCode()][$case][$word]) ) {
+                       return $wgGrammarForms[$this->getCode()][$case][$word];
                }
                return $word;
        }
@@ -1770,7 +1809,7 @@ class Language {
         * @param array $forms Array of forms given to convertPlural
         * @return array Padded array of forms or an exception if not an array
         */
-       protected function preConvertPlural( Array $forms, $count ) {
+       protected function preConvertPlural( /* Array */ $forms, $count ) {
                while ( count($forms) < $count ) {
                        $forms[] = $forms[count($forms)-1];
                }
@@ -2096,6 +2135,13 @@ class Language {
 
                # Replace spaces with underscores in namespace names
                $cache['namespaceNames'] = str_replace( ' ', '_', $cache['namespaceNames'] );
+
+               # And do the same for specialpage aliases. $page is an array.
+               foreach ( $cache['specialPageAliases'] as &$page ) {
+                       $page = str_replace( ' ', '_', $page );
+               }
+               # Decouple the reference to prevent accidental damage
+               unset($page);
                
                # Save to both caches
                self::$mLocalisationCache[$code] = $cache;