Initial commit

This commit is contained in:
Ronald Huynen
2026-03-23 21:37:59 +01:00
commit 2547717edb
2193 changed files with 972171 additions and 0 deletions

330
app/Traits/ProfileTrait.php Normal file
View File

@@ -0,0 +1,330 @@
<?php
namespace App\Traits;
use App\Models\Account;
use App\Models\Tag;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Spatie\Activitylog\Models\Activity;
trait ProfileTrait
{
/***
* Retrieve the online status of the user and sets the properties isOnline and isAway accordingly.
*
* @return void
*/
public function getOnlineStatus()
{
// TODO: Replace commented rtippin messenger logic with wirechat logic
// Check online status of the user
// $messenger = app(Messenger::class);
// $status = $messenger->getProviderOnlineStatus($this->profile);
// if ($status === 1) {
// $this->isOnline = true;
// $this->isAway = false;
// } elseif ($status === 2) {
// $this->isOnline = false;
// $this->isAway = true;
// } else {
// $this->isOnline = false;
// $this->isAway = false;
// }
}
/**
* Retrieve the phone number of the profile.
*
* @return void
*/
public function getPhone($profile)
{
if ($profile->phone_public) {
return $profile->phone;
} else {
return null;
}
}
/**
* Get the profile's location and generate a link to OpenStreetMap.
*
* @return void
*/
public function getLocation($profile)
{
return$profile->getLocationFirst(true);
}
/**
* Retrieve the user's languages and their language competence.
*
* @return void
*/
public function getLanguages($profile)
{
// If languages is null, return an empty collection
if (empty($profile->languages)) {
return collect();
}
return $profile->languages->map(function ($language) {
$language->competence_name = DB::table('language_competences')->find($language->pivot->competence)->name;
return $language;
});
}
public function getLangPreference($profile)
{
// Get the user's language preference (if it exists)
$lang_preference = DB::table('languages')->where('lang_code',$profile->lang_preference)->first();
if ($lang_preference) {
return $lang_preference->name;
}
}
/**
* Retrieves the skills of this user.
*
* @return \Illuminate\Support\Collection
*/
//TODO! This will set the skill Cache, and not get the skills from cache! FIX THIS!
public function getSkills($profile)
{
$skillsCache = Cache::remember('skills-user-' .$profile->id . '-lang-' . app()->getLocale(), now()->addDays(7), function () use ($profile) { // remember cache
$tagIds = $profile->tags->pluck('tag_id');
$translatedTags = collect((new Tag())->translateTagIdsWithContexts($tagIds, App::getLocale(), App::getFallbackLocale())); // Translate to app locale, if not available to fallback locale, if not available do not translate
$skills = $translatedTags->map(function ($item) {
return [
'tag_id' => $item['tag_id'],
'name' => $item['tag'],
'foreign' => (isset($item['locale']['locale']) && $item['locale']['locale'] == App::getLocale()) ? false : true,
'example' => (isset($item['locale']) && isset($item['locale']['example'])) ? $item['locale']['example'] : null,
'category' => $item['category'],
'category_path' => $item['category_path'],
'category_color' => $item['category_color'],
'title' => $item['category_path']
];
});
$skills = collect($skills);
return $skills;
});
$skills = $skillsCache;
if ($skills) {
return $skills;
} else {
return null;
}
}
public function getAge($profile)
{
// Check if the table has the date_of_birth column
if (Schema::hasColumn($profile->getTable(), 'date_of_birth') && $profile->date_of_birth) {
return Carbon::parse($profile->date_of_birth)->age;
}
return null;
}
/**
* Get the last login time for the profile.
*
* @return void
*/
public function getLastLogin($profile)
{
$activityLog =
Activity::where('subject_id', $profile->id)
->where('subject_type', get_class($profile))
->whereNotNull('properties->old->last_login_at')
->get('properties')->last();
if (isset($activityLog)) {
$lastLoginAt = json_decode($activityLog, true)['properties']['old']['last_login_at'];
return Carbon::createFromTimeStamp(strtotime($lastLoginAt))->diffForHumans();
} elseif ($profile->last_login_at) {
$lastLoginAt = $profile->last_login_at;
return Carbon::createFromTimeStamp(strtotime($lastLoginAt))->diffForHumans();
} else {
return null;
}
}
/**
* Retrieves the totals of the user's accounts.
* This method calls the `getAccountsTotals` method of the `Account` model to calculate the totals of the user's accounts.
*
*/
public function getAccountsTotals($profile)
{
$type = strtolower(class_basename($profile));
$totals = (new Account())->getAccountsTotals(get_class($profile), $profile->id, timebank_config('account_info.'.$type.'.countTransfersSince'));
if ($totals) {
return $totals;
} else {
return null;
}
}
/**
* Get the last exchange date for the profile.
*
* @return void
*/
public function getLastExchangeAt($accountsTotals = null, $profile = null)
{
if (!$accountsTotals && $profile) {
$accountsTotals = (new Account())->getAccountsTotals($profile->id, timebank_config('account_info.account_totals.countTransfersSince'));
}
// Normalize lastTransferDate to always be an array
if (!isset($accountsTotals['lastTransferDate'])) {
$accountsTotals['lastTransferDate'] = [];
} elseif (!is_array($accountsTotals['lastTransferDate'])) {
$accountsTotals['lastTransferDate'] = [$accountsTotals['lastTransferDate']];
}
if (!empty($accountsTotals['lastTransferDate'][0])) {
$date = $accountsTotals['lastTransferDate'][0];
if ($date instanceof \Illuminate\Support\Carbon) {
return $date->diffForHumans();
} else {
return Carbon::parse($date)->diffForHumans();
}
} else {
return null; // no transfers
}
}
/**
* Calculates and sets the registered since date for the user.
*
* @return void
*/
public function getRegisteredSince($profile)
{
$createdAt = Carbon::parse($profile->created_at);
$registeredSince = $createdAt->diffForHumans();
if ($registeredSince) {
return $registeredSince;
} else {
return null;
}
}
/**
* Retrieves the social media accounts associated with this user.
*
* @return void
*/
public function getSocials($profile)
{
$socials = $profile->socials()
->withPivot(['user_on_social', 'server_of_social', 'created_at', 'updated_at'])
->orderByPivot('updated_at', 'desc')
->limit(10)
->get();
return $socials->isNotEmpty() ? $socials : collect();
}
/**
* Check if a model has an incomplete profile based on configured fields and relations.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return bool
*/
public function hasIncompleteProfile($model)
{
$config = timebank_config('profile_incomplete');
if (!$config) {
return false;
}
$checkFields = $config['check_fields'] ?? [];
$checkRelations = $config['check_relations'] ?? [];
$minTotalLength = $config['check_fields_min_total_length'] ?? 0;
// Check if at least one field has data and calculate total length
$hasFieldData = false;
$totalFieldLength = 0;
foreach ($checkFields as $field) {
if (!empty($model->{$field})) {
$hasFieldData = true;
$totalFieldLength += strlen(trim($model->{$field}));
}
}
// Check if minimum total length requirement is met
$meetsMinLength = $totalFieldLength >= $minTotalLength;
// Check if at least one relation has data
$hasRelationData = false;
foreach ($checkRelations as $relation) {
if (!$model->relationLoaded($relation)) {
$model->load($relation);
}
if (!$model->{$relation}->isEmpty()) {
$hasRelationData = true;
break;
}
}
// Profile is complete (return false) when ALL three conditions are met:
// 1. At least one field has data
// 2. Total length meets minimum requirement
// 3. At least one relation has data
$isComplete = $hasFieldData && $meetsMinLength && $hasRelationData;
// Return true if incomplete, false if complete
return !$isComplete;
}
/**
* Returns true if the profile has never received a transaction on any of its active accounts.
*/
public function hasNeverReceivedTransaction($model): bool
{
if (!method_exists($model, 'accounts')) {
return false;
}
$accountIds = $model->accounts()->pluck('id');
if ($accountIds->isEmpty()) {
return true;
}
return !\App\Models\Transaction::whereIn('to_account_id', $accountIds)->exists();
}
}