1785 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1785 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @package    JEM
 | |
|  * @copyright  (C) 2013-2024 joomlaeventmanager.net
 | |
|  * @copyright  (C) 2005-2009 Christoph Lukes
 | |
|  * @license    https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
 | |
|  */
 | |
| 
 | |
| defined('_JEXEC') or die;
 | |
| 
 | |
| use Joomla\CMS\HTML\HTMLHelper;
 | |
| use Joomla\CMS\Language\Text;
 | |
| use Joomla\CMS\Factory;
 | |
| use Joomla\CMS\Uri\Uri;
 | |
| use Joomla\CMS\Filesystem\File;
 | |
| use Joomla\CMS\Filesystem\Folder;
 | |
| use Joomla\CMS\Filesystem\Path;
 | |
| use Joomla\CMS\Log\LogEntry;
 | |
| use Joomla\CMS\Log\Log;
 | |
| use Joomla\CMS\Table\Table;
 | |
| use Joomla\Registry\Registry;
 | |
| use Joomla\CMS\Component\ComponentHelper;
 | |
| use Joomla\CMS\Plugin\PluginHelper;
 | |
| use Joomla\CMS\Router\Route;
 | |
| use Joomla\CMS\Application\ApplicationHelper;
 | |
| use Joomla\CMS\Date\Date;
 | |
| 
 | |
| // ensure JemFactory is loaded (because this class is used by modules or plugins too)
 | |
| require_once(JPATH_SITE.'/components/com_jem/factory.php');
 | |
| 
 | |
| /**
 | |
|  * Holds some usefull functions to keep the code a bit cleaner
 | |
|  */
 | |
| class JemHelper
 | |
| {
 | |
| 	/**
 | |
| 	 * Pulls settings from database and stores in an static object
 | |
| 	 *
 | |
| 	 * @return object
 | |
| 	 */
 | |
| 	static public function config()
 | |
| 	{
 | |
| 		static $config;
 | |
| 
 | |
| 		if (!is_object($config)) {
 | |
| 			$jemConfig = JemConfig::getInstance();
 | |
| 			$config = clone $jemConfig->toObject(); // We need a copy to ensure not to store 'params' we add below!
 | |
| 
 | |
| 			$config->params = ComponentHelper::getParams('com_jem');
 | |
| 		}
 | |
| 
 | |
| 		return $config;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Pulls settings from database and stores in an static object
 | |
| 	 *
 | |
| 	 * @return object
 | |
| 	 */
 | |
| 	static public function globalattribs()
 | |
| 	{
 | |
| 		static $globalregistry;
 | |
| 		if (!is_object($globalregistry)) {
 | |
| 			$globalregistry = new Registry(self::config()->globalattribs);
 | |
| 		}
 | |
| 
 | |
| 		return $globalregistry;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieves the CSS-settings from database and stores in an static object
 | |
| 	 */
 | |
| 	static public function retrieveCss()
 | |
| 	{
 | |
| 		static $registryCSS;
 | |
| 		if (!is_object($registryCSS)) {
 | |
| 			$registryCSS = new Registry(self::config()->css);
 | |
| 		}
 | |
| 
 | |
| 		return $registryCSS;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Setup a file logger for JEM.
 | |
| 	 */
 | |
| 	static public function addFileLogger()
 | |
| 	{
 | |
| 		// Let admin choose the log level.
 | |
| 		$jemconfig = JemConfig::getInstance()->toRegistry();
 | |
| 		$lvl = (int)$jemconfig->get('globalattribs.loglevel', 0);
 | |
| 
 | |
| 		switch ($lvl) {
 | |
| 		case 1: // ERROR or higher
 | |
| 			$loglevel = Log::ERROR   * 2 - 1;
 | |
| 			break;
 | |
| 		case 2: // WARNING or higher
 | |
| 			$loglevel = Log::WARNING * 2 - 1;
 | |
| 			break;
 | |
| 		case 3: // INFO or higher
 | |
| 			$loglevel = Log::INFO    * 2 - 1;
 | |
| 			break;
 | |
| 		case 4: // DEBUG or higher
 | |
| 			$loglevel = Log::DEBUG   * 2 - 1;
 | |
| 			break;
 | |
| 		case 5: // ALL
 | |
| 			$loglevel = Log::ALL;
 | |
| 			break;
 | |
| 		case 0: // OFF
 | |
| 		default:
 | |
| 			$loglevel = 0;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		if ($loglevel > 0) {
 | |
| 			Log::addLogger(array('text_file' => 'jem.log.php', 'text_entry_format' => '{DATE} {TIME} {PRIORITY} {CATEGORY} {WHERE} : {MESSAGE}'), $loglevel, array('JEM'));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add en entry to JEM's log file.
 | |
| 	 *
 | |
| 	 * @param  $message The message to print
 | |
| 	 * @param  $where   The location the message was generated, default: null
 | |
| 	 * @param  $type    The log level, default: DEBUG
 | |
| 	 */
 | |
| 	static public function addLogEntry($message, $where = null, $type = Log::DEBUG)
 | |
| 	{
 | |
| 		$logEntry = new LogEntry($message, $type, 'JEM');
 | |
| 		$logEntry->where = empty($where) ? '' : ($where . '()');
 | |
| 
 | |
| 		Log::add($logEntry);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Performs daily scheduled cleanups
 | |
| 	 *
 | |
| 	 * Currently it archives and removes outdated events
 | |
| 	 * and takes care of the recurrence of events
 | |
| 	 */
 | |
| 	static public function cleanup($forced = 0)
 | |
| 	{
 | |
| 		$jemsettings  = JemHelper::config();
 | |
| 		$weekstart    = $jemsettings->weekdaystart;
 | |
| 
 | |
| 		$now = time(); // UTC
 | |
| 		$offset = idate('Z'); // timezone offset for "new day" test
 | |
| 		$lastupdate = (int)$jemsettings->lastupdate;
 | |
| 		$runningupdate = isset($jemsettings->runningupdate) ? $jemsettings->runningupdate : 0;
 | |
| 		$maxexectime = get_cfg_var('max_execution_time');
 | |
| 		$delay = min(86400, max(300, $maxexectime * 2));
 | |
| 
 | |
| 		// New (local) day since last update?
 | |
| 		$nrdaysnow = floor(($now + $offset) / 86400);
 | |
| 		$nrdaysupdate = floor(($lastupdate + $offset) / 86400);
 | |
| 
 | |
| 		if (($nrdaysnow > $nrdaysupdate) || $forced) {
 | |
| 			JemHelper::addLogEntry('forced: ' . $forced . ', now: '. $now . ', last update: ' . $lastupdate .
 | |
| 		                           ', running update: ' . $runningupdate . ', delay: ' . $delay . ', tz-offset: ' . $offset, __METHOD__);
 | |
| 
 | |
| 			if (($runningupdate + $delay) < $now) {
 | |
| 				// Set timestamp of running cleanup
 | |
| 				JemConfig::getInstance()->set('runningupdate', $now);
 | |
| 
 | |
| 				JemHelper::addLogEntry('  do cleanup...', __METHOD__);
 | |
| 
 | |
| 				// trigger an event to let plugins handle whatever cleanup they want to do.
 | |
| 				if (PluginHelper::importPlugin('jem')) {
 | |
| 					$dispatcher = JemFactory::getDispatcher();
 | |
| 					$dispatcher->triggerEvent('onJemBeforeCleanup', array($jemsettings, $forced));
 | |
| 				}
 | |
| 
 | |
|                 $db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 				$query = $db->getQuery(true);
 | |
| 
 | |
| 				// Get the last event occurence of each recurring published events, with unlimited repeat, or last date not passed.
 | |
| 				// Ignore published field to prevent duplicate events.
 | |
| 				$query = ' SELECT id, CASE recurrence_first_id WHEN 0 THEN id ELSE recurrence_first_id END AS first_id, '
 | |
| 				       . ' recurrence_number, recurrence_type, recurrence_limit_date, recurrence_limit, recurrence_byday, '
 | |
| 				       . ' MAX(dates) as dates, MAX(enddates) as enddates, MAX(recurrence_counter) as counter '
 | |
| 				       . ' FROM #__jem_events '
 | |
| 				       . ' WHERE recurrence_type <> "0" '
 | |
| 				       . ' AND CASE  WHEN recurrence_limit_date IS null THEN 1 ELSE NOW() < recurrence_limit_date END '
 | |
| 				       . ' AND recurrence_number <> "0" '
 | |
| 				       . ' GROUP BY first_id'
 | |
| 				       . ' ORDER BY dates DESC';
 | |
| 
 | |
| 				$db->SetQuery($query);
 | |
| 				$recurrence_array = $db->loadAssocList();
 | |
| 
 | |
| 				// If there are results we will be doing something with it
 | |
| 				foreach ($recurrence_array as $recurrence_row)
 | |
| 				{
 | |
| 					// get the info of reference event for the duplicates
 | |
| 					$ref_event = Table::getInstance('Event', 'JemTable');
 | |
| 					$ref_event->load($recurrence_row['id']);
 | |
| 
 | |
|                     $db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 					$query = $db->getQuery(true);
 | |
| 					$query->select('*');
 | |
| 					$query->from($db->quoteName('#__jem_events').' AS a');
 | |
| 					$query->where('id = '.(int)$recurrence_row['id']);
 | |
| 					$db->setQuery($query);
 | |
| 					$reference = $db->loadAssoc();
 | |
| 
 | |
| 					// if reference event is "unpublished"(0) new event is "unpublished" too
 | |
| 					// but on "archived"(2) and "trashed"(-2) reference events create "published"(1) event
 | |
| 					if ($reference['published'] != 0) {
 | |
| 						$reference['published'] = 1;
 | |
| 					}
 | |
| 
 | |
| 					// the first day of the week is used for certain rules
 | |
| 					$recurrence_row['weekstart'] = $weekstart;
 | |
| 
 | |
| 					// calculate next occurence date
 | |
| 					$recurrence_row = JemHelper::calculate_recurrence($recurrence_row);
 | |
| 
 | |
|                     switch ($recurrence_row["recurrence_type"]) {
 | |
|                         case 1:
 | |
|                             $anticipation	= $jemsettings->recurrence_anticipation_day;
 | |
|                             break;
 | |
|                         case 2:
 | |
|                             $anticipation	= $jemsettings->recurrence_anticipation_week;
 | |
|                             break;
 | |
|                         case 3:
 | |
|                             $anticipation	= $jemsettings->recurrence_anticipation_month;
 | |
|                             break;
 | |
|                         case 4:
 | |
|                             $anticipation	= $jemsettings->recurrence_anticipation_week;
 | |
|                             break;
 | |
|                         case 5:
 | |
|                             $anticipation	= $jemsettings->recurrence_anticipation_year;
 | |
|                             break;
 | |
|                         default:
 | |
|                             $anticipation	= $jemsettings->recurrence_anticipation_day;
 | |
|                             break;
 | |
|                     }
 | |
| 
 | |
| 					// add events as long as we are under the interval and under the limit, if specified.
 | |
| 					$shieldDate = new Date('now + ' . $anticipation . ' month');
 | |
| 					while (($recurrence_row['recurrence_limit_date'] == null
 | |
| 							|| strtotime($recurrence_row['dates']) <= strtotime($recurrence_row['recurrence_limit_date']))
 | |
| 							&& strtotime($recurrence_row['dates']) <= strtotime($shieldDate))
 | |
| 					{
 | |
| 						$new_event = Table::getInstance('Event', 'JemTable');
 | |
| 						$new_event->bind($reference, array('id', 'hits', 'dates', 'enddates','checked_out_time','checked_out'));
 | |
| 						$new_event->recurrence_first_id = $recurrence_row['first_id'];
 | |
| 						$new_event->recurrence_counter = $recurrence_row['counter'] + 1;
 | |
| 						$new_event->dates = $recurrence_row['dates'];
 | |
| 						$new_event->enddates = $recurrence_row['enddates'];
 | |
| 						$new_event->_autocreate = true; // to tell table class this has to be stored AS IS (the underscore is important!)
 | |
| 
 | |
| 						if ($new_event->store())
 | |
| 						{
 | |
| 							$recurrence_row['counter']++;
 | |
| 							//duplicate categories event relationships
 | |
| 							$query = ' INSERT INTO #__jem_cats_event_relations (itemid, catid) '
 | |
| 							       . ' SELECT ' . $db->Quote($new_event->id) . ', catid FROM #__jem_cats_event_relations '
 | |
| 							       . ' WHERE itemid = ' . $db->Quote($ref_event->id);
 | |
| 							$db->setQuery($query);
 | |
| 
 | |
| 							if ($db->execute() === false) {
 | |
| 								// run query always but don't show error message to "normal" users
 | |
| 								$user = JemFactory::getUser();
 | |
| 								if($user->authorise('core.manage')) {
 | |
| 									echo Text::_('Error saving categories for event "' . $ref_event->title . '" new recurrences\n');
 | |
| 								}
 | |
| 							}
 | |
| 						}
 | |
| 
 | |
| 						$recurrence_row = JemHelper::calculate_recurrence($recurrence_row);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				//delete outdated events
 | |
| 				if ($jemsettings->oldevent == 1) {
 | |
| 					$query = 'DELETE FROM #__jem_events WHERE dates > 0 AND '
 | |
| 					       .' DATE_SUB(NOW(), INTERVAL '.(int)$jemsettings->minus.' DAY) > (IF (enddates IS NOT NULL, enddates, dates))';
 | |
| 					$db->SetQuery($query);
 | |
| 					$db->execute();
 | |
| 				}
 | |
| 
 | |
| 				//Set state archived of outdated events
 | |
| 				if ($jemsettings->oldevent == 2) {
 | |
| 					$query = 'UPDATE #__jem_events SET published = 2 WHERE dates > 0 AND '
 | |
| 					       .' DATE_SUB(NOW(), INTERVAL '.(int)$jemsettings->minus.' DAY) > (IF (enddates IS NOT NULL, enddates, dates)) '
 | |
| 					       .' AND published = 1';
 | |
| 					$db->SetQuery($query);
 | |
| 					$db->execute();
 | |
| 				}
 | |
| 
 | |
| 				//Set state trashed of outdated events
 | |
| 				if ($jemsettings->oldevent == 3) {
 | |
| 					$query = 'UPDATE #__jem_events SET published = -2 WHERE dates > 0 AND '
 | |
| 					       .' DATE_SUB(NOW(), INTERVAL '.(int)$jemsettings->minus.' DAY) > (IF (enddates IS NOT NULL, enddates, dates)) '
 | |
| 					       .' AND published = 1';
 | |
| 					$db->SetQuery($query);
 | |
| 					$db->execute();
 | |
| 				}
 | |
| 
 | |
| 				//Set state unpublished of outdated events
 | |
| 				if ($jemsettings->oldevent == 4) {
 | |
| 					$query = 'UPDATE #__jem_events SET published = 0 WHERE dates > 0 AND '
 | |
| 					       .' DATE_SUB(NOW(), INTERVAL '.(int)$jemsettings->minus.' DAY) > (IF (enddates IS NOT NULL, enddates, dates)) '
 | |
| 					       .' AND published = 1';
 | |
| 					$db->SetQuery($query);
 | |
| 					$db->execute();
 | |
| 				}
 | |
| 
 | |
| 				// Cleanup registrations
 | |
| 				$query = 'DELETE FROM #__jem_register WHERE event NOT IN (SELECT id FROM #__jem_events)';
 | |
| 				$db->SetQuery($query);
 | |
| 				$db->execute();
 | |
| 
 | |
| 				// Set timestamp of last cleanup
 | |
| 				JemConfig::getInstance()->set('lastupdate', $now);
 | |
| 				// Clear timestamp of running cleanup
 | |
| 				JemConfig::getInstance()->set('runningupdate', 0);
 | |
| 			}
 | |
| 
 | |
| 			JemHelper::addLogEntry('finished.', __METHOD__);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * this methode calculate the next date
 | |
| 	 */
 | |
| 	static public function calculate_recurrence($recurrence_row)
 | |
| 	{
 | |
| 		// get the recurrence information
 | |
| 		$recurrence_number = $recurrence_row['recurrence_number'];
 | |
| 		$recurrence_type = $recurrence_row['recurrence_type'];
 | |
| 
 | |
| 		$day_time = 86400;	// 60s * 60min * 24h
 | |
| 		$week_time = $day_time * 7;
 | |
| 		$date_array = JemHelper::generate_date($recurrence_row['dates'], $recurrence_row['enddates']);
 | |
| 
 | |
| 		switch($recurrence_type) {
 | |
| 			case "1":
 | |
| 				// +1 hour for the Summer to Winter clock change
 | |
| 				$start_day = mktime(1, 0, 0, $date_array["month"], $date_array["day"], $date_array["year"]);
 | |
| 				$start_day = $start_day + ($recurrence_number * $day_time);
 | |
| 				break;
 | |
| 			case "2":
 | |
| 				// +1 hour for the Summer to Winter clock change
 | |
| 				$start_day = mktime(1, 0, 0, $date_array["month"], $date_array["day"], $date_array["year"]);
 | |
| 				$start_day = $start_day + ($recurrence_number * $week_time);
 | |
| 				break;
 | |
| 			case "3": // month recurrence
 | |
| 				/*
 | |
| 				 * warning here, we have to make sure the date exists:
 | |
| 				 * 31 of october + 1 month = 31 of november, which doesn't exists => skip the date!
 | |
| 				 */
 | |
| 				$start_day = mktime(1,0,0,($date_array["month"] + $recurrence_number),$date_array["day"],$date_array["year"]);
 | |
| 
 | |
| 				$i = 1;
 | |
| 				while (date('d', $start_day) != $date_array["day"] && $i < 20) { // not the same day of the month... try next date !
 | |
| 					$i++;
 | |
| 					$start_day = mktime(1,0,0,($date_array["month"] + $recurrence_number*$i),$date_array["day"],$date_array["year"]);
 | |
| 				}
 | |
| 				break;
 | |
| 			case "4": // weekday
 | |
| 				// the selected weekdays
 | |
| 				$selected = JemHelper::convert2CharsDaysToInt(explode(',', $recurrence_row['recurrence_byday']), 0);
 | |
| 				$days_names = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
 | |
| 				$litterals = array('first', 'second', 'third', 'fourth', 'fifth');
 | |
| 				if (count($selected) == 0)
 | |
| 				{
 | |
| 					// this shouldn't happen, but if it does, to prevent problem use the current weekday for the repetition.
 | |
| 					Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_WRONG_EVENTRECURRENCE_WEEKDAY'), 'warning');
 | |
| 					$current_weekday = (int) $date_array["weekday"];
 | |
| 					$selected = array($current_weekday);
 | |
| 				}
 | |
| 
 | |
| 				$start_day = null;
 | |
| 				foreach ($selected as $s)
 | |
| 				{
 | |
| 					$next = null;
 | |
|                     $nextmonth = null;
 | |
| 
 | |
| 					switch ($recurrence_number) {
 | |
| 						case 7: // before last 'x' of the month
 | |
| 							$next      = strtotime("previous ".$days_names[$s].' - 1 week ',
 | |
| 							                mktime(1,0,0,$date_array["month"]+1 ,1,$date_array["year"]));
 | |
| 							$nextmonth = strtotime("previous ".$days_names[$s].' - 1 week ',
 | |
| 							                mktime(1,0,0,$date_array["month"]+2 ,1,$date_array["year"]));
 | |
| 							break;
 | |
| 						case 6: // last 'x' of the month
 | |
| 							$next      = strtotime("previous ".$days_names[$s],
 | |
| 							                mktime(1,0,0,$date_array["month"]+1 ,1,$date_array["year"]));
 | |
| 							$nextmonth = strtotime("previous ".$days_names[$s],
 | |
| 							                mktime(1,0,0,$date_array["month"]+2 ,1,$date_array["year"]));
 | |
| 							break;
 | |
| 						case 5: // 5th of the month
 | |
|                             $currentMonth = $date_array["month"];
 | |
|                             do {
 | |
|                                 $timeFisrtDayMonth = mktime(1,0,0, $currentMonth ,1,$date_array["year"]);
 | |
|                                 $timeLastDayNextMonth = mktime(23, 59, 59, $currentMonth+1, 0, $date_array["year"]);
 | |
|                                 $next = strtotime($litterals[$recurrence_number - 1] . " " . $days_names[$s] . ' of this month',$timeFisrtDayMonth);
 | |
|                                 $currentMonth++;
 | |
|                             } while ($next > $timeLastDayNextMonth || $next < $date_array['unixtime']);
 | |
| 							break;
 | |
| 						case 4: // xth 'x' of the month
 | |
| 						case 3:
 | |
| 						case 2:
 | |
| 						case 1:
 | |
| 						default:
 | |
| 							$next      = strtotime($litterals[$recurrence_number-1]." ".$days_names[$s].' of this month',
 | |
| 							                mktime(1,0,0,$date_array["month"]   ,1,$date_array["year"]));
 | |
| 							$nextmonth = strtotime($litterals[$recurrence_number-1]." ".$days_names[$s].' of this month',
 | |
| 							                mktime(1,0,0,$date_array["month"]+1 ,1,$date_array["year"]));
 | |
| 							break;
 | |
| 					}
 | |
| 
 | |
| 					// is the next / nextm day eligible for next date ?
 | |
| 					if ($next && $next > strtotime($recurrence_row['dates'])) // after current date !
 | |
| 					{
 | |
| 						if (!$start_day || $start_day > $next) { // comes before the current 'start_date'
 | |
| 							$start_day = $next;
 | |
| 						}
 | |
| 					}
 | |
| 					if ($nextmonth && (!$start_day || $start_day > $nextmonth)) {
 | |
| 						$start_day = $nextmonth;
 | |
| 					}
 | |
| 				}
 | |
| 				break;
 | |
|             case "5": // year recurrence
 | |
|                 $start_day = mktime(1,0,0,($date_array["month"]),$date_array["day"],$date_array["year"]+ $recurrence_number);
 | |
|                 break;
 | |
| 		}
 | |
| 
 | |
| 		if (!$start_day) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		$recurrence_row['dates'] = date("Y-m-d", $start_day);
 | |
| 
 | |
| 		if ($recurrence_row['enddates']) {
 | |
| 			$recurrence_row['enddates'] = date("Y-m-d", $start_day + $date_array["day_diff"]);
 | |
| 		}
 | |
| 
 | |
| 		if ($start_day < $date_array["unixtime"]) {
 | |
| 			throw new Exception(Text::_('COM_JEM_RECURRENCE_DATE_GENERATION_ERROR'), 500);
 | |
| 		}
 | |
| 
 | |
| 		return $recurrence_row;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Method to dissolve recurrence of given id.
 | |
| 	 *
 | |
| 	 * @param  int     The id to clear as recurrence first id.
 | |
| 	 *
 | |
| 	 * @return boolean True on success.
 | |
| 	 */
 | |
| 	static public function dissolve_recurrence($first_id)
 | |
| 	{
 | |
| 		// Sanitize the id.
 | |
| 		$first_id = (int)$first_id;
 | |
| 
 | |
| 		if (empty($first_id)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		try {
 | |
|             $db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 			$db->setQuery('UPDATE #__jem_events'
 | |
| 			            . ' SET recurrence_first_id = 0, recurrence_type = 0'
 | |
| 			            . '   , recurrence_counter = 0, recurrence_number = 0'
 | |
| 			            . '   , recurrence_limit = 0, recurrence_limit_date = null'
 | |
| 			            . '   , recurrence_byday = ' . $db->quote('')
 | |
| 			            . ' WHERE recurrence_first_id = ' . $first_id
 | |
| 			             );
 | |
| 			$db->execute();
 | |
| 		} catch (Exception $e) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * This method deletes an image file if unused.
 | |
| 	 *
 | |
| 	 * @param  string $type     one of 'event', 'venue', 'category', 'events', 'venues', 'categories'
 | |
| 	 * @param  mixed  $filename filename as stored in db, or null (which deletes all unused files)
 | |
| 	 *
 | |
| 	 * @return bool true on success, false on error
 | |
| 	 * @access public
 | |
| 	 */
 | |
| 	static public function delete_unused_image_files($type, $filename = null)
 | |
| 	{
 | |
| 		switch ($type) {
 | |
| 		case 'event':
 | |
| 		case 'events':
 | |
| 			$folder = 'events';
 | |
| 			$countquery_tmpl = ' SELECT id FROM #__jem_events WHERE datimage = ';
 | |
| 			$imagequery      = ' SELECT datimage AS image, COUNT(*) AS count FROM #__jem_events GROUP BY datimage';
 | |
| 			break;
 | |
| 		case 'venue':
 | |
| 		case 'venues':
 | |
| 			$folder = 'venues';
 | |
| 			$countquery_tmpl = ' SELECT id FROM #__jem_venues WHERE locimage = ';
 | |
| 			$imagequery      = ' SELECT locimage AS image, COUNT(*) AS count FROM #__jem_venues GROUP BY locimage';
 | |
| 			break;
 | |
| 		case 'category':
 | |
| 		case 'categories':
 | |
| 			$folder = 'categories';
 | |
| 			$countquery_tmpl = ' SELECT id FROM #__jem_categories WHERE image = ';
 | |
| 			$imagequery      = ' SELECT image, COUNT(*) AS count FROM #__jem_categories GROUP BY image';
 | |
| 			break;
 | |
| 		default;
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$fullPath = Path::clean(JPATH_SITE.'/images/jem/'.$folder.'/'.$filename);
 | |
| 		$fullPaththumb = Path::clean(JPATH_SITE.'/images/jem/'.$folder.'/small/'.$filename);
 | |
| 		if (is_file($fullPath)) {
 | |
| 			// Count usage and don't delete if used elsewhere.
 | |
| 			$db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 			$db->setQuery($countquery_tmpl . $db->quote($filename));
 | |
| 			if (null === ($usage = $db->loadObjectList())) {
 | |
| 				return false;
 | |
| 			}
 | |
| 			if (empty($usage)) {
 | |
| 				File::delete($fullPath);
 | |
| 				if (File::exists($fullPaththumb)) {
 | |
| 					File::delete($fullPaththumb);
 | |
| 				}
 | |
| 
 | |
| 				return true;
 | |
| 			}
 | |
| 		}
 | |
| 		elseif (empty($filename) && is_dir($fullPath)) {
 | |
| 			// get image files used
 | |
| 			$db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 			$db->setQuery($imagequery);
 | |
| 			if (null === ($used = $db->loadAssocList('image', 'count'))) {
 | |
| 				return false;
 | |
| 			}
 | |
| 
 | |
| 			// get all files and delete if not in $used
 | |
| 			$fileList = Folder::files($fullPath);
 | |
| 			if ($fileList !== false) {
 | |
| 				foreach ($fileList as $file)
 | |
| 				{
 | |
| 					if (is_file($fullPath.$file) && substr($file, 0, 1) != '.' && !isset($used[$file])) {
 | |
| 						File::delete($fullPath.$file);
 | |
| 						if (File::exists($fullPaththumb.$file)) {
 | |
| 							File::delete($fullPaththumb.$file);
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * This method deletes attachment files if unused.
 | |
| 	 *
 | |
| 	 * @param  mixed $type one of 'event', 'venue', 'category', ... or false for all
 | |
| 	 *
 | |
| 	 * @return bool true on success, false on error
 | |
| 	 * @access public
 | |
| 	 */
 | |
| 	static public function delete_unused_attachment_files($type = false)
 | |
| 	{
 | |
| 		$jemsettings = JemHelper::config();
 | |
| 		$basepath    = JPATH_SITE.'/'.$jemsettings->attachments_path;
 | |
| 		$db          = Factory::getContainer()->get('DatabaseDriver');
 | |
| 		$res         = true;
 | |
| 
 | |
| 		// Get list of all folders matching type (format is "$type$id")
 | |
| 		$folders = Folder::folders($basepath, ($type ? '^'.$type : '.'), false, false, array('.', '..'));
 | |
| 
 | |
| 		// Get list of all used attachments of given type
 | |
| 		$fnames = array();
 | |
| 		foreach ($folders as $f) {
 | |
| 			$fnames[] = $db->Quote($f);
 | |
| 		}
 | |
| 		$query = ' SELECT object, file '
 | |
| 		       . ' FROM #__jem_attachments ';
 | |
| 		if (!empty($fnames)) {
 | |
| 			$query .= ' WHERE object IN ('.implode(',', $fnames).')';
 | |
| 		}
 | |
| 		$db->setQuery($query);
 | |
| 		$files_used = $db->loadObjectList();
 | |
| 		$files = array();
 | |
| 		foreach ($files_used as $used) {
 | |
| 			$files[$used->object.'/'.$used->file] = true;
 | |
| 		}
 | |
| 
 | |
| 		// Delete unused files and folders (ignore 'index.html')
 | |
| 		foreach ($folders as $folder) {
 | |
| 			$files = Folder::files($basepath.'/'.$folder, '.', false, false, array('index.html'), array());
 | |
| 			if (!empty($files)) {
 | |
| 				foreach ($files as $file) {
 | |
| 					if (!array_key_exists($folder.'/'.$file, $files)) {
 | |
| 						$res &= File::delete($basepath.'/'.$folder.'/'.$file);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			$files = Folder::files($basepath.'/'.$folder, '.', false, true, array('index.html'), array());
 | |
| 			if (empty($files)) {
 | |
| 				$res &= Folder::delete($basepath.'/'.$folder);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * this method generate the date string to a date array
 | |
| 	 *
 | |
| 	 * @param  string the date string
 | |
| 	 * @return array  the date informations
 | |
| 	 * @access public
 | |
| 	 */
 | |
| 	static public function generate_date($startdate, $enddate)
 | |
| 	{
 | |
| 		$validStardate = JemHelper::isValidDate($startdate);
 | |
|         $validEnddate = JemHelper::isValidDate($enddate);
 | |
| 
 | |
|         if($validStardate) {
 | |
|             $startdate = explode("-", $startdate);
 | |
| 		$date_array = array("year" => $startdate[0],
 | |
| 							"month" => $startdate[1],
 | |
| 							"day" => $startdate[2],
 | |
| 							"weekday" => date("w",mktime(1,0,0,$startdate[1],$startdate[2],$startdate[0])),
 | |
| 							"unixtime" => mktime(1,0,0,$startdate[1],$startdate[2],$startdate[0]));
 | |
| 
 | |
|             if ($validEnddate) {
 | |
|                 $enddate = explode("-", $enddate);
 | |
|                 $day_diff = (mktime(1, 0, 0, $enddate[1], $enddate[2], $enddate[0]) - mktime(1, 0, 0, $startdate[1], $startdate[2], $startdate[0]));
 | |
|                 $date_array["day_diff"] = $day_diff;
 | |
|             }
 | |
| 
 | |
| 
 | |
|             return $date_array;
 | |
|         }else{
 | |
|             return false;
 | |
|         }
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * return day number of the week starting with 0 for first weekday
 | |
| 	 *
 | |
| 	 * @param  array of 2 letters day
 | |
| 	 * @return array of int
 | |
| 	 */
 | |
| 	static function convert2CharsDaysToInt($days, $firstday = 0)
 | |
| 	{
 | |
| 		$result = array();
 | |
| 		foreach ($days as $day)
 | |
| 		{
 | |
| 			switch (strtoupper($day))
 | |
| 			{
 | |
| 				case 'MO':
 | |
| 					$result[] = 1 - $firstday;
 | |
| 					break;
 | |
| 				case 'TU':
 | |
| 					$result[] = 2 - $firstday;
 | |
| 					break;
 | |
| 				case 'WE':
 | |
| 					$result[] = 3 - $firstday;
 | |
| 					break;
 | |
| 				case 'TH':
 | |
| 					$result[] = 4 - $firstday;
 | |
| 					break;
 | |
| 				case 'FR':
 | |
| 					$result[] = 5 - $firstday;
 | |
| 					break;
 | |
| 				case 'SA':
 | |
| 					$result[] = 6 - $firstday;
 | |
| 					break;
 | |
| 				case 'SU':
 | |
| 					$result[] = (7 - $firstday) % 7;
 | |
| 					break;
 | |
| 				default:
 | |
| 					\Joomla\CMS\Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_WRONG_EVENTRECURRENCE_WEEKDAY'), 'warning');
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $result;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Build the select list for access level
 | |
| 	 */
 | |
| 	static public function getAccesslevelOptions($ownonly = false, $disabledLevels = false)
 | |
| 	{
 | |
| 		$db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 		$where = '';
 | |
| 		$selDisabled = '';
 | |
| 		if ($ownonly) {
 | |
| 			$levels = Factory::getApplication()->getIdentity()->getAuthorisedViewLevels();
 | |
| 			$allLevels = $levels;
 | |
| 			if (!empty($disabledLevels)) {
 | |
| 				if (!is_array($disabledLevels)) {
 | |
| 					$disabledLevels = array($disabledLevels);
 | |
| 				}
 | |
| 				foreach ($disabledLevels as $level) {
 | |
| 					if (((int)$level > 0) && (!in_array((int)$level, $levels))) {
 | |
| 						$allLevels[] = $level;
 | |
| 					}
 | |
| 				}
 | |
| 				$selDisabled = ', IF (id IN ('.implode(',', $levels).'), \'\', \'disabled\') AS disabled';
 | |
| 			}
 | |
| 			$where = ' WHERE id IN ('.implode(',', $allLevels).')';
 | |
| 		}
 | |
| 
 | |
| 		$query = 'SELECT id AS value, title AS text' . $selDisabled
 | |
| 		       . ' FROM #__viewlevels'
 | |
| 		       . $where
 | |
| 		       . ' ORDER BY ordering, id'
 | |
| 		       ;
 | |
| 
 | |
| 		//JemHelper::addLogEntry('AccessLevel query: ' . $query, __METHOD__);
 | |
| 
 | |
| 		$db->setQuery($query);
 | |
| 		$groups = $db->loadObjectList();
 | |
| 
 | |
| 		//JemHelper::addLogEntry('result: ' . print_r($groups, true), __METHOD__);
 | |
| 
 | |
| 		return $groups;
 | |
| 	}
 | |
| 
 | |
| 	static public function buildtimeselect($max, $name, $selected, $class = array('class'=>'inputbox'))
 | |
| 	{
 | |
| 		$timelist = array();
 | |
| 		$timelist[0] = HTMLHelper::_('select.option', '', '');
 | |
| 
 | |
| 		if ($max == 23) {
 | |
| 			// does user prefer 12 or 24 hours format?
 | |
| 			$jemreg = JemConfig::getInstance()->toRegistry();
 | |
| 			$format = $jemreg->get('formathour', false);
 | |
| 		} else {
 | |
| 			$format = false;
 | |
| 		}
 | |
| 
 | |
| 		foreach (range(0, $max) as $value) {
 | |
| 			if ($value < 10) {
 | |
| 				$value = '0'.$value;
 | |
| 			}
 | |
| 
 | |
| 			$timelist[] = HTMLHelper::_('select.option', $value, ($format ? date($format, strtotime("$value:00:00")) : $value));
 | |
| 		}
 | |
| 
 | |
| 		return HTMLHelper::_('select.genericlist', $timelist, $name, $class, 'value', 'text', $selected);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * returns mime type of a file
 | |
| 	 *
 | |
| 	 * @param  string file path
 | |
| 	 * @return string mime type
 | |
| 	 */
 | |
| 	static public function getMimeType($filename)
 | |
| 	{
 | |
| 		if (function_exists('finfo_open')) {
 | |
| 			$finfo = finfo_open(FILEINFO_MIME);
 | |
| 			$mimetype = finfo_file($finfo, $filename);
 | |
| 			finfo_close($finfo);
 | |
| 			return $mimetype;
 | |
| 		}
 | |
| 		else if (function_exists('mime_content_type') && 0)
 | |
| 		{
 | |
| 			return mime_content_type($filename);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$mime_types = array(
 | |
| 				'txt' => 'text/plain',
 | |
| 				'htm' => 'text/html',
 | |
| 				'html' => 'text/html',
 | |
| 				'php' => 'text/html',
 | |
| 				'css' => 'text/css',
 | |
| 				'js' => 'application/javascript',
 | |
| 				'json' => 'application/json',
 | |
| 				'xml' => 'application/xml',
 | |
| 				'swf' => 'application/x-shockwave-flash',
 | |
| 				'flv' => 'video/x-flv',
 | |
| 
 | |
| 				// images
 | |
| 				'png' => 'image/png',
 | |
| 				'jpe' => 'image/jpeg',
 | |
| 				'jpeg' => 'image/jpeg',
 | |
| 				'jpg' => 'image/jpeg',
 | |
| 				'gif' => 'image/gif',
 | |
| 				'bmp' => 'image/bmp',
 | |
| 				'ico' => 'image/vnd.microsoft.icon',
 | |
| 				'tiff' => 'image/tiff',
 | |
| 				'tif' => 'image/tiff',
 | |
| 				'svg' => 'image/svg+xml',
 | |
| 				'svgz' => 'image/svg+xml',
 | |
| 
 | |
| 				// archives
 | |
| 				'zip' => 'application/zip',
 | |
| 				'rar' => 'application/x-rar-compressed',
 | |
| 				'exe' => 'application/x-msdownload',
 | |
| 				'msi' => 'application/x-msdownload',
 | |
| 				'cab' => 'application/vnd.ms-cab-compressed',
 | |
| 
 | |
| 				// audio/video
 | |
| 				'mp3' => 'audio/mpeg',
 | |
| 				'qt' => 'video/quicktime',
 | |
| 				'mov' => 'video/quicktime',
 | |
| 
 | |
| 				// adobe
 | |
| 				'pdf' => 'application/pdf',
 | |
| 				'psd' => 'image/vnd.adobe.photoshop',
 | |
| 				'ai' => 'application/postscript',
 | |
| 				'eps' => 'application/postscript',
 | |
| 				'ps' => 'application/postscript',
 | |
| 
 | |
| 				// ms office
 | |
| 				'doc' => 'application/msword',
 | |
| 				'rtf' => 'application/rtf',
 | |
| 				'xls' => 'application/vnd.ms-excel',
 | |
| 				'ppt' => 'application/vnd.ms-powerpoint',
 | |
| 
 | |
| 				// open office
 | |
| 				'odt' => 'application/vnd.oasis.opendocument.text',
 | |
| 				'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
 | |
| 			);
 | |
| 
 | |
| 			//$ext = strtolower(array_pop(explode('.',$filename)));
 | |
| 			$var = explode('.',$filename);
 | |
| 			$ext = strtolower(array_pop($var));
 | |
| 			if (array_key_exists($ext, $mime_types)) {
 | |
| 				return $mime_types[$ext];
 | |
| 			}
 | |
| 			else {
 | |
| 				return 'application/octet-stream';
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * updates waiting list of specified event
 | |
| 	 *
 | |
| 	 * @param  int     event id
 | |
| 	 * @param  boolean bump users off/to waiting list
 | |
| 	 * @return bool
 | |
| 	 */
 | |
| 	static public function updateWaitingList($event)
 | |
| 	{
 | |
| 		$db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 
 | |
| 		// get event details for registration
 | |
| 		$query = ' SELECT maxplaces, waitinglist, reservedplaces FROM #__jem_events WHERE id = ' . $db->Quote($event);
 | |
| 		$db->setQuery($query);
 | |
| 		$event_places = $db->loadObject();
 | |
| 
 | |
| 		// get attendees after deletion, and their status
 | |
| 		$query = 'SELECT r.id, r.waiting, r.places'
 | |
| 		       . ' FROM #__jem_register AS r'
 | |
| 		       . ' WHERE r.status = 1 AND r.event = '.$db->Quote($event)
 | |
| 		       . ' ORDER BY r.uregdate ASC '
 | |
| 		       ;
 | |
| 		$db->SetQuery($query);
 | |
| 		$res = $db->loadObjectList();
 | |
| 
 | |
| 		$registered = 0;
 | |
| 		$waitingregs = array();
 | |
| 		foreach ((array) $res as $r)
 | |
| 		{
 | |
| 			if ($r->waiting) {
 | |
| 				$waitingregs[] = $r;
 | |
| 			} else {
 | |
| 				$registered+=$r->places;
 | |
| 			}
 | |
| 		}
 | |
| 		//Add the Reserved Places of the event
 | |
| 		$registered+=$event_places->reservedplaces;
 | |
| 
 | |
| 		if (($registered < $event_places->maxplaces) && count($waitingregs))
 | |
| 		{
 | |
| 			$placesavailable = $event_places->maxplaces - $registered;
 | |
| 			// need to bump users to attending status
 | |
| 			foreach ($waitingregs as $waitreg)
 | |
| 			{
 | |
| 				if($waitreg->places <= $placesavailable)
 | |
| 				{
 | |
| 					$query   = ' UPDATE #__jem_register SET waiting = 0 WHERE id = ' . $waitreg->id;
 | |
| 					$db->setQuery($query);
 | |
| 					if ($db->execute() === false)
 | |
| 					{
 | |
| 						Factory::getApplication()->enqueueMessage(
 | |
| 							Text::_(
 | |
| 								'COM_JEM_FAILED_BUMPING_USERS_FROM_WAITING_TO_CONFIRMED_LIST'
 | |
| 							) . ': ' . $db->getErrorMsg(),
 | |
| 							'warning'
 | |
| 						);
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						PluginHelper::importPlugin('jem');
 | |
| 						$dispatcher = JemFactory::getDispatcher();
 | |
| 						$res        = $dispatcher->triggerEvent('onUserOnOffWaitinglist', array($waitreg->id));
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adds attendees numbers to rows
 | |
| 	 *
 | |
| 	 * @param  $data reference to event rows
 | |
| 	 * @return false on error, $data on success
 | |
| 	 */
 | |
| 	static public function getAttendeesNumbers(& $data)
 | |
| 	{
 | |
| 		// Make sure this is an array and it is not empty
 | |
| 		if (!is_array($data) || !count($data)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Get the ids of events
 | |
| 		$ids = array();
 | |
| 		foreach ($data as $event) {
 | |
| 			$ids[] = (int)$event->id;
 | |
| 		}
 | |
| 		$ids = implode(",", $ids);
 | |
| 
 | |
| 		$db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 
 | |
| 		// status 1: user registered (attendee or waiting list), status -1: user exlicitely unregistered, status 0: user is invited but hadn't answered yet
 | |
| 		$query = ' SELECT COUNT(id) as total,'
 | |
| 		       . '        SUM(IF(status =  1 AND waiting = 0, places, 0)) AS registered,'
 | |
| 		       . '        SUM(IF(status =  1 AND waiting >  0, places, 0)) AS waiting,'
 | |
| 		       . '        SUM(IF(status = -1,                  places, 0)) AS unregistered,'
 | |
| 		       . '        SUM(IF(status =  0,                  places, 0)) AS invited,'
 | |
| 		       . '        event '
 | |
| 		       . ' FROM #__jem_register '
 | |
| 		       . ' WHERE event IN (' . $ids .')'
 | |
| 		       . ' GROUP BY event ';
 | |
| 
 | |
| 		$db->setQuery($query);
 | |
| 		$res = $db->loadObjectList('event');
 | |
| 
 | |
| 		foreach ($data as $k => &$event) { // by reference for direct edit
 | |
| 			if (isset($res[$event->id])) {
 | |
| 				$event->regTotal   = $res[$event->id]->total;
 | |
| 				$event->regCount   = $res[$event->id]->registered;
 | |
| 				$event->reserved   = $event->reservedplaces;
 | |
| 				$event->waiting    = $res[$event->id]->waiting;
 | |
| 				$event->unregCount = $res[$event->id]->unregistered;
 | |
| 				$event->invited    = $res[$event->id]->invited;
 | |
| 			} else {
 | |
| 				$event->regTotal   = 0;
 | |
| 				$event->regCount   = 0;
 | |
| 				$event->reserved   = 0;
 | |
| 				$event->waiting    = 0;
 | |
| 				$event->unregCount = 0;
 | |
| 				$event->invited    = 0;
 | |
| 			}
 | |
| 			$event->available = max(0, $event->maxplaces - $event->regCount -$event->reservedplaces);
 | |
| 		}
 | |
| 
 | |
| 		return $data;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * returns timezone name
 | |
| 	 */
 | |
| 	static public function getTimeZoneName()
 | |
| 	{
 | |
| 		$user     = JemFactory::getUser();
 | |
| 		$userTz   = $user->getParam('timezone');
 | |
| 		$timeZone = Factory::getConfig()->get('offset');
 | |
| 
 | |
| 		/* disabled for now
 | |
| 		if($userTz) {
 | |
| 			$timeZone = $userTz;
 | |
| 		}
 | |
| 		*/
 | |
| 		return $timeZone;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * return initialized calendar tool class for ics export
 | |
| 	 *
 | |
| 	 * @return object
 | |
| 	 */
 | |
| 	static public function getCalendarTool()
 | |
| 	{
 | |
| 		require_once JPATH_SITE.'/components/com_jem/classes/iCalcreator.class.php';
 | |
| 		$timezone_name = JemHelper::getTimeZoneName();
 | |
| 
 | |
| 		$vcal = new vcalendar();
 | |
| 		if (!file_exists(JPATH_SITE.'/cache/com_jem')) {
 | |
| 			Folder::create(JPATH_SITE.'/cache/com_jem');
 | |
| 		}
 | |
| 		$vcal->setConfig('directory', JPATH_SITE.'/cache/com_jem');
 | |
| 		$vcal->setProperty("calscale", "GREGORIAN");
 | |
| 		$vcal->setProperty('method', 'PUBLISH');
 | |
| 		if ($timezone_name) {
 | |
| 			$vcal->setProperty("X-WR-TIMEZONE", $timezone_name);
 | |
| 		}
 | |
| 		return $vcal;
 | |
| 	}
 | |
| 
 | |
| 	static public function icalAddEvent(&$calendartool, $event)
 | |
| 	{
 | |
| 		require_once JPATH_SITE.'/components/com_jem/classes/iCalcreator.class.php';
 | |
| 		$jemsettings   = JemHelper::config();
 | |
| 		$timezone_name = JemHelper::getTimeZoneName();
 | |
| 		$config        = Factory::getConfig();
 | |
| 		$sitename      = $config->get('sitename');
 | |
|         $uri           = Uri::getInstance();
 | |
| 
 | |
| 		// get categories names
 | |
| 		$categories = array();
 | |
| 		foreach ($event->categories as $c) {
 | |
| 			$categories[] = $c->catname;
 | |
| 		}
 | |
| 
 | |
| 		// no start date...
 | |
| 		$validdate = JemHelper::isValidDate($event->dates);
 | |
| 
 | |
| 		if (!$event->dates || !$validdate) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// make end date same as start date if not set
 | |
| 		if (!$event->enddates) {
 | |
| 			$event->enddates = $event->dates;
 | |
| 		}
 | |
| 
 | |
| 		// start
 | |
| 		if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/', $event->dates, $start_date)) {
 | |
| 			throw new Exception(Text::_('COM_JEM_ICAL_EXPORT_WRONG_STARTDATE_FORMAT'), 0);
 | |
| 		}
 | |
| 
 | |
| 		$date = array('year' => (int) $start_date[1], 'month' => (int) $start_date[2], 'day' => (int) $start_date[3]);
 | |
| 
 | |
| 		// all day event if start time is not set
 | |
| 		if (!$event->times) // all day !
 | |
| 		{
 | |
| 			$dateparam = array('VALUE' => 'DATE');
 | |
| 
 | |
| 			// for ical all day events, dtend must be send to the next day
 | |
| 			$event->enddates = date('Y-m-d', strtotime($event->enddates.' +1 day'));
 | |
| 
 | |
| 			if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/', $event->enddates, $end_date)) {
 | |
| 				throw new Exception(Text::_('COM_JEM_ICAL_EXPORT_WRONG_ENDDATE_FORMAT'), 0);
 | |
| 			}
 | |
| 
 | |
| 			$date_end = array('year' => $end_date[1], 'month' => $end_date[2], 'day' => $end_date[3]);
 | |
| 			$dateendparam = array('VALUE' => 'DATE');
 | |
| 		}
 | |
| 		else // not all day events, there is a start time
 | |
| 		{
 | |
| 			if (!preg_match('/([0-9]{2}):([0-9]{2}):([0-9]{2})/', $event->times, $start_time)) {
 | |
| 				throw new Exception(Text::_('COM_JEM_ICAL_EXPORT_WRONG_STARTTIME_FORMAT'), 0);
 | |
| 			}
 | |
| 
 | |
| 			$date['hour'] = $start_time[1];
 | |
| 			$date['min']  = $start_time[2];
 | |
| 			$date['sec']  = $start_time[3];
 | |
| 			$dateparam = array('VALUE' => 'DATE-TIME');
 | |
| 			if ($jemsettings->ical_tz == 1) {
 | |
| 				$dateparam['TZID'] = $timezone_name;
 | |
| 			}
 | |
| 
 | |
| 			if (!$event->endtimes || $event->endtimes == '00:00:00') {
 | |
| 				$event->endtimes = $event->times;
 | |
| 			}
 | |
| 
 | |
| 			// if same day but end time < start time, change end date to +1 day
 | |
| 			if ($event->enddates == $event->dates &&
 | |
| 			    strtotime($event->dates.' '.$event->endtimes) < strtotime($event->dates.' '.$event->times))
 | |
| 			{
 | |
| 				$event->enddates = date('Y-m-d', strtotime($event->enddates.' +1 day'));
 | |
| 			}
 | |
| 
 | |
| 			if (!preg_match('/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/', $event->enddates, $end_date)) {
 | |
| 				throw new Exception(Text::_('COM_JEM_ICAL_EXPORT_WRONG_ENDDATE_FORMAT'), 0);
 | |
| 			}
 | |
| 
 | |
| 			$date_end = array('year' => $end_date[1], 'month' => $end_date[2], 'day' => $end_date[3]);
 | |
| 
 | |
| 			if (!preg_match('/([0-9]{2}):([0-9]{2}):([0-9]{2})/', $event->endtimes, $end_time)) {
 | |
| 				throw new Exception(Text::_('COM_JEM_ICAL_EXPORT_WRONG_STARTTIME_FORMAT'), 0);
 | |
| 			}
 | |
| 
 | |
| 			$date_end['hour'] = $end_time[1];
 | |
| 			$date_end['min']  = $end_time[2];
 | |
| 			$date_end['sec']  = $end_time[3];
 | |
| 			$dateendparam = array('VALUE' => 'DATE-TIME');
 | |
| 			if ($jemsettings->ical_tz == 1) {
 | |
| 				$dateendparam['TZID'] = $timezone_name;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// item description text
 | |
| 		$description = $event->title.'\\n';
 | |
| 		$description .= Text::_('COM_JEM_CATEGORY').': '.implode(', ', $categories).'\\n';
 | |
| 
 | |
| 		$link = $uri->root().JemHelperRoute::getEventRoute($event->slug);
 | |
| 		$link = Route::_($link);
 | |
| 		$description .= Text::_('COM_JEM_ICS_LINK').': '.$link.'\\n';
 | |
| 
 | |
| 		// location
 | |
| 		$location = array($event->venue);
 | |
| 		if (isset($event->street) && !empty($event->street)) {
 | |
| 			$location[] = $event->street;
 | |
| 		}
 | |
| 
 | |
| 		if (isset($event->postalCode) && !empty($event->postalCode) && isset($event->city) && !empty($event->city)) {
 | |
| 			$location[] = $event->postalCode.' '.$event->city;
 | |
| 		} else {
 | |
| 			if (isset($event->postalCode) && !empty($event->postalCode)) {
 | |
| 				$location[] = $event->postalCode;
 | |
| 			}
 | |
| 			if (isset($event->city) && !empty($event->city)) {
 | |
| 				$location[] = $event->city;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (isset($event->countryname) && !empty($event->countryname)) {
 | |
| 			$exp = explode(",",$event->countryname);
 | |
| 			$location[] = $exp[0];
 | |
| 		}
 | |
| 
 | |
| 		$location = implode(",", $location);
 | |
| 
 | |
| 		$e = new vevent();
 | |
| 		$e->setProperty('summary', $event->title);
 | |
| 		$e->setProperty('categories', implode(', ', $categories));
 | |
| 		$e->setProperty('dtstart', $date, $dateparam);
 | |
| 		if (count($date_end)) {
 | |
| 			$e->setProperty('dtend', $date_end, $dateendparam);
 | |
| 		}
 | |
| 		$e->setProperty('description', $description);
 | |
| 		if ($location != '') {
 | |
| 			$e->setProperty('location', $location);
 | |
| 		}
 | |
| 		$e->setProperty('url', $link);
 | |
| 		$e->setProperty('uid', 'event'.$event->id.'@'.$sitename);
 | |
| 		$calendartool->addComponent($e); // add component to calendar
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * return true is a date is valid (not null, or 0000-00...)
 | |
| 	 *
 | |
| 	 * @param  string $date
 | |
| 	 * @return boolean
 | |
| 	 */
 | |
| 	static public function isValidDate($date)
 | |
| 	{
 | |
| 		if (is_null($date)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		if ($date == '0000-00-00' || $date == '0000-00-00 00:00:00') {
 | |
| 			return false;
 | |
| 		}
 | |
| 		if (!strtotime($date)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * return true is a time is valid (not null, or 00:00:00...)
 | |
| 	 *
 | |
| 	 * @param  string $time
 | |
| 	 * @return boolean
 | |
| 	 */
 | |
| 	static public function isValidTime($time)
 | |
| 	{
 | |
| 		if (is_null($time)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		if (!strtotime($time)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns array of positive numbers
 | |
| 	 *
 | |
| 	 * @param  mixed array or string with comma separated list of ids
 | |
| 	 * @return mixed array of numbers greater zero or false
 | |
| 	 */
 | |
| 	static public function getValidIds($ids_in)
 | |
| 	{
 | |
| 		$ids_out = array();
 | |
|         if($ids_in) {
 | |
|             $tmp = is_array($ids_in) ? $ids_in : explode(',', $ids_in);
 | |
|             if (!empty($tmp)) {
 | |
|                 foreach ($tmp as $id) {
 | |
|                     if ((int)$id > 0) {
 | |
|                         $ids_out[] = (int)$id;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 		return (empty($ids_out) ? false : $ids_out);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Creates a tooltip
 | |
| 	 */
 | |
| 	static public function caltooltip($tooltip, $title = '', $text = '', $href = '', $class = '', $time = '', $color = '')
 | |
| 	{
 | |
|         HTMLHelper::_('bootstrap.tooltip');
 | |
|         if (0) { /* old style using 'hasTip' */
 | |
|             $title = HTMLHelper::tooltipText($title, '<div style="font-weight:normal;">'.$tooltip.'</div>', 0);
 | |
|         } else { /* new style using 'has Tooltip' */
 | |
|             $class = str_replace('hasTip', '', $class) . ' hasTooltip';
 | |
|             $title = HTMLHelper::tooltipText($title, $tooltip, 0); // this calls htmlspecialchars()
 | |
|         }
 | |
|         $tooltip = '';
 | |
| 
 | |
| 
 | |
| 		if ($href) {
 | |
| 			$href = Route::_ ($href);
 | |
| 			$tip = '<span class="'.$class.'" data-bs-toggle="tooltip" title="'.$title.$tooltip.'"><a href="'.$href.'">'.$time.$text.'</a></span>';
 | |
| 		} else {
 | |
| 			$tip = '<span class="'.$class.'" data-bs-toggle="tooltip" title="'.$title.$tooltip.'">'.$text.'</span>';
 | |
| 		}
 | |
| 
 | |
| 		return $tip;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function to retrieve IP
 | |
| 	 * @author: https://gist.github.com/cballou/2201933
 | |
| 	 */
 | |
| 	static public function retrieveIP()
 | |
| 	{
 | |
| 		$ip_keys = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');
 | |
| 		foreach ($ip_keys as $key) {
 | |
| 			if (array_key_exists($key, $_SERVER) === true) {
 | |
| 				foreach (explode(',', $_SERVER[$key]) as $ip) {
 | |
| 					// trim for safety measures
 | |
| 					$ip = trim($ip);
 | |
| 					// attempt to validate IP
 | |
| 					if (self::validate_ip($ip)) {
 | |
| 						return $ip;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Ensures an ip address is both a valid IP and does not fall within
 | |
| 	 * a private network range.
 | |
| 	 *
 | |
| 	 * @author: https://gist.github.com/cballou/2201933
 | |
| 	 */
 | |
| 	static public function validate_ip($ip)
 | |
| 	{
 | |
| 		if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	static public function getLayoutStyleSuffix()
 | |
| 	{
 | |
| 		$jemsettings = self::config();
 | |
| 		$layoutstyle = isset($jemsettings->layoutstyle) ? (int)$jemsettings->layoutstyle : 0;
 | |
| 
 | |
| 		return $layoutstyle === 1 ? 'responsive' : '';
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the path to a layout for a module respecting layout style configured in JEM Settings.
 | |
| 	 *
 | |
| 	 * @param   string  $module  The name of the module
 | |
| 	 * @param   string  $layout  The name of the module layout. If alternative layout, in the form template:filename.
 | |
| 	 *
 | |
| 	 * @return  string  The path to the module layout
 | |
| 	 *
 | |
| 	 * @since   2.3
 | |
| 	 */
 | |
| 	public static function getModuleLayoutPath($module, $layout = 'default')
 | |
| 	{
 | |
| 		$template = Factory::getApplication()->getTemplate();
 | |
| 		$defaultLayout = $layout;
 | |
| 		$suffix = self::getLayoutStyleSuffix();
 | |
| 
 | |
| 		if (strpos($layout, ':') !== false)
 | |
| 		{
 | |
| 			// Get the template and file name from the string
 | |
| 			$temp = explode(':', $layout);
 | |
| 			$template = $temp[0] === '_' ? $template : $temp[0];
 | |
| 			$layout = $temp[1];
 | |
| 			$defaultLayout = $temp[1] ?: 'default';
 | |
| 		}
 | |
| 
 | |
| 		// Build the template and base path for the layout
 | |
| 		$pathes = array();
 | |
| 		if (!empty($suffix)) {
 | |
| 			$pathes[] = JPATH_THEMES . '/' . $template . '/html/' . $module . '/' . $suffix . '/' . $layout . '.php';
 | |
| 			$pathes[] = JPATH_BASE . '/modules/' . $module . '/tmpl/' . $suffix . '/' . $defaultLayout . '.php';
 | |
| 		}
 | |
| 		$pathes[] = JPATH_THEMES . '/' . $template . '/html/' . $module . '/' . $layout . '.php';
 | |
| 		$pathes[] = JPATH_BASE . '/modules/' . $module . '/tmpl/' . $defaultLayout . '.php';
 | |
| 
 | |
| 		// Return the first match
 | |
| 		foreach ($pathes as $path) {
 | |
| 			if (file_exists($path)) {
 | |
| 				return $path;
 | |
| 			}
 | |
| 		}
 | |
| 		// last chance
 | |
| 		return JPATH_BASE . '/modules/' . $module . '/tmpl/default.php';
 | |
| 	}
 | |
| 
 | |
| 	static public function loadCss($css)
 | |
| 	{
 | |
| 		$settings = self::retrieveCss();
 | |
| 		$suffix   = self::getLayoutStyleSuffix();
 | |
|         $app      = Factory::getApplication();
 | |
|         $document = $app->getDocument();
 | |
|         $uri      = Uri::getInstance();
 | |
| 		$url      = $uri->root();
 | |
| 		if (!empty($suffix)) {
 | |
| 			$suffix = '-' . $suffix;
 | |
| 		}
 | |
| 
 | |
| 		if ($settings->get('css_' . $css . '_usecustom', '0')) {
 | |
| 
 | |
| 			# we want to use custom so now check if we've a file
 | |
| 			$file = $settings->get('css_' . $css . '_customfile');
 | |
| 			$is_file = false;
 | |
| 
 | |
| 			# something was filled, now check if we've a valid file
 | |
| 			if ($file) {
 | |
| 				$file = preg_replace('%^/([^/]*)%', '$1', $file); // remove leading single slash
 | |
| 				$is_file = File::exists(JPATH_SITE . '/media/com_jem/css/custom/' . $file);
 | |
| 
 | |
| 				if ($is_file) {
 | |
| 					# at this point we do have a valid file but let's check the extension too.
 | |
| 					$ext =  File::getExt($file);
 | |
| 					if ($ext != 'css') {
 | |
| 						# the file is valid but the extension not so let's return false
 | |
| 						$is_file = false;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			
 | |
| 			if ($is_file) {
 | |
| 				# we do have a valid file so we will use it.
 | |
| 				// $css = HTMLHelper::_('stylesheet', $file, array(), false);
 | |
| 				$css = $document->addStyleSheet($url.'media/com_jem/css/custom/' . $file);
 | |
| 			} else {
 | |
| 				# unfortunately we don't have a valid file so we're looking at the default
 | |
| 				// $files = HTMLHelper::_('stylesheet', 'com_jem/' . $css . $suffix . '.css', array(), true, true);
 | |
| 				$files = $document->addStyleSheet($url.'media/com_jem/css/custom/' . $css . $suffix . '.css');
 | |
| 				if (!empty($files)) {
 | |
| 					# we have to call this stupid function twice; no other way to know if something was loaded
 | |
| 					// $css = HTMLHelper::_('stylesheet', 'com_jem/' . $css . $suffix . '.css', array(), true);
 | |
| 					$css = $document->addStyleSheet($url.'media/com_jem/css/custom/' . $css . $suffix . '.css');
 | |
| 
 | |
| 				} else {
 | |
| 					# no css for layout style configured, so use the default css
 | |
| 					// $css = HTMLHelper::_('stylesheet', 'com_jem/' . $css . '.css', array(), true);
 | |
| 					$css = $document->addStyleSheet($url.'media/com_jem/css/custom/'. $css. '.css');
 | |
| 
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			# here we want to use the normal css
 | |
| 			// $files = HTMLHelper::_('stylesheet', 'com_jem/' . $css . $suffix . '.css', array(), true, true);
 | |
| 			$files = $document->addStyleSheet($url.'media/com_jem/css/' . $css . $suffix . '.css');
 | |
| 
 | |
| 			if (!empty($files)) {
 | |
| 				# we have to call this stupid function twice; no other way to know if something was loaded
 | |
| 				// $css = HTMLHelper::_('stylesheet', 'com_jem/' . $css . $suffix . '.css', array(), true);
 | |
| 				$css = $document->addStyleSheet($url.'media/com_jem/css/' . $css . $suffix . '.css');
 | |
| 
 | |
| 			} else {
 | |
| 				# no css for layout style configured, so use the default css
 | |
| 				// $css = HTMLHelper::_('stylesheet', 'com_jem/' . $css . '.css', array(), true);
 | |
| 				$css = $document->addStyleSheet($url.'media/com_jem/css/'. $css. '.css');
 | |
| 
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $css;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get the url to a css file for a module respecting layout style configured in JEM Settings.
 | |
| 	 *
 | |
| 	 * @param   string  $module  The name of the module
 | |
| 	 * @param   string  $css     The name of the css file (in the root path). If null, the name of module is used (in the suffix directory).
 | |
| 	 *
 | |
| 	 * @since   2.3
 | |
| 	 */
 | |
| 	public static function loadModuleStyleSheet($module, $css = null)
 | |
| 	{
 | |
|         $app = Factory::getApplication();
 | |
|         $wa = $app->getDocument()->getWebAssetManager();
 | |
|         $templateName = $app->getTemplate();
 | |
|         $suffix = self::getLayoutStyleSuffix();
 | |
| 
 | |
|         if (empty($css)) {
 | |
| 			$css = $module;
 | |
|             $filestyle = ($suffix? $suffix . '/':'') . $css . '.css';
 | |
| 		}else{
 | |
|             $filestyle = $css . '.css';
 | |
|         }
 | |
| 
 | |
|         //Search for template overrides
 | |
|         if(file_exists(JPATH_BASE . '/templates/' . $templateName . '/html/' . $module . '/' . $filestyle)) {
 | |
|             $wa->registerAndUseStyle($module . ($css? '.' . $css: ''), 'templates/' . $templateName . '/html/'. $module . '/' . $filestyle);
 | |
|         }
 | |
|         //Search in media folder
 | |
|         else if (file_exists(JPATH_BASE . '/media/' . $module . '/css/' . $filestyle)) {
 | |
|             $wa->registerAndUseStyle($module . ($css? '.' . $css: ''), 'media/' . $module . '/css/' . $filestyle);
 | |
|         }
 | |
|         //Search in the module
 | |
|         else if (file_exists(JPATH_BASE . '/modules/' . $module . '/tmpl/' . $filestyle)) {
 | |
|             $wa->registerAndUseStyle($module . ($css? '.' . $css: ''), 'modules/'. $module . '/tmpl/' . $filestyle);
 | |
|         }
 | |
|         //Error the css file doesn't found
 | |
|         else {
 | |
|             JemHelper::addLogEntry("Warning: The " . $filestyle . " file doesn't found.", __METHOD__);
 | |
|         }
 | |
| 	}
 | |
| 
 | |
| 	static public function loadIconFont()
 | |
| 	{
 | |
| 		$jemsettings = JemHelper::config();
 | |
| 		if ($jemsettings->useiconfont == 1) {
 | |
| 			# This will automaticly search for 'font-awesome.css' if site is in debug mode.
 | |
| 			# Note: css files must be stored on /media/com_jem/css/ to be conform to Joomla and also allow template overrides.
 | |
| 			HTMLHelper::_('stylesheet', 'media/vendor/fontawesome-free/css/font-awesome.min.css', array(), true);
 | |
| 			HTMLHelper::_('stylesheet', 'com_jem/css/jem-icon-font.css', array(), true);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static public function defineCenterMap($data = false)
 | |
| 	{
 | |
| 		# retrieve venue
 | |
| 		$venue = $data->getValue('venue');
 | |
| 
 | |
| 		if ($venue) {
 | |
| 			# latitude/longitude
 | |
| 			$lat  = $data->getValue('latitude');
 | |
| 			$long = $data->getValue('longitude');
 | |
| 
 | |
| 			if ($lat == 0.000000) {
 | |
| 				$lat = null;
 | |
| 			}
 | |
| 
 | |
| 			if ($long == 0.000000) {
 | |
| 				$long = null;
 | |
| 			}
 | |
| 
 | |
| 			if ($lat && $long) {
 | |
| 				$location = '['.$data->getValue('latitude').','.$data->getValue('longitude').']';
 | |
| 			} else {
 | |
| 				# retrieve address-info
 | |
| 				$postalCode = $data->getValue('postalCode');
 | |
| 				$city       = $data->getValue('city');
 | |
| 				$street     = $data->getValue('street');
 | |
| 
 | |
| 				$location = '"'.$street.' '.$postalCode.' '.$city.'"';
 | |
| 			}
 | |
| 			$location = 'location:'.$location.',';
 | |
| 		} else {
 | |
| 			$location = '';
 | |
| 		}
 | |
| 
 | |
| 		return $location;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Load Custom CSS
 | |
| 	 *
 | |
| 	 * @return boolean
 | |
|      */
 | |
| 	static public function loadCustomCss()
 | |
| 	{
 | |
|         $app         = Factory::getApplication();
 | |
|         $document    = $app->getDocument();
 | |
| 		$settings    = self::retrieveCss();
 | |
| 		$jemsettings = self::config();
 | |
| 		$layoutstyle = isset($jemsettings->layoutstyle) ? (int)$jemsettings->layoutstyle : 0;
 | |
| 		$style       = "";
 | |
| 
 | |
| 		# background-colors
 | |
| 		$bg_filter            = $settings->get('css_color_bg_filter');
 | |
| 		$bg_h2                = $settings->get('css_color_bg_h2');
 | |
| 		$bg_jem               = $settings->get('css_color_bg_jem');
 | |
| 		$bg_table_th          = $settings->get('css_color_bg_table_th');
 | |
| 		$bg_table_td          = $settings->get('css_color_bg_table_td');
 | |
| 		$bg_table_tr_entry2   = $settings->get('css_color_bg_table_tr_entry2');
 | |
| 		$bg_table_tr_hover    = $settings->get('css_color_bg_table_tr_hover');
 | |
| 		$bg_table_tr_featured = $settings->get('css_color_bg_table_tr_featured');
 | |
| 		# border-colors
 | |
| 		$border_filter        = $settings->get('css_color_border_filter');
 | |
| 		$border_h2            = $settings->get('css_color_border_h2');
 | |
| 		$border_table_th      = $settings->get('css_color_border_table_th');
 | |
| 		$border_table_td      = $settings->get('css_color_border_table_td');
 | |
| 		# font-color
 | |
| 		$font_table_h2        = $settings->get('css_color_font_h2');
 | |
| 		$font_table_th        = $settings->get('css_color_font_table_th');
 | |
| 		$font_table_td        = $settings->get('css_color_font_table_td');
 | |
| 		$font_table_td_a      = $settings->get('css_color_font_table_td_a');
 | |
| 
 | |
| 		switch ($layoutstyle) {
 | |
| 		case 1: // 'responsive'
 | |
| 			if (!empty($bg_filter)) {
 | |
| 				$style .= "div#jem #jem_filter {background-color:".$bg_filter.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_h2)) {
 | |
| 				$style .= "div#jem h2 {background-color:".$bg_h2.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_jem)) {
 | |
| 				$style .= "div#jem {background-color:".$bg_jem.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_th)) {
 | |
| 				$style .= "div#jem .jem-misc, div#jem .jem-sort-small {background-color:" . $bg_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_td)) { //Caused by the row-layout of JEM-Responsive, there exist no cells, we use that for row-color
 | |
| 				$style .= "div#jem .eventlist li:nth-child(odd) {background-color:" . $bg_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_tr_entry2)) {
 | |
| 				$style .= "div#jem .eventlist li:nth-child(even) {background-color:" . $bg_table_tr_entry2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_tr_featured)) {
 | |
| 				$style .= "div#jem .eventlist .jem-featured {background-color:" . $bg_table_tr_featured . ";}";
 | |
| 			}
 | |
| 			// Important: :hover must be after .featured to overrule
 | |
| 			if (!empty($bg_table_tr_hover)) {
 | |
| 				$style .= "div#jem .eventlist li:hover {background-color:" . $bg_table_tr_hover . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_filter)) {
 | |
| 				$style .= "div#jem #jem_filter {border: 1px solid " . $border_filter . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_h2)) {
 | |
| 				$style .= "div#jem h2 {border: 1px solid " . $border_h2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_table_th)) {
 | |
| 				$style .= "div#jem .jem-misc, div#jem .jem-sort-small {border: 1px solid " . $border_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_table_td)) {
 | |
| 				$style .= "div#jem .jem-event, div#jem .jem-event:first-child {border-color: " . $border_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_h2)) {
 | |
| 				$style .= "div#jem h2 {color:" . $font_table_h2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_th)) {
 | |
| 				$style .= "div#jem .jem-misc, div#jem .jem-sort-small {color:" . $font_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_td)) {
 | |
| 				$style .= "div#jem .jem-event {color:" . $font_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_td_a)) {
 | |
| 				$style .= "div#jem .jem-event a {color:" . $font_table_td_a . ";}";
 | |
| 			}
 | |
| 			break;
 | |
| 		case 2: // 'alternative'
 | |
| 			if (!empty($bg_filter)) {
 | |
| 				$style .= "div#jem #jem_filter {background-color:".$bg_filter.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_h2)) {
 | |
| 				$style .= "div#jem h2 {background-color:".$bg_h2.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_jem)) {
 | |
| 				$style .= "div#jem {background-color:".$bg_jem.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_th)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableheader {background-color:" . $bg_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_td)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry:nth-child(even) {background-color:" . $bg_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_tr_entry2)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry:nth-child(odd) {background-color:" . $bg_table_tr_entry2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_tr_featured)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry.featured {background-color:" . $bg_table_tr_featured . ";}";
 | |
| 			}
 | |
| 			// Important: :hover must be after .featured to overrule
 | |
| 			if (!empty($bg_table_tr_hover)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry:hover {background-color:" . $bg_table_tr_hover . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_filter)) {
 | |
| 				$style .= "div#jem #jem_filter {border-color:" . $border_filter . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_h2)) {
 | |
| 				$style .= "div#jem h2 {border-color:".$border_h2.";}";
 | |
| 			}
 | |
| 			if (!empty($border_table_th)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableheader {border-color:" . $border_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_table_td)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry {border-color:" . $border_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_h2)) {
 | |
| 				$style .= "div#jem h2 {color:" . $font_table_h2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_th)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableheader {color:" . $font_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_td)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry {color:" . $font_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_td_a)) {
 | |
| 				$style .= "div#jem div.eventtable .sectiontableentry a {color:" . $font_table_td_a . ";}";
 | |
| 			}
 | |
| 			break;
 | |
| 		default: // 'original'
 | |
| 			if (!empty($bg_filter)) {
 | |
| 				$style .= "div#jem #jem_filter {background-color:".$bg_filter.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_h2)) {
 | |
| 				$style .= "div#jem h2 {background-color:".$bg_h2.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_jem)) {
 | |
| 				$style .= "div#jem {background-color:".$bg_jem.";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_th)) {
 | |
| 				$style .= "div#jem table.eventtable th {background-color:" . $bg_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_td)) {
 | |
| 				$style .= "div#jem table.eventtable td {background-color:" . $bg_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_tr_entry2)) {
 | |
| 				$style .= "div#jem table.eventtable tr.sectiontableentry2 td {background-color:" . $bg_table_tr_entry2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($bg_table_tr_featured)) {
 | |
| 				$style .= "div#jem table.eventtable tr.featured td {background-color:" . $bg_table_tr_featured . ";}";
 | |
| 			}
 | |
| 			// Important: :hover must be after .featured to overrule
 | |
| 			if (!empty($bg_table_tr_hover)) {
 | |
| 				$style .= "div#jem table.eventtable tr:hover td {background-color:" . $bg_table_tr_hover . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_filter)) {
 | |
| 				$style .= "div#jem #jem_filter {border-color:" . $border_filter . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_h2)) {
 | |
| 				$style .= "div#jem h2 {border-color:".$border_h2.";}";
 | |
| 			}
 | |
| 			if (!empty($border_table_th)) {
 | |
| 				$style .= "div#jem table.eventtable th {border-color:" . $border_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($border_table_td)) {
 | |
| 				$style .= "div#jem table.eventtable td {border-color:" . $border_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_h2)) {
 | |
| 				$style .= "div#jem h2 {color:" . $font_table_h2 . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_th)) {
 | |
| 				$style .= "div#jem table.eventtable th {color:" . $font_table_th . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_td)) {
 | |
| 				$style .= "div#jem table.eventtable td {color:" . $font_table_td . ";}";
 | |
| 			}
 | |
| 			if (!empty($font_table_td_a)) {
 | |
| 				$style .= "div#jem table.eventtable td a {color:" . $font_table_td_a . ";}";
 | |
| 			}
 | |
| 			break;
 | |
| 		} // switch
 | |
| 
 | |
| 		$document->addStyleDeclaration($style);
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Loads Custom Tags
 | |
| 	 *
 | |
| 	 * @return boolean
 | |
| 	 */
 | |
| 	static public function loadCustomTag()
 | |
| 	{
 | |
|         $app = Factory::getApplication();
 | |
|         $document = $app->getDocument();
 | |
| 		$tag = "";
 | |
| 		$tag .= "<!--[if IE]><style type='text/css'>.floattext{zoom:1;}, * html #jem dd { height: 1%; }</style><![endif]-->";
 | |
| 
 | |
| 		$document->addCustomTag($tag);
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get a variable from the manifest file (actually, from the manifest cache).
 | |
| 	 *
 | |
| 	 * @param  $column  manifest_cache(1),params(2)
 | |
| 	 * @param  $setting name of setting to retrieve
 | |
| 	 * @param  $type    compononent(1), plugin(2)
 | |
| 	 * @param  $name    name to search in column name
 | |
| 	 */
 | |
| 	static public function getParam($column, $setting, $type, $name)
 | |
| 	{
 | |
| 		switch ($column) {
 | |
| 			case 1:
 | |
| 				$column = 'manifest_cache';
 | |
| 				break;
 | |
| 			case 2:
 | |
| 				$column = 'params';
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
| 		switch ($type) {
 | |
| 			case 1:
 | |
| 				$type = 'component';
 | |
| 				break;
 | |
| 			case 2:
 | |
| 				$type = 'plugin';
 | |
| 				break;
 | |
| 			case 3:
 | |
| 				$type = 'module';
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
|         $db = Factory::getContainer()->get('DatabaseDriver');
 | |
| 		$query = $db->getQuery(true);
 | |
| 		$query->select(array($column));
 | |
| 		$query->from('#__extensions');
 | |
| 		$query->where(array('name = '.$db->quote($name),'type = '.$db->quote($type)));
 | |
| 		$db->setQuery($query);
 | |
| 
 | |
| 		$manifest = json_decode($db->loadResult(), true);
 | |
| 		$result = $manifest[ $setting ];
 | |
| 
 | |
| 		if (empty($result)) {
 | |
| 			$result = 'N/A';
 | |
| 		}
 | |
| 
 | |
| 		return $result;
 | |
| 	}
 | |
| 
 | |
| 	static public function getCountryOptions()
 | |
| 	{
 | |
| 		$options = array();
 | |
| 		$options = array_merge(JemHelperCountries::getCountryOptions(),$options);
 | |
| 
 | |
| 		array_unshift($options, HTMLHelper::_('select.option', '0', Text::_('COM_JEM_SELECT_COUNTRY')));
 | |
| 
 | |
| 		return $options;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * This method transliterates a string into a URL
 | |
| 	 * safe string or returns a URL safe UTF-8 string
 | |
| 	 * based on the global configuration
 | |
| 	 *
 | |
| 	 * @param  string  $string  String to process
 | |
| 	 *
 | |
| 	 * @return string  Processed string
 | |
| 	 *
 | |
| 	 * @see    ApplicationHelper
 | |
| 	 * @since  2.1.7
 | |
| 	 */
 | |
| 	static public function stringURLSafe($string)
 | |
| 	{
 | |
| 		return ApplicationHelper::stringURLSafe($string);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * This method returns true if a string is within another string.
 | |
| 	 *
 | |
| 	 * @param  string $masterstring
 | |
| 	 * @param  string $string
 | |
| 	 * @return boolean
 | |
| 	 */
 | |
| 	static public function jemStringContains($masterstring, $string)
 | |
| 	{
 | |
| 		return ($masterstring && $string && strpos($masterstring, $string) !== false);
 | |
| 	}
 | |
| }
 |