<?php
/**
* Copyright (C) 2021 Rhyme Digital, LLC.
*
* @link https://rhyme.digital
* @license http://www.gnu.org/licenses/lgpl-3.0.html LGPL
*/
namespace Rhyme\WMassArtsHub\Model;
use Contao\Calendar;
use Contao\ContentModel;
use Contao\Controller;
use Contao\Date;
use Contao\Environment;
use Contao\FilesModel;
use Contao\FrontendTemplate;
use Contao\Model\Collection;
use Contao\CalendarEventsModel;
use Contao\ModuleModel;
use Contao\PageModel;
use Contao\StringUtil;
use Contao\System;
use Rhyme\WMassArtsHub\Helper\EventHelper;
use Rhyme\WMassArtsHub\Helper\ImageToTemplateHelper;
use Rhyme\WMassArtsHub\Model\CreativeGround\Profile;
use Rhyme\WMassArtsHub\Model\Profile\Item as ProfileItemModel;
/**
* Reads and writes calendar events - extends base class
*
* @method static string getAliasKey()
*
*/
/**
* Class Event
* @package Rhyme\WMassArtsHub\Model
*/
class Event extends CalendarEventsModel
{
protected static $placeholderImagePath = 'files/assets/img/placeholders/event-placeholder.jpg';
/**
* Get the alias key
* @return string
*/
public static function getAliasKey()
{
return 'events';
}
/**
* Return the average ranking of the record
* We can then customize this based on any number of criteria
*
* @return int A ranking of 1-5
*/
public function getRank()
{
if($this->featured) {
return 5;
}
return $this->rating;
}
/**
* Return the sorting field for A-Z sorting
*
* @return string
*/
public function getSortingValue()
{
return $this->title;
}
/**
* Return the date for this item
* We can then customize this based on any number of criteria
*
* @return int A timestamp for the date of this item
*/
public function getDate()
{
return $this->startDate;
}
/**
* The class type for this element
*
* @return string
*/
public function getClass()
{
return 'artshub-event';
}
/**
* Get the page title
* @return string
*/
public function getPageTitle()
{
return $this->title;
}
/**
* Get the frontend URL for the modal popup
* @param ModuleModel $objModule
* @return string
*/
public function getFrontendUrlFromModule(ModuleModel $objModule) {
return EventHelper::generateEventUrlFromModule($this, $objModule);
}
/**
* Generate the item
*
* @param ModuleModel $objModule
* @return string the parsed item
* @throws \Exception
*/
public function generate( $objModule )
{
/** @var PageModel $objPage */
global $objPage;
$strTemplate = $objModule->cal_template;
$objTemplate = new FrontendTemplate($strTemplate);
$event = $this->row();
$objTemplate->setData($event);
$rootDir = System::getContainer()->getParameter('kernel.project_dir');
EventHelper::addImageMethodsToTemplate($this, $objModule, $objTemplate);
//Get address and location from business if none given
$objTemplate->location = $this->getLocation();
$objTemplate->address = $this->getAddress();
//Add date related items
$intStart = $this->startTime;
$intEnd = $this->endTime;
$intDate = $intStart;
$intKey = date('Ymd', $intStart);
$strDate = Date::parse($objPage->dateFormat, $intStart);
$strDay = $GLOBALS['TL_LANG']['DAYS'][date('w', $intStart)];
$strMonth = $GLOBALS['TL_LANG']['MONTHS'][(date('n', $intStart)-1)];
// Clean the RTE output
if ($event['teaser'] != '')
{
$objTemplate->hasTeaser = true;
$objTemplate->teaser = StringUtil::toHtml5($objTemplate->teaser);
$objTemplate->teaser = StringUtil::encodeEmail($objTemplate->teaser);
}
$objTemplate->event = $this;
$objTemplate->customDate = $this->getFormattedDate();
$objTemplate->date = $strDate;
$objTemplate->time = $this->getFormattedTime();
$objTemplate->datetime = $this->addTime ? date('Y-m-d\TH:i:sP', $intStart) : date('Y-m-d', $intStart);
$objTemplate->day = $strDay;
$objTemplate->month = $strMonth;
$objTemplate->parent = $this->pid;
$objTemplate->calendar = $this->getRelated('pid');
$objTemplate->link = EventHelper::generateEventUrlFromModule($this, $objModule);
$objTemplate->link_absolute = EventHelper::generateEventUrlFromModule($this, $objModule, true);
$objTemplate->short_teaser = strlen($this->teaser) ? '<p>' . StringUtil::substr(strip_tags($this->teaser), 100) . '</p>' : '';
// Display the "read more" button for external/article links
if ($this->source != 'default' && $this->source != '')
{
$objTemplate->details = true;
$objTemplate->hasDetails = true;
}
// Compile the event text
else
{
$id = $this->id;
$objTemplate->details = function () use ($id)
{
$strDetails = '';
$objElement = ContentModel::findPublishedByPidAndTable($id, 'tl_calendar_events');
if ($objElement !== null)
{
while ($objElement->next())
{
$strDetails .= Controller::getContentElement($objElement->current());
}
}
return $strDetails;
};
$objTemplate->hasDetails = function () use ($id)
{
return ContentModel::countPublishedByPidAndTable($id, 'tl_calendar_events') > 0;
};
}
return $objTemplate->parse();
}
/**
* Get the formatted date string
* @return string
*/
public function getFormattedDate() {
if ($this->recurring)
{
$arrRange = StringUtil::deserialize($this->repeatEach);
if (\is_array($arrRange) && isset($arrRange['unit']) && isset($arrRange['value']))
{
// Todo: build out more cases
if ($arrRange['value'] == 1 && $arrRange['unit'] == 'weeks')
{
return 'Every '.Date::parse('l', $this->startTime).($this->recurrences && $this->repeatEnd ? ' Until '.Date::parse('F jS', $this->repeatEnd) : '');
}
}
}
$intStart = $this->startTime;
$intEnd = $this->endTime;
$span = Calendar::calculateSpan($intStart, $intEnd);
//Custom Date Formatting
$customDayNameStart = Date::parse('l', $intStart);
$customDayNameEnd = Date::parse('l', $intEnd);
$customMonthNameStart = Date::parse('F', $intStart);
$customMonthNameEnd = Date::parse('F', $intEnd);
$blnMonthSame = $customMonthNameStart == $customMonthNameEnd;
$customDateStart = Date::parse('jS', $intStart);
$customDateEnd = Date::parse('jS', $intEnd);
$customDate = $customDayNameStart . ', ' . $customMonthNameStart . ' ' . $customDateStart;
if($span > 0) {
$customDate = $customDayNameStart . '-' . $customDayNameEnd . ', ';
if(!$blnMonthSame) {
$customDate .= $customMonthNameStart . ' ' . $customDateStart . '-' . $customMonthNameEnd . ' ' . $customDateEnd;
} else {
$customDate .= $customMonthNameStart . ' ' . $customDateStart . '-' . $customDateEnd;
}
}
return $customDate;
}
/**
* Get the formatted time string
* @return string
*/
public function getFormattedTime() {
/** @var PageModel $objPage */
global $objPage;
$strTime = '';
$span = Calendar::calculateSpan($this->startTime, $this->endTime);
if ($this->addTime)
{
if ($span > 0)
{
$strTime = Date::parse($objPage->datimFormat, $this->startTime) . $GLOBALS['TL_LANG']['MSC']['cal_timeSeparator'] . Date::parse($objPage->datimFormat, $this->endTime);
}
elseif ($this->startTime == $this->endTime)
{
$strTime = Date::parse($objPage->timeFormat, $this->startTime);
}
else
{
$strTime = Date::parse($objPage->timeFormat, $this->startTime) . $GLOBALS['TL_LANG']['MSC']['cal_timeSeparator'] . Date::parse($objPage->timeFormat, $this->endTime);
}
}
return $strTime;
}
/*
* Get the address string
*/
public function getAddress()
{
// If the address is just the concatenated version of null values, use the first business
if ($this->address == '')
{
// Just get the first one selected in the back end for now
$arrSelected = StringUtil::deserialize($this->profiles, true);
$objBusiness = ProfileItemModel::findByPk($arrSelected[0]);
return $objBusiness !== null ? ($objBusiness->street . ', ' . $objBusiness->city . ' ' . $objBusiness->state . ' ' . $objBusiness->postal) : 'Western Massachusetts';
}
return $this->address;
}
/*
* Get the location string
*/
public function getLocation()
{
// If the location is just the concatenated version of null values, use the first business
if ($this->location == '')
{
// Just get the first one selected in the back end for now
$arrSelected = StringUtil::deserialize($this->profiles, true);
$objBusiness = ProfileItemModel::findByPk($arrSelected[0]);
return $objBusiness !== null ? $objBusiness->name : '';
}
return $this->location;
}
/**
* Find an event post by its ID or alias
*
* @param mixed $varId The numeric ID or alias name
* @param array $arrOptions An optional options array
*
* @return CalendarEventsModel|null The model or null if there is no event
*/
public static function findPublishedByIdOrAlias($varId, array $arrOptions=array())
{
$t = static::$strTable;
$arrColumns = !is_numeric($varId) ? array("$t.alias=?") : array("$t.id=?");
if (!static::isPreviewMode($arrOptions))
{
$time = Date::floorToMinute();
$arrColumns[] = "($t.start='' OR $t.start<='$time') AND ($t.stop='' OR $t.stop>'" . ($time + 60) . "') AND $t.published='1'";
}
return static::findOneBy($arrColumns, $varId, $arrOptions);
}
/**
* Find upcoming events by their Business IDs
*
* @param array $arrIds An array of business IDs
* @param integer $intLimit An optional limit
* @param array $arrOptions An optional options array
*
* @return Collection|CalendarEventsModel[]|CalendarEventsModel|null A collection of models or null if there are no events
*/
public static function findUpcomingByProfileIds($arrIds, $intLimit=0, array $arrOptions=array())
{
if (empty($arrIds) || !\is_array($arrIds))
{
return null;
}
$t = static::$strTable;
$time = Date::floorToMinute();
$strWhereBiz = "";
foreach (array_map('\intval', $arrIds) as $bizId)
{
$strWhereBiz .= (strlen($strWhereBiz) ? " OR " : "") . "$t.profiles LIKE '%\"".$bizId."\"%'";
}
$strWhereBiz = strlen($strWhereBiz) ? " AND (" . $strWhereBiz . ")" : "";
// Get upcoming events using endTime instead of startTime (see #3917)
$arrColumns = array("($t.endTime>=$time OR ($t.recurring='1' AND ($t.recurrences=0 OR $t.repeatEnd>=$time))) $strWhereBiz AND ($t.start='' OR $t.start<='$time') AND ($t.stop='' OR $t.stop>'" . ($time + 60) . "') AND $t.published='1'");
if ($intLimit > 0)
{
$arrOptions['limit'] = $intLimit;
}
if (!isset($arrOptions['order']))
{
$arrOptions['order'] = "$t.startTime";
}
return static::findBy($arrColumns, null, $arrOptions);
}
}