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:
751
app/Models/Account/Account.php
Normal file
751
app/Models/Account/Account.php
Normal file
@@ -0,0 +1,751 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Models\User\User;
|
||||
use App\Models\Contact\Tag;
|
||||
use App\Models\Journal\Day;
|
||||
use App\Models\User\Module;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\Contact\Call;
|
||||
use App\Models\Contact\Debt;
|
||||
use App\Models\Contact\Gift;
|
||||
use App\Models\Contact\Note;
|
||||
use App\Models\Contact\Task;
|
||||
use App\Traits\Subscription;
|
||||
use App\Models\Journal\Entry;
|
||||
use App\Models\Contact\Gender;
|
||||
use App\Models\Contact\Address;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Contact\Message;
|
||||
use App\Models\Contact\Document;
|
||||
use App\Models\Contact\Reminder;
|
||||
use App\Models\Contact\LifeEvent;
|
||||
use App\Models\Instance\AuditLog;
|
||||
use App\Services\User\CreateUser;
|
||||
use App\Models\Contact\Occupation;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\Contact\ContactField;
|
||||
use App\Models\Contact\Conversation;
|
||||
use App\Models\Contact\ReminderRule;
|
||||
use App\Models\Instance\SpecialDate;
|
||||
use App\Models\Journal\JournalEntry;
|
||||
use App\Models\Contact\LifeEventType;
|
||||
use App\Models\Contact\ReminderOutbox;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\Contact\ContactFieldType;
|
||||
use App\Models\Contact\LifeEventCategory;
|
||||
use App\Models\Relationship\Relationship;
|
||||
use App\Models\Relationship\RelationshipType;
|
||||
use App\Models\Relationship\RelationshipTypeGroup;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use App\Services\Auth\Population\PopulateModulesTable;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use App\Services\Auth\Population\PopulateLifeEventsTable;
|
||||
use App\Services\Auth\Population\PopulateContactFieldTypesTable;
|
||||
|
||||
/**
|
||||
* @property int $reminders_count
|
||||
* @property int $notes_count
|
||||
* @property int $activities_count
|
||||
* @property int $gifts_count
|
||||
* @property int $tasks_count
|
||||
*/
|
||||
class Account extends Model
|
||||
{
|
||||
use Subscription, HasUuid;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'number_of_invitations_sent',
|
||||
'api_key',
|
||||
'default_time_reminder_is_sent',
|
||||
'default_gender_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'has_access_to_paid_version_for_free' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the activity records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contact records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function allContacts()
|
||||
{
|
||||
return $this->hasMany(Contact::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the addressBook's contacts.
|
||||
*
|
||||
* @param string|null $addressBookName
|
||||
* @return HasMany<Contact>
|
||||
*/
|
||||
public function contacts(string $addressBookName = null)
|
||||
{
|
||||
$contacts = $this->allContacts();
|
||||
|
||||
return $addressBookName
|
||||
? $contacts->addressBook($this->id, $addressBookName)
|
||||
: $contacts->addressBook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the invitations associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function invitations()
|
||||
{
|
||||
return $this->hasMany(Invitation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the debt records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function debts()
|
||||
{
|
||||
return $this->hasMany(Debt::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the gift records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function gifts()
|
||||
{
|
||||
return $this->hasMany(Gift::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the note records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function notes()
|
||||
{
|
||||
return $this->hasMany(Note::class)->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reminder records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function reminders()
|
||||
{
|
||||
return $this->hasMany(Reminder::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reminder outboxes records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function reminderOutboxes()
|
||||
{
|
||||
return $this->hasMany(ReminderOutbox::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the task records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function tasks()
|
||||
{
|
||||
return $this->hasMany(Task::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function relationships()
|
||||
{
|
||||
return $this->hasMany(Relationship::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity statistics record associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function activityStatistics()
|
||||
{
|
||||
return $this->hasMany(ActivityStatistic::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function activityTypes()
|
||||
{
|
||||
return $this->hasMany(ActivityType::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type category records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function activityTypeCategories()
|
||||
{
|
||||
return $this->hasMany(ActivityTypeCategory::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the task records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function entries()
|
||||
{
|
||||
return $this->hasMany(Entry::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import jobs records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function importjobs()
|
||||
{
|
||||
return $this->hasMany(ImportJob::class)->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import job reports records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function importJobReports()
|
||||
{
|
||||
return $this->hasMany(ImportJobReport::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tags records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function tags()
|
||||
{
|
||||
return $this->hasMany(Tag::class)->orderBy('name', 'asc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the calls records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function calls()
|
||||
{
|
||||
return $this->hasMany(Call::class)->orderBy('called_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Contact Field types records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function contactFieldTypes()
|
||||
{
|
||||
return $this->hasMany(ContactFieldType::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Contact Field records associated with the contact.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function contactFields()
|
||||
{
|
||||
return $this->hasMany(ContactField::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Journal Entries records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function journalEntries()
|
||||
{
|
||||
return $this->hasMany(JournalEntry::class)->orderBy('date', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the special dates records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function specialDates()
|
||||
{
|
||||
return $this->hasMany(SpecialDate::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Days records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function days()
|
||||
{
|
||||
return $this->hasMany(Day::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Genders records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function genders()
|
||||
{
|
||||
return $this->hasMany(Gender::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Reminder Rules records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function reminderRules()
|
||||
{
|
||||
return $this->hasMany(ReminderRule::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship types records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function relationshipTypes()
|
||||
{
|
||||
return $this->hasMany(RelationshipType::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship type groups records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function relationshipTypeGroups()
|
||||
{
|
||||
return $this->hasMany(RelationshipTypeGroup::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the modules records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function modules()
|
||||
{
|
||||
return $this->hasMany(Module::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Conversation records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function conversations()
|
||||
{
|
||||
return $this->hasMany(Conversation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Message records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function messages()
|
||||
{
|
||||
return $this->hasMany(Message::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Document records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function documents()
|
||||
{
|
||||
return $this->hasMany(Document::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Life Event Category records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function lifeEventCategories()
|
||||
{
|
||||
return $this->hasMany(LifeEventCategory::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Life Event Type records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function lifeEventTypes()
|
||||
{
|
||||
return $this->hasMany(LifeEventType::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Life Event records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function lifeEvents()
|
||||
{
|
||||
return $this->hasMany(LifeEvent::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Photos records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function photos()
|
||||
{
|
||||
return $this->hasMany(Photo::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Weather records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function weathers()
|
||||
{
|
||||
return $this->hasMany(Weather::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Places records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function places()
|
||||
{
|
||||
return $this->hasMany(Place::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Addresses records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function addresses()
|
||||
{
|
||||
return $this->hasMany(Address::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Address Books records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function addressBooks()
|
||||
{
|
||||
return $this->hasMany(AddressBook::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Address Book Subscriptions records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function addressBookSubscriptions()
|
||||
{
|
||||
return $this->hasMany(AddressBookSubscription::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Company records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function companies()
|
||||
{
|
||||
return $this->hasMany(Company::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Occupation records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function occupations()
|
||||
{
|
||||
return $this->hasMany(Occupation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* * Get the Audit log records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function auditLogs()
|
||||
{
|
||||
return $this->hasMany(AuditLog::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the Activity Type table right after an account is
|
||||
* created.
|
||||
*/
|
||||
public function populateActivityTypeTable()
|
||||
{
|
||||
$defaultActivityTypeCategories = DB::table('default_activity_type_categories')->get();
|
||||
|
||||
foreach ($defaultActivityTypeCategories as $defaultActivityTypeCategory) {
|
||||
$activityTypeCategoryId = DB::table('activity_type_categories')->insertGetId([
|
||||
'account_id' => $this->id,
|
||||
'translation_key' => $defaultActivityTypeCategory->translation_key,
|
||||
]);
|
||||
|
||||
$defaultActivityTypes = DB::table('default_activity_types')
|
||||
->where('default_activity_type_category_id', $defaultActivityTypeCategory->id)
|
||||
->get();
|
||||
|
||||
foreach ($defaultActivityTypes as $defaultActivityType) {
|
||||
DB::table('activity_types')->insert([
|
||||
'account_id' => $this->id,
|
||||
'activity_type_category_id' => $activityTypeCategoryId,
|
||||
'translation_key' => $defaultActivityType->translation_key,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the default genders in a new account.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populateDefaultGendersTable()
|
||||
{
|
||||
Gender::create(['type' => Gender::MALE, 'name' => trans('app.gender_male'), 'account_id' => $this->id]);
|
||||
Gender::create(['type' => Gender::FEMALE, 'name' => trans('app.gender_female'), 'account_id' => $this->id]);
|
||||
Gender::create(['type' => Gender::OTHER, 'name' => trans('app.gender_none'), 'account_id' => $this->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the default reminder rules in a new account.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populateDefaultReminderRulesTable()
|
||||
{
|
||||
ReminderRule::create(['number_of_days_before' => 7, 'account_id' => $this->id, 'active' => 1]);
|
||||
ReminderRule::create(['number_of_days_before' => 30, 'account_id' => $this->id, 'active' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the default relationship types in a new account.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populateRelationshipTypeGroupsTable($ignoreTableAlreadyMigrated = false)
|
||||
{
|
||||
$defaultRelationshipTypeGroups = DB::table('default_relationship_type_groups')->get();
|
||||
foreach ($defaultRelationshipTypeGroups as $defaultRelationshipTypeGroup) {
|
||||
if (! $ignoreTableAlreadyMigrated || $defaultRelationshipTypeGroup->migrated == 0) {
|
||||
DB::table('relationship_type_groups')->insert([
|
||||
'account_id' => $this->id,
|
||||
'name' => $defaultRelationshipTypeGroup->name,
|
||||
'delible' => $defaultRelationshipTypeGroup->delible,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the relationship types table based on the default ones.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function populateRelationshipTypesTable($migrateOnlyNewTypes = false)
|
||||
{
|
||||
if ($migrateOnlyNewTypes) {
|
||||
$defaultRelationshipTypes = DB::table('default_relationship_types')->where('migrated', 0)->get();
|
||||
} else {
|
||||
$defaultRelationshipTypes = DB::table('default_relationship_types')->get();
|
||||
}
|
||||
|
||||
foreach ($defaultRelationshipTypes as $defaultRelationshipType) {
|
||||
$defaultRelationshipTypeGroup = DB::table('default_relationship_type_groups')
|
||||
->where('id', $defaultRelationshipType->relationship_type_group_id)
|
||||
->first();
|
||||
|
||||
$relationshipTypeGroup = $this->getRelationshipTypeGroupByType($defaultRelationshipTypeGroup->name);
|
||||
|
||||
if ($relationshipTypeGroup) {
|
||||
RelationshipType::create([
|
||||
'account_id' => $this->id,
|
||||
'name' => $defaultRelationshipType->name,
|
||||
'name_reverse_relationship' => $defaultRelationshipType->name_reverse_relationship,
|
||||
'relationship_type_group_id' => $relationshipTypeGroup->id,
|
||||
'delible' => $defaultRelationshipType->delible,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new account and associate a new User.
|
||||
*
|
||||
* @param string $first_name
|
||||
* @param string $last_name
|
||||
* @param string $email
|
||||
* @param string $password
|
||||
* @param string $ipAddress
|
||||
* @return self
|
||||
*/
|
||||
public static function createDefault($first_name, $last_name, $email, $password, $ipAddress = null, $lang = null)
|
||||
{
|
||||
// create new account
|
||||
$account = new self;
|
||||
$account->api_key = Str::random(30);
|
||||
$account->created_at = now();
|
||||
$account->save();
|
||||
|
||||
try {
|
||||
// create the first user for this account
|
||||
$user = app(CreateUser::class)->execute([
|
||||
'account_id' => $account->id,
|
||||
'first_name' => $first_name,
|
||||
'last_name' => $last_name,
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'locale' => $lang,
|
||||
'ip_address' => $ipAddress,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$account->delete();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$account->populateDefaultFields();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates all the default column that should be there when a new account
|
||||
* is created or reset.
|
||||
*/
|
||||
public function populateDefaultFields()
|
||||
{
|
||||
app(PopulateContactFieldTypesTable::class)->execute([
|
||||
'account_id' => $this->id,
|
||||
'migrate_existing_data' => true,
|
||||
]);
|
||||
|
||||
$this->populateDefaultGendersTable();
|
||||
$this->populateDefaultReminderRulesTable();
|
||||
$this->populateRelationshipTypeGroupsTable();
|
||||
$this->populateRelationshipTypesTable();
|
||||
$this->populateActivityTypeTable();
|
||||
|
||||
app(PopulateLifeEventsTable::class)->execute([
|
||||
'account_id' => $this->id,
|
||||
'migrate_existing_data' => true,
|
||||
]);
|
||||
|
||||
app(PopulateModulesTable::class)->execute([
|
||||
'account_id' => $this->id,
|
||||
'migrate_existing_data' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RelationshipType object matching the given type.
|
||||
*
|
||||
* @param string $relationshipTypeName
|
||||
* @return RelationshipType|null
|
||||
*/
|
||||
public function getRelationshipTypeByType(string $relationshipTypeName)
|
||||
{
|
||||
return $this->relationshipTypes->where('name', $relationshipTypeName)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RelationshipType object matching the given type.
|
||||
*
|
||||
* @param string $relationshipTypeGroupName
|
||||
* @return RelationshipTypeGroup|null
|
||||
*/
|
||||
public function getRelationshipTypeGroupByType(string $relationshipTypeGroupName)
|
||||
{
|
||||
return $this->relationshipTypeGroups->where('name', $relationshipTypeGroupName)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first available locale in an account. This gets the first user
|
||||
* in the account and reads his locale.
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function getFirstLocale(): ?string
|
||||
{
|
||||
try {
|
||||
$user = $this->users()->firstOrFail();
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $user->locale;
|
||||
}
|
||||
}
|
||||
160
app/Models/Account/Activity.php
Normal file
160
app/Models/Account/Activity.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Helpers\DateHelper;
|
||||
use App\Traits\Journalable;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\Journal\JournalEntry;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\Instance\Emotion\Emotion;
|
||||
use App\Interfaces\IsJournalableInterface;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use App\Http\Resources\Contact\ContactShort as ContactShortResource;
|
||||
|
||||
/**
|
||||
* @property int|null $activity_type_id
|
||||
*/
|
||||
class Activity extends Model implements IsJournalableInterface
|
||||
{
|
||||
use Journalable, HasUuid;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'activities';
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $dates = ['happened_at'];
|
||||
|
||||
/**
|
||||
* The relations to eager load on every query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $with = [
|
||||
'account',
|
||||
'type',
|
||||
'contacts',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the activity.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contact record associated with the activity.
|
||||
*
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function contacts()
|
||||
{
|
||||
return $this->belongsToMany(Contact::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type record associated with the activity.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function type()
|
||||
{
|
||||
return $this->belongsTo(ActivityType::class, 'activity_type_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the activities journal entries.
|
||||
*/
|
||||
public function journalEntries()
|
||||
{
|
||||
return $this->morphMany(JournalEntry::class, 'journalable');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the emotion records associated with the activity.
|
||||
*
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function emotions()
|
||||
{
|
||||
return $this->belongsToMany(Emotion::class, 'emotion_activity', 'activity_id', 'emotion_id')
|
||||
->withPivot('account_id')
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the summary for this activity.
|
||||
*
|
||||
* @return string or null
|
||||
*/
|
||||
public function getSummary()
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key of the title of the activity.
|
||||
*
|
||||
* @return string or null
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->type ? $this->type->translation_key : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the contacts this activity is associated with.
|
||||
*/
|
||||
public function getContactsForAPI()
|
||||
{
|
||||
$attendees = $this->contacts->filter(function ($contact) {
|
||||
// This should not be possible!
|
||||
return $contact->account_id === $this->account_id;
|
||||
});
|
||||
|
||||
return ContactShortResource::collection($attendees);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the information about the activity for the journal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getInfoForJournalEntry()
|
||||
{
|
||||
return [
|
||||
'type' => 'activity',
|
||||
'id' => $this->id,
|
||||
'activity_type' => (! is_null($this->type) ? $this->type->name : null),
|
||||
'summary' => $this->summary,
|
||||
'description' => $this->description,
|
||||
'day' => $this->happened_at->day,
|
||||
'day_name' => mb_convert_case(DateHelper::getShortDay($this->happened_at), MB_CASE_TITLE, 'UTF-8'),
|
||||
'month' => $this->happened_at->month,
|
||||
'month_name' => mb_convert_case(DateHelper::getShortMonth($this->happened_at), MB_CASE_UPPER, 'UTF-8'),
|
||||
'year' => $this->happened_at->year,
|
||||
'attendees' => $this->getContactsForAPI(),
|
||||
];
|
||||
}
|
||||
}
|
||||
39
app/Models/Account/ActivityStatistic.php
Normal file
39
app/Models/Account/ActivityStatistic.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Models\Contact\Contact;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ActivityStatistic extends Model
|
||||
{
|
||||
protected $table = 'activity_statistics';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'account_id',
|
||||
'contact_id',
|
||||
'year',
|
||||
'count',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the activity statistic.
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contact record associated with the activity statistic.
|
||||
*/
|
||||
public function contact()
|
||||
{
|
||||
return $this->belongsTo(Contact::class);
|
||||
}
|
||||
}
|
||||
82
app/Models/Account/ActivityType.php
Normal file
82
app/Models/Account/ActivityType.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class ActivityType extends Model
|
||||
{
|
||||
use HasUuid;
|
||||
|
||||
protected $table = 'activity_types';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'activity_type_category_id',
|
||||
'account_id',
|
||||
'translation_key',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the activity type.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type category record associated with the activity types.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(ActivityTypeCategory::class, 'activity_type_category_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity records associated with the activity type.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type's attribute.
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
if ($this->translation_key && ! $value) {
|
||||
return trans('people.activity_type_'.$this->translation_key);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all associated activities with this category type.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetAssociationWithActivities()
|
||||
{
|
||||
foreach ($this->activities as $activity) {
|
||||
$activity->activity_type_id = null;
|
||||
$activity->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
63
app/Models/Account/ActivityTypeCategory.php
Normal file
63
app/Models/Account/ActivityTypeCategory.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class ActivityTypeCategory extends Model
|
||||
{
|
||||
use HasUuid;
|
||||
|
||||
protected $table = 'activity_type_categories';
|
||||
|
||||
protected $appends = ['name'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'translation_key',
|
||||
'account_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the activity type group.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type records associated with the category.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function activityTypes()
|
||||
{
|
||||
return $this->hasMany(ActivityType::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity type category's attribute.
|
||||
*
|
||||
* @return string
|
||||
* @psalm-suppress InvalidReturnStatement
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
if ($this->translation_key && ! $value) {
|
||||
return trans('people.activity_type_category_'.$this->translation_key);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
75
app/Models/Account/AddressBook.php
Normal file
75
app/Models/Account/AddressBook.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Models\User\User;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class AddressBook extends Model
|
||||
{
|
||||
use HasFactory, HasUuid;
|
||||
|
||||
protected $table = 'addressbooks';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'account_id',
|
||||
'user_id',
|
||||
'name',
|
||||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the address book.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user record associated with the address book.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all contacts for this address book.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function contacts()
|
||||
{
|
||||
return $this->hasMany(Contact::class);
|
||||
}
|
||||
}
|
||||
175
app/Models/Account/AddressBookSubscription.php
Normal file
175
app/Models/Account/AddressBookSubscription.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Models\User\User;
|
||||
use function safe\json_decode;
|
||||
use function safe\json_encode;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Services\DavClient\Utils\Dav\DavClient;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class AddressBookSubscription extends Model
|
||||
{
|
||||
use HasFactory, HasUuid;
|
||||
|
||||
protected $table = 'addressbook_subscriptions';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'account_id',
|
||||
'user_id',
|
||||
'address_book_id',
|
||||
'name',
|
||||
'uri',
|
||||
'capabilities',
|
||||
'username',
|
||||
'password',
|
||||
'readonly',
|
||||
'syncToken',
|
||||
'localSyncToken',
|
||||
'frequency',
|
||||
'last_synchronized_at',
|
||||
'active',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $dates = [
|
||||
'last_synchronized_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'readonly' => 'boolean',
|
||||
'active' => 'boolean',
|
||||
'localSyncToken' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Eager load account with every contact.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $with = [
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the subscription.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user record associated with the subscription.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the addressbook record associated with the subscription.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function addressBook()
|
||||
{
|
||||
return $this->belongsTo(AddressBook::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get capabilities.
|
||||
*
|
||||
* @param string $value
|
||||
* @return array
|
||||
*/
|
||||
public function getCapabilitiesAttribute($value)
|
||||
{
|
||||
return json_decode($value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set capabilities.
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function setCapabilitiesAttribute($value)
|
||||
{
|
||||
$this->attributes['capabilities'] = json_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get password.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function getPasswordAttribute($value)
|
||||
{
|
||||
return decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set password.
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function setPasswordAttribute($value)
|
||||
{
|
||||
$this->attributes['password'] = encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope a query to only include active subscriptions.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('active', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new client.
|
||||
*
|
||||
* @return DavClient
|
||||
*/
|
||||
public function getClient(): DavClient
|
||||
{
|
||||
return app(DavClient::class)
|
||||
->setBaseUri($this->uri)
|
||||
->setCredentials($this->username, $this->password);
|
||||
}
|
||||
}
|
||||
21
app/Models/Account/ApiUsage.php
Normal file
21
app/Models/Account/ApiUsage.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ApiUsage extends Model
|
||||
{
|
||||
protected $table = 'api_usage';
|
||||
|
||||
/**
|
||||
* Log a request made through the API.
|
||||
*/
|
||||
public function log(\Illuminate\Http\Request $request)
|
||||
{
|
||||
$this->url = $request->fullUrl();
|
||||
$this->method = $request->getMethod();
|
||||
$this->client_ip = $request->getClientIp();
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
53
app/Models/Account/Company.php
Normal file
53
app/Models/Account/Company.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Models\Contact\Occupation;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Company extends Model
|
||||
{
|
||||
protected $table = 'companies';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'weather_json',
|
||||
'account_id',
|
||||
'name',
|
||||
'website',
|
||||
'number_of_employees',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the company.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Occupation records associated with the contact.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function occupations()
|
||||
{
|
||||
return $this->hasMany(Occupation::class);
|
||||
}
|
||||
}
|
||||
114
app/Models/Account/ExportJob.php
Normal file
114
app/Models/Account/ExportJob.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Models\User\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Notifications\ExportAccountDone;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class ExportJob extends Model
|
||||
{
|
||||
use HasUuid, HasFactory;
|
||||
|
||||
public const EXPORT_TODO = 'todo';
|
||||
public const EXPORT_DOING = 'doing';
|
||||
public const EXPORT_DONE = 'done';
|
||||
public const EXPORT_FAILED = 'failed';
|
||||
|
||||
/**
|
||||
* Export as SQL format.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const SQL = 'sql';
|
||||
|
||||
/**
|
||||
* Export as JSON format.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const JSON = 'json';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'uuid',
|
||||
'account_id',
|
||||
'user_id',
|
||||
'type',
|
||||
'status',
|
||||
'filesystem',
|
||||
'filename',
|
||||
'started_at',
|
||||
'ended_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $dates = [
|
||||
'started_at',
|
||||
'ended_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the import job.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user record associated with the import job.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the export job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function start(): void
|
||||
{
|
||||
$this->status = self::EXPORT_DOING;
|
||||
$this->started_at = now();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* End the export job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function end(): void
|
||||
{
|
||||
$this->status = self::EXPORT_DONE;
|
||||
$this->ended_at = now();
|
||||
$this->save();
|
||||
|
||||
$this->user->notify(new ExportAccountDone($this));
|
||||
}
|
||||
}
|
||||
311
app/Models/Account/ImportJob.php
Normal file
311
app/Models/Account/ImportJob.php
Normal file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Models\User\User;
|
||||
use Sabre\VObject\Reader;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Helpers\AccountHelper;
|
||||
use Sabre\VObject\Component\VCard;
|
||||
use App\Services\VCard\ImportVCard;
|
||||
use League\Flysystem\UnableToReadFile;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use League\Flysystem\UnableToDeleteFile;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Sabre\VObject\Splitter\VCard as VCardReader;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property Account $account
|
||||
* @property int $account_id
|
||||
* @property User $user
|
||||
* @property int $user_id
|
||||
* @property bool $failed
|
||||
* @property string $failed_reason
|
||||
* @property string $filename
|
||||
* @property int $contacts_found
|
||||
* @property int $contacts_skipped
|
||||
* @property int $contacts_imported
|
||||
* @property \Illuminate\Support\Carbon|null $started_at
|
||||
* @property \Illuminate\Support\Carbon|null $ended_at
|
||||
*/
|
||||
class ImportJob extends Model
|
||||
{
|
||||
const VCARD_SKIPPED = true;
|
||||
const VCARD_IMPORTED = false;
|
||||
|
||||
protected $table = 'import_jobs';
|
||||
|
||||
/**
|
||||
* The physical vCard file on disk.
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
public $physicalFile;
|
||||
|
||||
/**
|
||||
* All individual entries in the vCard file.
|
||||
*
|
||||
* @var VCardReader
|
||||
*/
|
||||
public $entries = null;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $dates = ['started_at', 'ended_at'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the import job.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user record associated with the import job.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import jobs reports records associated with the account.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function importJobReports()
|
||||
{
|
||||
return $this->hasMany(ImportJobReport::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an import job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process($behaviour = ImportVCard::BEHAVIOUR_ADD)
|
||||
{
|
||||
$this->initJob();
|
||||
|
||||
if (! $this->failed && $this->getPhysicalFile()) {
|
||||
$this->getEntries();
|
||||
|
||||
$this->processEntries($behaviour);
|
||||
}
|
||||
|
||||
$this->deletePhysicalFile();
|
||||
|
||||
if (! $this->failed) {
|
||||
$this->endJob();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform preliminary steps to start the import job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function initJob(): void
|
||||
{
|
||||
if (AccountHelper::hasLimitations($this->account)) {
|
||||
$this->fail(trans('auth.not_authorized'));
|
||||
}
|
||||
|
||||
$this->started_at = now();
|
||||
$this->contacts_imported = 0;
|
||||
$this->contacts_skipped = 0;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the steps to finalize the import job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function endJob(): void
|
||||
{
|
||||
$this->ended_at = now();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the import job as failed.
|
||||
*
|
||||
* @param string $reason
|
||||
* @return void
|
||||
*/
|
||||
private function fail(string $reason): void
|
||||
{
|
||||
$this->failed = true;
|
||||
if (! $this->failed_reason) {
|
||||
$this->failed_reason = $reason;
|
||||
}
|
||||
$this->endJob();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the physical file (the vCard file).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function getPhysicalFile(): bool
|
||||
{
|
||||
try {
|
||||
$this->physicalFile = Storage::disk(config('filesystems.default'))->readStream($this->filename);
|
||||
} catch (UnableToReadFile $exception) {
|
||||
$this->fail(trans('settings.import_vcard_file_not_found'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the physical file from the disk.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function deletePhysicalFile(): bool
|
||||
{
|
||||
try {
|
||||
if (Storage::disk(config('filesystems.default'))->delete($this->filename) === false) {
|
||||
$this->fail(trans('settings.import_vcard_file_not_found'));
|
||||
|
||||
return false;
|
||||
}
|
||||
} catch (UnableToDeleteFile $exception) {
|
||||
$this->fail(trans('settings.import_vcard_file_not_found'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of matches in the vCard file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function getEntries()
|
||||
{
|
||||
if ($this->physicalFile !== null) {
|
||||
$this->entries = new VCardReader($this->physicalFile, Reader::OPTION_FORGIVING + Reader::OPTION_IGNORE_INVALID_LINES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all entries contained in the vCard file.
|
||||
*
|
||||
* @param string $behaviour
|
||||
* @return void
|
||||
*/
|
||||
private function processEntries($behaviour = ImportVCard::BEHAVIOUR_ADD)
|
||||
{
|
||||
while (true) {
|
||||
try {
|
||||
/** @var VCard|null */
|
||||
$entry = $this->entries !== null ? $this->entries->getNext() : null;
|
||||
if (! $entry) {
|
||||
// file end
|
||||
break;
|
||||
}
|
||||
$this->contacts_found++;
|
||||
} catch (\Throwable $e) {
|
||||
$this->skipEntry('?', (string) $e);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->processSingleEntry($entry, $behaviour);
|
||||
}
|
||||
|
||||
if ($this->contacts_found == 0) {
|
||||
$this->fail(trans('settings.import_vcard_file_no_entries'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single vCard entry.
|
||||
*
|
||||
* @param string|VCard $entry
|
||||
* @param string $behaviour
|
||||
* @return void
|
||||
*/
|
||||
private function processSingleEntry($entry, $behaviour = ImportVCard::BEHAVIOUR_ADD): void
|
||||
{
|
||||
try {
|
||||
$result = app(ImportVCard::class)->execute([
|
||||
'account_id' => $this->account_id,
|
||||
'user_id' => $this->user_id,
|
||||
'entry' => $entry,
|
||||
'behaviour' => $behaviour,
|
||||
]);
|
||||
} catch (ValidationException $e) {
|
||||
$this->fail(implode(',', $e->validator->errors()->all()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Arr::has($result, 'error') && ! empty($result['error'])) {
|
||||
$this->skipEntry($result['name'], $result['reason']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->contacts_imported++;
|
||||
$this->fileImportJobReport($result['name'], self::VCARD_IMPORTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the current entry.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $reason
|
||||
* @return void
|
||||
*/
|
||||
private function skipEntry($name, $reason = null): void
|
||||
{
|
||||
$this->fileImportJobReport($name, self::VCARD_SKIPPED, $reason);
|
||||
$this->contacts_skipped++;
|
||||
}
|
||||
|
||||
/**
|
||||
* File an import job report for the current entry.
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $status
|
||||
* @param string $reason
|
||||
* @return void
|
||||
*/
|
||||
private function fileImportJobReport($name, $status, $reason = null): void
|
||||
{
|
||||
$importJobReport = new ImportJobReport;
|
||||
$importJobReport->account_id = $this->account_id;
|
||||
$importJobReport->user_id = $this->user_id;
|
||||
$importJobReport->import_job_id = $this->id;
|
||||
$importJobReport->contact_information = trim($name);
|
||||
$importJobReport->skipped = $status;
|
||||
$importJobReport->skip_reason = $reason;
|
||||
$importJobReport->save();
|
||||
}
|
||||
}
|
||||
59
app/Models/Account/ImportJobReport.php
Normal file
59
app/Models/Account/ImportJobReport.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Models\User\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property Account $account
|
||||
* @property int $account_id
|
||||
* @property User $user
|
||||
* @property int $user_id
|
||||
* @property int $import_job_id
|
||||
* @property string $contact_information
|
||||
* @property bool $skipped
|
||||
* @property string $skip_reason
|
||||
*/
|
||||
class ImportJobReport extends Model
|
||||
{
|
||||
protected $table = 'import_job_reports';
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the import job report.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user record associated with the import job report.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import job record associated with the gift.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function importJob()
|
||||
{
|
||||
return $this->belongsTo(ImportJob::class);
|
||||
}
|
||||
}
|
||||
45
app/Models/Account/Invitation.php
Normal file
45
app/Models/Account/Invitation.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Models\User\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* @property Account $account
|
||||
* @property User $invitedBy
|
||||
* @property string $invitation_key
|
||||
*/
|
||||
class Invitation extends Model
|
||||
{
|
||||
use Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the invitation.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contact record associated with the task.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function invitedBy()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'invited_by_user_id');
|
||||
}
|
||||
}
|
||||
110
app/Models/Account/Photo.php
Normal file
110
app/Models/Account/Photo.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use App\Traits\HasUuid;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Intervention\Image\Facades\Image;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
|
||||
class Photo extends Model
|
||||
{
|
||||
use HasUuid;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'photos';
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the photo.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contacts record associated with the photo.
|
||||
*
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function contacts()
|
||||
{
|
||||
return $this->belongsToMany(Contact::class)->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first contact record associated with the photo.
|
||||
*
|
||||
* @return Contact
|
||||
*/
|
||||
public function contact()
|
||||
{
|
||||
return $this->contacts->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full path of the photo.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
if (config('filesystems.default_visibility') === 'public') {
|
||||
return asset(StorageHelper::disk(config('filesystems.default'))->url($this->new_filename));
|
||||
}
|
||||
|
||||
return route('storage', ['file' => $this->new_filename]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data-url format of the photo.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function dataUrl(): ?string
|
||||
{
|
||||
try {
|
||||
$url = $this->new_filename;
|
||||
$file = StorageHelper::disk(config('filesystems.default'))->get($url);
|
||||
|
||||
return (string) Image::make($file)->encode('data-url');
|
||||
} catch (FileNotFoundException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the model from the database.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
Storage::disk(config('filesystems.default'))
|
||||
->delete($this->new_filename);
|
||||
} catch (FileNotFoundException $e) {
|
||||
// continue
|
||||
}
|
||||
|
||||
return parent::delete();
|
||||
}
|
||||
}
|
||||
126
app/Models/Account/Place.php
Normal file
126
app/Models/Account/Place.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Helpers\CountriesHelper;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* A Place is not the same as an address.
|
||||
* An Address in Monica is a way of contacting the contact. An Address is linked
|
||||
* to a Place. But Places can exist without the Address object.
|
||||
* Places will be linked to activities, for instance.
|
||||
*/
|
||||
class Place extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'places';
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the place.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Weather record associated with the place.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function weathers()
|
||||
{
|
||||
return $this->hasMany(Weather::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address as a sentence.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAddressAsString(): ?string
|
||||
{
|
||||
$address = '';
|
||||
|
||||
if (! is_null($this->street)) {
|
||||
$address = $this->street;
|
||||
}
|
||||
|
||||
if (! is_null($this->city)) {
|
||||
$address .= ' '.$this->city;
|
||||
}
|
||||
|
||||
if (! is_null($this->province)) {
|
||||
$address .= ' '.$this->province;
|
||||
}
|
||||
|
||||
if (! is_null($this->postal_code)) {
|
||||
$address .= ' '.$this->postal_code;
|
||||
}
|
||||
|
||||
if (! is_null($this->country)) {
|
||||
$address .= ' '.$this->getCountryName();
|
||||
}
|
||||
|
||||
if (empty($address)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// trim extra whitespaces inside the address
|
||||
return Str::of($address)->replaceMatches('/\s+/', ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the country of the place.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCountryName(): ?string
|
||||
{
|
||||
if ($this->country) {
|
||||
return CountriesHelper::get($this->country);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an URL for Google Maps for the place.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGoogleMapAddress()
|
||||
{
|
||||
$place = $this->getAddressAsString();
|
||||
$place = urlencode($place);
|
||||
|
||||
return "https://www.google.com/maps/place/{$place}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Google Maps url for the latitude/longitude.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGoogleMapsAddressWithLatitude()
|
||||
{
|
||||
return 'http://maps.google.com/maps?q='.$this->latitude.','.+$this->longitude;
|
||||
}
|
||||
}
|
||||
245
app/Models/Account/Weather.php
Normal file
245
app/Models/Account/Weather.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Weather extends Model
|
||||
{
|
||||
protected $table = 'weather';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'account_id',
|
||||
'place_id',
|
||||
'weather_json',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'weather_json' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the weather data.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the place record associated with the weather data.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function place()
|
||||
{
|
||||
return $this->belongsTo(Place::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the weather code.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSummaryCodeAttribute(): ?string
|
||||
{
|
||||
$json = $this->weather_json;
|
||||
|
||||
// currently.icon: Darksky version
|
||||
if (! ($icon = Arr::get($json, 'currently.icon'))) {
|
||||
if (($text = Arr::get($json, 'current.condition.text')) === 'Partly cloudy') {
|
||||
$icon = ((bool) Arr::get($json, 'current.is_day')) ? 'partly-cloudy-day' : 'partly-cloudy-night';
|
||||
} else {
|
||||
$icon = (string) Str::of($text)->lower()->replace(' ', '-');
|
||||
}
|
||||
}
|
||||
|
||||
return $icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the weather summary.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSummaryAttribute(): ?string
|
||||
{
|
||||
$summary_code = $this->summary_code;
|
||||
if (empty($summary_code)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (string) Str::of(trans('app.weather_'.$summary_code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the weather location.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getLocationAttribute(): ?string
|
||||
{
|
||||
return Arr::get($this->weather_json, 'location.name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the weather update date.
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getDateAttribute(): ?Carbon
|
||||
{
|
||||
if (($timestamp = Arr::get($this->weather_json, 'current.last_updated_epoch')) !== null) {
|
||||
return Carbon::createFromTimestamp($timestamp);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the weather icon.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getEmojiAttribute(): string
|
||||
{
|
||||
switch ($this->summary_code) {
|
||||
case 'sunny':
|
||||
case 'clear-day':
|
||||
$string = '🌞';
|
||||
break;
|
||||
case 'clear':
|
||||
case 'clear-night':
|
||||
$string = '🌃';
|
||||
break;
|
||||
case 'light-drizzle':
|
||||
case 'patchy-light-drizzle':
|
||||
case 'patchy-light-rain':
|
||||
case 'light-rain':
|
||||
case 'moderate-rain-at-times':
|
||||
case 'moderate-rain':
|
||||
case 'patchy-rain-possible':
|
||||
case 'heavy-rain-at-times':
|
||||
case 'heavy-rain':
|
||||
case 'light-freezing-rain':
|
||||
case 'moderate-or-heavy-freezing-rain':
|
||||
case 'light-sleet':
|
||||
case 'moderate-or-heavy-rain-shower':
|
||||
case 'light-rain-shower':
|
||||
case 'torrential-rain-shower':
|
||||
case 'rain':
|
||||
$string = '🌧️';
|
||||
break;
|
||||
case 'snow':
|
||||
case 'blowing-snow':
|
||||
case 'patchy-light-snow':
|
||||
case 'light-snow':
|
||||
case 'patchy-moderate-snow':
|
||||
case 'moderate-snow':
|
||||
case 'patchy-heavy-snow':
|
||||
case 'heavy-snow':
|
||||
case 'light-snow-showers':
|
||||
case 'moderate-or-heavy-snow-showers':
|
||||
$string = '❄️';
|
||||
break;
|
||||
case 'patchy-snow-possible':
|
||||
case 'patchy-sleet-possible':
|
||||
case 'moderate-or-heavy-sleet':
|
||||
case 'light-sleet-showers':
|
||||
case 'moderate-or-heavy-sleet-showers':
|
||||
case 'sleet':
|
||||
$string = '🌨️';
|
||||
break;
|
||||
case 'wind':
|
||||
$string = '💨';
|
||||
break;
|
||||
case 'fog':
|
||||
case 'mist':
|
||||
case 'blizzard':
|
||||
case 'freezing-fog':
|
||||
$string = '🌫️';
|
||||
break;
|
||||
case 'overcast':
|
||||
case 'cloudy':
|
||||
$string = '☁️';
|
||||
break;
|
||||
case 'partly-cloudy-day':
|
||||
$string = '⛅';
|
||||
break;
|
||||
case 'partly-cloudy-night':
|
||||
$string = '🎑';
|
||||
break;
|
||||
case 'freezing-drizzle':
|
||||
case 'heavy-freezing-drizzle':
|
||||
case 'patchy-freezing-drizzle-possible':
|
||||
case 'ice-pellets':
|
||||
case 'light-showers-of-ice-pellets':
|
||||
case 'moderate-or-heavy-showers-of-ice-pellets':
|
||||
$string = '🧊';
|
||||
break;
|
||||
case 'thundery-outbreaks-possible':
|
||||
case 'patchy-light-rain-with-thunder':
|
||||
case 'moderate-or-heavy-rain-with-thunder':
|
||||
case 'patchy-light-snow-with-thunder':
|
||||
case 'moderate-or-heavy-snow-with-thunder':
|
||||
$string = '⛈️';
|
||||
break;
|
||||
default:
|
||||
$string = '🌈';
|
||||
break;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the temperature attribute.
|
||||
* Temperature is fetched in Celsius. It needs to be
|
||||
* converted to Fahrenheit depending on the user.
|
||||
*
|
||||
* @param string $scale
|
||||
* @return string
|
||||
*/
|
||||
public function temperature($scale = 'celsius')
|
||||
{
|
||||
$json = $this->weather_json;
|
||||
|
||||
$temperature = Arr::get($json, 'currently.temperature') ?? Arr::get($json, 'current.temp_c');
|
||||
|
||||
if ($scale === 'fahrenheit') {
|
||||
$temperature = Arr::get($json, 'current.temp_f', 9 / 5 * $temperature + 32);
|
||||
}
|
||||
|
||||
$temperature = round($temperature, 1);
|
||||
|
||||
$numberFormatter = new \NumberFormatter(App::getLocale(), \NumberFormatter::DECIMAL);
|
||||
|
||||
return $numberFormatter->format($temperature);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user