src/LaravelEventsCalendar.php
<?php
namespace DavideCasiraghi\LaravelEventsCalendar;
use Carbon\Carbon;
use DateTime;
use DavideCasiraghi\LaravelEventsCalendar\Models\Event;
use DavideCasiraghi\LaravelEventsCalendar\Models\EventRepetition;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManagerStatic as Image;
class LaravelEventsCalendar
{
/***************************************************************************/
/**
* Format a date from datepicker (d/m/Y) to a format ready to be stored on DB (Y-m-d).
* If the date picker date is null return today's date.
* the PARAM is a date in the d/m/Y format - the RETURN is a date in the Y-m-d format.
* If $todaysDateIfNull = 1, when the date is null return the date of today.
*
* @param string $DatePickerDate
* @param bool $todaysDateIfNull
* @return string $ret
*/
public static function formatDatePickerDateForMysql($DatePickerDate, bool $todaysDateIfNull = null)
{
if ($DatePickerDate) {
[$tid, $tim, $tiy] = explode('/', $DatePickerDate);
$ret = "$tiy-$tim-$tid";
} elseif ($todaysDateIfNull) {
date_default_timezone_set('Europe/Rome');
$ret = date('Y-m-d', time());
} else {
$ret = '';
}
return $ret;
}
/***************************************************************************/
/**
* It returns a string that is composed by the array values separated by a comma.
*
* @param iterable $items
* @return string $ret
*/
public static function getStringFromArraySeparatedByComma(iterable $items)
{
$ret = '';
$i = 0;
$len = count($items); // to put "," to all items except the last
foreach ($items as $key => $item) {
$ret .= $item;
if ($i != $len - 1) { // not last
$ret .= ', ';
}
$i++;
}
return $ret;
}
/***************************************************************************/
/**
* Check the date and return true if the weekday is the one specified in $dayOfTheWeek. eg. if $dayOfTheWeek = 3, is true if the date is a Wednesday
* $dayOfTheWeek: 1|2|3|4|5|6|7 (MONDAY-SUNDAY)
* https://stackoverflow.com/questions/2045736/getting-all-dates-for-mondays-and-tuesdays-for-the-next-year.
*
* @param string $date
* @param int $dayOfTheWeek
* @return bool
*/
public static function isWeekDay(string $date, int $dayOfTheWeek)
{
// Fix the bug that was avoiding to save Sunday. Date 'w' identify sunday as 0 and not 7.
if ($dayOfTheWeek == 7) {
$dayOfTheWeek = 0;
}
return date('w', strtotime($date)) == $dayOfTheWeek;
}
/***************************************************************************/
/**
* GET number of the specified weekday in this month (1 for the first).
* $dateTimestamp - unix timestramp of the date specified
* $dayOfWeekValue - 1 (for Monday) through 7 (for Sunday)
* Return the number of the week in the month of the weekday specified.
* @param string $dateTimestamp
* @param string $dayOfWeekValue
* @return int
*/
public static function weekdayNumberOfMonth(string $dateTimestamp, string $dayOfWeekValue)
{
$cut = substr($dateTimestamp, 0, 8);
$daylen = 86400;
$timestamp = strtotime($dateTimestamp);
$first = strtotime($cut.'01');
$elapsed = (($timestamp - $first) / $daylen) + 1;
$i = 1;
$weeks = 0;
for ($i == 1; $i <= $elapsed; $i++) {
$dayfind = $cut.(strlen((string) $i) < 2 ? '0'.$i : $i);
$daytimestamp = strtotime($dayfind);
$day = strtolower(date('N', $daytimestamp));
if ($day == strtolower($dayOfWeekValue)) {
$weeks++;
}
}
if ($weeks == 0) {
$weeks++;
}
return $weeks;
}
/***************************************************************************/
/**
* GET number of week from the end of the month - https://stackoverflow.com/questions/5853380/php-get-number-of-week-for-month
* Week of the month = Week of the year - Week of the year of first day of month + 1.
* Return the number of the week in the month of the day specified
* $when - unix timestramp of the date specified.
*
* @param int $when
* @return int
*/
public static function weekOfMonthFromTheEnd(int $when)
{
$numberOfDayOfTheMonth = strftime('%e', $when); // Day of the month 1-31
$lastDayOfMonth = strftime('%e', strtotime(date('Y-m-t', $when))); // the last day of the month of the specified date
$dayDifference = (int) $lastDayOfMonth - (int) $numberOfDayOfTheMonth;
switch (true) {
case $dayDifference < 7:
$weekFromTheEnd = 1;
break;
case $dayDifference < 14:
$weekFromTheEnd = 2;
break;
case $dayDifference < 21:
$weekFromTheEnd = 3;
break;
case $dayDifference < 28:
$weekFromTheEnd = 4;
break;
default:
$weekFromTheEnd = 5;
break;
}
return $weekFromTheEnd;
}
/***************************************************************************/
/**
* GET number of day from the end of the month.
* $when - unix timestramp of the date specified
* Return the number of day of the month from end.
*
* @param int $when
* @return int
*/
public static function dayOfMonthFromTheEnd(int $when)
{
$numberOfDayOfTheMonth = strftime('%e', $when); // Day of the month 1-31
$lastDayOfMonth = strftime('%e', strtotime(date('Y-m-t', $when))); // the last day of the month of the specified date
$dayDifference = (int) $lastDayOfMonth - (int) $numberOfDayOfTheMonth;
return $dayDifference;
}
/***************************************************************************/
/**
* Decode the event repeat_weekly_on field - used in event.show.
* Return a string like "Monday".
*
* @param string $repeatWeeklyOn
* @return string
*/
public static function decodeRepeatWeeklyOn(string $repeatWeeklyOn)
{
$weekdayArray = [
'',
__('laravel-events-calendar::general.monday'),
__('laravel-events-calendar::general.tuesday'),
__('laravel-events-calendar::general.wednesday'),
__('laravel-events-calendar::general.thursday'),
__('laravel-events-calendar::general.friday'),
__('laravel-events-calendar::general.saturday'),
__('laravel-events-calendar::general.sunday'),
];
$ret = $weekdayArray[$repeatWeeklyOn];
return $ret;
}
/***************************************************************************/
/**
* Decode the event on_monthly_kind field - used in event.show.
* Return a string like "the 4th to last Thursday of the month".
*
* @param string $onMonthlyKindCode
* @return string
*/
public static function decodeOnMonthlyKind(string $onMonthlyKindCode)
{
$ret = '';
$onMonthlyKindCodeArray = explode('|', $onMonthlyKindCode);
$weekDays = [
'',
__('laravel-events-calendar::general.monday'),
__('laravel-events-calendar::general.tuesday'),
__('laravel-events-calendar::general.wednesday'),
__('laravel-events-calendar::general.thursday'),
__('laravel-events-calendar::general.friday'),
__('laravel-events-calendar::general.saturday'),
__('laravel-events-calendar::general.sunday'),
];
//dd($onMonthlyKindCodeArray);
switch ($onMonthlyKindCodeArray[0]) {
case '0': // 0|7 eg. the 7th day of the month
$dayNumber = $onMonthlyKindCodeArray[1];
$format = __('laravel-events-calendar::ordinalDays.the_'.($dayNumber).'_x_of_the_month');
$ret = sprintf($format, __('laravel-events-calendar::general.day'));
break;
case '1': // 1|2|4 eg. the 2nd Thursday of the month
$dayNumber = $onMonthlyKindCodeArray[1];
$weekDay = $weekDays[$onMonthlyKindCodeArray[2]]; // Monday, Tuesday, Wednesday
$format = __('laravel-events-calendar::ordinalDays.the_'.($dayNumber).'_x_of_the_month');
$ret = sprintf($format, $weekDay);
break;
case '2': // 2|20 eg. the 21st to last day of the month
$dayNumber = (int) $onMonthlyKindCodeArray[1] + 1;
$format = __('laravel-events-calendar::ordinalDays.the_'.($dayNumber).'_to_last_x_of_the_month');
$ret = sprintf($format, __('laravel-events-calendar::general.day'));
break;
case '3': // 3|3|4 eg. the 4th to last Thursday of the month
$dayNumber = (int) $onMonthlyKindCodeArray[1] + 1;
$weekDay = $weekDays[$onMonthlyKindCodeArray[2]]; // Monday, Tuesday, Wednesday
$format = __('laravel-events-calendar::ordinalDays.the_'.($dayNumber).'_to_last_x_of_the_month');
$ret = sprintf($format, $weekDay);
break;
}
return $ret;
}
/***************************************************************************/
/**
* Return the GPS coordinates of the venue
* https://developer.mapquest.com/.
*
* @param string $address
* @return array $ret
*/
public static function getVenueGpsCoordinates(string $address)
{
$address = self::cleanString($address);
$key = 'Ad5KVnAISxX6aHyj6fAnHcKeh30n4W60';
$url = 'https://www.mapquestapi.com/geocoding/v1/address?key='.$key.'&location='.$address;
$response = @file_get_contents($url);
if (! $response) {
$url = 'http://open.mapquestapi.com/geocoding/v1/address?key='.$key.'&location='.$address;
$response = @file_get_contents($url);
}
$response = json_decode($response, true);
$ret = [];
$ret['lat'] = $response['results'][0]['locations'][0]['latLng']['lat'];
$ret['lng'] = $response['results'][0]['locations'][0]['latLng']['lng'];
return $ret;
}
/***************************************************************************/
/**
* Return a string with the list of the collection id separated by comma.
* without any space. eg. "354,320,310".
*
* @param iterable $items
* @return string $ret
*/
public static function getCollectionIdsSeparatedByComma(iterable $items)
{
$itemsIds = [];
foreach ($items as $item) {
array_push($itemsIds, $item->id);
}
$ret = implode(',', $itemsIds);
return $ret;
}
/***************************************************************************/
/**
* Return a string that describe the report misuse reason.
*
* @param int $reason
* @return string $ret
*/
public static function getReportMisuseReasonDescription(int $reason)
{
$ret = '';
switch ($reason) {
case '1':
$ret = 'Not about Contact Improvisation';
break;
case '2':
$ret = 'Contains wrong informations';
break;
case '3':
$ret = 'It is not translated in english';
break;
case '4':
$ret = 'Other (specify in the message)';
break;
}
return $ret;
}
/***************************************************************************/
/**
* Return a string that describe repetition kind in the event show view.
*
* @param \DavideCasiraghi\LaravelEventsCalendar\Models\Event $event
* @param \DavideCasiraghi\LaravelEventsCalendar\Models\EventRepetition $firstRpDates
* @return string $ret
*/
public static function getRepetitionTextString(Event $event, EventRepetition $firstRpDates)
{
$ret = '';
switch ($event->repeat_type) {
case '1': // noRepeat
break;
case '2': // repeatWeekly
$repeatUntil = new DateTime($event->repeat_until);
// Get the name of the weekly day when the event repeat, if two days, return like "Thursday and Sunday"
$repetitonWeekdayNumbersArray = explode(',', $event->repeat_weekly_on);
$repetitonWeekdayNamesArray = [];
foreach ($repetitonWeekdayNumbersArray as $key => $repetitonWeekdayNumber) {
$repetitonWeekdayNamesArray[] = self::decodeRepeatWeeklyOn($repetitonWeekdayNumber);
}
// create from an array a string with all the values divided by " and "
$nameOfTheRepetitionWeekDays = implode(' and ', $repetitonWeekdayNamesArray);
//$ret = 'The event happens every '.$nameOfTheRepetitionWeekDays.' until '.$repeatUntil->format('d/m/Y');
$format = __('laravel-events-calendar::event.the_event_happens_every_x_until_x');
$ret .= sprintf($format, $nameOfTheRepetitionWeekDays, $repeatUntil->format('d/m/Y'));
break;
case '3': //repeatMonthly
$repeatUntil = new DateTime($event->repeat_until);
$repetitionFrequency = self::decodeOnMonthlyKind($event->on_monthly_kind);
//$ret = 'The event happens '.$repetitionFrequency.' until '.$repeatUntil->format('d/m/Y');
$format = __('laravel-events-calendar::event.the_event_happens_x_until_x');
$ret .= sprintf($format, $repetitionFrequency, $repeatUntil->format('d/m/Y'));
break;
case '4': //repeatMultipleDays
$dateStart = date('d/m/Y', strtotime($firstRpDates->start_repeat));
$singleDaysRepeatDatas = explode(',', $event->multiple_dates);
// Sort the datas
usort($singleDaysRepeatDatas, function ($a, $b) {
$a = Carbon::createFromFormat('d/m/Y', $a);
$b = Carbon::createFromFormat('d/m/Y', $b);
return strtotime($a) - strtotime($b);
});
$ret .= __('laravel-events-calendar::event.the_event_happens_on_this_dates');
$ret .= $dateStart.', ';
$ret .= self::getStringFromArraySeparatedByComma($singleDaysRepeatDatas);
break;
}
return $ret;
}
/***************************************************************************/
/**
* Return the map marker icon color.
*
* @param int $eventCategoryId
* @return string $ret
*/
public static function getMapMarkerIconColor(int $eventCategoryId)
{
$ret = '';
switch ($eventCategoryId) {
case 1: //Regular Jam
$ret = 'greenIcon';
break;
case 10: // Special Jam
$ret = 'yellowIcon';
break;
case 2: // Class
$ret = 'goldIcon';
break;
case 3: // Workshop
$ret = 'orangeIcon';
break;
case 6: // Festival
case 16: // Camp / Journey
$ret = 'redIcon';
break;
case 11: // Underscore
$ret = 'blueIcon';
break;
case 13: // Performance
case 14: // Lecture / Conference / Film
case 17: // Other event
$ret = 'violetIcon';
break;
case 15: // Lab
$ret = 'greyIcon';
break;
case 12: // Teachers Meeting
$ret = 'blackIcon';
break;
}
return $ret;
}
/***************************************************************************/
/**
* Remove all special characters from a string - Remove all special characters from a string.
*
* @param string $text
* @return string $ret
*/
public static function cleanString(string $text)
{
// Transform whitespaces to %20 for the URL
$text = str_replace(' ', '%20', $text);
$text = str_replace('ß', '%DF', $text);
$utf8 = [
'/[áàâãªä]/u' => 'a',
'/[ÁÀÂÃÄ]/u' => 'A',
'/[ÍÌÎÏİ]/u' => 'I',
'/[íìîïı]/u' => 'i',
'/[éèêëěė]/u' => 'e',
'/[ÉÈÊË]/u' => 'E',
'/[óòôõºöø]/u' => 'o',
'/[ÓÒÔÕÖ]/u' => 'O',
'/[úùûüüū]/u' => 'u',
'/[ÚÙÛÜ]/u' => 'U',
'/[çć]/u' => 'c',
'/Ç/' => 'C',
'/ğ/' => 'g',
'/ñ/' => 'n',
'/Ñ/' => 'N',
'/ř/' => 'r',
'/[šş]/u' => 's',
'/–/' => '-', // UTF-8 hyphen to "normal" hyphen
'/[’‘‹›‚]/u' => ' ', // Literally a single quote
'/[“”«»„]/u' => ' ', // Double quote
'/ /' => ' ', // nonbreaking space (equiv. to 0x160)
];
$ret = preg_replace(array_keys($utf8), array_values($utf8), $text);
return $ret;
}
// **********************************************************************
/**
* Upload image on server.
* $imageFile - the file to upload
* $imageSubdir is the subdir in /storage/app/public/images/..
*
* @param mixed $imageFile
* @param string $imageName
* @param string $imageSubdir
* @param int $imageWidth
* @param int $thumbWidth
* @return void
*/
public static function uploadImageOnServer($imageFile, string $imageName, string $imageSubdir, int $imageWidth, int $thumbWidth): void
{
// Create dir if not exist (in /storage/app/public/images/..)
if (! Storage::disk('public')->has('images/'.$imageSubdir.'/')) {
Storage::disk('public')->makeDirectory('images/'.$imageSubdir.'/');
}
$destinationPath = 'app/public/images/'.$imageSubdir.'/';
// Resize the image with Intervention - http://image.intervention.io/api/resize
// - resize and store the image to a width of 300 and constrain aspect ratio (auto height)
// - save file as jpg with medium quality
$image = Image::make($imageFile->getRealPath())
->resize($imageWidth, null,
function ($constraint) {
$constraint->aspectRatio();
})
->save(storage_path($destinationPath.$imageName), 75);
// Create the thumb
$image->resize($thumbWidth, null,
function ($constraint) {
$constraint->aspectRatio();
})
->save(storage_path($destinationPath.'thumb_'.$imageName), 75);
}
}