Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
wp-content
/
plugins
/
vikbooking
/
admin
/
helpers
:
festivities.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * @package VikBooking * @subpackage com_vikbooking * @author Alessio Gaggii - e4j - Extensionsforjoomla.com * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE * @link https://vikwp.com */ defined('ABSPATH') or die('No script kiddies please!'); /** * Check whether we can extend the VCM's main Festivities class * or if we need to define a new middle-man class just to make VBO work. * The main class VikBookingFestivities is declared at the bottom of the file. */ $vcm_festivites = false; if (is_file(VCM_ADMIN_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'festivities.php')) { if (!class_exists('VCMFestivities')) { require_once(VCM_ADMIN_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'festivities.php'); } if (method_exists('VCMFestivities', 'getInstance')) { // VCM is up to date and so we can extend its main class for the festivites $vcm_festivites = true; } } if ($vcm_festivites === true) { // we can use the updated, native and main class of VCM class VikBookingFestivitiesBC extends VCMFestivities { } } else { /** * VCM missing/outdated. We need to define the old class for backward compatibility. * The class of VCM has to be the MAIN one, so all festivities should be * declared there and the new class VikBookingFestivities will extend it. */ class VikBookingFestivitiesBC { /** * The singleton instance of the class. * * @var VCMFestivities */ protected static $instance = null; /** * The (current) timestamp from which the class * should calculate the closest festivities. * * @var int */ protected $now; /** * Whether the class should translate the names * of the festivities. False by default in this BC class. * * @var boolean */ public $translate = false; /** * The list of all the supported regions for the festivities. * * @var array */ protected $regions = array( 'global' => 'GLOBAL', 'ita' => 'ITA', 'fra' => 'FRA', 'ger' => 'GER', 'spa' => 'SPA', 'usa' => 'USA' ); /** * The list of all the supported festivities. * * @var array */ protected $festivities = array( 'newYearsDay' => array( 'regions' => array('global'), 'mon' => 1, 'mday' => 1 ), 'epiphany' => array( 'regions' => array('global'), 'mon' => 1, 'mday' => 6 ), 'mlkDay' => array( 'regions' => array('usa'), 'func' => 'getMLKDate' //3rd monday of January ), 'valentinesDay' => array( 'regions' => array('global'), 'mon' => 2, 'mday' => 14 ), 'presidentsDay' => array( 'regions' => array('usa'), 'func' => 'getPresidentsDate' //3rd monday of February ), 'rosenmontag' => array( 'regions' => array('ger'), 'func' => 'getRosenmontagDate' //monday before Ash Wednesday (7th week before Easter) ), 'mardiGras' => array( 'regions' => array('global'), 'func' => 'getMardigrasDate' //tuesday before Ash Wednesday (7th week before Easter) ), 'easter' => array( 'regions' => array('global'), 'func' => 'getEasterDate' ), 'endofwarita' => array( 'regions' => array('ita'), 'mon' => 4, 'mday' => 25 ), 'walpurgisNight'=> array( 'regions' => array('ger'), 'mon' => 4, 'mday' => 30 ), 'dayOfWork' => array( 'regions' => array('ita', 'fra', 'ger'), 'mon' => 5, 'mday' => 1 ), 'cincomayo' => array( 'regions' => array('usa'), 'mon' => 5, 'mday' => 5 ), 'vedayfra' => array( 'regions' => array('fra'), 'mon' => 5, 'mday' => 8 ), 'memorialDay' => array( 'regions' => array('usa'), 'func' => 'getMemorialDate' //last monday of May ), 'republicDay' => array( 'regions' => array('ita'), 'mon' => 6, 'mday' => 2 ), '4thJuly' => array( 'regions' => array('usa'), 'mon' => 7, 'mday' => 4 ), 'bastilleDay' => array( 'regions' => array('fra'), 'mon' => 7, 'mday' => 14 ), 'ferragosto' => array( 'regions' => array('ita'), 'mon' => 8, 'mday' => 15 ), 'laborDay' => array( 'regions' => array('usa'), 'func' => 'getLaborDate' //1st Monday of September ), 'columbusDay' => array( 'regions' => array('usa'), 'func' => 'getColumbusDate' //2nd Monday of October ), 'hispanityDay' => array( 'regions' => array('spa'), 'mon' => 10, 'mday' => 12, ), 'halloween' => array( 'regions' => array('global'), 'mon' => 10, 'mday' => 31, 'bridge' => array('saintsDay', 'soulsDay') ), 'saintsDay' => array( 'regions' => array('ita'), 'mon' => 11, 'mday' => 1, 'bridge' => array('soulsDay') ), 'soulsDay' => array( 'regions' => array('ita'), 'mon' => 11, 'mday' => 2 ), 'wallOfBerlin' => array( 'regions' => array('ger'), 'mon' => 11, 'mday' => 9 ), 'armisticeDay' => array( 'regions' => array('fra'), 'mon' => 11, 'mday' => 11 ), 'veteransDay' => array( 'regions' => array('usa'), 'mon' => 11, 'mday' => 11 ), 'thanksgiving' => array( 'regions' => array('usa'), 'func' => 'getThanksgivingDate' //4th Thursday of November ), 'immacolata' => array( 'regions' => array('ita', 'spa'), 'mon' => 12, 'mday' => 8 ), 'christmasEve' => array( 'regions' => array('global'), 'mon' => 12, 'mday' => 24, 'bridge' => array('christmasDay', 'stStephensDay', 'newYearsEve', 'newYearsDay') ), 'christmasDay' => array( 'regions' => array('global'), 'mon' => 12, 'mday' => 25, 'bridge' => array('stStephensDay', 'newYearsEve', 'newYearsDay') ), 'stStephensDay' => array( 'regions' => array('global'), 'mon' => 12, 'mday' => 26, 'bridge' => array('newYearsEve', 'newYearsDay') ), 'newYearsEve' => array( 'regions' => array('global'), 'mon' => 12, 'mday' => 31, 'bridge' => array('newYearsDay') ), ); /** * Class constructor is still public, even though * it is possible to access the Singletone instance * of the class through the method getInstance(). * * @see getInstance() * @since VCM 1.6.13 */ public function __construct() { $this->now = time(); } /** * Returns the global class object, either * a new instance or the existing instance * if the class was already instantiated. * This method was introduced in the v 1.6.13 for * VBO to check whether the class can be extended. * It used to have private vars and methods that * have now been changed to protected. * * @return self A new instance of the class. * * @since VCM 1.6.13 */ public static function getInstance() { if (is_null(static::$instance)) { static::$instance = new static(); } return static::$instance; } /** * Method to set the current timestamp from which * the class should find the closest festivities. * * @param int $from_ts * * @return self */ public function setFromTimestamp($from_ts) { if (!empty($from_ts)) { $this->now = $from_ts; } return $this; } /** * Returns all the supported regions with * the corresponding translated names. * * @return array */ public function getTranslatedRegions() { $trans_regions = $this->regions; foreach ($trans_regions as $k => $v) { if ($this->translate) { $say_name = JText::translate('VCMFEST'.strtoupper($v)); // make sure the lang definition is available $say_name = substr($say_name, 0, 7) == 'VCMFEST' ? $k : $say_name; } else { $say_name = $k; } $trans_regions[$k] = $say_name; } return $trans_regions; } /** * Main method to get a list of the closest festivities * for the given region, starting from the current timestamp. * * @param string [$region] * * @return array */ public function loadFestivities($region = 'global') { return $this->calculateFestivititesDates( $this->getFestivitiesByRegion(strtolower($region)) ); } /** * Method that filters the festivities by the * requested region or the global ones. * * @param string $region * * @return array */ protected function getFestivitiesByRegion($region) { $fests = array(); foreach ($this->festivities as $k => $v) { if ($v['regions'][0] == 'global' || in_array($region, $v['regions'])) { $fests[$k] = $v; } } return $fests; } /** * Method that parses all the region-filtered festivities to * calculate the next timestamp for each fest and the end date, * by setting the properties 'from_ts' and 'to_ts' for each fest. * Ex. If a holiday is on Monday, the method sets the dates to Sat-Mon. * Ex. If a holiday is on Thursday, the method sets the dates to Thu-Sat. * Ex. If a holiday is on Friday, the method sets the dates to Fri-Sat. * The method returns a sorted and filtered array of key-value pairs with * some new properties: 'next_ts', 'from_ts', 'to_ts', 'wday', 'trans_name'. * * @param array $regions_festivities (global festivities + region's festivities) * * @return array */ protected function calculateFestivititesDates($regions_festivities) { $fests = array(); $info_from = getdate($this->now); //calculate the next timestamp from today of each festivity ('from_ts') foreach ($regions_festivities as $k => $v) { if (isset($v['func'])) { //custom function if (!method_exists($this, $v['func']) || !is_callable(array($this, $v['func']))) { continue; } $next_ts = $this->{$v['func']}(); } else { //fixed month and month-day $next_ts = mktime(0, 0, 0, $v['mon'], $v['mday'], $info_from['year']); if ($next_ts < $this->now) { $next_ts = mktime(0, 0, 0, $v['mon'], $v['mday'], ($info_from['year'] + 1)); } } if (empty($next_ts)) { continue; } $info_next = getdate($next_ts); $v['wday'] = $info_next['wday']; $v['from_ts'] = $v['next_ts'] = $next_ts; $regions_festivities[$k] = $v; $fests[$k] = $v; } // //calculate the end date for each festivity by considering weekends and bridges ('to_ts', and 'from_ts', if necessary) foreach ($fests as $k => $v) { $info_date = getdate($v['from_ts']); if ((int)$info_date['wday'] < 2) { //Festivity is on a Sunday or a Monday, switch 'from_ts' to the Saturday before $fests[$k]['from_ts'] = mktime(0, 0, 0, $info_date['mon'], ($info_date['mday'] - ((int)$info_date['wday'] + 1)), $info_date['year']); } if (isset($v['bridge']) && count($v['bridge'])) { //Check next bridges of this festivity $bridges_ts = array(); foreach ($v['bridge'] as $fest_key) { if (isset($fests[$fest_key]) && isset($fests[$fest_key]['from_ts'])) { $bridges_ts[] = $regions_festivities[$fest_key]['from_ts']; } } if (count($bridges_ts)) { //bridges found: set the 'to_ts' to the last festivity of the bridge and continue $info_max = getdate(max($bridges_ts)); $fests[$k]['to_ts'] = mktime(23, 59, 59, $info_max['mon'], $info_max['mday'], $info_max['year']); continue; } } if ((int)$info_date['wday'] == 4) { //Festivity is on a Thursday, set 'to_ts' to the Saturday after $fests[$k]['to_ts'] = mktime(0, 0, 0, $info_date['mon'], ($info_date['mday'] + 2), $info_date['year']); continue; } if ((int)$info_date['wday'] == 5) { //Festivity is on a Friday, set 'to_ts' to the Saturday after $fests[$k]['to_ts'] = mktime(0, 0, 0, $info_date['mon'], ($info_date['mday'] + 1), $info_date['year']); continue; } //no bridges, set 'to_ts' to the end of the same day at 23:59:59 $fests[$k]['to_ts'] = mktime(23, 59, 59, $info_date['mon'], $info_date['mday'], $info_date['year']); } // // sorting and translation $sort_map = array(); foreach ($fests as $k => $v) { $sort_map[$k] = $v['next_ts']; if ($this->translate) { $say_name = JText::translate('VCMFEST'.strtoupper($k)); // make sure the lang definition is available $say_name = substr($say_name, 0, 7) == 'VCMFEST' ? $k : $say_name; } else { $say_name = $k; } $fests[$k]['trans_name'] = $say_name; } asort($sort_map); $sorted_fests = array(); foreach ($sort_map as $k => $v) { $sorted_fests[$k] = $fests[$k]; } $fests = $sorted_fests; return $fests; } /** * Custom method that returns the next Easter ts. * We use easter_days() to get the number of days where Easter * falls after March 21st of the given year. * * @return int */ public function getEasterDate() { $next_ts = mktime(0, 0, 0, 3, (21 + easter_days(date('Y', $this->now))), date('Y', $this->now)); if ($next_ts < $this->now) { $next_ts = mktime(0, 0, 0, 3, (21 + easter_days(((int)date('Y', $this->now) + 1))), ((int)date('Y', $this->now) + 1)); } return $next_ts; } /** * Custom method that returns the Rosenmontag ts. * (Monday before the Ash Wednesday, 7th week before Easter) * * @return int */ public function getRosenmontagDate() { $eightw_easter = getdate(strtotime('-7 weeks', mktime(0, 0, 0, 3, (21 + easter_days(date('Y', $this->now))), date('Y', $this->now)))); $next_ts = mktime(0, 0, 0, $eightw_easter['mon'], ($eightw_easter['mday'] + 1), $eightw_easter['year']); if ($next_ts < $this->now) { $eightw_easter = getdate(strtotime('-7 weeks', mktime(0, 0, 0, 3, (21 + easter_days(((int)date('Y', $this->now) + 1))), ((int)date('Y', $this->now) + 1)))); $next_ts = mktime(0, 0, 0, $eightw_easter['mon'], ($eightw_easter['mday'] + 1), $eightw_easter['year']); } return $next_ts; } /** * Custom method that returns the Mardi Gras ts. * (Tuesday before the Ash Wednesday, 7th week before Easter) * * @return int */ public function getMardigrasDate() { $eightw_easter = getdate(strtotime('-7 weeks', mktime(0, 0, 0, 3, (21 + easter_days(date('Y', $this->now))), date('Y', $this->now)))); $next_ts = mktime(0, 0, 0, $eightw_easter['mon'], ($eightw_easter['mday'] + 2), $eightw_easter['year']); if ($next_ts < $this->now) { $eightw_easter = getdate(strtotime('-7 weeks', mktime(0, 0, 0, 3, (21 + easter_days(((int)date('Y', $this->now) + 1))), ((int)date('Y', $this->now) + 1)))); $next_ts = mktime(0, 0, 0, $eightw_easter['mon'], ($eightw_easter['mday'] + 2), $eightw_easter['year']); } return $next_ts; } /** * Custom method that returns the next ts for the * Martin Luther King's Day (3rd Monday of January). * * @return int */ public function getMLKDate() { $next_ts = strtotime('third Monday of January '.date('Y', $this->now)); if (!empty($next_ts) && $next_ts < $this->now) { $next_ts = strtotime('third Monday of January '.((int)date('Y', $this->now) + 1)); } return $next_ts; } /** * Custom method that returns the next ts for the * President's Day (3rd Monday of February). * * @return int */ public function getPresidentsDate() { $next_ts = strtotime('third Monday of February '.date('Y', $this->now)); if (!empty($next_ts) && $next_ts < $this->now) { $next_ts = strtotime('third Monday of February '.((int)date('Y', $this->now) + 1)); } return $next_ts; } /** * Custom method that returns the next ts for the * Memorial's Day (last Monday of May). * * @return int */ public function getMemorialDate() { $next_ts = strtotime('last Monday of May '.date('Y', $this->now)); if (!empty($next_ts) && $next_ts < $this->now) { $next_ts = strtotime('last Monday of May '.((int)date('Y', $this->now) + 1)); } return $next_ts; } /** * Custom method that returns the next ts for the * Labor's Day (first Monday of September). * * @return int */ public function getLaborDate() { $next_ts = strtotime('first Monday of September '.date('Y', $this->now)); if (!empty($next_ts) && $next_ts < $this->now) { $next_ts = strtotime('first Monday of September '.((int)date('Y', $this->now) + 1)); } return $next_ts; } /** * Custom method that returns the next ts for the * Columbus's Day (second Monday of October). * * @return int */ public function getColumbusDate() { $next_ts = strtotime('second Monday of October '.date('Y', $this->now)); if (!empty($next_ts) && $next_ts < $this->now) { $next_ts = strtotime('second Monday of October '.((int)date('Y', $this->now) + 1)); } return $next_ts; } /** * Custom method that returns the next ts for the * Thanksgiving Day (4th Thursday of November). * * @return int */ public function getThanksgivingDate() { $next_ts = strtotime('fourth Thursday of November '.date('Y', $this->now)); if (!empty($next_ts) && $next_ts < $this->now) { $next_ts = strtotime('fourth Thursday of November '.((int)date('Y', $this->now) + 1)); } return $next_ts; } } } /** * Festivities handler class for Vik Booking. * * @since 1.12.0 */ class VikBookingFestivities extends VikBookingFestivitiesBC { /** * The singleton instance of the class. * * @var VikBookingTracker */ protected static $instance = null; /** * The guessed region for the festivities. * * @var string */ protected $guessed_region = 'global'; /** * Regions adapter values to find the proper region key in festivities. * * @var array */ protected $region_adapters = array( 'de' => 'ger', 'es' => 'spa', 'en' => 'usa', ); /** * Class constructor is public for bc. * * @see getInstance() */ public function __construct() { // call parent constructor parent::__construct(); // load the language file of VCM $this->loadLanguage(); // guess the region to use for the festivities $this->guessRegion(); } /** * Returns the global Tracker object, either * a new instance or the existing instance * if the class was already instantiated. * * @return self A new instance of the class. */ public static function getInstance() { if (is_null(static::$instance)) { static::$instance = new static(); } return static::$instance; } /** * Checks whether the next festivities should be verified * depending on the last time they were checked. * By default we check new festivities every month. * * @param string $current_check the current checking identifier. * * @return boolean True if it's time to check, false otherwise. */ public function shouldCheckFestivities($current_check = '') { if (empty($current_check)) { $current_check = date('Y-m'); } $dbo = JFactory::getDbo(); $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='fests_last_check';"; $dbo->setQuery($q); $last_check = $dbo->loadResult(); if ($last_check) { $should_check = ($last_check != $current_check); if ($should_check) { // update last time we checked $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($current_check)." WHERE `param`='fests_last_check';"; $dbo->setQuery($q); $dbo->execute(); } return $should_check; } // first time we access this method $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES ('fests_last_check', ".$dbo->quote($current_check).");"; $dbo->setQuery($q); $dbo->execute(); return true; } /** * Main method to find the next festivities for the calculated/given region * and to store them onto the database, only if they do not exist already. * * @return int the total number of festivities stored * * @see shouldCheckFestivities() should be called before this method to not waste resources. */ public function storeNextFestivities() { $tot_added = 0; $all_fests = $this->getNextFestivities(); // stores the festivities found if they do not exist already foreach ($all_fests as $k => $v) { $fest_ymd = date('Y-m-d', $v['next_ts']); if (!$this->festivityExists($fest_ymd, $k) && $this->storeFestivity($fest_ymd, $v, $k)) { $tot_added++; } } return $tot_added; } /** * Gets all the next festivities for the current region. * * @return array */ public function getNextFestivities() { $all_fests = $this->loadFestivities($this->guessed_region); // add up some useful properties for other methods, not really for storing foreach ($all_fests as $k => $v) { $all_fests[$k]['next_day'] = date('Y-m-d', $v['next_ts']); $all_fests[$k]['from_day'] = date('Y-m-d', $v['from_ts']); $all_fests[$k]['to_day'] = date('Y-m-d', $v['to_ts']); $all_fests[$k]['all_timestamps'] = $this->getFestsDatesArray($v['from_ts'], $v['to_ts']); } return $all_fests; } /** * Checks whether a precise festivity exists on the given date. * * @param string $ymd the date string in Y-m-d format. * @param string $key the key name of the fest (custom/VCM). * @param boolean $get whether to get the found record. * * @return mixed True/array if festivity exists, false otherwise. */ public function festivityExists($ymd, $key = '', $get = false) { $dbo = JFactory::getDbo(); $q = "SELECT * FROM `#__vikbooking_fests_dates` WHERE `dt`=".$dbo->quote($ymd); $dbo->setQuery($q); $festivity = $dbo->loadAssoc(); if (!$festivity) { return false; } $fests_info = json_decode($festivity['festinfo']); if (!$fests_info) { return false; } // update this information in the array in case it needs to be returned $festivity['festinfo'] = $fests_info; // seek for the requested fest foreach ($fests_info as $fest) { if (!empty($fest->type) && $fest->type == $key) { return $get ? $festivity : true; } } return false; } /** * Stores/updates a festivity for the given date. If a record for the given date exists, then the * festivity is added to or updated in the current record. Otherwise a new record is created. * * @param string $ymd the date string in Y-m-d format. * @param array $fest the array information of the festivity to be JSON-encoded. * @param string $type the key name of the festivity ('custom' for manual entries). * @param string $descr the description of the festivity (some notes). * * @return boolean True if the new record is stored or updated, false otherwise. */ public function storeFestivity($ymd, $fest, $type = 'custom', $descr = '') { // build "hot dates" next to the main festivity if set, and if description is empty $descr = empty($descr) && isset($fest['all_timestamps']) && count($fest['all_timestamps']) > 1 ? $this->parseBridgeTimestamps($fest['all_timestamps']) : $descr; // build festivity mandatory properties ('trans_name' is another mandatory prop which must be already set) $fest['type'] = $type; $fest['descr'] = $descr; $dbo = JFactory::getDbo(); $q = "SELECT * FROM `#__vikbooking_fests_dates` WHERE `dt`=".$dbo->quote($ymd); $dbo->setQuery($q); $dbo->execute(); if (!$dbo->getNumRows()) { // create a new record $q = "INSERT INTO `#__vikbooking_fests_dates` (`dt`, `festinfo`) VALUES (".$dbo->quote($ymd).", ".$dbo->quote(json_encode(array($fest))).");"; $dbo->setQuery($q); $dbo->execute(); return ((int)$dbo->insertid() > 0); } // update current record by pushing the festivity into the existing festinfo array of objects $festivity = $dbo->loadAssoc(); $fests_arr = json_decode($festivity['festinfo']); array_push($fests_arr, (object)$fest); $q = "UPDATE `#__vikbooking_fests_dates` SET `festinfo`=".$dbo->quote(json_encode($fests_arr))." WHERE `id`=".$festivity['id']; $dbo->setQuery($q); $dbo->execute(); return ((int)$dbo->getAffectedRows() > 0); } /** * Deletes a specific festivity for the given date. * If the day will not contain anymore fests, then * the whole record will be deleted. * * @param string $ymd the date string in Y-m-d format. * @param int $index the array index of the fest. * @param string $type the key name of the festivity ('custom' for manual entries). * * @return boolean True if the fest is removed, false otherwise. */ public function deleteFestivity($ymd, $index, $type = 'custom') { $record = $this->festivityExists($ymd, $type, true); if (!$record) { return false; } $drop_record = false; if (isset($record['festinfo'][$index])) { // fest was found by array-index array_splice($record['festinfo'], $index, 1); if (!count($record['festinfo'])) { // this day has got no more fests $drop_record = true; } } else { // seek for the requested fest by type foreach ($record['festinfo'] as $k => $fest) { if (!empty($fest->type) && $fest->type == $type) { // fest found array_splice($record['festinfo'], $k, 1); if (!count($record['festinfo'])) { // this day has got no more fests $drop_record = true; } break; } } } $dbo = JFactory::getDbo(); if ($drop_record) { $q = "DELETE FROM `#__vikbooking_fests_dates` WHERE `dt`=".$dbo->quote($ymd); } else { $q = "UPDATE `#__vikbooking_fests_dates` SET `festinfo`=".$dbo->quote(json_encode($record['festinfo']))." WHERE `dt`=".$dbo->quote($ymd); } $dbo->setQuery($q); $dbo->execute(); return true; } /** * Loads all the fests from Vik Booking, either the custom and the global ones. * Returns an associative array indexed by date with decoded fests information. * * @param string $from_ymd the optional minimum date in Y-m-d (defaults to today). * @param string $to_ymd the optional maximum date in Y-m-d (defaults to none). * * @return array the list of festivities found in Vik Booking. */ public function loadFestDates($from_ymd = null, $to_ymd = null) { $fests = array(); if (empty($from_ymd)) { $from_ymd = date('Y-m-d'); } $dbo = JFactory::getDbo(); $q = "SELECT * FROM `#__vikbooking_fests_dates` WHERE `dt`>=".$dbo->quote($from_ymd).(!empty($to_ymd) ? " AND `dt`<=".$dbo->quote($to_ymd) : '')." ORDER BY `dt` ASC;"; $dbo->setQuery($q); $all_fests = $dbo->loadAssocList(); if ($all_fests) { // make sure to decode all festivity infos foreach ($all_fests as $k => $v) { $v['festinfo'] = json_decode($v['festinfo']); // make sure the TS properties are set for custom fests foreach ($v['festinfo'] as $fk => $fv) { if (!isset($fv->next_ts)) { $start_ts = strtotime($v['dt']); $start_info = getdate($start_ts); $v['festinfo'][$fk]->next_ts = $start_ts; $v['festinfo'][$fk]->from_ts = $start_ts; $v['festinfo'][$fk]->to_ts = mktime(23, 59, 59, $start_info['mon'], $start_info['mday'], $start_info['year']); } } // $fests[$v['dt']] = $v; } } return $fests; } /** * Sets the proper region for the festivities to look for. * If the given region identifier does not exist, the 'global' region is used. * By instantiating the class object, the constructor will guess automatically * the region and will call this method. * * @param string $identifier the region identifier (array key). * * @return boolean True if region exists, false otherwise by using the global region. */ public function setRegion($identifier) { if (isset($this->regions[$identifier])) { // region requested exists $this->guessed_region = $identifier; return true; } // use default region $this->guessed_region = 'global'; return false; } /** * Attempts to find the proper region for the festivities * from a given identifier, or from the language tag if empty. * If the guessed region does not exist, then we revert to 'global'. * * @param string $identifier the region identifier (array key). * * @return boolean True if region exists, false otherwise. * * @uses setRegion() */ protected function guessRegion($identifier = '') { if (empty($identifier)) { $identifier = substr(JFactory::getLanguage()->getTag(), 0, 2); } // make sure the identifier is in lower case $identifier = strtolower($identifier); // check if identifier is an adapter value for a region if (isset($this->region_adapters[$identifier])) { // adapter value was found, so this is more likely a valid identifier $identifier = $this->region_adapters[$identifier]; } // parse all festivities to find the proper matching region identifier if not yet found if (!isset($this->regions[$identifier])) { $regions = array_keys($this->regions); foreach ($regions as $region) { $haystack = strlen($identifier) > strlen($region) ? $identifier : $region; $needle = strlen($identifier) > strlen($region) ? $region : $identifier; if (strpos($haystack, $needle) !== false) { // we were lucky enough to find a valid region, so just update the identifier $identifier = $region; break; } } } return $this->setRegion($identifier); } /** * Calculates the range of dates affecting the festivity start and end times. * * @param int $from_ts festivity start timestamp * @param int $to_ts festivity end timestamp * * @return array the range of dates (timestamps) touching the festivity */ protected function getFestsDatesArray($from_ts, $to_ts) { $dates_ts = array(); if (empty($from_ts) || empty($to_ts) || $to_ts < $from_ts) { return $dates_ts; } $from_info = getdate($from_ts); while ($from_info[0] <= $to_ts) { array_push($dates_ts, $from_info[0]); // next day $from_info = getdate(mktime(0, 0, 0, $from_info['mon'], ($from_info['mday'] + 1), $from_info['year'])); } return $dates_ts; } /** * Converts a list of timestamps into a list of readable dates. * * @param array $all_ts list of timestamps affecting the fest. * * @return string the list (c.s.v.) of dates touching this festivity or an empty string. */ protected function parseBridgeTimestamps($all_ts) { $hot_dates = array(); if (empty($all_ts) || !is_array($all_ts)) { return ''; } $nowdf = VikBooking::getDateFormat(); if ($nowdf == "%d/%m/%Y") { $df = 'd/m/Y'; } elseif ($nowdf == "%m/%d/%Y") { $df = 'm/d/Y'; } else { $df = 'Y/m/d'; } $datesep = VikBooking::getDateSeparator(); foreach ($all_ts as $ts) { array_push($hot_dates, date(str_replace("/", $datesep, $df), $ts)); } return implode(', ', $hot_dates); } /** * Loads the language file from VCM, necessary to translate most festivities. * This method does not extend anything from the VCM's parent class. It's a * method only of VikBookingFestivities. Compatible with both Joomla and WordPress. * * @return void */ protected function loadLanguage() { // load the VCM admin language file $vcm_admin_lang_path = ''; if (VBOPlatformDetection::isJoomla()) { $vcm_admin_lang_path = JPATH_ADMINISTRATOR; } elseif (defined('VIKCHANNELMANAGER_ADMIN_LANG')) { $vcm_admin_lang_path = VIKCHANNELMANAGER_ADMIN_LANG; } elseif (VBOPlatformDetection::isWordPress()) { /** * If running within Vik Booking, the constant VIKCHANNELMANAGER_ADMIN_LANG may not be available * * @since 1.4.3 (WP) - 1.14.2 (J) */ $vcm_admin_lang_path = str_replace('vikbooking', 'vikchannelmanager', VIKBOOKING_ADMIN_LANG); } if (empty($vcm_admin_lang_path)) { return; } $lang = JFactory::getLanguage(); $lang->load('com_vikchannelmanager', $vcm_admin_lang_path); if (VBOPlatformDetection::isWordPress() && defined('VIKCHANNELMANAGER_LIBRARIES')) { /** * @wponly load language admin handler as well for WP. * We do this only because of WordPress, but in a way also compatible with Joomla as * the constant VIKCHANNELMANAGER_LIBRARIES and method attachHandler are not in Joomla. */ $lang->attachHandler(VIKCHANNELMANAGER_LIBRARIES . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR . 'admin.php', 'vikchannelmanager'); } } }