primo commit

This commit is contained in:
2024-12-17 17:34:10 +01:00
commit e650f8df99
16435 changed files with 2451012 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
<?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
*/
/**
* @subclass: activeCalendarWeek
* @class: activeCalendar
* @project: Active Calendar
* @license: GNU LESSER GENERAL PUBLIC LICENSE;
* Special thanks to Jeremy D. Frens, Professor, Computer Science <jdfrens@calvin.edu> for his help developing this code
* This subclass generates weekly calendars as a html table (XHTML Valid) using the activeCalendar class
* Support, feature requests and bug reports please at : https://www.micronetwork.de/activecalendar/
*/
defined('_JEXEC') or die;
require_once('calendar.class.php');
class ActiveCalendarWeek extends JEMCalendar {
/*
********************************************************************************
Names of the generated html classes. You may change them to avoid any conflicts with your existing CSS
********************************************************************************
*/
var $cssWeeksTable="week";
var $cssMonthWeek="monthweek";
/*
----------------------
@START PUBLIC METHODS
----------------------
*/
/*
********************************************************************************
PUBLIC class constructor. Calls the main class constructor
********************************************************************************
*/
public function __construct($year=false, $month=false, $day=false, $GMTDiff="none") {
parent::__construct($year, $month, $day, $GMTDiff);
$this->GMT=$GMTDiff;
}
/*
********************************************************************************
PUBLIC showWeeks() -> returns the week view as html table string
The week calendar starts on the date set in the constructor
It generates as many rows as set in $numberOfWeeks
********************************************************************************
*/
function showWeeks($numberOfWeeks=1) {
$out=$this->mkWeeksHead();
$out.=$this->mkWeekDayz();
$out.=$this->mkWeeksBody($numberOfWeeks);
$out.=$this->mkWeeksFoot();
return $out;
}
/*
********************************************************************************
PUBLIC showWeeksByID() -> returns the week view as html table string
The week calendar starts with the week row, that has the same week number of the year as set in the weekID
It generates as many rows as set in $numberOfWeeks
********************************************************************************
*/
function showWeeksByID($weekID=1, $numberOfWeeks=1) {
$xday=1;
$from = ($weekID-2) * 7;
$to = ($weekID+1) * 7;
for ($day = $from; $day < $to; $day++) {
$tmp=parent::getWeekNum($day);
if ($tmp==$weekID) {
$xday=$day;
break;
}
}
if ($this->startOnSun) $xday=$xday-1;
$this->__construct($this->actyear, $this->actmonth, $xday, $this->GMT);
return $this->showWeeks($numberOfWeeks);
}
/*
********************************************************************************
PUBLIC getFirstDayTime() -> returns the first day of given week as unixtime
********************************************************************************
*/
function getFirstDayTimeOfWeek($weekID = 1) {
$unixdate = false;
/* There should be an inverse function but for now trying some days is ok */
$from = ($weekID-2) * 7;
$to = ($weekID+1) * 7;
for ($day = $from; $day < $to; $day++) {
$tmp = parent::getWeekNum($day);
if ($tmp == $weekID) {
$xday = ($this->startOnSun) ? $day - 1 : $day;
$unixdate = $this->mkActiveTime(0, 0, 1, $this->actmonth, $xday, $this->actyear);
break;
}
}
return $unixdate;
}
/*
----------------------
@START PRIVATE METHODS
----------------------
*/
/*
********************************************************************************
PRIVATE mkWeeksHead() -> creates the week table tag
********************************************************************************
*/
function mkWeeksHead() {
return "<table class=\"".$this->cssWeeksTable."\">\n";
}
/*
********************************************************************************
PRIVATE mkWeekDayz() -> creates the tr tag of the week table for the weekdays
********************************************************************************
*/
function mkWeekDayz() {
$out='<tr class="daynamesRow">';
if ($this->weekNum) {
$out .= "<td class=\"" . $this->cssWeekNumTitle . "\">" . $this->weekNumTitle . "</td>";
}
for ($x=0; $x<=6; $x++) {
$out.=$this->mkSingleWeekDay($this->actday+$x);
}
$out.="</tr>\n";
return $out;
}
/*
********************************************************************************
PRIVATE mkWeeksBody() -> creates the tr tags of the week table
********************************************************************************
*/
function mkWeeksBody($numberOfWeeks) {
$this->resetSelectedToToday();
$out = $this->mkMonthRow();
for ($week = 0; $week < $numberOfWeeks; $week++) {
$out .= '<tr class="daysRow">';
$weeknumber=parent::mkWeekNum($this->actday);
$weekday=parent::getWeekday($this->actday);
if ($this->startOnSun && ($weekday>4 || $weekday==0)) $weeknumber=parent::mkWeekNum($this->actday+1); // week starts on Monday in date("w")
if ($this->weekNum) $out.="<td class=\"".$this->cssWeekNum."\">".$weeknumber."</td>";
for ($i = 0; $i <= 6; $i++) {
$out.=$this->mkDay($this->actday);
$this->__construct($this->actyear, $this->actmonth, $this->actday+1, $this->GMT);
$this->resetSelectedToToday();
}
$out.="</tr>\n";
if ($this->actday+6>$this->getDaysThisMonth() && $week<$numberOfWeeks-1) $out.= $this->mkMonthRow(false);
elseif ($this->actday==1 && $week<$numberOfWeeks-1) $out.=$this->mkMonthRow();
}
return $out;
}
/*
********************************************************************************
PRIVATE mkWeeksFoot() -> closes the week table tag
********************************************************************************
*/
function mkWeeksFoot() {
return "</table>\n";
}
/*
********************************************************************************
PRIVATE mkMonthRow() -> creates the tr tag of the week table to tisplay month names when needed
The parameter indicates if the name of the first month is needed (at the beginning of the weekly calendar).
********************************************************************************
*/
function mkMonthRow($bothMonths=true) {
$colspanLeft = min($this->getDaysThisMonth() - $this->actday + 1, 7);
$colspanRight = 7 - $colspanLeft;
$out = '<tr class="newMonthRow">';
if ($this->weekNum) $out.='<td class="'.$this->cssWeekNum.'"></td>';
$out .= '<td class="' . $this->cssMonthWeek . '" colspan="' . $colspanLeft . '">';
if ($bothMonths) $out .= parent::getMonthName($this->actmonth).$this->monthYearDivider.$this->actyear;
$out .= '</td>';
if ($colspanRight>0) {
if ($this->actmonth+1>12) {
$calmonth=1;
$calyear=$this->actyear+1;
} else {
$calmonth=$this->actmonth+1;
$calyear=$this->actyear;
}
$out .= '<td class="' . $this->cssMonthWeek . '" colspan="' . $colspanRight . '">'.parent::getMonthName($calmonth).$this->monthYearDivider.$calyear.'</td>';
}
return $out;
}
/* Helper methods */
function mkSingleWeekDay($var) {
$weekday=parent::getWeekday($var);
$out ="<td class=\"".$this->cssWeekDay."\">".parent::getDayName($weekday)."</td>";
return $out;
}
function getDaysThisMonth() {
return $this->getMonthDays($this->actmonth, $this->actyear);
}
function resetSelectedToToday() {
$this->selectedyear = $this->yeartoday;
$this->selectedmonth = $this->monthtoday;
// Setting to an invalid day to prevent selection
$this->selectedday = -2; // $this->daytoday;
}
}
?>

View File

@ -0,0 +1,301 @@
<?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\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Filesystem\Path;
// ensure JemFactory is loaded (because this class is used by modules or plugins too)
require_once(JPATH_SITE.'/components/com_jem/factory.php');
/**
* Holds the logic for attachments manipulation
*
* @package JEM
*/
class JemAttachment extends CMSObject
{
/**
* upload files for the specified object
*
* @param array data from JInputFiles (as array of n arrays of params, [n][params])
* @param string object identification (should be event<eventid>, category<categoryid>, etc...)
*/
static public function postUpload($post_files, $object)
{
require_once JPATH_SITE.'/components/com_jem/classes/image.class.php';
$user = JemFactory::getUser();
$jemsettings = JemHelper::config();
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$object;
if (!(is_array($post_files) && count($post_files))) {
return false;
}
$allowed = explode(",", $jemsettings->attachments_types);
foreach ($allowed as $k => $v) {
$allowed[$k] = ($v ? trim($v) : $v);
}
$maxsizeinput = $jemsettings->attachments_maxsize*1024; //size in kb
foreach ($post_files as $k => $rec)
{
$file = array_key_exists('name', $rec) ? $rec['name'] : '';
if (empty($file)) {
continue;
}
// check if the filetype is valid
$fileext = strtolower(File::getExt($file));
if (!in_array($fileext, $allowed)) {
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_ATTACHEMENT_EXTENSION_NOT_ALLOWED').': '.$file, 'warning');
continue;
}
// check size
if ($rec['size'] > $maxsizeinput) {
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_JEM_ERROR_ATTACHEMENT_FILE_TOO_BIG', $file, $rec['size'], $maxsizeinput), 'warning');
continue;
}
if (!Folder::exists($path)) {
// try to create it
$res = Folder::create($path);
if (!$res) {
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_COULD_NOT_CREATE_FOLDER').': '.$path, 'warning');
return false;
}
}
// TODO: Probably move this to a helper class
$sanitizedFilename = JemImage::sanitize($path, $file);
// Make sure that the full file path is safe.
$filepath = Path::clean( $path.'/'.$sanitizedFilename);
// Since Joomla! 3.4.0 File::upload has some more params to control new security parsing
// switch off parsing archives for byte sequences looking like a script file extension
// but keep all other checks running
File::upload($rec['tmp_name'], $filepath, false, false, array('fobidden_ext_in_content' => false));
$table = Table::getInstance('jem_attachments', '');
$table->file = $sanitizedFilename;
$table->object = $object;
if (isset($rec['customname']) && !empty($rec['customname'])) {
$table->name = $rec['customname'];
}
if (isset($rec['description']) && !empty($rec['description'])) {
$table->description = $rec['description'];
}
if (isset($rec['access'])) {
$table->access = intval($rec['access']);
}
$table->added = date('Y-m-d H:i:s');
$table->added_by = $user->get('id');
if (!($table->check() && $table->store())) {
\Joomla\CMS\Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_ATTACHMENT_SAVING_TO_DB').': '.$table->getError(), 'warning');
}
} // foreach
return true;
}
/**
* update attachment record in db
* @param array (id, name, description, access)
*/
static public function update($attach)
{
if (!is_array($attach) || !isset($attach['id']) || !(intval($attach['id']))) {
return false;
}
$table = Table::getInstance('jem_attachments', '');
$table->load($attach['id']);
$table->bind($attach);
if (!($table->check() && $table->store())) {
\Joomla\CMS\Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_ATTACHMENT_UPDATING_RECORD').': '.$table->getError(), 'warning');
return false;
}
return true;
}
/**
* return attachments for objects
* @param string object identification (should be event<eventid>, category<categoryid>, etc...)
* @return array
*/
static public function getAttachments($object)
{
$jemsettings = JemHelper::config();
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$object;
if (!file_exists($path)) {
return array();
}
// first list files in the folder
$files = Folder::files($path, null, false, false);
// then get info for files from db
$db = Factory::getContainer()->get('DatabaseDriver');
$fnames = array();
foreach ($files as $f) {
$fnames[] = $db->Quote($f);
}
if (!count($fnames)) {
return array();
}
// Check access level if not a Super User on Backend.
$user = JemFactory::getUser();
if (Factory::getApplication()->isClient('administrator') && $user->authorise('core.manage')) {
$qAccess = '';
} else {
$levels = $user->getAuthorisedViewLevels();
$qAccess = ' AND access IN (' . implode(',', $levels) . ')';
}
$query = 'SELECT * '
. ' FROM #__jem_attachments '
. ' WHERE file IN ('. implode(',', $fnames) .')'
. ' AND object = '. $db->Quote($object)
. $qAccess
. ' ORDER BY ordering ASC ';
$db->setQuery($query);
$res = $db->loadObjectList();
return $res;
}
/**
* get the file
*
* @param int $id
*/
static public function getAttachmentPath($id)
{
$jemsettings = JemHelper::config();
$user = JemFactory::getUser();
// Support Joomla access levels instead of single group id
$levels = $user->getAuthorisedViewLevels();
$db = Factory::getContainer()->get('DatabaseDriver');
$query = 'SELECT * '
. ' FROM #__jem_attachments '
. ' WHERE id = '. $db->Quote(intval($id));
$db->setQuery($query);
$res = $db->loadObject();
if (!$res) {
throw new Exception(Text::_('COM_JEM_FILE_NOT_FOUND'), 404);
}
if (!in_array($res->access, $levels)) {
throw new Exception(Text::_('COM_JEM_NO_ACCESS'), 403);
}
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$res->object.'/'.$res->file;
if (!file_exists($path)) {
throw new Exception(Text::_('COM_JEM_FILE_NOT_FOUND'), 404);
}
return $path;
}
/**
* remove attachment for objects
*
* @param id from db
* @param string object identification (should be event<eventid>, category<categoryid>, etc...)
* @return boolean
*/
static public function remove($id)
{
$jemsettings = JemHelper::config();
$user = JemFactory::getUser();
// Support Joomla access levels instead of single group id
$levels = $user->getAuthorisedViewLevels();
$userid = $user->get('id');
// then get info for files from db
$db = Factory::getContainer()->get('DatabaseDriver');
$query = 'SELECT file, object, added_by '
. ' FROM #__jem_attachments '
. ' WHERE id = ' . $db->Quote($id) . ' AND access IN (0,' . implode(',', $levels) . ')';
$db->setQuery($query);
$res = $db->loadObject();
if (!$res) {
return false;
}
// check permission
if (empty($userid) || ($userid != $res->added_by)) {
if (strncasecmp($res->object, 'event', 5) == 0) {
$type = 'event';
$itemid = (int)substr($res->object, 5);
$table = '#__jem_events';
} elseif (strncasecmp($res->object, 'venue', 5) == 0) {
$type = 'venue';
$itemid = (int)substr($res->object, 5);
$table = '#__jem_venues';
} else {
return false;
}
// get item owner
$query = 'SELECT created_by FROM ' . $table . ' WHERE id = ' . $db->Quote($itemid);
$db->setQuery($query);
$created_by = $db->loadResult();
if (!$user->can('edit', $type, $itemid, $created_by)) {
JemHelper::addLogEntry("User {$userid} is not permritted to remove attachment " . $res->object, __METHOD__);
return false;
}
}
JemHelper::addLogEntry("User {$userid} removes attachment " . $res->object.'/'.$res->file, __METHOD__);
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$res->object.'/'.$res->file;
if (file_exists($path)) {
File::delete($path);
}
$query = 'DELETE FROM #__jem_attachments '
. ' WHERE id = '. $db->Quote($id);
$db->setQuery($query);
$res = $db->execute();
if (!$res) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,985 @@
<?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
*/
/**
* Based on
* @class: activeCalendar
* @project: Active Calendar
* @version: 1.2.0;
* @author: Giorgos Tsiledakis;
* @date: 23 Feb 2006;
* @copyright: Giorgos Tsiledakis;
* @license: GNU LESSER GENERAL PUBLIC LICENSE;
* Support, feature requests and bug reports please at : https://www.micronetwork.de/activecalendar/
* Special thanks to Corissia S.A (https://www.corissia.com) for the permission to publish the source code
* Thanks to Maik Lindner (https://nifox.com) for his help developing this class
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
#[AllowDynamicProperties]
class JemCalendar
{
/*
----------------------
@START CONFIGURATION
----------------------
*/
/*
********************************************************************************
You can change below the month and day names, according to your language
This is just the default configuration. You may set the month and day names by calling setMonthNames() and setDayNames()
********************************************************************************
*/
var $jan="January";
var $feb="February";
var $mar="March";
var $apr="April";
var $may="May";
var $jun="June";
var $jul="July";
var $aug="August";
var $sep="September";
var $oct="October";
var $nov="November";
var $dec="December";
var $sun="Sun";
var $mon="Mon";
var $tue="Tue";
var $wed="Wed";
var $thu="Thu";
var $fri="Fri";
var $sat="Sat";
/*
********************************************************************************
$startOnSun = false: first day of week is Monday
$startOnSun = true: first day of week is Sunday
You may use the method setFirstWeekDay() instead
********************************************************************************
*/
var $startOnSun=false;
/*
********************************************************************************
$rowCount : defines the number of months in a row in yearview (can be also set by the method showYear())
********************************************************************************
*/
var $rowCount=4;
/*
********************************************************************************
Names of the generated html classes. You may change them to avoid any conflicts with your existing CSS
********************************************************************************
*/
var $cssYearTable="year"; // table tag: calendar year
var $cssYearTitle="yearname"; // td tag: calendar year title
var $cssYearNav="yearnavigation"; // td tag: calendar year navigation
var $cssMonthTable="month"; // table tag: calendar month
var $cssMonthTitle="monthname"; // td tag: calendar month title
var $cssMonthNav="monthnavigation"; // td tag: calendar month navigation
var $cssWeekDay="dayname"; // td tag: calendar weekdays
var $cssWeekNumTitle="weeknumtitle"; // td tag: title of the week numbers
var $cssWeekNum="weeknum"; // td tag: week numbers
var $cssPicker="datepicker"; // td tag: date picker
var $cssPickerForm="datepickerform"; // form tag: date picker form
var $cssPickerMonth="monthpicker"; // select tag: month picker
var $cssPickerYear="yearpicker"; // select tag: year picker
var $cssPickerButton="pickerbutton"; // input (submit) tag: date picker button
var $cssMonthDay="monthday"; // td tag: days, that belong to the current month
var $cssNoMonthDay="nomonthday"; // td tag: days, that do not belong to the current month
var $cssToday="today"; // td tag: the current day
var $cssSelecDay="selectedday"; // td tag: the selected day
var $cssSunday="sunday"; // td tag: all Sundays (can be disabled, see below)
var $cssSaturday="saturday"; // td tag: all Saturdays (can be disabled, see below)
var $cssEvent="event"; // td tag: event day set by setEvent(). Multiple class names can be generated
var $cssPrefixSelecEvent="selected"; // prefix for the event class name if the event is selected
var $cssPrefixTodayEvent="today"; // prefix for the event class name if the event is the current day
var $cssEventContent="eventcontent"; // table tag: calendar event content. Multiple class names can be generated
var $crSunClass=true; // true: creates a td class on every Sunday (set above)
var $crSatClass=true; // true: creates a td class on every Saturday (set above)
/*
********************************************************************************
You can change below the GET VARS NAMES [url parameter names] (navigation + day links)
You should modify the private method mkUrl() or mkWeekNum(), if you want to change the structure of the generated links
********************************************************************************
*/
var $yearID="yearID";
var $monthID="monthID";
var $dayID="dayID";
var $weekID="weekID";
/*
********************************************************************************
Default start and end year for the date picker (can be changed, if using the ADOdb Date Library)
********************************************************************************
*/
var $startYear=1971;
var $endYear=2037;
/*
----------------------
@START PUBLIC METHODS
----------------------
*/
/*
********************************************************************************
PUBLIC activeCalendar() -> class constructor, does the initial date calculation
$GMTDiff: GMT Zone for current day calculation, do not set to use local server time
********************************************************************************
*/
public function __construct($year=false,$month=false,$day=false,$GMTDiff="none") {
$this->timetoday=time();
$this->selectedday=-2;
$this->selectedyear=$year;
$this->selectedmonth=$month;
if (!$month) $month=1;
if (!$day) $day=1;
else $this->selectedday=$day;
$h=$this->mkActiveGMDate("H");
$m=$this->mkActiveGMDate("i");
$s=$this->mkActiveGMDate("s");
$d=$this->mkActiveGMDate("j");
$mo=$this->mkActiveGMDate("n");
$y=$this->mkActiveGMDate("Y");
$is_dst=$this->mkActiveDate("I");
if ($GMTDiff!="none") $this->timetoday=$this->mkActiveTime($h,$m,$s,$mo,$d,$y)+(3600*($GMTDiff+$is_dst));
$this->unixtime=$this->mkActiveTime($h,$m,$s,$month,$day,$year);
if ($this->unixtime==-1 || !$year) $this->unixtime=$this->timetoday;
$this->daytoday=$this->mkActiveDate("j");
$this->monthtoday=$this->mkActiveDate("n");
$this->yeartoday=$this->mkActiveDate("Y");
if (!$day) $this->actday=$this->daytoday;
else $this->actday=$this->mkActiveDate("j",$this->unixtime);
if (!$month) $this->actmonth=$this->monthtoday;
else $this->actmonth=$this->mkActiveDate("n",$this->unixtime);
if (!$year) $this->actyear=$this->yeartoday;
else $this->actyear=$this->mkActiveDate("Y",$this->unixtime);
$this->has31days=checkdate($this->actmonth,31,$this->actyear);
$this->isSchalt=checkdate(2,29,$this->actyear);
if ($this->isSchalt==1 && $this->actmonth==2) $this->maxdays=29;
elseif ($this->isSchalt!=1 && $this->actmonth==2) $this->maxdays=28;
elseif ($this->has31days==1) $this->maxdays=31;
else $this->maxdays=30;
$this->firstday=$this->mkActiveDate("w", $this->mkActiveTime(0,0,1,$this->actmonth,1,$this->actyear));
$this->GMTDiff=$GMTDiff;
/*
********************************************************************************
You can change below the default year's and month's view navigation controls
********************************************************************************
*/
if (version_compare(JVERSION, '5.0.0', '>=')) {
// Joomla 5
$this->yearNavBack=" <i class='fa-solid fa-backward'></i> "; // Previous year
$this->yearNavForw=" <i class='fa-solid fa-forward'></i> "; // Next year
$this->monthNavBack=" <i class='fa-solid fa-backward-step'></i> "; // Previous month
$this->monthNavForw=" <i class='fa-solid fa-forward-step'></i> "; // Next month
} elseif (version_compare(JVERSION, '4.0.0', '>=')) {
// Joomla 4
$this->yearNavBack=" &lt;&lt; "; // Previous year, this could be an image link
$this->yearNavForw=" &gt;&gt; "; // Next year, this could be an image link
$this->monthNavBack=" &lt;&lt; "; // Previous month, this could be an image link
$this->monthNavForw=" &gt;&gt; "; // Next month, this could be an image link
}
$this->selBtn="Go"; // value of the date picker button (if enabled)
$this->monthYearDivider=" "; // the divider between month and year in the month`s title
}
/*
********************************************************************************
PUBLIC enableYearNav() -> enables the year's navigation controls
********************************************************************************
*/
function enableYearNav($link=false,$arrowBack=false,$arrowForw=false) {
if ($link) $this->urlNav=$link;
if ($arrowBack) $this->yearNavBack=$arrowBack;
if ($arrowForw) $this->yearNavForw=$arrowForw;
$this->yearNav=true;
}
/*
********************************************************************************
PUBLIC enableMonthNav() -> enables the month's navigation controls
********************************************************************************
*/
function enableMonthNav($link=false,$arrowBack=false,$arrowForw=false) {
if ($link) $this->urlNav=$link;
if ($arrowBack) $this->monthNavBack=$arrowBack;
if ($arrowForw) $this->monthNavForw=$arrowForw;
$this->monthNav=true;
}
/*
********************************************************************************
PUBLIC enableDayLinks() -> enables the day links
param javaScript: sets a Javascript function on each day link
********************************************************************************
*/
function enableDayLinks($link=false,$javaScript=false) {
if ($link) $this->url=$link;
if ($javaScript) $this->javaScriptDay=$javaScript;
$this->dayLinks=true;
}
/*
********************************************************************************
PUBLIC enableNewEventLinks() -> enables links on each day to create new events
param link: full html template with token "{date}" to get day's date
********************************************************************************
*/
function enableNewEventLinks($link) {
if ($link && (stripos($link, '{date}') !== false)) {
$this->htmlNewEventLink = $link;
$this->dayNewEventLinks = true;
} else {
$this->dayNewEventLinks = false;
}
return $this->dayNewEventLinks;
}
/*
********************************************************************************
PUBLIC enableDatePicker() -> enables the day picker control
********************************************************************************
*/
function enableDatePicker($startYear=false,$endYear=false,$link=false,$button=false) {
if ($link) $this->urlPicker=$link;
if ($startYear && $endYear) {
if ($startYear>=$this->startYear && $startYear<$this->endYear) $this->startYear=$startYear;
if ($endYear>$this->startYear && $endYear<=$this->endYear) $this->endYear=$endYear;
}
if ($button) $this->selBtn=$button;
$this->datePicker=true;
}
/*
********************************************************************************
PUBLIC enableWeekNum() -> enables a week number column
********************************************************************************
*/
function enableWeekNum($title="",$link=false,$javaScript=false) {
// checking before enabling, as week number calulation works only if php version > 4.1.0 [php function: date ("W")]
if (is_integer($this->getWeekNum($this->actday))) {
$this->weekNum=true;
$this->weekNumTitle=$title;
$this->monthSpan++;
if (empty($link)) {
$this->weekUrl='';
} else {
$this->weekUrl=$link;
}
if (empty($javaScript)) {
$this->javaScriptWeek='';
} else {
$this->javaScriptWeek=$javaScript;
}
}
}
/*
********************************************************************************
PUBLIC setEvent() -> sets a calendar event, $id: the HTML class (css layout)
********************************************************************************
*/
function setEvent($year,$month,$day,$id=false,$url=false) {
$eventTime=$this->mkActiveTime(0,0,1,$month,$day,$year);
if (!$id) $id=$this->cssEvent;
$this->calEvents[$eventTime]=$id;
$this->calEventsUrl[$eventTime]=$url;
}
/*
********************************************************************************
PUBLIC setEventContent() -> sets a calendar event content,
$content: can be a string or an array, $id: the HTML class (css layout)
********************************************************************************
*/
/**
* set event content
*
* @param int $year
* @param int $month
* @param int $day
* @param string or array $content
* @param string $url
* @param string $id the HTML class
*/
function setEventContent($year, $month, $day, $content, $url=false, $id=false)
{
// event time
$eventTime = $this->mkActiveTime(0, 0, 1, $month, $day, $year);
// add to eventcontent array
$eventContent[$eventTime] = $content;
$this->calEventContent[] = $eventContent;
// add specific id
if (!$id) $id = $this->cssEventContent;
$this->calEventContentId[] = $id;
// add url
if ($url) $this->calEventContentUrl[] = $url;
else $this->calEventContentUrl[] = $this->calInit++;
}
/*
********************************************************************************
PUBLIC setMonthNames() -> sets the month names, $namesArray must be an array of 12 months starting with January
********************************************************************************
*/
function setMonthNames($namesArray) {
if (!is_array($namesArray) || count($namesArray)!=12) return false;
else $this->monthNames=$namesArray;
}
/*
********************************************************************************
PUBLIC setDayNames() -> sets the week day names, $namesArray must be an array of 7 days starting with Sunday
********************************************************************************
*/
function setDayNames($namesArray) {
if (!is_array($namesArray) || count($namesArray)!=7) return false;
else $this->dayNames=$namesArray;
}
/*
********************************************************************************
PUBLIC setFirstWeekDay() -> sets the first day of the week, currently only Sunday and Monday supported, $daynum=0 -> Sunday
********************************************************************************
*/
function setFirstWeekDay($daynum) {
if ($daynum==0) $this->startOnSun=true;
else $this->startOnSun=false;
}
/*
********************************************************************************
PUBLIC showYear() -> returns the year's view as html table string
Each private method returns a tr tag of the table as a string.
You can change the calendar structure by simply calling these private methods in another order
********************************************************************************
*/
function showYear($rowCount=false,$startMonth=false) {
if ($rowCount) $this->rowCount=$rowCount;
$this->monthNav=false; // disables month navigation in yearview
$out=$this->mkYearHead(); // this should remain first: opens table tag
$out.=$this->mkYearTitle(); // tr tag: year title and navigation
$out.=$this->mkDatePicker("yearonly"); // tr tag: year date picker (only year selection)
$this->datePicker=false; // disables month date picker in yearview
$out.=$this->mkYearBody($startMonth); // tr tag(s): year month (html tables)
$out.=$this->mkYearFoot(); // this should remain last: closes table tag
return $out;
}
/*
********************************************************************************
PUBLIC showMonth() -> returns the month's view as html table string
Each private method returns a tr tag of the table as a string.
You can change the calendar structure by simply calling these private methods in another order
$showNoMonthDays = false: days, that do not belong to the current month, will not be displayed
$showNoMonthDays = true: days, that do not belong to the current month, will be displayed
(note: these 'noMonthDays' will not contain any events or eventcontents!)
********************************************************************************
*/
function showMonth($showNoMonthDays=false) {
$this->showNoMonthDays=$showNoMonthDays;
$out=$this->mkMonthHead(); // this should remain first: opens table tag
$out.=$this->mkMonthTitle(); // tr tag: month title and navigation
$out.=$this->mkDatePicker(); // tr tag: month date picker (month and year selection)
$out.=$this->mkWeekDays(); // tr tag: the weekday names
if ($this->showNoMonthDays==false) $out.=$this->mkMonthBody(); // tr tags: the days of the month
else $out.=$this->mkMonthBody(1); // tr tags: the days of the month
$out.=$this->mkMonthFoot(); // this should remain last: closes table tag
return $out;
}
/*
----------------------
@START PRIVATE METHODS
----------------------
*/
/*
********************************************************************************
THE FOLLOWING METHODS AND VARIABLES ARE PRIVATE. PLEASE DO NOT CALL OR MODIFY THEM
********************************************************************************
*/
var $version="1.2.0";
var $releaseDate="23 Feb 2006";
var $monthSpan=7;
var $timezone=false;
var $yearNav=false;
var $monthNav=false;
var $dayLinks=false;
var $dayNewEventLinks=false;
var $datePicker=false;
var $url=false;
var $urlNav=false;
var $urlPicker=false;
var $htmlNewEventLink=false;
var $calEvents=false;
var $calEventsUrl=false;
var $eventUrl=false;
var $javaScriptDay=false;
var $monthNames=false;
var $dayNames=false;
var $calEventContent=[];
var $calEventContentUrl=[];
var $calEventContentId=[];
var $calInit=0;
var $weekNum=false;
var $WeekUrl=false;
var $javaScriptWeek=false;
/*
********************************************************************************
PRIVATE mkYearHead() -> creates the year table tag
********************************************************************************
*/
function mkYearHead() {
return "<table class=\"".$this->cssYearTable."\">\n";
}
/*
********************************************************************************
PRIVATE mkYearTitle() -> creates the tile and navigation tr tag of the year table
********************************************************************************
*/
function mkYearTitle() {
if ($this->rowCount<1 || $this->rowCount>12) $this->rowCount=4;
if (!$this->yearNav) {
$out="<tr><td colspan=\"".$this->rowCount."\" class=\"".$this->cssYearTitle."\">";
$out.=$this->actyear;
$out.="</td></tr>\n";
} else {
$out="<tr><td colspan=\"".$this->rowCount."\" align=\"center\">";
$out.="<table><tr><td class=\"".$this->cssYearNav."\">";
$out.=$this->mkUrl($this->actyear-1);
$out.=$this->yearNavBack."</a></td>";
$out.="<td class=\"".$this->cssYearTitle."\">".$this->actyear."</td>";
$out.="<td class=\"".$this->cssYearNav."\">";
$out.=$this->mkUrl($this->actyear+1);
$out.=$this->yearNavForw."</a></td></tr></table></td></tr>\n";
}
return $out;
}
/*
********************************************************************************
PRIVATE mkYearBody() -> creates the tr tags of the year table
********************************************************************************
*/
function mkYearBody($stmonth=false) {
if (!$stmonth || $stmonth>12) $stmonth=1;
$TrMaker = $this->rowCount;
$curyear = $this->actyear;
$out="<tr>\n";
for ($x=1; $x<=12; $x++) {
$this->activeCalendar($curyear,$stmonth,false,$this->GMTDiff);
$out.="<td valign=\"top\">\n".$this->showMonth()."</td>\n";
if ($x == $TrMaker && $x < 12) {
$out.="</tr><tr>";
$TrMaker = ($TrMaker+$this->rowCount);
}
if ($stmonth == 12) {
$stmonth = 1;
$curyear++;
}
else $stmonth++;
}
$out.="</tr>\n";
return $out;
}
/*
********************************************************************************
PRIVATE mkYearFoot() -> closes the year table tag
********************************************************************************
*/
function mkYearFoot() {
return "</table>\n";
}
/*
********************************************************************************
PRIVATE mkMonthHead() -> creates the month table tag
********************************************************************************
*/
function mkMonthHead() {
return "<table class=\"".$this->cssMonthTable."\">\n";
}
/*
********************************************************************************
PRIVATE mkMonthTitle() -> creates the tile and navigation tr tag of the month table
********************************************************************************
*/
function mkMonthTitle() {
if (!$this->monthNav) {
$out="<tr><td class=\"".$this->cssMonthTitle."\" colspan=\"".$this->monthSpan."\">";
$out.=$this->getMonthName().$this->monthYearDivider.$this->actyear;
$out.="</td></tr>\n";
} else {
$out = "<tr><td class=\"".$this->cssMonthNav."\" colspan=\"2\" style=\"text-align:right;\">";
if ($this->actmonth==1) { // january
$out.=$this->mkUrl($this->actyear-1,"12");
} else {
$out.=$this->mkUrl($this->actyear,$this->actmonth-1);
}
$out .= $this->monthNavBack."</a></td>";
$out .= "<td class=\"".$this->cssMonthTitle."\" colspan=\"".($this->monthSpan-4)."\">";
$out .= $this->getMonthName().$this->monthYearDivider.$this->actyear."</td>";
$out .= "<td class=\"".$this->cssMonthNav."\" colspan=\"2\" style=\"text-align:left;\">";
if ($this->actmonth==12) { //december
$out.=$this->mkUrl($this->actyear+1,"1");
}
else {
$out.=$this->mkUrl($this->actyear,$this->actmonth+1);
}
$out.=$this->monthNavForw."</a></td></tr>\n";
}
return $out;
}
/*
********************************************************************************
PRIVATE mkDatePicker() -> creates the tr tag for the date picker
********************************************************************************
*/
function mkDatePicker($yearpicker=false) {
if ($this->datePicker && !empty($this->urlPicker)) {
if ($yearpicker) $pickerSpan=$this->rowCount;
else $pickerSpan=$this->monthSpan;
$out="<tr><td class=\"".$this->cssPicker."\" colspan=\"".$pickerSpan."\">\n";
$out.="<form name=\"".$this->cssPickerForm."\" class=\"".$this->cssPickerForm."\" action=\"".$this->urlPicker."\" method=\"get\">\n";
if (!$yearpicker) {
$out.="<select name=\"".$this->monthID."\" class=\"".$this->cssPickerMonth."\">\n";
for ($z=1;$z<=12;$z++) {
if ($z==$this->actmonth) $out.="<option value=\"".$z."\" selected=\"selected\">".$this->getMonthName($z)."</option>\n";
else $out.="<option value=\"".$z."\">".$this->getMonthName($z)."</option>\n";
}
$out.="</select>\n";
}
$out.="<select name=\"".$this->yearID."\" class=\"".$this->cssPickerYear."\">\n";
for ($z=$this->startYear;$z<=$this->endYear;$z++) {
if ($z==$this->actyear) $out.="<option value=\"".$z."\" selected=\"selected\">".$z."</option>\n";
else $out.="<option value=\"".$z."\">".$z."</option>\n";
}
$out.="</select>\n";
$out.="<input type=\"submit\" value=\"".$this->selBtn."\" class=\"".$this->cssPickerButton."\"></input>\n";
$out.="</form>\n";
$out.="</td></tr>\n";
}
else $out="";
return $out;
}
/*
********************************************************************************
PRIVATE mkWeekDays() -> creates the tr tag of the month table for the weekdays
********************************************************************************
*/
function mkWeekDays() {
if ($this->startOnSun) {
$out='<tr class="daynamesRow">';
if ($this->weekNum) $out.="<td class=\"".$this->cssWeekNumTitle."\">".$this->weekNumTitle."</td>";
for ($x=0;$x<=6;$x++) $out.="<td class=\"".$this->cssWeekDay."\">".$this->getDayName($x)."</td>";
$out.="</tr>\n";
} else {
$out='<tr class="daynamesRow">';
if ($this->weekNum) $out.="<td class=\"".$this->cssWeekNumTitle."\">".$this->weekNumTitle."</td>";
for ($x=1;$x<=6;$x++) $out.="<td class=\"".$this->cssWeekDay."\">".$this->getDayName($x)."</td>";
$out.="<td class=\"".$this->cssWeekDay."\">".$this->getDayName(0)."</td>";
$out.="</tr>\n";
$this->firstday=$this->firstday-1;
if ($this->firstday<0) $this->firstday=6;
}
return $out;
}
/*
********************************************************************************
PRIVATE mkMonthBody() -> creates the tr tags of the month table
********************************************************************************
*/
function mkMonthBody($showNoMonthDays=0) {
if ($this->actmonth==1) {
$pMonth=12;
$pYear=$this->actyear-1;
} else{
$pMonth=$this->actmonth-1;
$pYear=$this->actyear;
}
$out='<tr class="daysRow">';
$cor=0;
if ($this->startOnSun) {
$cor=1;
}
if ($this->weekNum) {
$out.="<td class=\"".$this->cssWeekNum."\">".$this->mkWeekNum(1+$cor)."</td>";
}
$monthday=0;
$nmonthday=1;
for ($x=0; $x<=6; $x++) {
if ($x>=$this->firstday) {
$monthday++;
$out.=$this->mkDay($monthday);
} else {
if ($showNoMonthDays==0) {
$out.="<td class=\"".$this->cssNoMonthDay."\"></td>";
} else {
$out.="<td class=\"".$this->cssNoMonthDay."\">".($this->getMonthDays($pMonth,$pYear)-($this->firstday-1)+$x)."</td>";
}
}
}
$out.="</tr>\n";
$goon=$monthday+1;
$stop=0;
for ($x=0; $x<=6; $x++) {
if ($goon>$this->maxdays) {
break;
}
if ($stop==1) {
break;
}
$out.='<tr class="daysRow">';
if ($this->weekNum) $out.="<td class=\"".$this->cssWeekNum."\">".$this->mkWeekNum($goon+$cor)."</td>";
for ($i=$goon; $i<=$goon+6; $i++) {
if ($i>$this->maxdays) {
if ($showNoMonthDays==0) {
$out.="<td class=\"".$this->cssNoMonthDay."\"></td>";
}
else {
$out.='<td class="'.$this->cssNoMonthDay.'"><div class="daynum">'.$nmonthday++.'</div></td>';
}
$stop=1;
} else {
$out.=$this->mkDay($i);
}
}
$goon=$goon+7;
$out.="</tr>\n";
}
$this->selectedday="-2";
return $out;
}
/*
********************************************************************************
PRIVATE mkDay() -> creates each td tag of the month body
********************************************************************************
*/
function mkDay($var) {
$eventContent = $this->mkEventContent($var);
$linktext = $var;
if ($this->dayLinks) {
if ($eventContent) {
if ($this->javaScriptDay) {
$linktext="<a href=\"javascript:".$this->javaScriptDay."(".$this->actyear.",".$this->actmonth.",".$var.")\">".$var."</a>";
} elseif (!empty($this->url)) {
$dayurl= Route::_($this->url.(strpos($this->url,"?") === false ? '?' : '&').'id='.sprintf('%04d%02d%02d',$this->actyear,$this->actmonth,$var));
$linktext="<a href=\"".$dayurl."\">".$var."</a>";
}
}
}
$htmlNewEventLink = '';
if ($this->dayNewEventLinks) {
$htmlNewEventLink = preg_replace('/{date}/', sprintf('%04d-%02d-%02d', $this->actyear, $this->actmonth, $var), $this->htmlNewEventLink);
}
if ($this->isEvent($var)) {
if ($this->eventUrl) {
$out="<td class=\"".$this->eventID."\"><div class=\"daynum\">".$htmlNewEventLink."<a href=\"".$this->eventUrl."\">".$var."</a></div>".$eventContent."</td>";
$this->eventUrl=false;
} else {
$out="<td class=\"".$this->eventID."\"><div class=\"daynum\">".$htmlNewEventLink.$linktext.'</div>'.$eventContent."</td>";
}
} else {
/* allow styling of multiple things like "today is Sunday" */
$cssClass = array($this->cssMonthDay);
if (($var == $this->selectedday) && ($this->actmonth == $this->selectedmonth) && ($this->actyear == $this->selectedyear)) {
$cssClass[] = $this->cssSelecDay;
}
if (($var == $this->daytoday) && ($this->actmonth == $this->monthtoday) && ($this->actyear == $this->yeartoday)) {
$cssClass[] = $this->cssToday;
}
if (($this->getWeekday($var) == 0) && $this->crSunClass) {
$cssClass[] = $this->cssSunday;
}
if (($this->getWeekday($var) == 6) && $this->crSatClass) {
$cssClass[] = $this->cssSaturday;
}
$out = "<td class=\"".implode(' ', $cssClass)."\"><div class=\"daynum\" jem-monthname=\"".$this->getMonthName()."\" jem-dayname=\"".$this->getDayName($this->getWeekday($var))."\">".$htmlNewEventLink.$linktext.'</div>'.$eventContent."</td>";
}
return $out;
}
/*
********************************************************************************
PRIVATE mkMonthFoot() -> closes the month table
********************************************************************************
*/
function mkMonthFoot() {
return "</table>\n";
}
/*
********************************************************************************
PRIVATE mkUrl() -> creates the day and navigation link structure
********************************************************************************
*/
function mkUrl($year, $month=false, $day=false) {
if (strpos($this->url,"?") === false) {
$glue="?";
} else {
$glue="&amp;";
}
if (strpos($this->urlNav,"?") === false) {
$glueNav="?";
} else {
$glueNav="&amp;";
}
$yearNavLink = empty($this->urlNav) ? '' : "<a href=\"".Route::_($this->urlNav.$glueNav.$this->yearID."=".$year)."\" rel=\"noindex, nofollow\">";
$monthNavLink = empty($this->urlNav) ? '' : "<a href=\"".Route::_($this->urlNav.$glueNav.$this->yearID."=".$year."&amp;".$this->monthID."=".$month)."\" rel=\"noindex, nofollow\">";
$dayLink = empty($this->url) ? $day : "<a href=\"".Route::_($this->url.$glue.$this->yearID."=".$year."&amp;".$this->monthID."=".$month."&amp;".$this->dayID."=".$day)."\">".$day."</a>";
if ($year && $month && $day) return $dayLink;
if ($year && !$month && !$day) return $yearNavLink;
if ($year && $month && !$day) return $monthNavLink;
}
/*
********************************************************************************
PRIVATE mkEventContent() -> creates the table for the event content
********************************************************************************
*/
/* see below
function mkEventContent_old($var)
{
$hasContent=$this->hasEventContent($var);
$out="";
if ($hasContent) {
for ($x=0;$x<count($hasContent);$x++) {
foreach($hasContent[$x] as $eventContentid => $eventContentData) {
foreach($eventContentData as $eventContentUrl => $eventContent) {
$out.="<table class=\"".$eventContentid."\">";
if (is_string($eventContent)) {
if (is_int($eventContentUrl)) {
$out.="<tr><td>".$eventContent."</td></tr></table>";
} else {
$out.="<tr><td><a href=\"".$eventContentUrl."\">".$eventContent."</a></td></tr></table>";
}
} else if (is_array($eventContent)) {
foreach($eventContent as $arrayContent) {
if (is_int($eventContentUrl)) {
$out.="<tr><td>".$arrayContent."</td></tr>";
} else {
$out.="<tr><td><a href=\"".$eventContentUrl."\">".$arrayContent."</a></td></tr>";
}
}
$out.="</table>";
}
else $out="";
}
}
}
}
return $out;
}
*/
/**
* creates the div for the event content
*
* @param int $var the day
* @return string
*/
function mkEventContent($var) {
$hasContent=$this->hasEventContent($var);
$out="";
if ($hasContent) {
$n = is_array($hasContent) ? count($hasContent) : 0;
for ($x = 0; $x < $n; $x++) {
foreach ($hasContent[$x] as $eventContentid => $eventContentData) {
foreach ($eventContentData as $eventContentUrl => $eventContent) {
if (is_string($eventContent)) {
$eventContent = array($eventContent);
}
foreach($eventContent as $arrayContent) {
$out .= '<div class="'.$eventContentid.'">';
if (is_int($eventContentUrl)) {
$out.= $arrayContent;
} else {
$out.='<a href="'.$eventContentUrl.'">'.$arrayContent.'</a>';
}
$out.='</div>';
}
}
}
}
}
return $out;
}
/*
********************************************************************************
PRIVATE mkWeekNum() -> returns the week number and optionally creates a link
********************************************************************************
*/
function mkWeekNum($var) {
$year=$this->actyear;
$week=$this->getWeekNum($var);
if ($week>50 && $this->actmonth==1) $year=$this->actyear-1;
$out="";
if ($this->weekUrl) {
if (strpos($this->weekUrl,"?") === false) $glue="?";
else $glue="&amp;";
$out.="<a href=\"".$this->weekUrl.$glue.$this->yearID."=".$year."&amp;".$this->weekID."=".$week."\">".$week."</a>";
}
elseif ($this->javaScriptWeek) $out.="<a href=\"javascript:".$this->javaScriptWeek."(".$year.",".$week.")\">".$week."</a>";
else $out.=$week;
return $out;
}
/*
********************************************************************************
PRIVATE getMonthName() -> returns the month's name, according to the configuration
********************************************************************************
*/
function getMonthName($var=false) {
if (!$var) $var=@$this->actmonth;
if ($this->monthNames) return $this->monthNames[$var-1];
switch($var) {
case 1: return Text::_($this->jan);
case 2: return Text::_($this->feb);
case 3: return Text::_($this->mar);
case 4: return Text::_($this->apr);
case 5: return Text::_($this->may);
case 6: return Text::_($this->jun);
case 7: return Text::_($this->jul);
case 8: return Text::_($this->aug);
case 9: return Text::_($this->sep);
case 10: return Text::_($this->oct);
case 11: return Text::_($this->nov);
case 12: return Text::_($this->dec);
}
}
/*
********************************************************************************
PRIVATE getDayName() -> returns the day's name, according to the configuration
********************************************************************************
*/
function getDayName($var=false) {
if ($this->dayNames) return $this->dayNames[$var];
switch($var) {
case 0: return Text::_($this->sun);
case 1: return Text::_($this->mon);
case 2: return Text::_($this->tue);
case 3: return Text::_($this->wed);
case 4: return Text::_($this->thu);
case 5: return Text::_($this->fri);
case 6: return Text::_($this->sat);
}
}
/*
********************************************************************************
PRIVATE getMonthDays() -> returns the number of days of the month specified
********************************************************************************
*/
function getMonthDays($month,$year) {
$has31days=checkdate($month,31,$year);
$isSchalt=checkdate(2,29,$year);
if ($isSchalt==1 && $month==2) $maxdays=29;
elseif ($isSchalt!=1 && $month==2) $maxdays=28;
elseif ($has31days==1) $maxdays=31;
else $maxdays=30;
return $maxdays;
}
/*
********************************************************************************
PRIVATE getWeekday() -> returns the weekday's number, 0 = Sunday ... 6 = Saturday
********************************************************************************
*/
function getWeekday($var) {
return $this->mkActiveDate("w", $this->mkActiveTime(0,0,1,$this->actmonth,$var,$this->actyear));
}
/*
********************************************************************************
PRIVATE getWeekNum() -> returns the week number, php version > 4.1.0, unsupported by the ADOdb Date Library
********************************************************************************
*/
function getWeekNum($var) {
return date("W", $this->mkActiveTime(0,0,1,$this->actmonth,$var,$this->actyear))+0;
}
/*
********************************************************************************
PRIVATE isEvent() -> checks if a date was set as an event and creates the eventID (css layout) and eventUrl
********************************************************************************
*/
function isEvent($var) {
if ($this->calEvents) {
$checkTime=$this->mkActiveTime(0,0,1,$this->actmonth,$var,$this->actyear);
$selectedTime=$this->mkActiveTime(0,0,1,$this->selectedmonth,$this->selectedday,$this->selectedyear);
$todayTime=$this->mkActiveTime(0,0,1,$this->monthtoday,$this->daytoday,$this->yeartoday);
foreach($this->calEvents as $eventTime => $eventID) {
if ($eventTime==$checkTime) {
if ($eventTime==$selectedTime) $this->eventID=$this->cssPrefixSelecEvent.$eventID;
elseif ($eventTime==$todayTime) $this->eventID=$this->cssPrefixTodayEvent.$eventID;
else $this->eventID=$eventID;
if ($this->calEventsUrl[$eventTime]) $this->eventUrl=$this->calEventsUrl[$eventTime];
return true;
}
}
return false;
}
}
/*
********************************************************************************
PRIVATE hasEventContent() -> checks if an event content was set
********************************************************************************
*/
/**
* checks if an event content was set for the day
*
* @param int $var day of the month
* @return array
*/
function hasEventContent($var) {
$hasContent = [];
if ($this->calEventContent) {
$checkTime = $this->mkActiveTime(0, 0, 1, $this->actmonth, $var, $this->actyear);
$n = is_array($this->calEventContent) ? count($this->calEventContent) : 0;
for ($x = 0; $x < $n; $x++) {
$eventContent = $this->calEventContent[$x];
$eventContentUrl = $this->calEventContentUrl[$x];
$eventContentId = $this->calEventContentId[$x];
foreach ($eventContent as $eventTime => $eventContent) {
if ($eventTime == $checkTime) $hasContent[][$eventContentId][$eventContentUrl] = $eventContent;
}
}
}
return $hasContent;
}
/*
********************************************************************************
PRIVATE mkActiveDate() -> checks if ADOdb Date Library is loaded and calls the date function
********************************************************************************
*/
function mkActiveDate($param,$acttime=false) {
if (!$acttime) $acttime=$this->timetoday;
if (function_exists("adodb_date")) return adodb_date($param,$acttime);
else return date($param,$acttime);
}
/*
********************************************************************************
PRIVATE mkActiveGMDate() -> checks if ADOdb Date Library is loaded and calls the gmdate function
********************************************************************************
*/
function mkActiveGMDate($param,$acttime=false) {
if (!$acttime) $acttime=time();
if (function_exists("adodb_gmdate")) return adodb_gmdate($param,$acttime);
else return gmdate($param,$acttime);
}
/*
********************************************************************************
PRIVATE mkActiveTime() -> checks if ADOdb Date Library is loaded and calls the mktime function
********************************************************************************
*/
/**
* checks if ADOdb Date Library is loaded and calls the mktime function
*
* @param int $hr
* @param int $min
* @param int $sec
* @param int $month [optional]
* @param int $day [optional]
* @param int $year [optional]
* @return int
*/
function mkActiveTime($hr,$min,$sec,$month=false,$day=false,$year=false) {
if (function_exists("adodb_mktime")) return adodb_mktime($hr,$min,$sec,$month,$day,$year);
else return mktime($hr,$min,$sec,$month,$day,$year);
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
<?php
/**
* @package JEM
* @copyright (C) 2013-2024 joomlaeventmanager.net
* @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\Registry\Registry;
/**
* JemConfig class to handle JEM configuration
*
* @package JEM
*/
class JemConfig
{
/**
* Data Object
*
* @var Registry object
* @since 2.1.6
*/
protected $_data;
/**
* Class instance.
*
* @var object
* @since 2.1.6
*/
protected static $instance;
/**
* Returns a reference to the global JemConfig object, only creating it
* if it doesn't already exist.
*
* This method must be invoked as:
* <pre>$jemConfig = JemConfig::getInstance();</pre>
*
* @return JemConfig The JemConfig object.
*
* @since 2.1.6
*/
public static function getInstance()
{
if (empty(self::$instance))
{
self::$instance = new self;
}
return self::$instance;
}
/**
* Constructor
*
* @param mixed $data The data to bind to the new Registry object.
*
* @since 1.0
*/
protected function __construct()
{
// Instantiate the internal data object.
$this->_data = new Registry($this->loadData());
// Load data from database
;
}
/**
* Gets configuration data as Registry.
*
* @return object An object holding the configuration data
*
* @since 2.1.6
*/
public function toRegistry()
{
return $this->_data;
}
/**
* Gets configuration data as object.
*
* @return object An object holding the configuration data
*
* @since 2.1.6
*/
public function toObject()
{
return $this->_data->toObject();
}
/**
* Loading the table data
*/
protected function loadData()
{
$db = Factory::getContainer()->get('DatabaseDriver');
// new table
$query = $db->getQuery(true);
$query->select(array($db->quoteName('keyname'), $db->quoteName('value')));
$query->from('#__jem_config');
$db->setQuery($query);
try {
$list = $db->loadAssocList('keyname', 'value');
} catch (Exception $e) {}
if (!empty($list)) {
$data = (object)$list;
} else {
// old table
$query = $db->getQuery(true);
$query->select(array('*'));
$query->from('#__jem_settings');
$query->where(array('id = 1 '));
$db->setQuery($query);
try {
$data = $db->loadObject();
} catch (Exception $e) {}
}
// Convert the params field to an array.
if (!empty($data->globalattribs)) {
$registry = new Registry;
$registry->loadString($data->globalattribs);
$data->globalattribs = $registry->toObject();
}
// Convert Css settings to an array
if (!empty($data->css)) {
$registryCss = new Registry;
$registryCss->loadString($data->css);
$data->css = $registryCss->toObject();
}
return $data;
}
/**
* Bind the data
*
*/
public function bind($data)
{
$reg = new Registry($data);
$this->_data->loadObject($reg->toObject());
return true;
}
/**
* Set a singla value.
*
* @param string $key The key.
* @param string $value Value to set.
* @return mixed The value set or null.
*/
public function set($key, $value)
{
$result = $this->_data->set($key, $value);
if (!is_null($result)) {
if (!$this->store()) {
$result = null;
}
}
return $result;
}
/**
* Store data
*
*/
public function store()
{
$data = $this->_data->toArray();
// Convert the params field to an array.
if (isset($data['globalattribs'])) {
$registry = new Registry($data['globalattribs']);
$data['globalattribs'] = $registry->toString();
}
// Convert Css settings to an array
if (isset($data['css'])) {
$registryCss = new Registry($data['css']);
$data['css'] = $registryCss->toString();
}
// Store into new table
$db = Factory::getContainer()->get('DatabaseDriver');
$query = $db->getQuery(true);
$query->select(array($db->quoteName('keyname'), $db->quoteName('value')));
$query->from('#__jem_config');
$db->setQuery($query);
$list = $db->loadAssocList('keyname', 'value');
$keys = array_keys($list);
foreach ($data as $k => $v) {
$query = $db->getQuery(true);
if (in_array($k, $keys)) {
if ($v == $list[$k]) {
continue; // skip if unchanged
}
$query->update('#__jem_config');
$query->where(array($db->quoteName('keyname') . ' = ' . $db->quote($k)));
} else {
$query->insert('#__jem_config');
$query->set(array($db->quoteName('keyname') . ' = ' . $db->quote($k)));
}
$query->set(array($db->quoteName('value') . ' = ' . $db->quote($v)));
$db->setQuery($query);
$db->execute();
}
return true;
}
}

View File

@ -0,0 +1,46 @@
<?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\MVC\Controller\FormController;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
abstract class JemControllerForm extends FormController
{
/**
* Function that allows child controller access to model data
* after the data has been saved.
*
* @see JemControllerForm::postSaveHook()
*
* @since JEM 2.1.5
*/
protected function _postSaveHook($model, $validData = array())
{
// Derived class will provide its own implementation if required.
}
/**
* Function that allows child controller access to model data
* after the data has been saved. - wrapper
*
* @param BaseDatabaseModel $model The data model object.
* @param array $validData The validated data.
*
* @return void
*
* @since 12.2
*/
protected function postSaveHook(BaseDatabaseModel $model, $validData = array())
{
$this->_postSaveHook($model, $validData);
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,318 @@
<?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\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Language\Text;
require_once(JPATH_SITE.'/components/com_jem/classes/Zebra_Image.php');
/**
* Holds the logic for image manipulation
*
* @package JEM
*/
class JemImage
{
static public function thumb($name,$filename,$new_w,$new_h)
{
// load the image manipulation class
//require 'path/to/Zebra_Image.php';
// create a new instance of the class
$image = new Zebra_Image();
// indicate a source image (a GIF, PNG or JPEG file)
$image->source_path = $name;
// indicate a target image
// note that there's no extra property to set in order to specify the target
// image's type -simply by writing '.jpg' as extension will instruct the script
// to create a 'jpg' file
$image->target_path = $filename;
// since in this example we're going to have a jpeg file, let's set the output
// image's quality (95% has no visible effect but saves some bytes)
$image->jpeg_quality = 95;
// some additional properties that can be set
// read about them in the documentation
$image->preserve_aspect_ratio = true;
$image->enlarge_smaller_images = false;
$image->preserve_time = true;
$image->auto_handle_exif_orientation = true;
// resize the image to at best 100x100 pixels by using the "not boxed" method
// (read more in the overview section or in the documentation)
// and if there is an error, check what the error is about
if (!$image->resize($new_w, $new_h, ZEBRA_IMAGE_NOT_BOXED, -1)) {
//only admins will see these errors
if (Factory::getApplication()->getIdentity()->authorise('core.manage')) {
// if there was an error, let's see what the error is about
switch ($image->error) {
case 1:
Factory::getApplication()->enqueueMessage("Source file $name could not be found!", 'warning');
break;
case 2:
Factory::getApplication()->enqueueMessage("Source file $name is not readable!", 'warning');
break;
case 3:
Factory::getApplication()->enqueueMessage("Could not write target file $filename !", 'warning');
break;
case 4:
Factory::getApplication()->enqueueMessage('Unsupported source file format!', 'warning');
break;
case 5:
Factory::getApplication()->enqueueMessage('Unsupported target file format!', 'warning');
break;
case 6:
Factory::getApplication()->enqueueMessage('GD library version does not support target file format!', 'warning');
break;
case 7:
Factory::getApplication()->enqueueMessage('GD library is not installed!', 'warning');
break;
case 8:
Factory::getApplication()->enqueueMessage('"chmod" command is disabled via configuration', 'warning');
break;
case 9:
Factory::getApplication()->enqueueMessage('"exif_read_data" function is not available', 'warning');
break;
}
}
}
}
/**
* Determine the GD version
* Code from php.net
*
* @param int
*
* @return int
*/
static public function gdVersion($user_ver = 0)
{
if (! extension_loaded('gd')) {
return;
}
static $gd_ver = 0;
// Just accept the specified setting if it's 1.
if ($user_ver == 1) {
$gd_ver = 1;
return 1;
}
// Use the static variable if function was called previously.
if ($user_ver != 2 && $gd_ver > 0) {
return $gd_ver;
}
// Use the gd_info() function if possible.
if (function_exists('gd_info')) {
$ver_info = gd_info();
preg_match('/\d/', $ver_info['GD Version'], $match);
$gd_ver = $match[0];
return $match[0];
}
// If phpinfo() is disabled use a specified / fail-safe choice...
if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
if ($user_ver == 2) {
$gd_ver = 2;
return 2;
} else {
$gd_ver = 1;
return 1;
}
}
// ...otherwise use phpinfo().
ob_start();
phpinfo(8);
$info = ob_get_contents();
ob_end_clean();
$info = stristr($info, 'gd version');
preg_match('/\d/', $info, $match);
$gd_ver = $match[0];
return $match[0];
}
/**
* Creates image information of an image
*
* @param string $image The image name
* @param array $settings
* @param string $type event or venue
*
* @return imagedata if available
*/
static public function flyercreator($image, $type)
{
$settings = JemHelper::config();
if (($settings->imagewidth < 1) || ($settings->imagehight < 1)) {
return false;
}
//define the environment based on the type
if ($type == 'event') {
$folder = 'events';
} else if ($type == 'category') {
$folder = 'categories';
} else if ($type == 'venue') {
$folder = 'venues';
} else {
return false;
}
if ($image) {
$img_orig = 'images/jem/'.$folder.'/'.$image;
$img_thumb = 'images/jem/'.$folder.'/small/'.$image;
$filepath = JPATH_SITE.'/'.$img_orig;
$save = JPATH_SITE.'/'.$img_thumb;
// At least original image must exist
if (!file_exists($filepath)) {
return false;
}
//Create thumbnail if enabled and it does not exist already
if ($settings->gddisabled == 1 && !file_exists($save)) {
JemImage::thumb($filepath, $save, $settings->imagewidth, $settings->imagehight);
}
//set paths
$dimage['original'] = $img_orig;
$dimage['thumb'] = $img_thumb;
//get imagesize of the original
$iminfo = @getimagesize($img_orig);
// and it should be an image
if (!is_array($iminfo) || count($iminfo) < 2) {
return false;
}
//if the width or height is too large this formula will resize them accordingly
if (($iminfo[0] > $settings->imagewidth) || ($iminfo[1] > $settings->imagehight)) {
$iRatioW = $settings->imagewidth / $iminfo[0];
$iRatioH = $settings->imagehight / $iminfo[1];
if ($iRatioW < $iRatioH) {
$dimage['width'] = round($iminfo[0] * $iRatioW);
$dimage['height'] = round($iminfo[1] * $iRatioW);
} else {
$dimage['width'] = round($iminfo[0] * $iRatioH);
$dimage['height'] = round($iminfo[1] * $iRatioH);
}
} else {
$dimage['width'] = $iminfo[0];
$dimage['height'] = $iminfo[1];
}
if (File::exists(JPATH_SITE.'/'.$img_thumb)) {
//get imagesize of the thumbnail
$thumbiminfo = @getimagesize($img_thumb);
$dimage['thumbwidth'] = $thumbiminfo[0];
$dimage['thumbheight'] = $thumbiminfo[1];
}
return $dimage;
}
return false;
}
static public function check($file, $jemsettings)
{
$sizelimit = $jemsettings->sizelimit*1024; //size limit in kb
$imagesize = $file['size'];
$filetypes = $jemsettings->image_filetypes ?: 'jpg,gif,png,webp';
//check if the upload is an image...getimagesize will return false if not
if (!getimagesize($file['tmp_name'])) {
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_UPLOAD_FAILED_NOT_AN_IMAGE').': '.htmlspecialchars($file['name'], ENT_COMPAT, 'UTF-8'), 'warning');
return false;
}
//check if the imagefiletype is valid
$fileext = strtolower(File::getExt($file['name']));
$allowable = explode(',', strtolower($filetypes));
array_walk($allowable, function(&$v){$v = trim($v);});
if (!in_array($fileext, $allowable)) {
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_WRONG_IMAGE_FILE_TYPE').': '.htmlspecialchars($file['name'], ENT_COMPAT, 'UTF-8'), 'warning');
return false;
}
//Check filesize
if ($imagesize > $sizelimit) {
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_IMAGE_FILE_SIZE').': '.htmlspecialchars($file['name'], ENT_COMPAT, 'UTF-8'), 'warning');
return false;
}
//XSS check
//$xss_check = File::read($file['tmp_name'], false, 256);
$xss_check = file_get_contents($file['tmp_name'], false, NULL, 0, 256);
$html_tags = array('abbr','acronym','address','applet','area','audioscope','base','basefont','bdo','bgsound','big','blackface','blink','blockquote','body','bq','br','button','caption','center','cite','code','col','colgroup','comment','custom','dd','del','dfn','dir','div','dl','dt','em','embed','fieldset','fn','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','iframe','ilayer','img','input','ins','isindex','keygen','kbd','label','layer','legend','li','limittext','link','listing','map','marquee','menu','meta','multicol','nobr','noembed','noframes','noscript','nosmartquotes','object','ol','optgroup','option','param','plaintext','pre','rt','ruby','s','samp','script','select','server','shadow','sidebar','small','spacer','span','strike','strong','style','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','ul','var','wbr','xml','xmp','!DOCTYPE', '!--');
foreach ($html_tags as $tag) {
// A tag is '<tagname ', so we need to add < and a space or '<tagname>'
if (stristr($xss_check, '<'.$tag.' ') || stristr($xss_check, '<'.$tag.'>')) {
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_WARN_IE_XSS'), 'warning');
return false;
}
}
return true;
}
/**
* Sanitize the image file name and return an unique string
*
*
* @param string $base_Dir the target directory
* @param string $filename the unsanitized imagefile name
*
* @return string $filename the sanitized and unique image file name
*/
static public function sanitize($base_Dir, $filename)
{
//check for any leading/trailing dots and remove them (trailing shouldn't be possible cause of the getEXT check)
$filename = preg_replace("/^[.]*/", '', $filename);
$filename = preg_replace("/[.]*$/", '', $filename); //shouldn't be necessary, see above
//we need to save the last dot position cause preg_replace will also replace dots
$lastdotpos = strrpos($filename, '.');
//replace invalid characters
$filename = strtolower(preg_replace("/[^0-9a-zA-Z_-]/", '_', $filename));
//get the parts before and after the dot (assuming we have an extension...check was done before)
$beforedot = substr($filename, 0, $lastdotpos);
$afterdot = substr($filename, $lastdotpos + 1);
//make a unique filename for the image and check it is not already taken
//if it is already taken keep trying till success
//$now = time();
$now = rand();
while (File::exists($base_Dir . $beforedot . '_' . $now . '.' . $afterdot)) {
$now++;
}
//create out of the seperated parts the new filename
$filename = $beforedot . '_' . $now . '.' . $afterdot;
return $filename;
}
}
?>

View File

@ -0,0 +1 @@
<!DOCTYPE html><title></title>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,559 @@
<?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\Factory;
use Joomla\CMS\User\User;
/**
* JEM user class with additional functions.
* Because User::getInstance has different paramters on different versions
* we must split out class.
*
* @package JEM
*/
abstract class JemUserAbstract extends User
{
/**
* @var array JemUser instances container.
*/
protected static $instances_jemuser = array();
static protected function _getInstance($id = 0)
{
$id = (int)$id;
// Check if the user ID is already cached.
if (empty(self::$instances_jemuser[$id]) || !(self::$instances_jemuser[$id] instanceof JemUser))
{
$user = new JemUser($id);
self::$instances_jemuser[$id] = $user;
}
return self::$instances_jemuser[$id];
}
/**
* Checks access permissions of the user regarding on the groupid
*
* @param int $recurse
* @param int $level
* @return boolean True on success
*/
public function validate_user($recurse, $level)
{
// Only check when user is logged in
if ($this->id) {
//open for superuser or registered and thats all what is needed
//level = -1 all registered users
//level = -2 disabled
if ((($level == -1) && $this->id) || (($level == -2) && ($this->authorise('core.manage')))) {
return true;
}
}
// User has no permissions
return false;
}
/**
* Checks if the user is allowed to edit an item
*
*
* @param int $allowowner
* @param int $ownerid
* @param int $recurse
* @param int $level
* @return boolean True on success
*/
public function editaccess($allowowner, $ownerid, $recurse, $level)
{
$generalaccess = $this->validate_user($recurse, $level);
if ((($allowowner == 1) || $this->authorise('core.edit.own','com_jem')) && ($this->id == $ownerid) && ($ownerid != 0)) {
return true;
} elseif (($generalaccess == 1) || $this->authorise('core.edit','com_jem')) {
return true;
}
return false;
}
/**
* Checks if the user is a superuser
* A superuser will allways have access if the feature is activated
*
* @return boolean True on success
*
* @deprecated since version 2.1.5
*/
static function superuser()
{
$user = Factory::getApplication()->getIdentity();
if ($user->authorise('core.manage', 'com_jem')) {
return true;
} else {
return false;
}
}
/**
* Checks if the user has the privileges to use the wysiwyg editor
*
* We could use the validate_user method instead of this to allow to set a groupid
* Not sure if this is a good idea
*
* @return boolean True on success
*
* @deprecated since version 2.1.5
*/
static function editoruser()
{
return false;
}
/**
* Checks if the user is a maintainer of a category
*
* @return NULL int of maintained categories or null
*
* @deprecated Use JemUser::can($action, 'event', $eventid) instead.
*/
public function ismaintainer($action, $eventid = false)
{
// lets look if the user is a maintainer
$db = Factory::getContainer()->get('DatabaseDriver');
$query = 'SELECT gr.id' . ' FROM #__jem_groups AS gr'
. ' LEFT JOIN #__jem_groupmembers AS g ON g.group_id = gr.id'
. ' WHERE g.member = ' . (int)$this->id
. ' AND ' . $db->quoteName('gr.' . $action . 'event') . ' = 1 '
. ' AND g.member NOT LIKE 0';
$db->setQuery($query);
$groupnumber = $db->loadColumn();
// no results, the user is not within a group with the required right
if (!$groupnumber) {
return false;
}
// the user is in a group with the required right but is there a
// published category where he is allowed to post in?
$categories = implode(' OR groupid = ', $groupnumber);
if ($action == 'edit') {
$query = 'SELECT a.catid' . ' FROM #__jem_cats_event_relations AS a'
. ' LEFT JOIN #__jem_categories AS c ON c.id = a.catid'
. ' WHERE c.published = 1'
. ' AND (c.groupid = ' . $categories . ')'
. ' AND a.itemid = ' . $eventid;
$db->setQuery($query);
}
else {
$query = 'SELECT id' . ' FROM #__jem_categories'
. ' WHERE published = 1'
. ' AND (groupid = ' . $categories . ')';
$db->setQuery($query);
}
$maintainer = $db->loadResult();
if (!$maintainer) {
return false;
}
else {
return true;
}
}
/**
* Checks if an user is a groupmember and if so
* if the group is allowed for $action on venues
*
*/
public function venuegroups($action)
{
/*
* just a basic check to see if the current user is in an usergroup with
* access for submitting venues. if a result then return true, otherwise false
*
* Actions: addvenue, publishvenue, editvenue
*
* views: venues, venue, editvenue
*/
$db = Factory::getContainer()->get('DatabaseDriver');
$query = 'SELECT gr.id'
. ' FROM #__jem_groups AS gr'
. ' LEFT JOIN #__jem_groupmembers AS g ON g.group_id = gr.id'
. ' AND '.$db->quoteName('gr.'.$action.'venue').' = 1 '
. ' WHERE g.member = ' . (int)$this->id
. ' AND g.member NOT LIKE 0';
;
$db->setQuery($query);
$groupnumber = $db->loadResult();
return !empty($groupnumber);
}
/**
* Returns all JEM groups user is member of.
* The array returned is keyed by group id where the value is
* an assoziative array of ['field_name' => 'row_value'] pairs.
*
* @param $asset mixed false, string or array of strings to restrict to groups
* with at least one of this asset(s) set;
* must be valid field names of #__jem_groups table. (optional)
* @return mixed List of JEM groups or null
*/
public function getJemGroups($asset = false)
{
$userId = (int)$this->id;
// no registered user -> no groups
if (empty($userId)) {
return false;
}
$db = Factory::getContainer()->get('DatabaseDriver');
if (is_array($asset) && !empty($asset)) {
array_walk($asset, function(&$v, $k, $db) { $v = $db->quoteName($v); }, $db);
$field = ' AND (' . implode(' > 0 OR ', $asset) . ' > 0)';
} else {
$field = empty($asset) ? '' : ' AND ' . $db->quoteName($asset) . ' > 0';
}
$query = 'SELECT gr.*'
. ' FROM #__jem_groups AS gr'
. ' LEFT JOIN #__jem_groupmembers AS gm ON gm.group_id = gr.id'
. ' WHERE gm.member = '. $userId . $field
. ' GROUP BY gr.id';
$db->setQuery($query);
$groups = $db->loadAssocList('id');
return $groups;
}
/**
* Method to return a list of all JEM categories that a user has permission for a given action
*
* @param mixed $action One or array of 'add', 'edit', 'publish'
* @param string $type One of 'event', 'venue'
* @param array $options additional options as 'option' => value, supported are:
* 'ignore_access' (bool) true if access level should be ignored
* 'use_disable' (bool) true to include non-allowed categories with attribute 'disable' set to true
* 'owner' (bbol) true if 'edit.own' can be used
*
* @return array List of categories that this user can do this action (empty array if none).
* Other categories will be returned too (with disable = true) if option 'disable' is set.
*/
public function getJemCategories($action, $type, $options = array())
{
$action = (array)$action;
$ignore_access = array_key_exists('ignore_access', $options) ? (bool)$options['ignore_access'] : false;
$use_disable = array_key_exists('use_disable', $options) ? (bool)$options['use_disable'] : false;
$owner = array_key_exists('owner', $options) ? (bool)$options['owner'] : false;
$jemsettings = JemHelper::config();
$asset = 'com_jem';
$all = (bool)$this->authorise('core.manage', $asset);
if (!$all) {
foreach ($action as $act) {
switch ($act) {
case 'add':
$all = (bool)$this->authorise('core.create', $asset);
break;
case 'edit':
$all = (bool)$this->authorise('core.edit', $asset) || (bool)$this->authorise('core.edit.own', $asset);
break;
case 'publish':
$all = (bool)$this->authorise('core.edit.state', $asset);
break;
default:
break;
}
}
}
$jemgroups = array();
if (!$all && (($type == 'event') || ($type == 'venue'))) {
$fields = array();
foreach ($action as $act) {
switch ($act) {
case 'add':
$fields[] = $act . $type;
break;
case 'edit':
$fields[] = $act . $type;
break;
case 'publish':
$fields[] = $act . $type;
break;
default:
break;
}
}
switch ($type) {
case 'event':
$create = ($jemsettings->delivereventsyes == -1);
$edit = ($jemsettings->eventedit == -1);
$edit_own = ($jemsettings->eventowner == 1) && $owner;
break;
case 'venue':
$create = ($jemsettings->deliverlocsyes == -1);
$edit = ($jemsettings->venueedit == -1);
$edit_own = ($jemsettings->venueowner == 1) && $owner;
break;
default:
$create = $edit = $edit_own = false;
break;
}
// Get all JEM groups with requested permissions and user is member of.
$jemgroups = empty($fields) ? array() : $this->getJemGroups($fields);
// If registered users are generally allowed (by JEM Settings) to edit events/venues
// add JEM group 0 and make category check
if (($create && in_array('add', $action)) || (($edit || $edit_own) && in_array('edit', $action))) {
$jemgroups[0] = true;
}
}
$disable = '';
$where = $ignore_access ? '' : ' AND c.access IN (' . implode(',', $this->getAuthorisedViewLevels()) . ')';
if (!empty($jemgroups)) {
if ($use_disable) {
$disable = ', IF (c.groupid IN (' . implode(',', array_keys($jemgroups)) . '), 0, 1) AS disable';
} else {
$where .= ' AND c.groupid IN (' . implode(',', array_keys($jemgroups)) . ')';
}
}
// We have to check ALL categories, also those not seen by user.
$db = Factory::getContainer()->get('DatabaseDriver');
$query = 'SELECT DISTINCT c.*' . $disable
. ' FROM #__jem_categories AS c'
. ' WHERE c.published = 1'
. $where
. ' ORDER BY c.lft';
$db->setQuery( $query );
$cats = $db->loadObjectList('id');
return $cats;
}
/**
* Checks if user is allowed to do actions on objects.
* Respects Joomla and JEM group permissions.
*
* @param $action mixed One or array of 'add', 'edit', 'publish', 'delete'
* @param $type string One of 'event', 'venue'
* @param $id mixed The event or venue id or false (default)
* @param $created_by mixed User id of creator or false (default)
* @param $categoryIds mixed List of category IDs to limit for or false (default)
* @return true if allowed, false otherwise
* @note If nno categoryIds are given this functions checks if there is any potential way
* to allow requested action. To prevent this check set categoryIds to 1 (root category)
*/
public function can($action, $type, $id = false, $created_by = false, $categoryIds = false)
{
$userId = (int)$this->id;
// guests are not allowed to do anything except looking
if (empty($userId) || $this->get('guest', 0)) {
return false;
}
$action = (array)$action;
if (!empty($categoryIds)) {
$categoryIds = (array)$categoryIds;
$catIds = array();
foreach ($categoryIds as $catId) {
if ((int)$catId > 0) { // allow 'root' category with which caller can skip "potentially allowed" check
$catIds[] = (int)$catId;
}
}
$categoryIds = $catIds; // non-zero integers
} else {
$categoryIds = array();
}
$created_by = (int)$created_by;
$id = ($id === false) ? $id : (int)$id;
$asset = 'com_jem';
$jemsettings = JemHelper::config();
switch ($type) {
case 'event':
$create = ($jemsettings->delivereventsyes == -1);
$edit = ($jemsettings->eventedit == -1);
$edit_own = ($jemsettings->eventowner == 1);
$autopubl = ($jemsettings->autopubl == -1); // auto-publish new events
// not supported yet
//if (!empty($id)) {
// $asset .= '.event.' . $id;
//}
break;
case 'venue':
$create = ($jemsettings->deliverlocsyes == -1);
$edit = ($jemsettings->venueedit == -1);
$edit_own = ($jemsettings->venueowner == 1);
$autopubl = ($jemsettings->autopublocate == -1); // auto-publish new venues
// not supported yet
//if (!empty($id)) {
// $asset .= '.venue.' . $id;
//}
break;
default:
$create = $edit = $edit_own = $autopubl = false;
break;
}
$assets[] = $asset;
// not supported yet
//foreach($categoryIds as $catId) {
// $assets[] = 'com_jem.category.'.$catId;
//}
// Joomla ACL system, JEM global settings
$authorised = false;
foreach ($assets as $asset) {
if ($authorised) { break; }
$authorised |= (boolean)$this->authorise('core.manage', $asset);
foreach ($action as $act) {
if ($authorised) { break; }
switch ($act) {
case 'add':
$authorised |= $create || $this->authorise('core.create', $asset);
break;
case 'edit':
$authorised |= $this->authorise('core.edit', $asset); // $edit is limited to events not attached to jem groups
// user is owner and edit-own is enabled
$authorised |= ($edit_own || $this->authorise('core.edit.own', $asset)) &&
!empty($created_by) && ($userId == $created_by);
break;
case 'publish':
$authorised |= $this->authorise('core.edit.state', $asset);
// user is creator of new item and auto-publish is enabled
$authorised |= $autopubl && ($id === 0) &&
(empty($created_by) || ($userId == $created_by));
// user is creator, can edit this item and auto-publish is enabled
// (that's because we allowed user to not publish new item with auto-puplish enabled)
$authorised |= $autopubl && ($edit || $edit_own) && ($id !== 0) &&
!empty($created_by) && ($userId == $created_by);
break;
case 'delete':
$authorised |= $this->authorise('core.delete', $asset);
break;
}
}
}
// JEM User groups
if (!$authorised) {
if (($type == 'event') || ($type == 'venue')) {
$fields = array();
foreach ($action as $act) {
switch ($act) {
case 'add':
case 'edit':
case 'publish':
$fields[] = $act.$type;
break;
default:
break;
}
}
// Get all JEM groups with requested permissions and user is member of.
$jemgroups = empty($fields) ? array() : $this->getJemGroups($fields);
// If registered users are generally allowed (by JEM Settings) to edit events/venues
// add JEM group 0 and make category check
if ($edit && (in_array('edit', $action))) {
$jemgroups[0] = true;
}
if (!empty($jemgroups)) {
if (empty($categoryIds) && (($type != 'event') || (empty($id) && (!in_array('publish', $action))))) {
$authorised = true; // new events and venues have no limiting categories, so generally authorised
} else { // we have a valid event object so check event's categories against jem groups
$whereCats = empty($categoryIds) ? '' : ' AND c.id IN ('.implode(',', $categoryIds).')';
$levels = $this->getAuthorisedViewLevels();
// We have to check ALL categories, also those not seen by user.
$db = Factory::getContainer()->get('DatabaseDriver');
$query = 'SELECT DISTINCT c.id, c.groupid, c.access'
. ' FROM #__jem_categories AS c';
if (!empty($id)) {
$query .= ' LEFT JOIN #__jem_cats_event_relations AS rel ON rel.catid = c.id'
. ' WHERE rel.itemid = ' . $id
. ' AND c.published = 1';
} else {
$query .= ' WHERE c.published = 1';
}
$query .= $whereCats;
$db->setQuery( $query );
$cats = $db->loadObjectList();
}
if (!empty($cats)) {
$unspecific = in_array('publish', $action) ? -1 : 0; // publish requires jemgroup
foreach($cats as $cat) {
if (empty($cat->groupid)) {
if ($unspecific === 0) {
$unspecific = 1;
}
} else {
$unspecific = -1; // at least one group assigned so group permissions take precedence
if (in_array($cat->access, $levels) && array_key_exists($cat->groupid, $jemgroups)) {
// user can "see" this category and is member of connected jem group granting permission
$authorised = true;
break; // foreach cats
}
}
}
if ($unspecific === 1) {
// only categories without connected JEM group found, so user is authorised
$authorised = true;
}
}
}
}
}
return (bool)$authorised;
}
}
/**
* JEM user class with additional functions.
* Compatible with Joomla since 3.4.0.
*
* @package JEM
*
* @see JemUserAbstract
*/
class JemUser extends JemUserAbstract
{
static function getInstance($id = 0, JUserWrapperHelper $userHelper = null)
{
// we don't need this helper
return parent::_getInstance($id);
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* @package JEM
* @copyright (C) 2013-2024 joomlaeventmanager.net
* @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\HtmlView;
/**
* JemView class with JEM specific extensions
*
* @package JEM
*/
class JemView extends HtmlView
{
/**
* Layout style suffix
*
* @var string
* @since 2.3
*/
protected $_layoutStyleSuffix = null;
public function __construct($config = array())
{
parent::__construct($config);
// additional path for layout style + corresponding override path
$suffix = JemHelper::getLayoutStyleSuffix();
if (!empty($suffix)) {
$this->_layoutStyleSuffix = $suffix;
if (is_dir($this->_basePath . '/view')) {
$this->addTemplatePath($this->_basePath . '/view/' . $this->getName() . '/tmpl/' . $suffix);
}
else {
$this->addTemplatePath($this->_basePath . '/views/' . $this->getName() . '/tmpl/' . $suffix);
}
$this->addTemplatePath(JPATH_THEMES . '/' . Factory::getApplication()->getTemplate() . '/html/com_jem/' . $this->getName() . '/' . $suffix);
}
}
/**
* Adds a row to data indicating even/odd row number
*
* @return object $rows
*/
public function getRows($rowname = "rows")
{
if (!isset($this->$rowname) || !is_array($this->$rowname) || !count($this->$rowname)) {
return;
}
$k = 0;
foreach($this->$rowname as $row) {
$row->odd = $k;
$k = 1 - $k;
}
return $this->$rowname;
}
/**
* Add path for common templates.
*/
protected function addCommonTemplatePath()
{
// additional path for list part + corresponding override path
$this->addTemplatePath(JPATH_COMPONENT.'/common/views/tmpl');
$this->addTemplatePath(JPATH_THEMES . '/' . Factory::getApplication()->getTemplate() . '/html/com_jem/common');
if (!empty($this->_layoutStyleSuffix)) {
$this->addTemplatePath(JPATH_COMPONENT.'/common/views/tmpl/'.$this->_layoutStyleSuffix);
$this->addTemplatePath(JPATH_THEMES . '/' . Factory::getApplication()->getTemplate() . '/html/com_jem/common/'.$this->_layoutStyleSuffix);
}
}
/**
* Prepares the document.
*/
protected function prepareDocument()
{
$app = Factory::getApplication();
$menus = $app->getMenu();
$menu = $menus->getActive();
$print = $app->input->getBool('print', false);
if ($print) {
JemHelper::loadCss('print');
$this->document->setMetaData('robots', 'noindex, nofollow');
}
if ($menu) {
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
} else {
// TODO
$this->params->def('page_heading', Text::_('COM_JEM_DEFAULT_PAGE_TITLE_DAY'));
}
$title = $this->params->get('page_title', '');
if (empty($title)) {
$title = $app->get('sitename');
} elseif ($app->get('sitename_pagetitles', 0) == 1) {
$title = Text::sprintf('JPAGETITLE', $app->get('sitename'), $title);
} elseif ($app->get('sitename_pagetitles', 0) == 2) {
$title = Text::sprintf('JPAGETITLE', $title, $app->get('sitename'));
}
$this->document->setTitle($title);
// TODO: Metadata
$this->document->setMetadata('keywords', $this->params->get('page_title'));
}
}