refactor: replace custom CRM with Monica fork
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
This commit is contained in:
219
app/Helpers/AccountHelper.php
Normal file
219
app/Helpers/AccountHelper.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\Contact\Gender;
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class AccountHelper
|
||||
{
|
||||
/**
|
||||
* Indicates whether the given account has limitations with her current
|
||||
* plan.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasLimitations(Account $account): bool
|
||||
{
|
||||
if ($account->has_access_to_paid_version_for_free) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! config('monica.requires_subscription')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($account->isSubscribed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether an account has reached the contact limit if the account
|
||||
* is on a free trial.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasReachedContactLimit(Account $account): bool
|
||||
{
|
||||
return $account->allContacts()->real()->active()->count() >= config('monica.number_of_allowed_contacts_free_account');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether an account has not reached the contact limit of free accounts.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return bool
|
||||
*/
|
||||
public static function isBelowContactLimit(Account $account): bool
|
||||
{
|
||||
return $account->allContacts()->real()->active()->count() <= config('monica.number_of_allowed_contacts_free_account');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the account can be downgraded, based on a set of rules.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return bool
|
||||
*/
|
||||
public static function canDowngrade(Account $account): bool
|
||||
{
|
||||
$canDowngrade = true;
|
||||
$numberOfUsers = $account->users()->count();
|
||||
$numberPendingInvitations = $account->invitations()->count();
|
||||
$numberActiveContacts = $account->allContacts()->active()->count();
|
||||
|
||||
// number of users in the account should be == 1
|
||||
if ($numberOfUsers > 1) {
|
||||
$canDowngrade = false;
|
||||
}
|
||||
|
||||
// there should not be any pending user invitations
|
||||
if ($numberPendingInvitations > 0) {
|
||||
$canDowngrade = false;
|
||||
}
|
||||
|
||||
// there should not be more than the number of contacts allowed
|
||||
if ($numberActiveContacts > config('monica.number_of_allowed_contacts_free_account')) {
|
||||
$canDowngrade = false;
|
||||
}
|
||||
|
||||
return $canDowngrade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default gender for this account.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return string
|
||||
*/
|
||||
public static function getDefaultGender(Account $account): string
|
||||
{
|
||||
$defaultGenderType = Gender::UNKNOWN;
|
||||
|
||||
if ($account->default_gender_id) {
|
||||
$defaultGender = Gender::where([
|
||||
'account_id' => $account->id,
|
||||
])->find($account->default_gender_id);
|
||||
|
||||
if ($defaultGender) {
|
||||
$defaultGenderType = $defaultGender->type;
|
||||
}
|
||||
}
|
||||
|
||||
return $defaultGenderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reminders for the month given in parameter.
|
||||
* - 0 means current month
|
||||
* - 1 means month+1
|
||||
* - 2 means month+2...
|
||||
*
|
||||
* @param Account $account
|
||||
* @param int $month
|
||||
*/
|
||||
public static function getUpcomingRemindersForMonth(Account $account, int $month)
|
||||
{
|
||||
$startOfMonth = now(DateHelper::getTimezone())->addMonthsNoOverflow($month)->startOfMonth();
|
||||
|
||||
// don't get reminders for past events:
|
||||
if ($startOfMonth->isPast()) {
|
||||
$startOfMonth = now(DateHelper::getTimezone());
|
||||
}
|
||||
|
||||
$endOfMonth = now(DateHelper::getTimezone())->addMonthsNoOverflow($month)->endOfMonth();
|
||||
|
||||
return $account->reminderOutboxes()
|
||||
->with(['reminder', 'reminder.contact'])
|
||||
->whereBetween('planned_date', [$startOfMonth, $endOfMonth])
|
||||
->where([
|
||||
'user_id' => auth()->user()->id,
|
||||
'nature' => 'reminder',
|
||||
])
|
||||
->orderBy('planned_date', 'asc')
|
||||
->get()
|
||||
->filter(function ($reminderOutbox) {
|
||||
return $reminderOutbox->reminder->contact !== null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of activities grouped by year.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getYearlyActivitiesStatistics(Account $account): Collection
|
||||
{
|
||||
$activitiesStatistics = collect([]);
|
||||
$activities = $account->activities()
|
||||
->select('happened_at')
|
||||
->latest('happened_at')
|
||||
->get();
|
||||
$years = [];
|
||||
|
||||
foreach ($activities as $activity) {
|
||||
$yearStatistic = $activity->happened_at->format('Y');
|
||||
$foundInYear = false;
|
||||
|
||||
foreach ($years as $year => $number) {
|
||||
if ($year == $yearStatistic) {
|
||||
$years[$year] = $number + 1;
|
||||
$foundInYear = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $foundInYear) {
|
||||
$years[$yearStatistic] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($years as $year => $number) {
|
||||
$activitiesStatistics->put($year, $number);
|
||||
}
|
||||
|
||||
return $activitiesStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of calls grouped by year.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getYearlyCallStatistics(Account $account): Collection
|
||||
{
|
||||
$callsStatistics = collect([]);
|
||||
$calls = $account->calls()
|
||||
->select('called_at')
|
||||
->latest('called_at')
|
||||
->get();
|
||||
$years = [];
|
||||
|
||||
foreach ($calls as $call) {
|
||||
$yearStatistic = $call->called_at->format('Y');
|
||||
$foundInYear = false;
|
||||
|
||||
foreach ($years as $year => $number) {
|
||||
if ($year == $yearStatistic) {
|
||||
$years[$year] = $number + 1;
|
||||
$foundInYear = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $foundInYear) {
|
||||
$years[$yearStatistic] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($years as $year => $number) {
|
||||
$callsStatistics->put($year, $number);
|
||||
}
|
||||
|
||||
return $callsStatistics;
|
||||
}
|
||||
}
|
||||
53
app/Helpers/AuditLogHelper.php
Normal file
53
app/Helpers/AuditLogHelper.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class AuditLogHelper
|
||||
{
|
||||
/**
|
||||
* Prepare a collection of audit logs that is displayed on the Settings page.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Pagination\LengthAwarePaginator|Collection<array-key, \App\Models\Instance\AuditLog> $logs
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getCollectionOfAudits($logs): Collection
|
||||
{
|
||||
$logsCollection = collect();
|
||||
|
||||
foreach ($logs as $log) {
|
||||
$object = null;
|
||||
$link = null;
|
||||
|
||||
// the log is about a contact
|
||||
if (isset($log->object->{'contact_id'})) {
|
||||
try {
|
||||
// check if the contact that the log is about still exists
|
||||
// in that case, we will display a link to point to this contact
|
||||
$contact = Contact::findOrFail($log->object->{'contact_id'});
|
||||
$object = $contact->name;
|
||||
$link = route('people.show', ['contact' => $contact]);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
// the contact doesn't exist anymore, we don't need a link, we'll only display a name
|
||||
$object = $log->object->{'contact_name'};
|
||||
}
|
||||
$description = trans('logs.settings_log_'.$log->action.'_with_name', ['name' => $object]);
|
||||
} else {
|
||||
$description = trans('logs.settings_log_'.$log->action, ['name' => $log->object->{'name'}]);
|
||||
}
|
||||
|
||||
$logsCollection->push([
|
||||
'author_name' => ($log->author) ? $log->author->name : $log->author_name,
|
||||
'description' => $description,
|
||||
'link' => $link,
|
||||
'object' => $object,
|
||||
'audited_at' => $log->audited_at,
|
||||
]);
|
||||
}
|
||||
|
||||
return $logsCollection;
|
||||
}
|
||||
}
|
||||
106
app/Helpers/CollectionHelper.php
Normal file
106
app/Helpers/CollectionHelper.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class CollectionHelper
|
||||
{
|
||||
/**
|
||||
* Sort the collection using the given callback.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $collect
|
||||
* @param callable|string $callback
|
||||
* @param int $options
|
||||
* @param bool $descending
|
||||
* @return Collection
|
||||
*/
|
||||
public static function sortByCollator($collect, $callback, $options = \Collator::SORT_STRING, $descending = false)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
$callback = static::valueRetriever($callback);
|
||||
|
||||
// First we will loop through the items and get the comparator from a callback
|
||||
// function which we were given. Then, we will sort the returned values and
|
||||
// and grab the corresponding values for the sorted keys from this array.
|
||||
foreach ($collect->all() as $key => $value) {
|
||||
$results[$key] = $callback($value, $key);
|
||||
}
|
||||
|
||||
// Using Collator to sort the array, with locale-sensitive sort ordering support.
|
||||
static::getCollator()->asort($results, $options);
|
||||
if ($descending) {
|
||||
$results = array_reverse($results);
|
||||
}
|
||||
|
||||
// Once we have sorted all of the keys in the array, we will loop through them
|
||||
// and grab the corresponding model so we can set the underlying items list
|
||||
// to the sorted version. Then we'll just return the collection instance.
|
||||
foreach (array_keys($results) as $key) {
|
||||
$results[$key] = $collect->get($key);
|
||||
}
|
||||
|
||||
return new Collection($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Collator object for the locale or current locale.
|
||||
*
|
||||
* @param string $locale
|
||||
* @return \Collator
|
||||
*/
|
||||
public static function getCollator($locale = null)
|
||||
{
|
||||
static $collators = [];
|
||||
|
||||
if (! $locale) {
|
||||
$locale = app()->getLocale();
|
||||
}
|
||||
if (! Arr::has($collators, $locale)) {
|
||||
$collator = new \Collator($locale);
|
||||
|
||||
if (LocaleHelper::getLang($locale) == 'fr') {
|
||||
$collator->setAttribute(\Collator::FRENCH_COLLATION, \Collator::ON);
|
||||
}
|
||||
|
||||
$collators[$locale] = $collator;
|
||||
|
||||
return $collator;
|
||||
}
|
||||
|
||||
return $collators[$locale];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value retrieving callback.
|
||||
*
|
||||
* @param string|callable $value
|
||||
* @return callable
|
||||
*/
|
||||
private static function valueRetriever($value)
|
||||
{
|
||||
if (! is_string($value) && is_callable($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return function ($item) use ($value) {
|
||||
return data_get($item, $value);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Group collection based on a specific property from its items.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $collection
|
||||
* @param string $property
|
||||
* @return mixed
|
||||
*/
|
||||
public static function groupByItemsProperty($collection, $property)
|
||||
{
|
||||
return $collection->mapToGroups(function ($item) use ($property) {
|
||||
return [data_get($item, $property) => $item];
|
||||
});
|
||||
}
|
||||
}
|
||||
45
app/Helpers/ComplianceHelper.php
Normal file
45
app/Helpers/ComplianceHelper.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Models\Settings\Term;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ComplianceHelper
|
||||
{
|
||||
/**
|
||||
* Give the status for the given term for the given user.
|
||||
*
|
||||
* @param User $user
|
||||
* @param Term $term
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasSignedGivenTerm(User $user, Term $term): bool
|
||||
{
|
||||
$termUser = DB::table('term_user')->where('user_id', $user->id)
|
||||
->where('account_id', $user->account_id)
|
||||
->where('term_id', $term->id)
|
||||
->first();
|
||||
|
||||
if (! $termUser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if the user has accepted the most recent terms and privacy.
|
||||
* This really is a shortcut of the `hasSignedGivenTerm` method.
|
||||
*
|
||||
* @param User $user
|
||||
* @return bool
|
||||
*/
|
||||
public static function isCompliantWithCurrentTerm(User $user): bool
|
||||
{
|
||||
$latestTerm = Term::latest()->first();
|
||||
|
||||
return self::hasSignedGivenTerm($user, $latestTerm);
|
||||
}
|
||||
}
|
||||
58
app/Helpers/ComposerScripts.php
Normal file
58
app/Helpers/ComposerScripts.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class ComposerScripts
|
||||
{
|
||||
const CONFIG = 'bootstrap/cache/config.php';
|
||||
|
||||
/**
|
||||
* Handle the pre-install Composer event.
|
||||
*
|
||||
* @param mixed $event
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function preInstall($event)
|
||||
{
|
||||
try {
|
||||
if (file_exists('vendor')) {
|
||||
\Illuminate\Foundation\ComposerScripts::postInstall($event);
|
||||
}
|
||||
static::clear();
|
||||
} catch (\Throwable $e) {
|
||||
// catch all
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the pre-update Composer event.
|
||||
*
|
||||
* @param mixed $event
|
||||
* @return void
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function preUpdate($event)
|
||||
{
|
||||
try {
|
||||
if (file_exists('vendor')) {
|
||||
\Illuminate\Foundation\ComposerScripts::postUpdate($event);
|
||||
}
|
||||
static::clear();
|
||||
} catch (\Throwable $e) {
|
||||
// catch all
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected static function clear()
|
||||
{
|
||||
if (file_exists(self::CONFIG)) {
|
||||
\unlink(self::CONFIG); /** @phpstan-ignore-line */
|
||||
}
|
||||
}
|
||||
}
|
||||
203
app/Helpers/CountriesHelper.php
Normal file
203
app/Helpers/CountriesHelper.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Rinvex\Country\Country;
|
||||
use Rinvex\Country\CountryLoader;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class CountriesHelper
|
||||
{
|
||||
/**
|
||||
* Get list of countries.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function getAll(): Collection
|
||||
{
|
||||
$x = collect(countries(true, true));
|
||||
$countries = $x->map(function (Country $item) {
|
||||
return [
|
||||
'id' => $item->getIsoAlpha2(),
|
||||
'country' => static::getCommonNameLocale($item),
|
||||
];
|
||||
});
|
||||
|
||||
return collect($countries->sortByCollator('country'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get country name.
|
||||
*
|
||||
* @param string $iso code of the country
|
||||
* @return string common name (localized) of the country
|
||||
*/
|
||||
public static function get($iso): string
|
||||
{
|
||||
$country = self::getCountry($iso);
|
||||
if (is_null($country)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return static::getCommonNameLocale($country);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a country by the (english) name of the country.
|
||||
*
|
||||
* @param string $name Common name of a country
|
||||
* @return string iso_3166_1_alpha2 code of the country
|
||||
*/
|
||||
public static function find($name): string
|
||||
{
|
||||
$country = collect(CountryLoader::where('name.common', $name));
|
||||
if ($country->count() === 0) {
|
||||
$country = collect(CountryLoader::where('iso_3166_1_alpha2', mb_strtoupper($name)));
|
||||
}
|
||||
if ($country->count() === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (new Country($country->first()))->getIsoAlpha2();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the common name of country, in locale version.
|
||||
*
|
||||
* @param \Rinvex\Country\Country $country
|
||||
* @return string
|
||||
*/
|
||||
private static function getCommonNameLocale(Country $country): string
|
||||
{
|
||||
$locale = App::getLocale();
|
||||
$lang = LocaleHelper::getLocaleAlpha($locale);
|
||||
|
||||
return $country->getTranslation($lang)['common'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get country for a specific iso code.
|
||||
*
|
||||
* @param string $iso
|
||||
* @return \Rinvex\Country\Country|null the Country element
|
||||
*/
|
||||
public static function getCountry($iso): ?Country
|
||||
{
|
||||
$country = collect(CountryLoader::where('iso_3166_1_alpha2', mb_strtoupper($iso)));
|
||||
if ($country->count() === 0) {
|
||||
$country = collect(CountryLoader::where('alt_spellings', mb_strtoupper($iso)));
|
||||
}
|
||||
if ($country->count() === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Country($country->first());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get country for a specific language.
|
||||
*
|
||||
* @param string $locale language code (iso)
|
||||
* @return \Rinvex\Country\Country|null the Country element
|
||||
*/
|
||||
public static function getCountryFromLocale($locale): ?Country
|
||||
{
|
||||
$countryCode = LocaleHelper::extractCountry($locale);
|
||||
if (empty($countryCode)) {
|
||||
$countryCode = self::getDefaultCountryFromLocale($locale);
|
||||
}
|
||||
|
||||
if (is_null($countryCode)) {
|
||||
$lang = LocaleHelper::getLocaleAlpha($locale);
|
||||
$country = collect(CountryLoader::where("languages.$lang", '>', '0'));
|
||||
if ($country->count() === 0) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$country = collect(CountryLoader::where('iso_3166_1_alpha2', mb_strtoupper($countryCode)));
|
||||
}
|
||||
|
||||
return new Country($country->first());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default country for a language.
|
||||
*
|
||||
* @param string $locale language code (iso)
|
||||
* @return string|null iso_3166_1_alpha2 code
|
||||
*/
|
||||
private static function getDefaultCountryFromLocale($locale): ?string
|
||||
{
|
||||
switch (mb_strtolower($locale)) {
|
||||
case 'cs':
|
||||
$country = 'CZ';
|
||||
break;
|
||||
case 'en':
|
||||
$country = 'US';
|
||||
break;
|
||||
case 'he':
|
||||
$country = 'IL';
|
||||
break;
|
||||
case 'zh':
|
||||
$country = 'CN';
|
||||
break;
|
||||
case 'de':
|
||||
case 'es':
|
||||
case 'fr':
|
||||
case 'hr':
|
||||
case 'it':
|
||||
case 'nl':
|
||||
case 'pt':
|
||||
case 'ru':
|
||||
case 'tr':
|
||||
$country = mb_strtoupper($locale);
|
||||
break;
|
||||
default:
|
||||
$country = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default timezone for the country.
|
||||
*
|
||||
* @param mixed $country Country element
|
||||
* @return string timezone fo this sountry
|
||||
*/
|
||||
public static function getDefaultTimezone($country): string
|
||||
{
|
||||
// https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
// https://en.wikipedia.org/wiki/List_of_time_zones_by_country
|
||||
switch ($country->getIsoAlpha3()) {
|
||||
case 'AUS':
|
||||
$timezone = 'Australia/Melbourne';
|
||||
break;
|
||||
case 'CHN':
|
||||
$timezone = 'Asia/Shanghai';
|
||||
break;
|
||||
case 'ESP':
|
||||
$timezone = 'Europe/Madrid';
|
||||
break;
|
||||
case 'PRT':
|
||||
$timezone = 'Europe/Lisbon';
|
||||
break;
|
||||
case 'RUS':
|
||||
$timezone = 'Europe/Moscow';
|
||||
break;
|
||||
case 'CAN':
|
||||
$timezone = 'America/Toronto';
|
||||
break;
|
||||
case 'USA':
|
||||
$timezone = 'America/Chicago';
|
||||
break;
|
||||
default:
|
||||
$timezone = collect($country->getTimezones())->first();
|
||||
break;
|
||||
}
|
||||
|
||||
return $timezone ?? config('app.timezone');
|
||||
}
|
||||
}
|
||||
67
app/Helpers/DBHelper.php
Normal file
67
app/Helpers/DBHelper.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use PDO;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Connection;
|
||||
|
||||
class DBHelper
|
||||
{
|
||||
/**
|
||||
* Get connection.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public static function connection($name = null): Connection
|
||||
{
|
||||
return DB::connection($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of DB engine.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function version(): ?string
|
||||
{
|
||||
try {
|
||||
return static::connection()->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if db version if greater than $version param.
|
||||
*
|
||||
* @param string $version
|
||||
* @return bool
|
||||
*/
|
||||
public static function testVersion($version)
|
||||
{
|
||||
return version_compare(static::version(), $version) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of tables on this instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getTables()
|
||||
{
|
||||
return DB::select('SELECT table_name as `table_name`
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = :table_schema
|
||||
AND table_name LIKE :table_prefix', [
|
||||
'table_schema' => static::connection()->getDatabaseName(),
|
||||
'table_prefix' => '%'.static::connection()->getTablePrefix().'%',
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getTable($name)
|
||||
{
|
||||
return '`'.static::connection()->getTablePrefix().$name.'`';
|
||||
}
|
||||
}
|
||||
366
app/Helpers/DateHelper.php
Normal file
366
app/Helpers/DateHelper.php
Normal file
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use function Safe\date;
|
||||
use function Safe\strtotime;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DateHelper
|
||||
{
|
||||
/**
|
||||
* Creates a Carbon object from DateTime format.
|
||||
* If timezone is given, it parse the date with this timezone.
|
||||
* Always return a date with default timezone (UTC).
|
||||
*
|
||||
* @param \DateTime|Carbon|string|null $date
|
||||
* @param string $timezone
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public static function parseDateTime($date, $timezone = null): ?Carbon
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return null;
|
||||
}
|
||||
if ($date instanceof Carbon) {
|
||||
// ok
|
||||
} elseif ($date instanceof \DateTimeInterface) {
|
||||
$date = Carbon::instance($date);
|
||||
} else {
|
||||
try {
|
||||
$date = Carbon::parse($date, $timezone);
|
||||
} catch (\Exception $e) {
|
||||
// Parse error
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$appTimezone = config('app.timezone');
|
||||
if ($date->timezone !== $appTimezone) {
|
||||
$date->setTimezone($appTimezone);
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Carbon object from Date format.
|
||||
* If timezone is given, it parse the date with this timezone.
|
||||
* Always return a date with default timezone (UTC).
|
||||
*
|
||||
* @param Carbon|string $date
|
||||
* @param string $timezone
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public static function parseDate($date, $timezone = null): ?Carbon
|
||||
{
|
||||
if (! $date instanceof Carbon) {
|
||||
try {
|
||||
$date = Carbon::parse($date);
|
||||
} catch (\Exception $e) {
|
||||
// Parse error
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$date = Carbon::create($date->year, $date->month, $date->day, 0, 0, 0, $timezone ?? $date->timezone);
|
||||
|
||||
$appTimezone = config('app.timezone');
|
||||
if ($date->timezone !== $appTimezone) {
|
||||
$date->setTimezone($appTimezone);
|
||||
}
|
||||
|
||||
return $date === false ? null : $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return timestamp date format.
|
||||
*
|
||||
* @param Carbon|\App\Models\Instance\SpecialDate|string|null $date
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getTimestamp($date): ?string
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return null;
|
||||
}
|
||||
if ($date instanceof \App\Models\Instance\SpecialDate) {
|
||||
$date = $date->date;
|
||||
}
|
||||
if (! $date instanceof Carbon) {
|
||||
$date = Carbon::parse($date);
|
||||
}
|
||||
|
||||
return $date->translatedFormat(config('api.timestamp_format'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return date timestamp format.
|
||||
*
|
||||
* @param Carbon|\App\Models\Instance\SpecialDate|string|null $date
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getDate($date): ?string
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return null;
|
||||
}
|
||||
if ($date instanceof \App\Models\Instance\SpecialDate) {
|
||||
$date = $date->date;
|
||||
}
|
||||
if (! $date instanceof Carbon) {
|
||||
$date = Carbon::parse($date);
|
||||
}
|
||||
|
||||
return $date->translatedFormat(config('api.date_timestamp_format'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timezone of the current user, or null.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getTimezone(): ?string
|
||||
{
|
||||
return Auth::check() ? Auth::user()->timezone : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a date in a short format like "Oct 29, 1981".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getShortDate(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.short_date_year');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a date in a full format like "October 29, 1981".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getFullDate(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.full_date_year');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the month of the date like "Oct", or "Dec".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getShortMonth(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.short_month');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the month and year of the date like "October 2010",
|
||||
* or "March 2032".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getFullMonthAndDate(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.full_month_year');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the day of the date like "Mon", or "Wed".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getShortDay(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.short_day');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a date in a short format
|
||||
* like "Oct 29".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getShortDateWithoutYear(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.short_date');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a date and the time according to the timezone of the user, in a short format
|
||||
* like "Oct 29, 1981 19:32".
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @return string
|
||||
*/
|
||||
public static function getShortDateWithTime(Carbon $date): string
|
||||
{
|
||||
return self::formatDate($date, 'format.short_date_year_time', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a date in a given format.
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @param string $format
|
||||
* @param bool $withTimezone
|
||||
* @return string
|
||||
*/
|
||||
private static function formatDate(Carbon $date, string $format, bool $withTimezone = false): string
|
||||
{
|
||||
$format = trans($format, [], Carbon::getLocale());
|
||||
if ($withTimezone) {
|
||||
$date = $date->setTimezone(static::getTimezone());
|
||||
}
|
||||
|
||||
return $date->translatedFormat($format) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a given number of week/month/year to a date.
|
||||
*
|
||||
* @param Carbon $date the start date
|
||||
* @param string $frequency week/month/year
|
||||
* @param int $number the number of week/month/year to increment to
|
||||
* @return Carbon
|
||||
*/
|
||||
public static function addTimeAccordingToFrequencyType(Carbon $date, string $frequency, int $number): Carbon
|
||||
{
|
||||
switch ($frequency) {
|
||||
case 'week':
|
||||
$date = $date->addWeeks($number);
|
||||
break;
|
||||
case 'month':
|
||||
$date = $date->addMonths($number);
|
||||
break;
|
||||
default:
|
||||
$date = $date->addYears($number);
|
||||
break;
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the month and year of a given date with a given number
|
||||
* of months more.
|
||||
*
|
||||
* @param int $month
|
||||
* @return string
|
||||
*/
|
||||
public static function getMonthAndYear(int $month): string
|
||||
{
|
||||
$date = Carbon::now(static::getTimezone())->addMonthsNoOverflow($month);
|
||||
$format = trans('format.short_month_year', [], Carbon::getLocale());
|
||||
|
||||
return $date->translatedFormat($format) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next theoritical billing date.
|
||||
* This is used on the Upgrade page to tell the user when the next billing
|
||||
* date would be if he subscribed.
|
||||
*
|
||||
* @param string $interval
|
||||
* @return Carbon
|
||||
*/
|
||||
public static function getNextTheoriticalBillingDate(string $interval): Carbon
|
||||
{
|
||||
if ($interval == 'monthly') {
|
||||
return now(static::getTimezone())->addMonth();
|
||||
}
|
||||
|
||||
return now(static::getTimezone())->addYear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the year from min to max (0 is the current year).
|
||||
*
|
||||
* @param int $max
|
||||
* @param int $min
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getListOfYears($max = 120, $min = 0): Collection
|
||||
{
|
||||
$years = collect([]);
|
||||
$maxYear = now(static::getTimezone())->subYears($min)->year;
|
||||
$minYear = now(static::getTimezone())->subYears($max)->year;
|
||||
|
||||
for ($year = $maxYear; $year >= $minYear; $year--) {
|
||||
$years->push([
|
||||
'id' => $year,
|
||||
'name' => $year,
|
||||
]);
|
||||
}
|
||||
|
||||
return $years;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the months in a year.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getListOfMonths(): Collection
|
||||
{
|
||||
$months = collect([]);
|
||||
$currentDate = Carbon::parse('2000-01-01');
|
||||
$format = trans('format.full_month', [], Carbon::getLocale());
|
||||
|
||||
for ($month = 1; $month <= 12; $month++) {
|
||||
$currentDate->month = $month;
|
||||
$months->push([
|
||||
'id' => $month,
|
||||
'name' => mb_convert_case($currentDate->translatedFormat($format), MB_CASE_TITLE, 'UTF-8'),
|
||||
]);
|
||||
}
|
||||
|
||||
return $months;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the days in a month.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getListOfDays(): Collection
|
||||
{
|
||||
$days = collect([]);
|
||||
for ($day = 1; $day <= 31; $day++) {
|
||||
$days->push(['id' => $day, 'name' => $day]);
|
||||
}
|
||||
|
||||
return $days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the hours in a day.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getListOfHours(): Collection
|
||||
{
|
||||
$currentDate = Carbon::parse('2000-01-01 00:00:00');
|
||||
$format = trans('format.full_hour', [], Carbon::getLocale());
|
||||
|
||||
$hours = collect([]);
|
||||
for ($hour = 1; $hour <= 24; $hour++) {
|
||||
$currentDate->hour = $hour;
|
||||
$hours->push([
|
||||
'id' => date('H:i', strtotime("$hour:00")),
|
||||
'name' => $currentDate->translatedFormat($format),
|
||||
]);
|
||||
}
|
||||
|
||||
return $hours;
|
||||
}
|
||||
}
|
||||
31
app/Helpers/FormHelper.php
Normal file
31
app/Helpers/FormHelper.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\User\User;
|
||||
|
||||
class FormHelper
|
||||
{
|
||||
/**
|
||||
* Get the name order that will be used when rendered the Add/Edit forms
|
||||
* about contacts.
|
||||
*
|
||||
* @param User $user
|
||||
* @return string
|
||||
*/
|
||||
public static function getNameOrderForForms(User $user): string
|
||||
{
|
||||
$nameOrder = 'firstname';
|
||||
|
||||
switch ($user->name_order) {
|
||||
case 'lastname_firstname':
|
||||
case 'lastname_firstname_nickname':
|
||||
case 'lastname_nickname_firstname':
|
||||
case 'nickname_lastname_firstname':
|
||||
$nameOrder = 'lastname';
|
||||
break;
|
||||
}
|
||||
|
||||
return $nameOrder;
|
||||
}
|
||||
}
|
||||
48
app/Helpers/GenderHelper.php
Normal file
48
app/Helpers/GenderHelper.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\Contact\Gender;
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class GenderHelper
|
||||
{
|
||||
/**
|
||||
* Return a collection of genders.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getGendersInput()
|
||||
{
|
||||
$genders = auth()->user()->account->genders->map(function (Gender $gender): array {
|
||||
return [
|
||||
'id' => $gender->id,
|
||||
'name' => $gender->name,
|
||||
];
|
||||
});
|
||||
$genders = CollectionHelper::sortByCollator($genders, 'name');
|
||||
$genders->prepend(['id' => '', 'name' => trans('app.gender_no_gender')]);
|
||||
|
||||
return $genders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a specific gender of all the contacts in the account with another
|
||||
* gender.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Gender $genderToDelete
|
||||
* @param Gender $genderToReplaceWith
|
||||
* @return bool
|
||||
*/
|
||||
public static function replace(Account $account, Gender $genderToDelete, Gender $genderToReplaceWith): bool
|
||||
{
|
||||
Contact::where('account_id', $account->id)
|
||||
->where('gender_id', $genderToDelete->id)
|
||||
->update(['gender_id' => $genderToReplaceWith->id]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
118
app/Helpers/InstanceHelper.php
Normal file
118
app/Helpers/InstanceHelper.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use function Safe\json_decode;
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\Instance\Instance;
|
||||
use App\Models\Settings\Currency;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use function Safe\file_get_contents;
|
||||
|
||||
class InstanceHelper
|
||||
{
|
||||
/**
|
||||
* Get the number of paid accounts in the instance.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getNumberOfPaidSubscribers()
|
||||
{
|
||||
return Account::where('stripe_id', '!=', null)->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plan information for the given time period.
|
||||
*
|
||||
* @param string $timePeriod Accepted values: 'monthly', 'annual'
|
||||
* @return array|null
|
||||
*/
|
||||
public static function getPlanInformationFromConfig(string $timePeriod): ?array
|
||||
{
|
||||
$timePeriod = strtolower($timePeriod);
|
||||
|
||||
if ($timePeriod != 'monthly' && $timePeriod != 'annual') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$currency = Currency::where('iso', strtoupper(config('cashier.currency')))->first();
|
||||
$amount = MoneyHelper::format(config('monica.paid_plan_'.$timePeriod.'_price'), $currency);
|
||||
|
||||
return [
|
||||
'type' => $timePeriod,
|
||||
'name' => config('monica.paid_plan_'.$timePeriod.'_friendly_name'),
|
||||
'id' => config('monica.paid_plan_'.$timePeriod.'_id'),
|
||||
'price' => config('monica.paid_plan_'.$timePeriod.'_price'),
|
||||
'friendlyPrice' => $amount,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plan information for the given time period.
|
||||
*
|
||||
* @param \Laravel\Cashier\Subscription $subscription
|
||||
* @return array|null
|
||||
*/
|
||||
public static function getPlanInformationFromSubscription(\Laravel\Cashier\Subscription $subscription): ?array
|
||||
{
|
||||
try {
|
||||
$stripeSubscription = $subscription->asStripeSubscription();
|
||||
$plan = $stripeSubscription->plan;
|
||||
} catch (\Stripe\Exception\ApiErrorException $e) {
|
||||
$stripeSubscription = null;
|
||||
$plan = null;
|
||||
}
|
||||
|
||||
if (is_null($stripeSubscription) || is_null($plan)) {
|
||||
return [
|
||||
'type' => $subscription->stripe_price,
|
||||
'name' => $subscription->name,
|
||||
'id' => $subscription->stripe_id,
|
||||
'price' => '?',
|
||||
'friendlyPrice' => '?',
|
||||
'nextBillingDate' => '',
|
||||
];
|
||||
}
|
||||
|
||||
$currency = Currency::where('iso', strtoupper($plan->currency))->first();
|
||||
$amount = MoneyHelper::format($plan->amount, $currency);
|
||||
|
||||
return [
|
||||
'type' => $plan->interval === 'month' ? 'monthly' : 'annual',
|
||||
'name' => $subscription->name,
|
||||
'id' => $plan->id,
|
||||
'price' => $plan->amount,
|
||||
'friendlyPrice' => $amount,
|
||||
'nextBillingDate' => DateHelper::getFullDate(Carbon::createFromTimestamp($stripeSubscription->current_period_end)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get changelogs entries.
|
||||
*
|
||||
* @param int $limit
|
||||
* @return array
|
||||
*/
|
||||
public static function getChangelogEntries($limit = null)
|
||||
{
|
||||
$json = public_path('changelog.json');
|
||||
$changelogs = json_decode(file_get_contents($json), true)['entries'];
|
||||
|
||||
if ($limit) {
|
||||
$changelogs = array_slice($changelogs, 0, $limit);
|
||||
}
|
||||
|
||||
return $changelogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the instance has at least one account.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasAtLeastOneAccount(): bool
|
||||
{
|
||||
return DB::table('accounts')->count() > 0;
|
||||
}
|
||||
}
|
||||
29
app/Helpers/JournalHelper.php
Normal file
29
app/Helpers/JournalHelper.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Models\Journal\Day;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class JournalHelper
|
||||
{
|
||||
/**
|
||||
* Get the number of paid accounts in the instance.
|
||||
*
|
||||
* @param User $user
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasAlreadyRatedToday(User $user): bool
|
||||
{
|
||||
try {
|
||||
Day::where('account_id', $user->account_id)
|
||||
->where('date', now($user->timezone)->toDateString())
|
||||
->firstOrFail();
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
210
app/Helpers/LocaleHelper.php
Normal file
210
app/Helpers/LocaleHelper.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Matriphe\ISO639\ISO639;
|
||||
use function Safe\preg_match;
|
||||
use function Safe\preg_split;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use libphonenumber\PhoneNumberFormat;
|
||||
use libphonenumber\NumberParseException;
|
||||
|
||||
class LocaleHelper
|
||||
{
|
||||
private const LANG_SPLIT = '/(-|_)/';
|
||||
|
||||
/**
|
||||
* Get the current or default locale.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLocale()
|
||||
{
|
||||
if (Auth::check()) {
|
||||
$locale = Auth::user()->locale;
|
||||
} else {
|
||||
$locale = app('language.detector')->detect() ?: config('app.locale');
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current lang from locale.
|
||||
*
|
||||
* @return string lang, lowercase form.
|
||||
*/
|
||||
public static function getLang($locale = null)
|
||||
{
|
||||
if (is_null($locale)) {
|
||||
$locale = App::getLocale();
|
||||
}
|
||||
if (preg_match(self::LANG_SPLIT, $locale)) {
|
||||
$locale = preg_split(self::LANG_SPLIT, $locale, 2)[0];
|
||||
}
|
||||
|
||||
return mb_strtolower($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current country from locale.
|
||||
*
|
||||
* @return string country, uppercase form.
|
||||
*/
|
||||
public static function getCountry($locale = null)
|
||||
{
|
||||
$countryCode = self::extractCountry($locale);
|
||||
|
||||
if (is_null($countryCode)) {
|
||||
$country = CountriesHelper::getCountryFromLocale($locale);
|
||||
$countryCode = $country->getIsoAlpha2();
|
||||
}
|
||||
|
||||
return mb_strtoupper($countryCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the current country from locale, i.e. 'en-US' will return 'US'.
|
||||
* If no country is present in the locale, it will return null.
|
||||
*
|
||||
* @return string|null country, uppercase form.
|
||||
*/
|
||||
public static function extractCountry($locale = null): ?string
|
||||
{
|
||||
if (is_null($locale)) {
|
||||
$locale = App::getLocale();
|
||||
}
|
||||
if (preg_match(self::LANG_SPLIT, $locale)) {
|
||||
$locale = preg_split(self::LANG_SPLIT, $locale, 2)[1];
|
||||
|
||||
return mb_strtoupper($locale);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of avalaible languages.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function getLocaleList()
|
||||
{
|
||||
return collect(config('lang-detector.languages'))->map(function (string $lang): array {
|
||||
return [
|
||||
'lang' => $lang,
|
||||
'name' => self::getLocaleName($lang),
|
||||
'name-orig' => self::getLocaleName($lang, $lang),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of one language.
|
||||
*
|
||||
* @param string $lang
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
private static function getLocaleName($lang, $locale = null): string
|
||||
{
|
||||
$name = trans('settings.locale_'.$lang, [], $locale);
|
||||
if ($name == 'settings.locale_'.$lang) {
|
||||
// The name of the new language is not already set, even in english
|
||||
$name = $lang;
|
||||
}
|
||||
|
||||
return (string) Str::of($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the direction: left to right/right to left.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDirection()
|
||||
{
|
||||
$lang = self::getLang();
|
||||
switch ($lang) {
|
||||
// Source: https://meta.wikimedia.org/wiki/Template:List_of_language_names_ordered_by_code
|
||||
case 'ar':
|
||||
case 'arc':
|
||||
case 'dv':
|
||||
case 'fa':
|
||||
case 'ha':
|
||||
case 'he':
|
||||
case 'khw':
|
||||
case 'ks':
|
||||
case 'ku':
|
||||
case 'ps':
|
||||
case 'ur':
|
||||
case 'yi':
|
||||
return 'rtl';
|
||||
default:
|
||||
return 'ltr';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Association ISO-639-1 => ISO-639-2.
|
||||
*
|
||||
* @var array<string,string>
|
||||
*/
|
||||
private static $locales = [];
|
||||
|
||||
/**
|
||||
* Get ISO-639-2/t (three-letter codes) from ISO-639-1 (two-letters code).
|
||||
*
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
public static function getLocaleAlpha($locale)
|
||||
{
|
||||
if (Arr::has(static::$locales, $locale)) {
|
||||
return Arr::get(static::$locales, $locale);
|
||||
}
|
||||
$locale = mb_strtolower($locale);
|
||||
$languages = (new ISO639)->allLanguages();
|
||||
$lang = '';
|
||||
foreach ($languages as $l) {
|
||||
if ($l[0] == $locale) {
|
||||
$lang = $l[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
static::$locales[$locale] = $lang;
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format phone number by country.
|
||||
*
|
||||
* @param string $tel
|
||||
* @param string|null $iso
|
||||
* @param int $format
|
||||
* @return string
|
||||
*/
|
||||
public static function formatTelephoneNumberByISO(string $tel, $iso, int $format = PhoneNumberFormat::INTERNATIONAL): string
|
||||
{
|
||||
if (empty($iso)) {
|
||||
return $tel;
|
||||
}
|
||||
|
||||
try {
|
||||
$phoneUtil = PhoneNumberUtil::getInstance();
|
||||
|
||||
$phoneInstance = $phoneUtil->parse($tel, mb_strtoupper($iso));
|
||||
|
||||
$tel = $phoneUtil->format($phoneInstance, $format);
|
||||
} catch (NumberParseException $e) {
|
||||
// Do nothing if the number cannot be parsed successfully
|
||||
}
|
||||
|
||||
return $tel;
|
||||
}
|
||||
}
|
||||
26
app/Helpers/MailHelper.php
Normal file
26
app/Helpers/MailHelper.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\User\User;
|
||||
use App\Interfaces\MailNotification;
|
||||
|
||||
class MailHelper
|
||||
{
|
||||
/**
|
||||
* Get the HTML view that is rendered by the default markdown Laravel
|
||||
* notification class.
|
||||
* Yes, this is weird, but it's the only way to do it (as of Laravel 5.7).
|
||||
*
|
||||
* @param MailNotification $notification
|
||||
* @param User $user
|
||||
* @return string
|
||||
*/
|
||||
public static function emailView($notification, $user)
|
||||
{
|
||||
$message = $notification->toMail($user);
|
||||
$markdown = new \Illuminate\Mail\Markdown(view(), config('mail.markdown'));
|
||||
|
||||
return $markdown->render($message->markdown, $message->toArray());
|
||||
}
|
||||
}
|
||||
139
app/Helpers/MoneyHelper.php
Normal file
139
app/Helpers/MoneyHelper.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Money\Money;
|
||||
use App\Models\Settings\Currency;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Money\Currencies\ISOCurrencies;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Money\Currency as MoneyCurrency;
|
||||
use Money\Parser\DecimalMoneyParser;
|
||||
use Money\Formatter\IntlMoneyFormatter;
|
||||
use Money\Formatter\DecimalMoneyFormatter;
|
||||
|
||||
class MoneyHelper
|
||||
{
|
||||
/**
|
||||
* Format a monetary amount with currency symbol.
|
||||
* The value is formatted using current langage, as per the currency symbol.
|
||||
*
|
||||
* If the currency parameter is not passed, then the currency specified in
|
||||
* the users's settings will be used. If the currency setting is not
|
||||
* defined, then the amount will be returned without a currency symbol.
|
||||
*
|
||||
* @param int|null $amount Amount value in storable format (ex: 100 for 1,00€).
|
||||
* @param Currency|int|null $currency Currency of amount.
|
||||
* @return string Formatted amount for display with currency symbol (ex '1,235.87 €').
|
||||
*/
|
||||
public static function format($amount, $currency = null): string
|
||||
{
|
||||
if (is_null($amount)) {
|
||||
$amount = 0;
|
||||
}
|
||||
|
||||
$currency = self::getCurrency($currency);
|
||||
|
||||
if (! $currency || ! $currency->iso) {
|
||||
$numberFormatter = new \NumberFormatter(App::getLocale(), \NumberFormatter::DECIMAL);
|
||||
|
||||
return $numberFormatter->format($amount);
|
||||
}
|
||||
|
||||
$moneyCurrency = new MoneyCurrency($currency->iso);
|
||||
$money = new Money($amount, $moneyCurrency);
|
||||
$numberFormatter = new \NumberFormatter(App::getLocale(), \NumberFormatter::CURRENCY);
|
||||
$moneyFormatter = new IntlMoneyFormatter($numberFormatter, new ISOCurrencies());
|
||||
|
||||
return $moneyFormatter->format($money);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a monetary amount, without the currency.
|
||||
* The value is formatted using current langage.
|
||||
*
|
||||
* @param int|null $amount Amount value in storable format (ex: 100 for 1,00€).
|
||||
* @param Currency|int|null $currency
|
||||
* @return string Formatted amount for display without currency symbol (ex: '1234.50').
|
||||
*/
|
||||
public static function getValue($amount, $currency = null): string
|
||||
{
|
||||
$currency = self::getCurrency($currency);
|
||||
|
||||
if (! $currency || ! $currency->iso) {
|
||||
return (string) ($amount / 100);
|
||||
}
|
||||
|
||||
$moneyCurrency = new MoneyCurrency($currency->iso);
|
||||
$money = new Money($amount ?? 0, $moneyCurrency);
|
||||
$numberFormatter = new \NumberFormatter(App::getLocale(), \NumberFormatter::PATTERN_DECIMAL);
|
||||
$moneyFormatter = new IntlMoneyFormatter($numberFormatter, new ISOCurrencies());
|
||||
|
||||
return $moneyFormatter->format($money);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a monetary exchange value as storable integer.
|
||||
* Currency is used to know the precision of this currency.
|
||||
*
|
||||
* @param mixed|null $exchange Amount value in exchange format (ex: 1.00).
|
||||
* @param Currency|int|null $currency
|
||||
* @return int Amount as storable format (ex: 14500).
|
||||
*/
|
||||
public static function parseInput($exchange, $currency): int
|
||||
{
|
||||
$currency = self::getCurrency($currency);
|
||||
|
||||
if (! $currency || ! $currency->iso) {
|
||||
return (int) ((float) $exchange * 100);
|
||||
}
|
||||
|
||||
$moneyParser = new DecimalMoneyParser(new ISOCurrencies());
|
||||
$money = $moneyParser->parse((string) $exchange, new MoneyCurrency($currency->iso));
|
||||
|
||||
return (int) $money->getAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a monetary value as exchange value.
|
||||
* Exchange value is the amount to be entered in an input by a user,
|
||||
* using ordinary format.
|
||||
*
|
||||
* @param int|null $amount Amount value in storable format (ex: 100 for 1,00€).
|
||||
* @param Currency|int|null $currency
|
||||
* @return string Real value of amount in exchange format (ex: 1.24).
|
||||
*/
|
||||
public static function exchangeValue($amount, $currency): string
|
||||
{
|
||||
$currency = self::getCurrency($currency);
|
||||
|
||||
if (! $currency || ! $currency->iso) {
|
||||
return (string) ($amount / 100);
|
||||
}
|
||||
|
||||
$moneyCurrency = new MoneyCurrency($currency->iso);
|
||||
$money = new Money($amount ?? 0, $moneyCurrency);
|
||||
$moneyFormatter = new DecimalMoneyFormatter(new ISOCurrencies());
|
||||
|
||||
return $moneyFormatter->format($money);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get currency object.
|
||||
*
|
||||
* @param Currency|int|null $currency
|
||||
* @return Currency|null
|
||||
*/
|
||||
public static function getCurrency($currency): ?Currency
|
||||
{
|
||||
if (is_int($currency)) {
|
||||
$currency = Currency::find($currency);
|
||||
}
|
||||
|
||||
if (! $currency && Auth::check()) {
|
||||
$currency = Auth::user()->currency;
|
||||
}
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
104
app/Helpers/RequestHelper.php
Normal file
104
app/Helpers/RequestHelper.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Vectorface\Whip\Whip;
|
||||
use Illuminate\Support\Arr;
|
||||
use OK\Ipstack\Client as Ipstack;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Stevebauman\Location\Facades\Location;
|
||||
|
||||
class RequestHelper
|
||||
{
|
||||
/**
|
||||
* Get client ip.
|
||||
*
|
||||
* @return array|string|null
|
||||
*/
|
||||
public static function ip()
|
||||
{
|
||||
$whip = new Whip();
|
||||
$ip = $whip->getValidIpAddress();
|
||||
if ($ip === false) {
|
||||
$ip = Request::header('Cf-Connecting-Ip');
|
||||
if (is_null($ip)) {
|
||||
$ip = Request::ip();
|
||||
}
|
||||
}
|
||||
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client country.
|
||||
*
|
||||
* @param string $ip
|
||||
* @return string|null
|
||||
*/
|
||||
public static function country($ip): ?string
|
||||
{
|
||||
$position = Location::get($ip);
|
||||
|
||||
return $position ? $position->countryCode : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client country and currency.
|
||||
*
|
||||
* @param string|null $ip
|
||||
* @return array
|
||||
*/
|
||||
public static function infos($ip)
|
||||
{
|
||||
$ip = $ip ?? static::ip();
|
||||
|
||||
if (config('location.ipstack_apikey') != null) {
|
||||
$ipstack = new Ipstack(config('location.ipstack_apikey'));
|
||||
$position = $ipstack->get($ip, true);
|
||||
|
||||
if ($position !== null && Arr::get($position, 'country_code')) {
|
||||
return [
|
||||
'country' => Arr::get($position, 'country_code'),
|
||||
'currency' => Arr::get($position, 'currency.code'),
|
||||
'timezone' => Arr::get($position, 'time_zone.id'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (config('location.ipdata.token') != null) {
|
||||
try {
|
||||
$position = static::getIpData($ip);
|
||||
|
||||
return [
|
||||
'country' => Arr::get($position, 'country_code'),
|
||||
'currency' => Arr::get($position, 'currency.code'),
|
||||
'timezone' => Arr::get($position, 'time_zone.name'),
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'country' => static::country($ip),
|
||||
'currency' => null,
|
||||
'timezone' => null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data from ipdata.
|
||||
*
|
||||
* @param string $ip
|
||||
* @return array
|
||||
*/
|
||||
private static function getIpData(string $ip): array
|
||||
{
|
||||
$token = config('location.ipdata.token', '');
|
||||
|
||||
$url = "https://api.ipdata.co/{$ip}?api-key=".$token;
|
||||
|
||||
return Http::get($url)->throw()->json();
|
||||
}
|
||||
}
|
||||
53
app/Helpers/SearchHelper.php
Normal file
53
app/Helpers/SearchHelper.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use function Safe\preg_match;
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class SearchHelper
|
||||
{
|
||||
/**
|
||||
* Search contacts by the given query.
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $orderByColumn
|
||||
* @param string $orderByDirection
|
||||
* @param string|null $addressBookName
|
||||
* @return Builder
|
||||
*/
|
||||
public static function searchContacts(string $needle, string $orderByColumn, string $orderByDirection = 'asc', string $addressBookName = null): Builder
|
||||
{
|
||||
$accountId = Auth::user()->account_id;
|
||||
|
||||
// match against `field: string` queries
|
||||
if (preg_match('/(.{1,})[:](.{1,})/', $needle, $matches)) {
|
||||
$search_field = $matches[1];
|
||||
$search_term = $matches[2];
|
||||
|
||||
$field = ContactFieldType::where('account_id', $accountId)
|
||||
->where('name', 'LIKE', $search_field)
|
||||
->first();
|
||||
|
||||
$field_id = is_null($field) ? 0 : $field->id;
|
||||
|
||||
/** @var Builder */
|
||||
$builder = Contact::whereHas('contactFields', function ($query) use ($accountId, $field_id, $search_term) {
|
||||
$query->where([
|
||||
['account_id', $accountId],
|
||||
['data', 'like', "$search_term%"],
|
||||
['contact_field_type_id', $field_id],
|
||||
]);
|
||||
});
|
||||
|
||||
return $builder->addressBook($accountId, $addressBookName)
|
||||
->orderBy($orderByColumn, $orderByDirection);
|
||||
}
|
||||
|
||||
return Contact::search($needle, $accountId, $orderByColumn, $orderByDirection)
|
||||
->addressBook($accountId, $addressBookName);
|
||||
}
|
||||
}
|
||||
60
app/Helpers/StorageHelper.php
Normal file
60
app/Helpers/StorageHelper.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\Account\Account;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Filesystem\FilesystemAdapter;
|
||||
|
||||
class StorageHelper
|
||||
{
|
||||
/**
|
||||
* Get a filesystem instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Filesystem\FilesystemAdapter
|
||||
*/
|
||||
public static function disk($name = null): FilesystemAdapter
|
||||
{
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = Storage::disk($name);
|
||||
|
||||
return $disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the storage size of the account, in bytes.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return int
|
||||
*/
|
||||
public static function getAccountStorageSize(Account $account): int
|
||||
{
|
||||
$documentsSize = DB::table('documents')
|
||||
->where('account_id', $account->id)
|
||||
->sum('filesize');
|
||||
$photosSize = DB::table('photos')
|
||||
->where('account_id', $account->id)
|
||||
->sum('filesize');
|
||||
|
||||
return $documentsSize + $photosSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the account has the reached the maximum storage size.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasReachedAccountStorageLimit(Account $account): bool
|
||||
{
|
||||
if (! config('monica.requires_subscription')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentAccountSize = self::getAccountStorageSize($account);
|
||||
|
||||
return $currentAccountSize > (config('monica.max_storage_size') * 1000000);
|
||||
}
|
||||
}
|
||||
17
app/Helpers/StringHelper.php
Normal file
17
app/Helpers/StringHelper.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class StringHelper
|
||||
{
|
||||
/**
|
||||
* Test if string is null or whitespace.
|
||||
*
|
||||
* @param mixed $text
|
||||
* @return bool
|
||||
*/
|
||||
public static function isNullOrWhitespace($text): bool
|
||||
{
|
||||
return ctype_space($text) || $text === '' || is_null($text);
|
||||
}
|
||||
}
|
||||
126
app/Helpers/TimezoneHelper.php
Normal file
126
app/Helpers/TimezoneHelper.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use DateTimeZone;
|
||||
|
||||
class TimezoneHelper
|
||||
{
|
||||
/**
|
||||
* Get a list of all timezones.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getListOfTimezones(): array
|
||||
{
|
||||
$list = [];
|
||||
$timezones = DateTimeZone::listIdentifiers();
|
||||
|
||||
if ($timezones !== false) {
|
||||
foreach ($timezones as $timezone) {
|
||||
[$tz, $name] = self::formatTimezone($timezone);
|
||||
array_push($list, [
|
||||
'id' => $tz,
|
||||
'timezone' => $timezone,
|
||||
'name' => $name,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$collect = collect($list)
|
||||
->groupBy('id')
|
||||
->sortKeys();
|
||||
|
||||
$result = [];
|
||||
foreach ($collect as $item) {
|
||||
$values = $item->sortByCollator(function ($value) {
|
||||
return $value['name'];
|
||||
});
|
||||
foreach ($values as $val) {
|
||||
array_push($result, $val);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a timezone to be displayed (english only).
|
||||
*
|
||||
* @param string $timezone
|
||||
* @return array int value of the offset, string formatted timezone
|
||||
*/
|
||||
private static function formatTimezone($timezone): array
|
||||
{
|
||||
$dtimezone = new DateTimeZone($timezone);
|
||||
$time = now($timezone);
|
||||
|
||||
$offset = $time->format('P');
|
||||
|
||||
$loc = $dtimezone->getLocation();
|
||||
|
||||
if ($timezone == 'UTC') {
|
||||
$formatted = '(UTC) Universal Time Coordinated';
|
||||
} else {
|
||||
$name = $time->tzName;
|
||||
$i = strpos($name, '/');
|
||||
if ($i > 0) {
|
||||
$name = substr($name, $i + 1);
|
||||
}
|
||||
$name = str_replace(['St_', '/', '_'], ['St. ', ', ', ' '], $name);
|
||||
|
||||
if (empty($loc['comments'])) {
|
||||
$formatted = '(UTC '.$offset.') '.$name;
|
||||
} else {
|
||||
$formatted = '(UTC '.$offset.') '.$loc['comments'].' ('.$name.')';
|
||||
}
|
||||
}
|
||||
|
||||
$tz = str_replace(':', '', $offset);
|
||||
$tz = intval($tz);
|
||||
|
||||
return [$tz, $formatted];
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent timezone to convert deprecated timezone.
|
||||
*
|
||||
* @var array<string>
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
*/
|
||||
protected static $equivalentTimezone = [
|
||||
'Australia/Canberra' => 'Australia/Sydney',
|
||||
'Asia/Calcutta' => 'Asia/Kolkata',
|
||||
'Asia/Chongqing' => 'Asia/Shanghai',
|
||||
'Asia/Katmandu' => 'Asia/Kathmandu',
|
||||
'Asia/Rangoon' => 'Asia/Yangon',
|
||||
'Asia/Ulan_Bator' => 'Asia/Ulaanbaatar',
|
||||
'Canada/Atlantic' => 'America/Halifax',
|
||||
'Canada/Newfoundland' => 'America/St_Johns',
|
||||
'Canada/Saskatchewan' => 'America/Regina',
|
||||
'Etc/Greenwich' => 'UTC', // This is not an equivalent, but it the same zone
|
||||
'Pacific/Samoa' => 'Pacific/Pago_Pago',
|
||||
'US/Alaska' => 'America/Anchorage',
|
||||
'US/Arizona' => 'America/Phoenix',
|
||||
'US/Central' => 'America/Chicago',
|
||||
'US/East-Indiana' => 'America/Indiana/Indianapolis',
|
||||
'US/Eastern' => 'America/New_York',
|
||||
'US/Mountain' => 'America/Denver',
|
||||
];
|
||||
|
||||
/**
|
||||
* Adjust a timezone with equivalent name (remove deprecated).
|
||||
*
|
||||
* @param string $timezone
|
||||
* @return string
|
||||
*/
|
||||
public static function adjustEquivalentTimezone($timezone): string
|
||||
{
|
||||
if (array_key_exists($timezone, self::$equivalentTimezone)) {
|
||||
return self::$equivalentTimezone[$timezone];
|
||||
}
|
||||
|
||||
return $timezone;
|
||||
}
|
||||
}
|
||||
28
app/Helpers/VCardHelper.php
Normal file
28
app/Helpers/VCardHelper.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Sabre\VObject\Component\VCard;
|
||||
|
||||
class VCardHelper
|
||||
{
|
||||
/**
|
||||
* Get country model object from given VCard file.
|
||||
*
|
||||
* @param VCard $vCard
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getCountryISOFromSabreVCard(VCard $vCard): ?string
|
||||
{
|
||||
$vCardAddress = $vCard->ADR;
|
||||
|
||||
if (empty($vCardAddress)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$country = Arr::get($vCardAddress->getParts(), '6');
|
||||
|
||||
return empty($country) ? null : CountriesHelper::find($country);
|
||||
}
|
||||
}
|
||||
59
app/Helpers/WeatherHelper.php
Normal file
59
app/Helpers/WeatherHelper.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Jobs\GetGPSCoordinate;
|
||||
use App\Models\Account\Weather;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Jobs\GetWeatherInformation;
|
||||
use Illuminate\Support\Facades\Bus;
|
||||
|
||||
class WeatherHelper
|
||||
{
|
||||
/**
|
||||
* Get the weather for the given address, if it exists.
|
||||
*
|
||||
* @param Address|null $address
|
||||
* @return Weather|null
|
||||
*/
|
||||
public static function getWeatherForAddress($address): ?Weather
|
||||
{
|
||||
if (is_null($address)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$weather = $address->place->weathers()
|
||||
->orderBy('created_at', 'desc')
|
||||
->first();
|
||||
|
||||
// only get weather data if weather is either not existant or if is
|
||||
// more than 6h old
|
||||
if (is_null($weather) || ! $weather->created_at->between(now()->subHours(6), now())) {
|
||||
self::callWeatherAPI($address);
|
||||
}
|
||||
|
||||
return $weather;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the call to the weather service.
|
||||
*
|
||||
* @param Address $address
|
||||
*/
|
||||
private static function callWeatherAPI(Address $address): void
|
||||
{
|
||||
$jobs = [];
|
||||
|
||||
if (is_null($address->place->latitude)
|
||||
&& config('monica.enable_geolocation') && ! is_null(config('monica.location_iq_api_key'))) {
|
||||
$jobs[] = new GetGPSCoordinate($address->place);
|
||||
}
|
||||
|
||||
if (config('monica.enable_weather') && ! is_null(config('monica.weatherapi_key'))) {
|
||||
$jobs[] = new GetWeatherInformation($address->place);
|
||||
}
|
||||
|
||||
Bus::batch($jobs)
|
||||
->dispatch();
|
||||
}
|
||||
}
|
||||
17
app/Helpers/helpers.php
Normal file
17
app/Helpers/helpers.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use App\Helpers\LocaleHelper;
|
||||
|
||||
if (! function_exists('htmldir')) {
|
||||
/**
|
||||
* Get the direction: left to right/right to left.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see LocaleHelper::getDirection()
|
||||
*/
|
||||
function htmldir()
|
||||
{
|
||||
return LocaleHelper::getDirection();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user