Plugin Directory

Changeset 3382962


Ignore:
Timestamp:
10/22/2025 11:20:27 PM (5 months ago)
Author:
stankovski
Message:

Version 1.1

Location:
muslim-prayer-times
Files:
5 edited
14 copied

Legend:

Unmodified
Added
Removed
  • muslim-prayer-times/tags/1.1/includes/helpers.php

    r3382840 r3382962  
    172172    $results = [];
    173173   
     174    // Get settings for Ramadan detection
     175    $opts = get_option('muslprti_settings', []);
     176    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     177    $ramadan_fajr_minutes = isset($opts['ramadan_fajr_minutes_after']) ? $opts['ramadan_fajr_minutes_after'] : 20;
     178    $ramadan_fajr_rounding = isset($opts['ramadan_fajr_rounding']) ? $opts['ramadan_fajr_rounding'] : 1;
     179   
    174180    // Use the new helper function to normalize all times
    175181    $normalized_days_data = muslprti_normalize_times_for_dst($days_data);
    176182   
    177     // Find latest Athan for weekly calculation
     183    // Find latest Athan for weekly calculation (only for non-Ramadan days)
    178184    $latest_fajr = null;
    179185    $latest_sunrise = null;
     
    181187    if ($is_weekly) {
    182188        foreach ($normalized_days_data as $day_data) {
     189            // Skip Ramadan days when finding weekly maximum
     190            $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_data['date'], $opts);
     191            if ($is_ramadan) {
     192                continue;
     193            }
     194           
    183195            if ($latest_fajr === null ||
    184196                muslprti_time_to_minutes($day_data['athan']['fajr']) > muslprti_time_to_minutes($latest_fajr)) {
     
    192204       
    193205        // Apply rounding to the latest times
    194         $latest_fajr = muslprti_round_up($latest_fajr, $fajr_rounding);
    195         $latest_sunrise = muslprti_round_down($latest_sunrise, $fajr_rounding);
     206        if ($latest_fajr) {
     207            $latest_fajr = muslprti_round_up($latest_fajr, $fajr_rounding);
     208        }
     209        if ($latest_sunrise) {
     210            $latest_sunrise = muslprti_round_down($latest_sunrise, $fajr_rounding);
     211        }
    196212    }
    197213   
     
    201217        $day_fajr_athan = $day_data['athan']['fajr'];
    202218       
     219        // Check if this day is during Ramadan
     220        $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_date, $opts);
     221       
    203222        // Determine iqama time based on rule
    204         if ($is_weekly) {
     223        if ($is_ramadan) {
     224            // Ramadan: always daily, after athan with Ramadan-specific settings
     225            $day_fajr_iqama = muslprti_round_up(clone $day_fajr_athan, $ramadan_fajr_rounding);
     226            $day_fajr_iqama->modify("+{$ramadan_fajr_minutes} minutes");
     227        } else if ($is_weekly) {
    205228            // Weekly calculation - use consistent time derived from latest athan/sunrise
    206229            if ($fajr_rule === 'after_athan') {
     
    244267        $max_fajr_time->setTime((int)$hours, (int)$minutes);
    245268       
    246         // Apply minimum constraint: use the greater of calculated time or min_fajr_time
    247         if (muslprti_time_to_minutes($day_fajr_iqama) < muslprti_time_to_minutes($min_fajr_time)) {
    248             $day_fajr_iqama = $min_fajr_time;
    249         }
    250        
    251         // Apply maximum constraint: use the lesser of result or max_fajr_time
    252         if (muslprti_time_to_minutes($day_fajr_iqama) > muslprti_time_to_minutes($max_fajr_time)) {
    253             $day_fajr_iqama = $max_fajr_time;
     269        // Apply minimum/maximum constraints (skip during Ramadan to allow custom times)
     270        if (!$is_ramadan) {
     271            // Apply minimum constraint: use the greater of calculated time or min_fajr_time
     272            if (muslprti_time_to_minutes($day_fajr_iqama) < muslprti_time_to_minutes($min_fajr_time)) {
     273                $day_fajr_iqama = $min_fajr_time;
     274            }
     275           
     276            // Apply maximum constraint: use the lesser of result or max_fajr_time
     277            if (muslprti_time_to_minutes($day_fajr_iqama) > muslprti_time_to_minutes($max_fajr_time)) {
     278                $day_fajr_iqama = $max_fajr_time;
     279            }
    254280        }
    255281       
     
    400426    $results = [];
    401427   
     428    // Get settings for Ramadan detection
     429    $opts = get_option('muslprti_settings', []);
     430    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     431    $ramadan_maghrib_minutes = isset($opts['ramadan_maghrib_minutes_after']) ? $opts['ramadan_maghrib_minutes_after'] : 10;
     432    $ramadan_maghrib_rounding = isset($opts['ramadan_maghrib_rounding']) ? $opts['ramadan_maghrib_rounding'] : 1;
     433   
    402434    // Use the new helper function to normalize all times
    403435    $normalized_days_data = muslprti_normalize_times_for_dst($days_data);
    404436   
    405     // Find latest Athan for weekly calculation
     437    // Find latest Athan for weekly calculation (only for non-Ramadan days)
    406438    $latest_maghrib = null;
    407439   
    408440    if ($is_weekly) {
    409441        foreach ($normalized_days_data as $day_data) {
     442            // Skip Ramadan days when finding weekly maximum
     443            $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_data['date'], $opts);
     444            if ($is_ramadan) {
     445                continue;
     446            }
     447           
    410448            if ($latest_maghrib === null ||
    411449                muslprti_time_to_minutes($day_data['athan']['maghrib']) > muslprti_time_to_minutes($latest_maghrib)) {
     
    415453       
    416454        // Apply rounding to the latest time
    417         $latest_maghrib = muslprti_round_up($latest_maghrib, $maghrib_rounding);
     455        if ($latest_maghrib) {
     456            $latest_maghrib = muslprti_round_up($latest_maghrib, $maghrib_rounding);
     457        }
    418458    }
    419459   
     
    423463        $day_maghrib_athan = $day_data['athan']['maghrib'];
    424464       
     465        // Check if this day is during Ramadan
     466        $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_date, $opts);
     467       
    425468        // Maghrib is always calculated as minutes after Athan
    426         if ($is_weekly) {
     469        if ($is_ramadan) {
     470            // Ramadan: always daily with Ramadan-specific settings
     471            $day_maghrib_iqama = muslprti_round_up(clone $day_maghrib_athan, $ramadan_maghrib_rounding);
     472            $day_maghrib_iqama->modify("+{$ramadan_maghrib_minutes} minutes");
     473        } else if ($is_weekly) {
    427474            // Use latest maghrib time + minutes for all days
    428475            $time_components = explode(':', $latest_maghrib->format('H:i'));
     
    450497    $results = [];
    451498   
     499    // Get settings for Ramadan detection
     500    $opts = get_option('muslprti_settings', []);
     501    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     502    $ramadan_isha_minutes = isset($opts['ramadan_isha_minutes_after']) ? $opts['ramadan_isha_minutes_after'] : 20;
     503    $ramadan_isha_rounding = isset($opts['ramadan_isha_rounding']) ? $opts['ramadan_isha_rounding'] : 1;
     504   
    452505    // Use the new helper function to normalize all times
    453506    $normalized_days_data = muslprti_normalize_times_for_dst($days_data);
    454507   
    455     // Find latest Athan for weekly calculation
     508    // Find latest Athan for weekly calculation (only for non-Ramadan days)
    456509    $latest_isha = null;
    457510   
    458511    if ($is_weekly) {
    459512        foreach ($normalized_days_data as $day_data) {
     513            // Skip Ramadan days when finding weekly maximum
     514            $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_data['date'], $opts);
     515            if ($is_ramadan) {
     516                continue;
     517            }
     518           
    460519            if ($latest_isha === null ||
    461520                muslprti_time_to_minutes($day_data['athan']['isha']) > muslprti_time_to_minutes($latest_isha)) {
     
    465524       
    466525        // Apply rounding to the latest time
    467         $latest_isha = muslprti_round_up($latest_isha, $isha_rounding);
     526        if ($latest_isha) {
     527            $latest_isha = muslprti_round_up($latest_isha, $isha_rounding);
     528        }
    468529    }
    469530   
     
    473534        $day_isha_athan = $day_data['athan']['isha'];
    474535       
     536        // Check if this day is during Ramadan
     537        $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_date, $opts);
     538       
    475539        // Determine iqama time based on rule
    476         if ($is_weekly) {
     540        if ($is_ramadan) {
     541            // Ramadan: always daily, after athan with Ramadan-specific settings
     542            $day_isha_iqama = muslprti_round_up(clone $day_isha_athan, $ramadan_isha_rounding);
     543            $day_isha_iqama->modify("+{$ramadan_isha_minutes} minutes");
     544        } else if ($is_weekly) {
    477545            // Weekly calculation
    478546            if ($isha_rule === 'after_athan') {
     
    491559        }
    492560       
     561        // Denormalize the result to account for DST before applying constraints
     562        // Use the original date for denormalization to maintain correct DST information
     563        $day_isha_iqama = muslprti_denormalize_time_for_dst($day_isha_iqama);
     564       
    493565        // Create min_isha_time and max_isha_time as DateTime objects
    494566        $min_isha_time = clone $day_date;
    495567        list($hours, $minutes) = explode(':', $isha_min_time);
    496568        $min_isha_time->setTime((int)$hours, (int)$minutes);
    497         $min_isha_time = muslprti_normalize_time_for_dst($min_isha_time);
    498569       
    499570        $max_isha_time = clone $day_date;
    500571        list($hours, $minutes) = explode(':', $isha_max_time);
    501572        $max_isha_time->setTime((int)$hours, (int)$minutes);
    502         $max_isha_time = muslprti_normalize_time_for_dst($max_isha_time);
    503        
    504         // Use the greater of either athan+minutes or min_isha_time
    505         if (muslprti_time_to_minutes($day_isha_iqama) < muslprti_time_to_minutes($min_isha_time)) {
    506             $day_isha_iqama = $min_isha_time;
    507         }
    508        
    509         // Apply max time constraint
    510         if (muslprti_time_to_minutes($day_isha_iqama) > muslprti_time_to_minutes($max_isha_time)) {
    511             $day_isha_iqama = $max_isha_time;
    512         }
    513        
    514         // Denormalize the result to account for DST before storing
    515         // Use the original date for denormalization to maintain correct DST information
    516         $day_isha_iqama = muslprti_denormalize_time_for_dst($day_isha_iqama);
     573       
     574        // Apply minimum/maximum constraints (skip during Ramadan to allow custom times)
     575        if (!$is_ramadan) {
     576            // Apply minimum constraint: use the greater of calculated time or min_isha_time
     577            if (muslprti_time_to_minutes($day_isha_iqama) < muslprti_time_to_minutes($min_isha_time)) {
     578                $day_isha_iqama = $min_isha_time;
     579            }
     580           
     581            // Apply maximum constraint: use the lesser of result or max_isha_time
     582            if (muslprti_time_to_minutes($day_isha_iqama) > muslprti_time_to_minutes($max_isha_time)) {
     583                $day_isha_iqama = $max_isha_time;
     584            }
     585        }
    517586       
    518587        $results[$day_index] = $day_isha_iqama;
     
    570639    return $tz;
    571640}
     641
     642/**
     643 * Detect if a given date falls within Ramadan
     644 *
     645 * @param string|DateTime $date Date to check
     646 * @param array $opts Plugin settings array (optional, will fetch if not provided)
     647 * @return bool True if date is in Ramadan
     648 */
     649function muslprti_is_ramadan_date($date, $opts = null) {
     650    if ($opts === null) {
     651        $opts = get_option('muslprti_settings', []);
     652    }
     653   
     654    // Check if Ramadan rules are enabled
     655    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     656    if (!$ramadan_enabled) {
     657        return false;
     658    }
     659   
     660    // Convert to DateTime if needed
     661    if (is_string($date)) {
     662        $date = new DateTime($date, new DateTimeZone(muslprti_get_timezone()));
     663    }
     664   
     665    $date_string = $date->format('Y-m-d');
     666   
     667    // Check manual date range if not auto-detecting
     668    $ramadan_auto_detect = isset($opts['ramadan_auto_detect']) ? $opts['ramadan_auto_detect'] : true;
     669   
     670    if (!$ramadan_auto_detect) {
     671        $start = isset($opts['ramadan_manual_start']) ? $opts['ramadan_manual_start'] : '';
     672        $end = isset($opts['ramadan_manual_end']) ? $opts['ramadan_manual_end'] : '';
     673       
     674        if (!empty($start) && !empty($end)) {
     675            return ($date_string >= $start && $date_string <= $end);
     676        }
     677        return false;
     678    }
     679   
     680    // Auto-detect using Hijri calendar
     681    // Load Hijri date converter if not already loaded
     682    if (!function_exists('muslprti_convert_to_hijri')) {
     683        require_once __DIR__ . '/hijri-date-converter.php';
     684    }
     685   
     686    $hijri_offset = isset($opts['hijri_offset']) ? intval($opts['hijri_offset']) : 0;
     687    $hijri_date = muslprti_convert_to_hijri($date, false, 'en', $hijri_offset);
     688   
     689    // Ramadan is month 9 in Islamic calendar
     690    return ($hijri_date['month'] == 9);
     691}
     692
     693/**
     694 * Get Ramadan date range for a given Gregorian year
     695 *
     696 * @param int $gregorian_year Year to check
     697 * @param array $opts Plugin settings (optional, will fetch if not provided)
     698 * @return array|false Array with 'start' and 'end' dates (Y-m-d format), or false if not found
     699 */
     700function muslprti_get_ramadan_dates($gregorian_year, $opts = null) {
     701    if ($opts === null) {
     702        $opts = get_option('muslprti_settings', []);
     703    }
     704   
     705    // Check cache first
     706    $cache_key = 'muslprti_ramadan_dates_' . $gregorian_year;
     707    $cached = wp_cache_get($cache_key, 'muslim_prayer_times');
     708   
     709    if ($cached !== false) {
     710        return $cached;
     711    }
     712   
     713    // Load Hijri date converter if not already loaded
     714    if (!function_exists('muslprti_convert_to_hijri')) {
     715        require_once __DIR__ . '/hijri-date-converter.php';
     716    }
     717   
     718    $hijri_offset = isset($opts['hijri_offset']) ? intval($opts['hijri_offset']) : 0;
     719    $timezone = muslprti_get_timezone();
     720   
     721    // Search for first day of Ramadan in the year
     722    $start_date = new DateTime("$gregorian_year-01-01", new DateTimeZone($timezone));
     723    $end_date = new DateTime("$gregorian_year-12-31", new DateTimeZone($timezone));
     724   
     725    $ramadan_start = null;
     726    $ramadan_end = null;
     727   
     728    $current = clone $start_date;
     729    while ($current <= $end_date) {
     730        $hijri = muslprti_convert_to_hijri($current, false, 'en', $hijri_offset);
     731       
     732        if ($hijri['month'] == 9) {
     733            if ($ramadan_start === null) {
     734                $ramadan_start = clone $current;
     735            }
     736            $ramadan_end = clone $current;
     737        } elseif ($ramadan_start !== null) {
     738            // We've exited Ramadan
     739            break;
     740        }
     741       
     742        $current->modify('+1 day');
     743    }
     744   
     745    $result = false;
     746    if ($ramadan_start && $ramadan_end) {
     747        $result = [
     748            'start' => $ramadan_start->format('Y-m-d'),
     749            'end' => $ramadan_end->format('Y-m-d')
     750        ];
     751    }
     752   
     753    // Cache for 24 hours (86400 seconds)
     754    wp_cache_set($cache_key, $result, 'muslim_prayer_times', 86400);
     755   
     756    return $result;
     757}
  • muslim-prayer-times/tags/1.1/muslim-prayer-times.php

    r3307273 r3382962  
    44Plugin URI: https://github.com/stankovski/wp-prayer-times
    55Description: A WordPress plugin for managing and displaying Islamic prayer times.
    6 Version: 1.0.2
     6Version: 1.1
    77Requires at least: 5.0
    88Requires PHP: 7.0
     
    1515if (!defined('ABSPATH')) exit;
    1616
    17 // Import the PrayerTimes class
    18 use IslamicNetwork\PrayerTimes\PrayerTimes;
     17// Import the PrayerTimes2 class
     18use IslamicNetwork\PrayerTimes\PrayerTimes2;
    1919
    2020// Define table name as a constant
  • muslim-prayer-times/tags/1.1/readme.txt

    r3382840 r3382962  
    44Requires at least: 5.0
    55Tested up to: 6.8.3
    6 Stable tag: 1.0.2
     6Stable tag: 1.1
    77Requires PHP: 7.0
    88License: MIT
     
    151151Initial release of Muslim Prayer Times plugin.
    152152
    153 = 1.0.3 =
     153= 1.0.2 =
    154154Bug fixes.
     155
     156= 1.1 =
     157* Added support for Ramadan overwrites
     158* Added High Latitude Adjustment Method
  • muslim-prayer-times/tags/1.1/settings-ajax.php

    r3382840 r3382962  
    33if (!defined('ABSPATH')) exit;
    44
    5 use IslamicNetwork\PrayerTimes\PrayerTimes;
     5use IslamicNetwork\PrayerTimes\PrayerTimes2;
    66
    77// Include helper functions
     
    6969        require_once __DIR__ . '/includes/islamic-network/autoload.php';
    7070       
    71         if (!class_exists('IslamicNetwork\PrayerTimes\PrayerTimes')) {
     71        if (!class_exists('IslamicNetwork\PrayerTimes\PrayerTimes2')) {
    7272            wp_send_json_error(esc_html__('Muslim Prayer Times library not available', 'muslim-prayer-times'));
    7373            return;
     
    133133        }
    134134       
    135         // Initialize the PrayerTimes object
    136         $pt = new PrayerTimes($method, $asr_calc);
     135        // Initialize the PrayerTimes2 object
     136        $pt = new PrayerTimes2($method, $asr_calc);
    137137       
    138138        // Prepare CSV data
     
    212212            }
    213213           
     214            // Get latitude adjustment method from settings
     215            $latitude_adjustment = isset($opts['latitude_adjustment']) ? $opts['latitude_adjustment'] : 'MOTN';
     216           
     217            // Convert string to constant
     218            $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_MOTN; // default
     219            switch ($latitude_adjustment) {
     220                case 'NONE':
     221                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_NONE;
     222                    break;
     223                case 'MOTN':
     224                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_MOTN;
     225                    break;
     226                case 'ANGLE':
     227                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_ANGLE;
     228                    break;
     229                case 'ONESEVENTH':
     230                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_ONESEVENTH;
     231                    break;
     232            }
     233           
    214234            // Get prayer times for the current day
    215235            $times = $pt->getTimes(
     
    218238                floatval($longitude),
    219239                null,
    220                 PrayerTimes::LATITUDE_ADJUSTMENT_METHOD_ANGLE,
    221                 PrayerTimes::MIDNIGHT_MODE_STANDARD,
    222                 PrayerTimes::TIME_FORMAT_24H
     240                $latitude_adjustment_const,
     241                PrayerTimes2::MIDNIGHT_MODE_STANDARD,
     242                PrayerTimes2::TIME_FORMAT_24H
    223243            );
    224244           
  • muslim-prayer-times/tags/1.1/settings.php

    r3382840 r3382962  
    33if (!defined('ABSPATH')) exit;
    44
    5 use IslamicNetwork\PrayerTimes\PrayerTimes;
     5use IslamicNetwork\PrayerTimes\PrayerTimes2;
    66
    77// Include the admin AJAX handlers
     
    190190                $('div[data-parent=\"' + name + '\"][data-show-for=\"' + value + '\"]').show();
    191191            });
     192           
     193            // Handle Ramadan settings visibility
     194            $('#muslprti_ramadan_enabled').change(function() {
     195                if ($(this).is(':checked')) {
     196                    $('.ramadan-settings-container').slideDown();
     197                } else {
     198                    $('.ramadan-settings-container').slideUp();
     199                }
     200            });
    192201        });
    193202    ";
     
    346355        $opts['method'] = isset($_POST['muslprti_method']) ? sanitize_text_field(wp_unslash($_POST['muslprti_method'])) : 'ISNA';
    347356        $opts['asr_calc'] = isset($_POST['muslprti_asr_calc']) ? sanitize_text_field(wp_unslash($_POST['muslprti_asr_calc'])) : 'STANDARD';
     357        $opts['latitude_adjustment'] = isset($_POST['muslprti_latitude_adjustment']) ? sanitize_text_field(wp_unslash($_POST['muslprti_latitude_adjustment'])) : 'MOTN';
    348358       
    349359        // Save Hijri day offset
     
    410420        $opts['isha_rounding'] = isset($_POST['muslprti_isha_rounding']) ? intval(wp_unslash($_POST['muslprti_isha_rounding'])) : 1;
    411421       
     422        // Ramadan settings
     423        $opts['ramadan_enabled'] = isset($_POST['muslprti_ramadan_enabled']) ? 1 : 0;
     424        $opts['ramadan_auto_detect'] = isset($_POST['muslprti_ramadan_auto_detect']) ? intval(wp_unslash($_POST['muslprti_ramadan_auto_detect'])) : 1;
     425        $opts['ramadan_manual_start'] = isset($_POST['muslprti_ramadan_manual_start']) ? sanitize_text_field(wp_unslash($_POST['muslprti_ramadan_manual_start'])) : '';
     426        $opts['ramadan_manual_end'] = isset($_POST['muslprti_ramadan_manual_end']) ? sanitize_text_field(wp_unslash($_POST['muslprti_ramadan_manual_end'])) : '';
     427        $opts['ramadan_fajr_minutes_after'] = isset($_POST['muslprti_ramadan_fajr_minutes_after']) ? intval(wp_unslash($_POST['muslprti_ramadan_fajr_minutes_after'])) : 20;
     428        $opts['ramadan_maghrib_minutes_after'] = isset($_POST['muslprti_ramadan_maghrib_minutes_after']) ? intval(wp_unslash($_POST['muslprti_ramadan_maghrib_minutes_after'])) : 10;
     429        $opts['ramadan_isha_minutes_after'] = isset($_POST['muslprti_ramadan_isha_minutes_after']) ? intval(wp_unslash($_POST['muslprti_ramadan_isha_minutes_after'])) : 20;
     430        $opts['ramadan_fajr_rounding'] = isset($_POST['muslprti_ramadan_fajr_rounding']) ? intval(wp_unslash($_POST['muslprti_ramadan_fajr_rounding'])) : 1;
     431        $opts['ramadan_maghrib_rounding'] = isset($_POST['muslprti_ramadan_maghrib_rounding']) ? intval(wp_unslash($_POST['muslprti_ramadan_maghrib_rounding'])) : 1;
     432        $opts['ramadan_isha_rounding'] = isset($_POST['muslprti_ramadan_isha_rounding']) ? intval(wp_unslash($_POST['muslprti_ramadan_isha_rounding'])) : 1;
     433       
    412434        update_option('muslprti_settings', $opts);
    413435        echo '<div class="updated"><p>Iqama rules settings saved.</p></div>';
     
    421443    $method = isset($opts['method']) ? $opts['method'] : 'ISNA';
    422444    $asr_calc = isset($opts['asr_calc']) ? $opts['asr_calc'] : 'STANDARD';
     445    $latitude_adjustment = isset($opts['latitude_adjustment']) ? $opts['latitude_adjustment'] : 'MOTN';
    423446    $hijri_offset = isset($opts['hijri_offset']) ? $opts['hijri_offset'] : 0;
    424447    $time_format = isset($opts['time_format']) ? $opts['time_format'] : '12hour';
     
    505528    $isha_daily_change = isset($opts['isha_daily_change']) ? $opts['isha_daily_change'] : 0;
    506529    $isha_rounding = isset($opts['isha_rounding']) ? $opts['isha_rounding'] : 1;
     530   
     531    // Ramadan defaults
     532    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : 0;
     533    $ramadan_auto_detect = isset($opts['ramadan_auto_detect']) ? $opts['ramadan_auto_detect'] : 1;
     534    $ramadan_manual_start = isset($opts['ramadan_manual_start']) ? $opts['ramadan_manual_start'] : '';
     535    $ramadan_manual_end = isset($opts['ramadan_manual_end']) ? $opts['ramadan_manual_end'] : '';
     536    $ramadan_fajr_minutes_after = isset($opts['ramadan_fajr_minutes_after']) ? $opts['ramadan_fajr_minutes_after'] : 20;
     537    $ramadan_maghrib_minutes_after = isset($opts['ramadan_maghrib_minutes_after']) ? $opts['ramadan_maghrib_minutes_after'] : 10;
     538    $ramadan_isha_minutes_after = isset($opts['ramadan_isha_minutes_after']) ? $opts['ramadan_isha_minutes_after'] : 20;
     539    $ramadan_fajr_rounding = isset($opts['ramadan_fajr_rounding']) ? $opts['ramadan_fajr_rounding'] : 1;
     540    $ramadan_maghrib_rounding = isset($opts['ramadan_maghrib_rounding']) ? $opts['ramadan_maghrib_rounding'] : 1;
     541    $ramadan_isha_rounding = isset($opts['ramadan_isha_rounding']) ? $opts['ramadan_isha_rounding'] : 1;
    507542    ?>
    508543    <div class="wrap">
     
    608643                        </tr>
    609644                        <tr>
     645                            <th scope="row"><label for="muslprti_latitude_adjustment">High Latitude Adjustment Method</label></th>
     646                            <td>
     647                                <select id="muslprti_latitude_adjustment" name="muslprti_latitude_adjustment">
     648                                    <option value="MOTN" <?php selected($latitude_adjustment, 'MOTN'); ?>>Middle of the Night (Recommended)</option>
     649                                    <option value="ANGLE" <?php selected($latitude_adjustment, 'ANGLE'); ?>>Angle Based</option>
     650                                    <option value="ONESEVENTH" <?php selected($latitude_adjustment, 'ONESEVENTH'); ?>>One Seventh</option>
     651                                    <option value="NONE" <?php selected($latitude_adjustment, 'NONE'); ?>>None</option>
     652                                </select>
     653                                <p class="description">Method for calculating Fajr and Isha times at high latitudes (above 48°).<br>Middle of the Night is the default used by most Islamic organizations.</p>
     654                            </td>
     655                        </tr>
     656                        <tr>
    610657                            <th scope="row"><label for="muslprti_hijri_offset">Hijri Day Offset</label></th>
    611658                            <td>
     
    886933                            </p>
    887934                            <p class="description">These settings ensure Isha Iqama is never before the minimum time or after the maximum time.</p>
     935                        </div>
     936                    </div>
     937                   
     938                    <div class="iqama-rule-section">
     939                        <h2>Ramadan Custom Iqama Rules</h2>
     940                        <p class="description">During Ramadan, you may want different iqama calculation rules. Enable this section to override Fajr, Maghrib, and Isha calculations during Ramadan with daily changes.</p>
     941                       
     942                        <div class="iqama-rule-option">
     943                            <label>
     944                                <input type="checkbox" id="muslprti_ramadan_enabled" name="muslprti_ramadan_enabled" value="1" <?php checked($ramadan_enabled, 1); ?>>
     945                                <strong>Enable Ramadan custom iqama rules</strong>
     946                            </label>
     947                        </div>
     948                       
     949                        <div class="ramadan-settings-container" style="<?php echo $ramadan_enabled ? '' : 'display:none;'; ?>">
     950                            <h3>Ramadan Date Detection</h3>
     951                            <div class="iqama-rule-option">
     952                                <label>
     953                                    <input type="radio" name="muslprti_ramadan_auto_detect" value="1" <?php checked($ramadan_auto_detect, 1); ?>>
     954                                    Automatically detect Ramadan using Hijri calendar
     955                                </label>
     956                                <p class="description">Uses your Hijri offset setting from General Settings to detect Ramadan dates.</p>
     957                            </div>
     958                           
     959                            <div class="iqama-rule-option">
     960                                <label>
     961                                    <input type="radio" name="muslprti_ramadan_auto_detect" value="0" <?php checked($ramadan_auto_detect, 0); ?>>
     962                                    Manually specify Ramadan date range
     963                                </label>
     964                                <div class="field-container" style="margin-left: 25px; margin-top: 10px;">
     965                                    <label>Start Date: <input type="date" name="muslprti_ramadan_manual_start" value="<?php echo esc_attr($ramadan_manual_start); ?>"></label><br>
     966                                    <label>End Date: <input type="date" name="muslprti_ramadan_manual_end" value="<?php echo esc_attr($ramadan_manual_end); ?>"></label>
     967                                </div>
     968                            </div>
     969                           
     970                            <div id="ramadan-date-info" class="hijri-preview" style="margin-top: 10px;">
     971                                <?php
     972                                // Display current/next Ramadan dates
     973                                require_once plugin_dir_path(__FILE__) . 'includes/helpers.php';
     974                                $current_year = intval(muslprti_date('Y'));
     975                                $ramadan_dates = muslprti_get_ramadan_dates($current_year, $opts);
     976                               
     977                                if ($ramadan_dates) {
     978                                    echo sprintf(
     979                                        'Ramadan %d: %s to %s',
     980                                        $current_year,
     981                                        esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['start']))),
     982                                        esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['end'])))
     983                                    );
     984                                } else {
     985                                    $ramadan_dates = muslprti_get_ramadan_dates($current_year + 1, $opts);
     986                                    if ($ramadan_dates) {
     987                                        echo sprintf(
     988                                            'Next Ramadan (%d): %s to %s',
     989                                            $current_year + 1,
     990                                            esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['start']))),
     991                                            esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['end'])))
     992                                        );
     993                                    }
     994                                }
     995                                ?>
     996                            </div>
     997                           
     998                            <h3>Fajr Iqama During Ramadan</h3>
     999                            <div class="iqama-rule-option">
     1000                                <p>During Ramadan, Fajr iqama will be calculated <strong>daily</strong> as:</p>
     1001                                <input type="number" name="muslprti_ramadan_fajr_minutes_after" value="<?php echo esc_attr($ramadan_fajr_minutes_after); ?>" min="0" max="120">
     1002                                minutes after Fajr Athan
     1003                            </div>
     1004                            <div class="iqama-rule-option">
     1005                                <label>Round to:
     1006                                    <select name="muslprti_ramadan_fajr_rounding">
     1007                                        <option value="1" <?php selected($ramadan_fajr_rounding, 1); ?>>1 minute</option>
     1008                                        <option value="5" <?php selected($ramadan_fajr_rounding, 5); ?>>5 minutes</option>
     1009                                        <option value="15" <?php selected($ramadan_fajr_rounding, 15); ?>>15 minutes</option>
     1010                                        <option value="30" <?php selected($ramadan_fajr_rounding, 30); ?>>30 minutes</option>
     1011                                    </select>
     1012                                </label>
     1013                            </div>
     1014                           
     1015                            <h3>Maghrib Iqama During Ramadan</h3>
     1016                            <div class="iqama-rule-option">
     1017                                <p>During Ramadan, Maghrib iqama (Iftar time) will be calculated <strong>daily</strong> as:</p>
     1018                                <input type="number" name="muslprti_ramadan_maghrib_minutes_after" value="<?php echo esc_attr($ramadan_maghrib_minutes_after); ?>" min="0" max="30">
     1019                                minutes after Maghrib Athan
     1020                            </div>
     1021                            <div class="iqama-rule-option">
     1022                                <label>Round to:
     1023                                    <select name="muslprti_ramadan_maghrib_rounding">
     1024                                        <option value="1" <?php selected($ramadan_maghrib_rounding, 1); ?>>1 minute</option>
     1025                                        <option value="5" <?php selected($ramadan_maghrib_rounding, 5); ?>>5 minutes</option>
     1026                                        <option value="15" <?php selected($ramadan_maghrib_rounding, 15); ?>>15 minutes</option>
     1027                                        <option value="30" <?php selected($ramadan_maghrib_rounding, 30); ?>>30 minutes</option>
     1028                                    </select>
     1029                                </label>
     1030                            </div>
     1031                           
     1032                            <h3>Isha Iqama During Ramadan</h3>
     1033                            <div class="iqama-rule-option">
     1034                                <p>During Ramadan, Isha iqama (Taraweeh time) will be calculated <strong>daily</strong> as:</p>
     1035                                <input type="number" name="muslprti_ramadan_isha_minutes_after" value="<?php echo esc_attr($ramadan_isha_minutes_after); ?>" min="0" max="120">
     1036                                minutes after Isha Athan
     1037                            </div>
     1038                            <div class="iqama-rule-option">
     1039                                <label>Round to:
     1040                                    <select name="muslprti_ramadan_isha_rounding">
     1041                                        <option value="1" <?php selected($ramadan_isha_rounding, 1); ?>>1 minute</option>
     1042                                        <option value="5" <?php selected($ramadan_isha_rounding, 5); ?>>5 minutes</option>
     1043                                        <option value="15" <?php selected($ramadan_isha_rounding, 15); ?>>15 minutes</option>
     1044                                        <option value="30" <?php selected($ramadan_isha_rounding, 30); ?>>30 minutes</option>
     1045                                    </select>
     1046                                </label>
     1047                            </div>
     1048                           
     1049                            <p class="description"><strong>Note:</strong> Dhuhr and Asr prayers will continue to use the regular iqama rules defined above, even during Ramadan. Fajr, Maghrib, and Isha min/max constraints (if set above) still apply during Ramadan.</p>
    8881050                        </div>
    8891051                    </div>
  • muslim-prayer-times/trunk/includes/helpers.php

    r3382840 r3382962  
    172172    $results = [];
    173173   
     174    // Get settings for Ramadan detection
     175    $opts = get_option('muslprti_settings', []);
     176    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     177    $ramadan_fajr_minutes = isset($opts['ramadan_fajr_minutes_after']) ? $opts['ramadan_fajr_minutes_after'] : 20;
     178    $ramadan_fajr_rounding = isset($opts['ramadan_fajr_rounding']) ? $opts['ramadan_fajr_rounding'] : 1;
     179   
    174180    // Use the new helper function to normalize all times
    175181    $normalized_days_data = muslprti_normalize_times_for_dst($days_data);
    176182   
    177     // Find latest Athan for weekly calculation
     183    // Find latest Athan for weekly calculation (only for non-Ramadan days)
    178184    $latest_fajr = null;
    179185    $latest_sunrise = null;
     
    181187    if ($is_weekly) {
    182188        foreach ($normalized_days_data as $day_data) {
     189            // Skip Ramadan days when finding weekly maximum
     190            $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_data['date'], $opts);
     191            if ($is_ramadan) {
     192                continue;
     193            }
     194           
    183195            if ($latest_fajr === null ||
    184196                muslprti_time_to_minutes($day_data['athan']['fajr']) > muslprti_time_to_minutes($latest_fajr)) {
     
    192204       
    193205        // Apply rounding to the latest times
    194         $latest_fajr = muslprti_round_up($latest_fajr, $fajr_rounding);
    195         $latest_sunrise = muslprti_round_down($latest_sunrise, $fajr_rounding);
     206        if ($latest_fajr) {
     207            $latest_fajr = muslprti_round_up($latest_fajr, $fajr_rounding);
     208        }
     209        if ($latest_sunrise) {
     210            $latest_sunrise = muslprti_round_down($latest_sunrise, $fajr_rounding);
     211        }
    196212    }
    197213   
     
    201217        $day_fajr_athan = $day_data['athan']['fajr'];
    202218       
     219        // Check if this day is during Ramadan
     220        $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_date, $opts);
     221       
    203222        // Determine iqama time based on rule
    204         if ($is_weekly) {
     223        if ($is_ramadan) {
     224            // Ramadan: always daily, after athan with Ramadan-specific settings
     225            $day_fajr_iqama = muslprti_round_up(clone $day_fajr_athan, $ramadan_fajr_rounding);
     226            $day_fajr_iqama->modify("+{$ramadan_fajr_minutes} minutes");
     227        } else if ($is_weekly) {
    205228            // Weekly calculation - use consistent time derived from latest athan/sunrise
    206229            if ($fajr_rule === 'after_athan') {
     
    244267        $max_fajr_time->setTime((int)$hours, (int)$minutes);
    245268       
    246         // Apply minimum constraint: use the greater of calculated time or min_fajr_time
    247         if (muslprti_time_to_minutes($day_fajr_iqama) < muslprti_time_to_minutes($min_fajr_time)) {
    248             $day_fajr_iqama = $min_fajr_time;
    249         }
    250        
    251         // Apply maximum constraint: use the lesser of result or max_fajr_time
    252         if (muslprti_time_to_minutes($day_fajr_iqama) > muslprti_time_to_minutes($max_fajr_time)) {
    253             $day_fajr_iqama = $max_fajr_time;
     269        // Apply minimum/maximum constraints (skip during Ramadan to allow custom times)
     270        if (!$is_ramadan) {
     271            // Apply minimum constraint: use the greater of calculated time or min_fajr_time
     272            if (muslprti_time_to_minutes($day_fajr_iqama) < muslprti_time_to_minutes($min_fajr_time)) {
     273                $day_fajr_iqama = $min_fajr_time;
     274            }
     275           
     276            // Apply maximum constraint: use the lesser of result or max_fajr_time
     277            if (muslprti_time_to_minutes($day_fajr_iqama) > muslprti_time_to_minutes($max_fajr_time)) {
     278                $day_fajr_iqama = $max_fajr_time;
     279            }
    254280        }
    255281       
     
    400426    $results = [];
    401427   
     428    // Get settings for Ramadan detection
     429    $opts = get_option('muslprti_settings', []);
     430    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     431    $ramadan_maghrib_minutes = isset($opts['ramadan_maghrib_minutes_after']) ? $opts['ramadan_maghrib_minutes_after'] : 10;
     432    $ramadan_maghrib_rounding = isset($opts['ramadan_maghrib_rounding']) ? $opts['ramadan_maghrib_rounding'] : 1;
     433   
    402434    // Use the new helper function to normalize all times
    403435    $normalized_days_data = muslprti_normalize_times_for_dst($days_data);
    404436   
    405     // Find latest Athan for weekly calculation
     437    // Find latest Athan for weekly calculation (only for non-Ramadan days)
    406438    $latest_maghrib = null;
    407439   
    408440    if ($is_weekly) {
    409441        foreach ($normalized_days_data as $day_data) {
     442            // Skip Ramadan days when finding weekly maximum
     443            $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_data['date'], $opts);
     444            if ($is_ramadan) {
     445                continue;
     446            }
     447           
    410448            if ($latest_maghrib === null ||
    411449                muslprti_time_to_minutes($day_data['athan']['maghrib']) > muslprti_time_to_minutes($latest_maghrib)) {
     
    415453       
    416454        // Apply rounding to the latest time
    417         $latest_maghrib = muslprti_round_up($latest_maghrib, $maghrib_rounding);
     455        if ($latest_maghrib) {
     456            $latest_maghrib = muslprti_round_up($latest_maghrib, $maghrib_rounding);
     457        }
    418458    }
    419459   
     
    423463        $day_maghrib_athan = $day_data['athan']['maghrib'];
    424464       
     465        // Check if this day is during Ramadan
     466        $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_date, $opts);
     467       
    425468        // Maghrib is always calculated as minutes after Athan
    426         if ($is_weekly) {
     469        if ($is_ramadan) {
     470            // Ramadan: always daily with Ramadan-specific settings
     471            $day_maghrib_iqama = muslprti_round_up(clone $day_maghrib_athan, $ramadan_maghrib_rounding);
     472            $day_maghrib_iqama->modify("+{$ramadan_maghrib_minutes} minutes");
     473        } else if ($is_weekly) {
    427474            // Use latest maghrib time + minutes for all days
    428475            $time_components = explode(':', $latest_maghrib->format('H:i'));
     
    450497    $results = [];
    451498   
     499    // Get settings for Ramadan detection
     500    $opts = get_option('muslprti_settings', []);
     501    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     502    $ramadan_isha_minutes = isset($opts['ramadan_isha_minutes_after']) ? $opts['ramadan_isha_minutes_after'] : 20;
     503    $ramadan_isha_rounding = isset($opts['ramadan_isha_rounding']) ? $opts['ramadan_isha_rounding'] : 1;
     504   
    452505    // Use the new helper function to normalize all times
    453506    $normalized_days_data = muslprti_normalize_times_for_dst($days_data);
    454507   
    455     // Find latest Athan for weekly calculation
     508    // Find latest Athan for weekly calculation (only for non-Ramadan days)
    456509    $latest_isha = null;
    457510   
    458511    if ($is_weekly) {
    459512        foreach ($normalized_days_data as $day_data) {
     513            // Skip Ramadan days when finding weekly maximum
     514            $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_data['date'], $opts);
     515            if ($is_ramadan) {
     516                continue;
     517            }
     518           
    460519            if ($latest_isha === null ||
    461520                muslprti_time_to_minutes($day_data['athan']['isha']) > muslprti_time_to_minutes($latest_isha)) {
     
    465524       
    466525        // Apply rounding to the latest time
    467         $latest_isha = muslprti_round_up($latest_isha, $isha_rounding);
     526        if ($latest_isha) {
     527            $latest_isha = muslprti_round_up($latest_isha, $isha_rounding);
     528        }
    468529    }
    469530   
     
    473534        $day_isha_athan = $day_data['athan']['isha'];
    474535       
     536        // Check if this day is during Ramadan
     537        $is_ramadan = $ramadan_enabled && muslprti_is_ramadan_date($day_date, $opts);
     538       
    475539        // Determine iqama time based on rule
    476         if ($is_weekly) {
     540        if ($is_ramadan) {
     541            // Ramadan: always daily, after athan with Ramadan-specific settings
     542            $day_isha_iqama = muslprti_round_up(clone $day_isha_athan, $ramadan_isha_rounding);
     543            $day_isha_iqama->modify("+{$ramadan_isha_minutes} minutes");
     544        } else if ($is_weekly) {
    477545            // Weekly calculation
    478546            if ($isha_rule === 'after_athan') {
     
    491559        }
    492560       
     561        // Denormalize the result to account for DST before applying constraints
     562        // Use the original date for denormalization to maintain correct DST information
     563        $day_isha_iqama = muslprti_denormalize_time_for_dst($day_isha_iqama);
     564       
    493565        // Create min_isha_time and max_isha_time as DateTime objects
    494566        $min_isha_time = clone $day_date;
    495567        list($hours, $minutes) = explode(':', $isha_min_time);
    496568        $min_isha_time->setTime((int)$hours, (int)$minutes);
    497         $min_isha_time = muslprti_normalize_time_for_dst($min_isha_time);
    498569       
    499570        $max_isha_time = clone $day_date;
    500571        list($hours, $minutes) = explode(':', $isha_max_time);
    501572        $max_isha_time->setTime((int)$hours, (int)$minutes);
    502         $max_isha_time = muslprti_normalize_time_for_dst($max_isha_time);
    503        
    504         // Use the greater of either athan+minutes or min_isha_time
    505         if (muslprti_time_to_minutes($day_isha_iqama) < muslprti_time_to_minutes($min_isha_time)) {
    506             $day_isha_iqama = $min_isha_time;
    507         }
    508        
    509         // Apply max time constraint
    510         if (muslprti_time_to_minutes($day_isha_iqama) > muslprti_time_to_minutes($max_isha_time)) {
    511             $day_isha_iqama = $max_isha_time;
    512         }
    513        
    514         // Denormalize the result to account for DST before storing
    515         // Use the original date for denormalization to maintain correct DST information
    516         $day_isha_iqama = muslprti_denormalize_time_for_dst($day_isha_iqama);
     573       
     574        // Apply minimum/maximum constraints (skip during Ramadan to allow custom times)
     575        if (!$is_ramadan) {
     576            // Apply minimum constraint: use the greater of calculated time or min_isha_time
     577            if (muslprti_time_to_minutes($day_isha_iqama) < muslprti_time_to_minutes($min_isha_time)) {
     578                $day_isha_iqama = $min_isha_time;
     579            }
     580           
     581            // Apply maximum constraint: use the lesser of result or max_isha_time
     582            if (muslprti_time_to_minutes($day_isha_iqama) > muslprti_time_to_minutes($max_isha_time)) {
     583                $day_isha_iqama = $max_isha_time;
     584            }
     585        }
    517586       
    518587        $results[$day_index] = $day_isha_iqama;
     
    570639    return $tz;
    571640}
     641
     642/**
     643 * Detect if a given date falls within Ramadan
     644 *
     645 * @param string|DateTime $date Date to check
     646 * @param array $opts Plugin settings array (optional, will fetch if not provided)
     647 * @return bool True if date is in Ramadan
     648 */
     649function muslprti_is_ramadan_date($date, $opts = null) {
     650    if ($opts === null) {
     651        $opts = get_option('muslprti_settings', []);
     652    }
     653   
     654    // Check if Ramadan rules are enabled
     655    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : false;
     656    if (!$ramadan_enabled) {
     657        return false;
     658    }
     659   
     660    // Convert to DateTime if needed
     661    if (is_string($date)) {
     662        $date = new DateTime($date, new DateTimeZone(muslprti_get_timezone()));
     663    }
     664   
     665    $date_string = $date->format('Y-m-d');
     666   
     667    // Check manual date range if not auto-detecting
     668    $ramadan_auto_detect = isset($opts['ramadan_auto_detect']) ? $opts['ramadan_auto_detect'] : true;
     669   
     670    if (!$ramadan_auto_detect) {
     671        $start = isset($opts['ramadan_manual_start']) ? $opts['ramadan_manual_start'] : '';
     672        $end = isset($opts['ramadan_manual_end']) ? $opts['ramadan_manual_end'] : '';
     673       
     674        if (!empty($start) && !empty($end)) {
     675            return ($date_string >= $start && $date_string <= $end);
     676        }
     677        return false;
     678    }
     679   
     680    // Auto-detect using Hijri calendar
     681    // Load Hijri date converter if not already loaded
     682    if (!function_exists('muslprti_convert_to_hijri')) {
     683        require_once __DIR__ . '/hijri-date-converter.php';
     684    }
     685   
     686    $hijri_offset = isset($opts['hijri_offset']) ? intval($opts['hijri_offset']) : 0;
     687    $hijri_date = muslprti_convert_to_hijri($date, false, 'en', $hijri_offset);
     688   
     689    // Ramadan is month 9 in Islamic calendar
     690    return ($hijri_date['month'] == 9);
     691}
     692
     693/**
     694 * Get Ramadan date range for a given Gregorian year
     695 *
     696 * @param int $gregorian_year Year to check
     697 * @param array $opts Plugin settings (optional, will fetch if not provided)
     698 * @return array|false Array with 'start' and 'end' dates (Y-m-d format), or false if not found
     699 */
     700function muslprti_get_ramadan_dates($gregorian_year, $opts = null) {
     701    if ($opts === null) {
     702        $opts = get_option('muslprti_settings', []);
     703    }
     704   
     705    // Check cache first
     706    $cache_key = 'muslprti_ramadan_dates_' . $gregorian_year;
     707    $cached = wp_cache_get($cache_key, 'muslim_prayer_times');
     708   
     709    if ($cached !== false) {
     710        return $cached;
     711    }
     712   
     713    // Load Hijri date converter if not already loaded
     714    if (!function_exists('muslprti_convert_to_hijri')) {
     715        require_once __DIR__ . '/hijri-date-converter.php';
     716    }
     717   
     718    $hijri_offset = isset($opts['hijri_offset']) ? intval($opts['hijri_offset']) : 0;
     719    $timezone = muslprti_get_timezone();
     720   
     721    // Search for first day of Ramadan in the year
     722    $start_date = new DateTime("$gregorian_year-01-01", new DateTimeZone($timezone));
     723    $end_date = new DateTime("$gregorian_year-12-31", new DateTimeZone($timezone));
     724   
     725    $ramadan_start = null;
     726    $ramadan_end = null;
     727   
     728    $current = clone $start_date;
     729    while ($current <= $end_date) {
     730        $hijri = muslprti_convert_to_hijri($current, false, 'en', $hijri_offset);
     731       
     732        if ($hijri['month'] == 9) {
     733            if ($ramadan_start === null) {
     734                $ramadan_start = clone $current;
     735            }
     736            $ramadan_end = clone $current;
     737        } elseif ($ramadan_start !== null) {
     738            // We've exited Ramadan
     739            break;
     740        }
     741       
     742        $current->modify('+1 day');
     743    }
     744   
     745    $result = false;
     746    if ($ramadan_start && $ramadan_end) {
     747        $result = [
     748            'start' => $ramadan_start->format('Y-m-d'),
     749            'end' => $ramadan_end->format('Y-m-d')
     750        ];
     751    }
     752   
     753    // Cache for 24 hours (86400 seconds)
     754    wp_cache_set($cache_key, $result, 'muslim_prayer_times', 86400);
     755   
     756    return $result;
     757}
  • muslim-prayer-times/trunk/muslim-prayer-times.php

    r3307273 r3382962  
    44Plugin URI: https://github.com/stankovski/wp-prayer-times
    55Description: A WordPress plugin for managing and displaying Islamic prayer times.
    6 Version: 1.0.2
     6Version: 1.1
    77Requires at least: 5.0
    88Requires PHP: 7.0
     
    1515if (!defined('ABSPATH')) exit;
    1616
    17 // Import the PrayerTimes class
    18 use IslamicNetwork\PrayerTimes\PrayerTimes;
     17// Import the PrayerTimes2 class
     18use IslamicNetwork\PrayerTimes\PrayerTimes2;
    1919
    2020// Define table name as a constant
  • muslim-prayer-times/trunk/readme.txt

    r3382840 r3382962  
    44Requires at least: 5.0
    55Tested up to: 6.8.3
    6 Stable tag: 1.0.2
     6Stable tag: 1.1
    77Requires PHP: 7.0
    88License: MIT
     
    151151Initial release of Muslim Prayer Times plugin.
    152152
    153 = 1.0.3 =
     153= 1.0.2 =
    154154Bug fixes.
     155
     156= 1.1 =
     157* Added support for Ramadan overwrites
     158* Added High Latitude Adjustment Method
  • muslim-prayer-times/trunk/settings-ajax.php

    r3382840 r3382962  
    33if (!defined('ABSPATH')) exit;
    44
    5 use IslamicNetwork\PrayerTimes\PrayerTimes;
     5use IslamicNetwork\PrayerTimes\PrayerTimes2;
    66
    77// Include helper functions
     
    6969        require_once __DIR__ . '/includes/islamic-network/autoload.php';
    7070       
    71         if (!class_exists('IslamicNetwork\PrayerTimes\PrayerTimes')) {
     71        if (!class_exists('IslamicNetwork\PrayerTimes\PrayerTimes2')) {
    7272            wp_send_json_error(esc_html__('Muslim Prayer Times library not available', 'muslim-prayer-times'));
    7373            return;
     
    133133        }
    134134       
    135         // Initialize the PrayerTimes object
    136         $pt = new PrayerTimes($method, $asr_calc);
     135        // Initialize the PrayerTimes2 object
     136        $pt = new PrayerTimes2($method, $asr_calc);
    137137       
    138138        // Prepare CSV data
     
    212212            }
    213213           
     214            // Get latitude adjustment method from settings
     215            $latitude_adjustment = isset($opts['latitude_adjustment']) ? $opts['latitude_adjustment'] : 'MOTN';
     216           
     217            // Convert string to constant
     218            $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_MOTN; // default
     219            switch ($latitude_adjustment) {
     220                case 'NONE':
     221                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_NONE;
     222                    break;
     223                case 'MOTN':
     224                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_MOTN;
     225                    break;
     226                case 'ANGLE':
     227                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_ANGLE;
     228                    break;
     229                case 'ONESEVENTH':
     230                    $latitude_adjustment_const = PrayerTimes2::LATITUDE_ADJUSTMENT_METHOD_ONESEVENTH;
     231                    break;
     232            }
     233           
    214234            // Get prayer times for the current day
    215235            $times = $pt->getTimes(
     
    218238                floatval($longitude),
    219239                null,
    220                 PrayerTimes::LATITUDE_ADJUSTMENT_METHOD_ANGLE,
    221                 PrayerTimes::MIDNIGHT_MODE_STANDARD,
    222                 PrayerTimes::TIME_FORMAT_24H
     240                $latitude_adjustment_const,
     241                PrayerTimes2::MIDNIGHT_MODE_STANDARD,
     242                PrayerTimes2::TIME_FORMAT_24H
    223243            );
    224244           
  • muslim-prayer-times/trunk/settings.php

    r3382840 r3382962  
    33if (!defined('ABSPATH')) exit;
    44
    5 use IslamicNetwork\PrayerTimes\PrayerTimes;
     5use IslamicNetwork\PrayerTimes\PrayerTimes2;
    66
    77// Include the admin AJAX handlers
     
    190190                $('div[data-parent=\"' + name + '\"][data-show-for=\"' + value + '\"]').show();
    191191            });
     192           
     193            // Handle Ramadan settings visibility
     194            $('#muslprti_ramadan_enabled').change(function() {
     195                if ($(this).is(':checked')) {
     196                    $('.ramadan-settings-container').slideDown();
     197                } else {
     198                    $('.ramadan-settings-container').slideUp();
     199                }
     200            });
    192201        });
    193202    ";
     
    346355        $opts['method'] = isset($_POST['muslprti_method']) ? sanitize_text_field(wp_unslash($_POST['muslprti_method'])) : 'ISNA';
    347356        $opts['asr_calc'] = isset($_POST['muslprti_asr_calc']) ? sanitize_text_field(wp_unslash($_POST['muslprti_asr_calc'])) : 'STANDARD';
     357        $opts['latitude_adjustment'] = isset($_POST['muslprti_latitude_adjustment']) ? sanitize_text_field(wp_unslash($_POST['muslprti_latitude_adjustment'])) : 'MOTN';
    348358       
    349359        // Save Hijri day offset
     
    410420        $opts['isha_rounding'] = isset($_POST['muslprti_isha_rounding']) ? intval(wp_unslash($_POST['muslprti_isha_rounding'])) : 1;
    411421       
     422        // Ramadan settings
     423        $opts['ramadan_enabled'] = isset($_POST['muslprti_ramadan_enabled']) ? 1 : 0;
     424        $opts['ramadan_auto_detect'] = isset($_POST['muslprti_ramadan_auto_detect']) ? intval(wp_unslash($_POST['muslprti_ramadan_auto_detect'])) : 1;
     425        $opts['ramadan_manual_start'] = isset($_POST['muslprti_ramadan_manual_start']) ? sanitize_text_field(wp_unslash($_POST['muslprti_ramadan_manual_start'])) : '';
     426        $opts['ramadan_manual_end'] = isset($_POST['muslprti_ramadan_manual_end']) ? sanitize_text_field(wp_unslash($_POST['muslprti_ramadan_manual_end'])) : '';
     427        $opts['ramadan_fajr_minutes_after'] = isset($_POST['muslprti_ramadan_fajr_minutes_after']) ? intval(wp_unslash($_POST['muslprti_ramadan_fajr_minutes_after'])) : 20;
     428        $opts['ramadan_maghrib_minutes_after'] = isset($_POST['muslprti_ramadan_maghrib_minutes_after']) ? intval(wp_unslash($_POST['muslprti_ramadan_maghrib_minutes_after'])) : 10;
     429        $opts['ramadan_isha_minutes_after'] = isset($_POST['muslprti_ramadan_isha_minutes_after']) ? intval(wp_unslash($_POST['muslprti_ramadan_isha_minutes_after'])) : 20;
     430        $opts['ramadan_fajr_rounding'] = isset($_POST['muslprti_ramadan_fajr_rounding']) ? intval(wp_unslash($_POST['muslprti_ramadan_fajr_rounding'])) : 1;
     431        $opts['ramadan_maghrib_rounding'] = isset($_POST['muslprti_ramadan_maghrib_rounding']) ? intval(wp_unslash($_POST['muslprti_ramadan_maghrib_rounding'])) : 1;
     432        $opts['ramadan_isha_rounding'] = isset($_POST['muslprti_ramadan_isha_rounding']) ? intval(wp_unslash($_POST['muslprti_ramadan_isha_rounding'])) : 1;
     433       
    412434        update_option('muslprti_settings', $opts);
    413435        echo '<div class="updated"><p>Iqama rules settings saved.</p></div>';
     
    421443    $method = isset($opts['method']) ? $opts['method'] : 'ISNA';
    422444    $asr_calc = isset($opts['asr_calc']) ? $opts['asr_calc'] : 'STANDARD';
     445    $latitude_adjustment = isset($opts['latitude_adjustment']) ? $opts['latitude_adjustment'] : 'MOTN';
    423446    $hijri_offset = isset($opts['hijri_offset']) ? $opts['hijri_offset'] : 0;
    424447    $time_format = isset($opts['time_format']) ? $opts['time_format'] : '12hour';
     
    505528    $isha_daily_change = isset($opts['isha_daily_change']) ? $opts['isha_daily_change'] : 0;
    506529    $isha_rounding = isset($opts['isha_rounding']) ? $opts['isha_rounding'] : 1;
     530   
     531    // Ramadan defaults
     532    $ramadan_enabled = isset($opts['ramadan_enabled']) ? $opts['ramadan_enabled'] : 0;
     533    $ramadan_auto_detect = isset($opts['ramadan_auto_detect']) ? $opts['ramadan_auto_detect'] : 1;
     534    $ramadan_manual_start = isset($opts['ramadan_manual_start']) ? $opts['ramadan_manual_start'] : '';
     535    $ramadan_manual_end = isset($opts['ramadan_manual_end']) ? $opts['ramadan_manual_end'] : '';
     536    $ramadan_fajr_minutes_after = isset($opts['ramadan_fajr_minutes_after']) ? $opts['ramadan_fajr_minutes_after'] : 20;
     537    $ramadan_maghrib_minutes_after = isset($opts['ramadan_maghrib_minutes_after']) ? $opts['ramadan_maghrib_minutes_after'] : 10;
     538    $ramadan_isha_minutes_after = isset($opts['ramadan_isha_minutes_after']) ? $opts['ramadan_isha_minutes_after'] : 20;
     539    $ramadan_fajr_rounding = isset($opts['ramadan_fajr_rounding']) ? $opts['ramadan_fajr_rounding'] : 1;
     540    $ramadan_maghrib_rounding = isset($opts['ramadan_maghrib_rounding']) ? $opts['ramadan_maghrib_rounding'] : 1;
     541    $ramadan_isha_rounding = isset($opts['ramadan_isha_rounding']) ? $opts['ramadan_isha_rounding'] : 1;
    507542    ?>
    508543    <div class="wrap">
     
    608643                        </tr>
    609644                        <tr>
     645                            <th scope="row"><label for="muslprti_latitude_adjustment">High Latitude Adjustment Method</label></th>
     646                            <td>
     647                                <select id="muslprti_latitude_adjustment" name="muslprti_latitude_adjustment">
     648                                    <option value="MOTN" <?php selected($latitude_adjustment, 'MOTN'); ?>>Middle of the Night (Recommended)</option>
     649                                    <option value="ANGLE" <?php selected($latitude_adjustment, 'ANGLE'); ?>>Angle Based</option>
     650                                    <option value="ONESEVENTH" <?php selected($latitude_adjustment, 'ONESEVENTH'); ?>>One Seventh</option>
     651                                    <option value="NONE" <?php selected($latitude_adjustment, 'NONE'); ?>>None</option>
     652                                </select>
     653                                <p class="description">Method for calculating Fajr and Isha times at high latitudes (above 48°).<br>Middle of the Night is the default used by most Islamic organizations.</p>
     654                            </td>
     655                        </tr>
     656                        <tr>
    610657                            <th scope="row"><label for="muslprti_hijri_offset">Hijri Day Offset</label></th>
    611658                            <td>
     
    886933                            </p>
    887934                            <p class="description">These settings ensure Isha Iqama is never before the minimum time or after the maximum time.</p>
     935                        </div>
     936                    </div>
     937                   
     938                    <div class="iqama-rule-section">
     939                        <h2>Ramadan Custom Iqama Rules</h2>
     940                        <p class="description">During Ramadan, you may want different iqama calculation rules. Enable this section to override Fajr, Maghrib, and Isha calculations during Ramadan with daily changes.</p>
     941                       
     942                        <div class="iqama-rule-option">
     943                            <label>
     944                                <input type="checkbox" id="muslprti_ramadan_enabled" name="muslprti_ramadan_enabled" value="1" <?php checked($ramadan_enabled, 1); ?>>
     945                                <strong>Enable Ramadan custom iqama rules</strong>
     946                            </label>
     947                        </div>
     948                       
     949                        <div class="ramadan-settings-container" style="<?php echo $ramadan_enabled ? '' : 'display:none;'; ?>">
     950                            <h3>Ramadan Date Detection</h3>
     951                            <div class="iqama-rule-option">
     952                                <label>
     953                                    <input type="radio" name="muslprti_ramadan_auto_detect" value="1" <?php checked($ramadan_auto_detect, 1); ?>>
     954                                    Automatically detect Ramadan using Hijri calendar
     955                                </label>
     956                                <p class="description">Uses your Hijri offset setting from General Settings to detect Ramadan dates.</p>
     957                            </div>
     958                           
     959                            <div class="iqama-rule-option">
     960                                <label>
     961                                    <input type="radio" name="muslprti_ramadan_auto_detect" value="0" <?php checked($ramadan_auto_detect, 0); ?>>
     962                                    Manually specify Ramadan date range
     963                                </label>
     964                                <div class="field-container" style="margin-left: 25px; margin-top: 10px;">
     965                                    <label>Start Date: <input type="date" name="muslprti_ramadan_manual_start" value="<?php echo esc_attr($ramadan_manual_start); ?>"></label><br>
     966                                    <label>End Date: <input type="date" name="muslprti_ramadan_manual_end" value="<?php echo esc_attr($ramadan_manual_end); ?>"></label>
     967                                </div>
     968                            </div>
     969                           
     970                            <div id="ramadan-date-info" class="hijri-preview" style="margin-top: 10px;">
     971                                <?php
     972                                // Display current/next Ramadan dates
     973                                require_once plugin_dir_path(__FILE__) . 'includes/helpers.php';
     974                                $current_year = intval(muslprti_date('Y'));
     975                                $ramadan_dates = muslprti_get_ramadan_dates($current_year, $opts);
     976                               
     977                                if ($ramadan_dates) {
     978                                    echo sprintf(
     979                                        'Ramadan %d: %s to %s',
     980                                        $current_year,
     981                                        esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['start']))),
     982                                        esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['end'])))
     983                                    );
     984                                } else {
     985                                    $ramadan_dates = muslprti_get_ramadan_dates($current_year + 1, $opts);
     986                                    if ($ramadan_dates) {
     987                                        echo sprintf(
     988                                            'Next Ramadan (%d): %s to %s',
     989                                            $current_year + 1,
     990                                            esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['start']))),
     991                                            esc_html(muslprti_date('F j, Y', strtotime($ramadan_dates['end'])))
     992                                        );
     993                                    }
     994                                }
     995                                ?>
     996                            </div>
     997                           
     998                            <h3>Fajr Iqama During Ramadan</h3>
     999                            <div class="iqama-rule-option">
     1000                                <p>During Ramadan, Fajr iqama will be calculated <strong>daily</strong> as:</p>
     1001                                <input type="number" name="muslprti_ramadan_fajr_minutes_after" value="<?php echo esc_attr($ramadan_fajr_minutes_after); ?>" min="0" max="120">
     1002                                minutes after Fajr Athan
     1003                            </div>
     1004                            <div class="iqama-rule-option">
     1005                                <label>Round to:
     1006                                    <select name="muslprti_ramadan_fajr_rounding">
     1007                                        <option value="1" <?php selected($ramadan_fajr_rounding, 1); ?>>1 minute</option>
     1008                                        <option value="5" <?php selected($ramadan_fajr_rounding, 5); ?>>5 minutes</option>
     1009                                        <option value="15" <?php selected($ramadan_fajr_rounding, 15); ?>>15 minutes</option>
     1010                                        <option value="30" <?php selected($ramadan_fajr_rounding, 30); ?>>30 minutes</option>
     1011                                    </select>
     1012                                </label>
     1013                            </div>
     1014                           
     1015                            <h3>Maghrib Iqama During Ramadan</h3>
     1016                            <div class="iqama-rule-option">
     1017                                <p>During Ramadan, Maghrib iqama (Iftar time) will be calculated <strong>daily</strong> as:</p>
     1018                                <input type="number" name="muslprti_ramadan_maghrib_minutes_after" value="<?php echo esc_attr($ramadan_maghrib_minutes_after); ?>" min="0" max="30">
     1019                                minutes after Maghrib Athan
     1020                            </div>
     1021                            <div class="iqama-rule-option">
     1022                                <label>Round to:
     1023                                    <select name="muslprti_ramadan_maghrib_rounding">
     1024                                        <option value="1" <?php selected($ramadan_maghrib_rounding, 1); ?>>1 minute</option>
     1025                                        <option value="5" <?php selected($ramadan_maghrib_rounding, 5); ?>>5 minutes</option>
     1026                                        <option value="15" <?php selected($ramadan_maghrib_rounding, 15); ?>>15 minutes</option>
     1027                                        <option value="30" <?php selected($ramadan_maghrib_rounding, 30); ?>>30 minutes</option>
     1028                                    </select>
     1029                                </label>
     1030                            </div>
     1031                           
     1032                            <h3>Isha Iqama During Ramadan</h3>
     1033                            <div class="iqama-rule-option">
     1034                                <p>During Ramadan, Isha iqama (Taraweeh time) will be calculated <strong>daily</strong> as:</p>
     1035                                <input type="number" name="muslprti_ramadan_isha_minutes_after" value="<?php echo esc_attr($ramadan_isha_minutes_after); ?>" min="0" max="120">
     1036                                minutes after Isha Athan
     1037                            </div>
     1038                            <div class="iqama-rule-option">
     1039                                <label>Round to:
     1040                                    <select name="muslprti_ramadan_isha_rounding">
     1041                                        <option value="1" <?php selected($ramadan_isha_rounding, 1); ?>>1 minute</option>
     1042                                        <option value="5" <?php selected($ramadan_isha_rounding, 5); ?>>5 minutes</option>
     1043                                        <option value="15" <?php selected($ramadan_isha_rounding, 15); ?>>15 minutes</option>
     1044                                        <option value="30" <?php selected($ramadan_isha_rounding, 30); ?>>30 minutes</option>
     1045                                    </select>
     1046                                </label>
     1047                            </div>
     1048                           
     1049                            <p class="description"><strong>Note:</strong> Dhuhr and Asr prayers will continue to use the regular iqama rules defined above, even during Ramadan. Fajr, Maghrib, and Isha min/max constraints (if set above) still apply during Ramadan.</p>
    8881050                        </div>
    8891051                    </div>
Note: See TracChangeset for help on using the changeset viewer.