Initial commit
This commit is contained in:
208
app/Models/Locations/City.php
Normal file
208
app/Models/Locations/City.php
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Bank;
|
||||
use App\Models\Category;
|
||||
use App\Models\Locations\CityLocale;
|
||||
use App\Models\Locations\Country;
|
||||
use App\Models\Locations\DistrictLocale;
|
||||
use App\Models\Locations\Division;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
|
||||
|
||||
class City extends Model
|
||||
{
|
||||
use HasRelationships;
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
/**
|
||||
* Return all available locales of the city.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(CityLocale::class, 'city_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the users of the cities.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->morphedByMany(User::class, 'districtable', 'districtables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the organizations of the cities.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function organizations()
|
||||
{
|
||||
return $this->morphedByMany(Organization::class, 'cityable', 'cityables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the banks of the cities.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function banks()
|
||||
{
|
||||
return $this->morphedByMany(Bank::class, 'cityable', 'cityables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the cityables of the cities.
|
||||
* Many-to-many polymorph
|
||||
* @return void
|
||||
*/
|
||||
public function cityables()
|
||||
{
|
||||
return $this->morphedByMany(City::class, 'cityable', 'cityables');
|
||||
// cityable refers to pivot columns and cityables refers to pivot table
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the related districts of the city.
|
||||
* @return void
|
||||
*/
|
||||
public function districtsRelation()
|
||||
{
|
||||
return $this->hasManyThrough(DistrictLocale::class, District::class, 'city_id', 'district_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all related locations of the division.
|
||||
* One-to-many.
|
||||
* @return void
|
||||
*/
|
||||
public function locations()
|
||||
{
|
||||
return $this->hasMany(Location::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the districts of the city in the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function districts()
|
||||
{
|
||||
// $locale = collect(
|
||||
// $this->hasManyThrough(DistrictLocale::class, District::class, 'city_id', 'district_id')
|
||||
// ->where('locale', App::getLocale())
|
||||
// ->get()
|
||||
// )->keyBy('district_id');
|
||||
|
||||
// $fallback = collect(
|
||||
// $this->hasManyThrough(DistrictLocale::class, District::class, 'city_id', 'district_id')
|
||||
// ->where('locale', App::getFallbackLocale())
|
||||
// ->get()
|
||||
// )->keyBy('district_id');
|
||||
|
||||
// $result = $locale
|
||||
// ->union($fallback)
|
||||
// ->filter(function ($item) use ($search) {
|
||||
// return false !== stripos($item->name, $search);
|
||||
// })
|
||||
// ->sortBy('name');
|
||||
|
||||
return $this->hasMany(District::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the country of the city in the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function country()
|
||||
{
|
||||
// $country = $this->belongsTo(Country::class, 'country_id')->pluck('id');
|
||||
// $result = CountryLocale::where('country_id', $country)
|
||||
// ->where('locale', App::getLocale());
|
||||
// if ($result->count() === 0) {
|
||||
// $result = CountryLocale::where('country_id', $country)
|
||||
// ->where('locale', App::getFallbackLocale());
|
||||
// }
|
||||
// return $result;
|
||||
return $this->belongsTo(Country::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the division of the city in the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function division()
|
||||
{
|
||||
// $division = $this->belongsTo(Division::class, 'division_id')->pluck('id');
|
||||
// $result = DivisionLocale::where('division_id', $division)
|
||||
// ->where('locale', App::getLocale());
|
||||
// if ($result->count() === 0) {
|
||||
// $result = DivisionLocale::where('division_id', $division)
|
||||
// ->where('locale', App::getFallbackLocale());
|
||||
// }
|
||||
// return $result;
|
||||
return $this->belongsTo(Division::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the related children of this model.
|
||||
*
|
||||
* @return collection
|
||||
*/
|
||||
public function children($search = '')
|
||||
{
|
||||
return $this->districts($search);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related parent of this model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
if ($this->division() === null) {
|
||||
return $this->country();
|
||||
}
|
||||
return $this->division();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the related categories for this model.
|
||||
*/
|
||||
public function categories()
|
||||
{
|
||||
return $this->morphMany(Category::class, 'categoryable');
|
||||
}
|
||||
|
||||
}
|
||||
37
app/Models/Locations/CityLocale.php
Normal file
37
app/Models/Locations/CityLocale.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Scopes\LocalizeScope;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class CityLocale extends Model
|
||||
{
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
// Scope a query to only include country locales that match the current application locale or fallback locale.
|
||||
static::addGlobalScope(new LocalizeScope);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return belonged City
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function city()
|
||||
{
|
||||
return $this->belongsTo(City::class, 'city_id');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
214
app/Models/Locations/Country.php
Normal file
214
app/Models/Locations/Country.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Bank;
|
||||
use App\Models\Category;
|
||||
use App\Models\Locations\Location;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
|
||||
|
||||
class Country extends Model
|
||||
{
|
||||
use HasRelationships;
|
||||
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
/**
|
||||
* Get all related locations of the division.
|
||||
* One-to-many.
|
||||
* @return void
|
||||
*/
|
||||
public function locations()
|
||||
{
|
||||
return $this->hasMany(Location::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all related locales.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(CountryLocale::class, 'country_id');
|
||||
}
|
||||
|
||||
|
||||
public function translationExists()
|
||||
{
|
||||
return $this->hasOne(CountryLocale::class, 'country_id')->where('locale', App::getLocale())->exists();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the users of the countries.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->morphedByMany(User::class, 'countryable', 'countryables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the organizations of the countries.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function organizations()
|
||||
{
|
||||
return $this->morphedByMany(Organization::class, 'countryable', 'countryables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the banks of the countries.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function banks()
|
||||
{
|
||||
return $this->morphedByMany(Bank::class, 'countryable', 'countryables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the related divisions of the country.
|
||||
* @return void
|
||||
*/
|
||||
public function divisionsRelation()
|
||||
{
|
||||
return $this->hasManyThrough(DivisionLocale::class, Division::class, 'country_id', 'division_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the divisions of the country.
|
||||
* One-to-many
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
public function divisions()
|
||||
{
|
||||
return $this->hasMany(Division::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the related cities of the country.
|
||||
* @return void
|
||||
*/
|
||||
public function cities()
|
||||
{
|
||||
return $this->hasManyThrough(CityLocale::class, City::class, 'country_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related cities locale of the country in the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* The optional property will filter the localized city names.
|
||||
* @return void
|
||||
*/
|
||||
public function citiesLocale(string $search = '')
|
||||
{
|
||||
$locale = collect(
|
||||
$this->hasManyThrough(CityLocale::class, City::class, 'country_id')
|
||||
->where('locale', App::getLocale())
|
||||
->get()
|
||||
)->keyBy('city_id');
|
||||
|
||||
$fallback = collect(
|
||||
$this->hasManyThrough(CityLocale::class, City::class, 'country_id')
|
||||
->where('locale', App::getFallbackLocale())
|
||||
->get()
|
||||
)->keyBy('city_id');
|
||||
|
||||
$result = $locale
|
||||
->union($fallback)
|
||||
->filter(function ($item) use ($search) {
|
||||
return false !== stripos($item->name, $search);
|
||||
})
|
||||
->sortBy('name');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get all the related districts of the country.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function districtsRelation()
|
||||
{
|
||||
return $this->hasManyDeep(DistrictLocale::class, [City::class, District::class], ['country_id', 'city_id', 'district_id'], ['id', 'id', 'id']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the districts of the countries.
|
||||
* Only fallback locale is used when App language is not a country language of the city to prevent double results.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function districts(string $search = '')
|
||||
{
|
||||
$locale = collect(
|
||||
$this->hasManyDeep(DistrictLocale::class, [City::class, District::class], ['country_id', 'city_id', 'district_id'], ['id', 'id', 'id'])
|
||||
->where('locale', App::getLocale())
|
||||
->get()
|
||||
)->keyBy('district_id');
|
||||
|
||||
$fallback = collect(
|
||||
$this->hasManyDeep(DistrictLocale::class, [City::class, District::class], ['country_id', 'city_id', 'district_id'], ['id', 'id', 'id'])
|
||||
->where('locale', App::getFallbackLocale())
|
||||
->get()
|
||||
)->keyBy('district_id');
|
||||
|
||||
$result = $locale
|
||||
->union($fallback)
|
||||
->filter(function ($item) use ($search) {
|
||||
return false !== stripos($item->name, $search);
|
||||
})
|
||||
->sortBy('name');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related children of this model.
|
||||
*
|
||||
* @return collection
|
||||
*/
|
||||
public function children(string $search = '')
|
||||
{
|
||||
if ($this->divisions() == true) {
|
||||
return $this->divisions($search);
|
||||
}
|
||||
return $this->cities($search);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the related categories for this model.
|
||||
*/
|
||||
public function categories()
|
||||
{
|
||||
return $this->morphMany(Category::class, 'categoryable');
|
||||
}
|
||||
|
||||
}
|
||||
19
app/Models/Locations/CountryLanguage.php
Normal file
19
app/Models/Locations/CountryLanguage.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CountryLanguage extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
}
|
||||
31
app/Models/Locations/CountryLocale.php
Normal file
31
app/Models/Locations/CountryLocale.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Scopes\LocalizeScope;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class CountryLocale extends Model
|
||||
{
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
// Scope a query to only include country locales that match the current application locale or fallback locale.
|
||||
static::addGlobalScope(new LocalizeScope);
|
||||
}
|
||||
|
||||
|
||||
public function country()
|
||||
{
|
||||
return $this->belongsTo(Country::class, 'country_id');
|
||||
}
|
||||
|
||||
}
|
||||
175
app/Models/Locations/District.php
Normal file
175
app/Models/Locations/District.php
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Bank;
|
||||
use App\Models\Category;
|
||||
use App\Models\Locations\DistrictLocale;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class District extends Model
|
||||
{
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
/**
|
||||
* Return all available locales of the district.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(DistrictLocale::class, 'district_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the local district name.
|
||||
* In the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* @return void
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
$result = $this->hasMany(DistrictLocale::class, 'district_id')
|
||||
->where('locale', App::getLocale());
|
||||
if ($result->count() === 0) {
|
||||
$result = $this->hasMany(DistrictLocale::class, 'district_id')
|
||||
->where('locale', App::getFallbackLocale());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the users of the districts.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->morphedByMany(User::class, 'districtable', 'districtables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the organizations of the districts.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function organizations()
|
||||
{
|
||||
return $this->morphedByMany(Organization::class, 'districtable', 'districtables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the banks of the districts.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function banks()
|
||||
{
|
||||
return $this->morphedByMany(Bank::class, 'districtable', 'districtables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all related locations of the division.
|
||||
* One-to-many.
|
||||
* @return void
|
||||
*/
|
||||
public function locations()
|
||||
{
|
||||
return $this->hasMany(Location::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related city of the district.
|
||||
* In the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* @return void
|
||||
*/
|
||||
public function city()
|
||||
{
|
||||
$city = $this->belongsTo(City::class, 'city_id')->pluck('id');
|
||||
$result = CityLocale::where('city_id', $city)
|
||||
->where('locale', App::getLocale());
|
||||
if ($result->count() === 0) {
|
||||
$result = CityLocale::where('city_id', $city)
|
||||
->where('locale', App::getFallbackLocale());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the related country of the district.
|
||||
* In the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* @return void
|
||||
*/
|
||||
public function country()
|
||||
{
|
||||
$country = $this->belongsTo(City::class, 'city_id')->pluck('country_id');
|
||||
$result = CountryLocale::where('country_id', $country)
|
||||
->where('locale', App::getLocale());
|
||||
if ($result->count() === 0) {
|
||||
$result = CountryLocale::where('country_id', $country)
|
||||
->where('locale', App::getFallbackLocale());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related division of the district.
|
||||
* In the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* @return void
|
||||
*/
|
||||
public function division()
|
||||
{
|
||||
$division = $this->belongsTo(City::class, 'city_id')->pluck('division_id');
|
||||
$result = DivisionLocale::where('division_id', $division)
|
||||
->where('locale', App::getLocale());
|
||||
if ($result->count() === 0) {
|
||||
$result = DivisionLocale::where('division_id', $division)
|
||||
->where('locale', App::getFallbackLocale());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related parent of this model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
// Check if division exists
|
||||
if ($this->division_id) {
|
||||
return $this->belongsTo(Division::class, 'division_id');
|
||||
}
|
||||
|
||||
// Otherwise, return the country relationship
|
||||
return $this->belongsTo(Country::class, 'country_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the related categories for this model.
|
||||
*/
|
||||
public function categories()
|
||||
{
|
||||
return $this->morphMany(Category::class, 'categoryable');
|
||||
}
|
||||
|
||||
}
|
||||
29
app/Models/Locations/DistrictLocale.php
Normal file
29
app/Models/Locations/DistrictLocale.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Scopes\LocalizeScope;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DistrictLocale extends Model
|
||||
{
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
// Scope a query to only include country locales that match the current application locale or fallback locale.
|
||||
static::addGlobalScope(new LocalizeScope);
|
||||
}
|
||||
|
||||
|
||||
public function district()
|
||||
{
|
||||
return $this->belongsTo(District::class, 'district_id');
|
||||
}
|
||||
}
|
||||
203
app/Models/Locations/Division.php
Normal file
203
app/Models/Locations/Division.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Bank;
|
||||
use App\Models\Category;
|
||||
use App\Models\Locations\City;
|
||||
use App\Models\Locations\DivisionLocale;
|
||||
use App\Models\Locations\Location;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class Division extends Model
|
||||
{
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
/**
|
||||
* Return all available locales of the division.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(DivisionLocale::class, 'division_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the local division name.
|
||||
* In the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* @return void
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
$result = $this->hasMany(DivisionLocale::class, 'division_id')
|
||||
->whereIn('locale', [App::getLocale()]);
|
||||
if ($result->count() === 0) {
|
||||
$result = $this->hasMany(DivisionLocale::class, 'division_id')
|
||||
->whereIn('locale', [App::getFallbackLocale()]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the users of the divisions.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->morphedByMany(User::class, 'divisionable', 'divisionables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the organizations of the divisions.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function organizations()
|
||||
{
|
||||
return $this->morphedByMany(Organization::class, 'divisionable', 'divisionables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the banks of the divisions.
|
||||
* Many-to-many polymorphic.
|
||||
* @return void
|
||||
*/
|
||||
public function banks()
|
||||
{
|
||||
return $this->morphedByMany(Bank::class, 'divisionable', 'divisionables');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all related locations of the division.
|
||||
* One-to-many.
|
||||
* @return void
|
||||
*/
|
||||
public function locations()
|
||||
{
|
||||
return $this->hasMany(Location::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related country of the division.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function countryRelation()
|
||||
{
|
||||
return $this->belongsTo(Country::class, 'country_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the country of the division in the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function country()
|
||||
{
|
||||
// $country = $this->belongsTo(Country::class, 'country_id')->pluck('id');
|
||||
// $result = CountryLocale::where('country_id', $country)
|
||||
// ->where('locale', App::getLocale());
|
||||
// if ($result->count() === 0) {
|
||||
// $result = CountryLocale::where('country_id', $country)
|
||||
// ->where('locale', App::getFallbackLocale());
|
||||
// }
|
||||
// return $result;
|
||||
|
||||
return $this->belongsTo(Country::class, 'country_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the related cities of the division.
|
||||
* @return void
|
||||
*/
|
||||
public function citiesRelation()
|
||||
{
|
||||
return $this->hasManyThrough(CityLocale::class, City::class, 'division_id', 'city_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the cities of the division in the App::getLocale, or if not exists, in the App::getFallbackLocale language.
|
||||
* The optional paramameter will filter the localized city names.
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function cities()
|
||||
{
|
||||
// {
|
||||
// $locale = collect(
|
||||
// $this->hasManyThrough(CityLocale::class, City::class, 'division_id', 'city_id')
|
||||
// ->where('locale', App::getLocale())
|
||||
// ->get()
|
||||
// )->keyBy('city_id');
|
||||
|
||||
// $fallback = collect(
|
||||
// $this->hasManyThrough(CityLocale::class, City::class, 'division_id', 'city_id')
|
||||
// ->where('locale', App::getFallbackLocale())
|
||||
// ->get()
|
||||
// )->keyBy('city_id');
|
||||
|
||||
// $result = $locale
|
||||
// ->union($fallback)
|
||||
// ->filter(function ($item) use ($search){
|
||||
// return false !== stripos($item->name, $search);
|
||||
// })
|
||||
// ->sortBy('name');
|
||||
|
||||
// return $result;
|
||||
|
||||
return $this->hasMany(City::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related children of this model.
|
||||
*
|
||||
* @param string $search
|
||||
* @return void
|
||||
*/
|
||||
public function children(string $search = '')
|
||||
{
|
||||
return $this->cities($search);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the related parent of this model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->country();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the related categories for this model.
|
||||
*/
|
||||
public function categories()
|
||||
{
|
||||
return $this->morphMany(Category::class, 'categoryable');
|
||||
}
|
||||
|
||||
}
|
||||
28
app/Models/Locations/DivisionLocale.php
Normal file
28
app/Models/Locations/DivisionLocale.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Scopes\LocalizeScope;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DivisionLocale extends Model
|
||||
{
|
||||
/**
|
||||
* The database table doesn't use 'created_at' and 'updated_at' so we disable it from Inserts/Updates.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
// Scope a query to only include country locales that match the current application locale or fallback locale.
|
||||
static::addGlobalScope(new LocalizeScope);
|
||||
}
|
||||
|
||||
public function division()
|
||||
{
|
||||
return $this->belongsTo(Division::class, 'division_id');
|
||||
}
|
||||
}
|
||||
305
app/Models/Locations/Location.php
Normal file
305
app/Models/Locations/Location.php
Normal file
@@ -0,0 +1,305 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Locations;
|
||||
|
||||
use App\Models\Locations\City;
|
||||
use App\Models\Locations\Country;
|
||||
use App\Models\Locations\District;
|
||||
use App\Models\Locations\Division;
|
||||
use App\Models\Meeting;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Location extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['name', 'country_id', 'division_id', 'city_id', 'district_id', 'locatable_id', 'locatable_type'];
|
||||
|
||||
/**
|
||||
* Return related country.
|
||||
* one-to-many
|
||||
* @return void
|
||||
*/
|
||||
public function country()
|
||||
{
|
||||
return $this->belongsTo(Country::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most appropriate country for this location.
|
||||
* Tries multiple sources in order of preference.
|
||||
* If resolved it syncs the location's missing country_id.
|
||||
*
|
||||
* @return Country|null
|
||||
*/
|
||||
public function getCountry()
|
||||
{
|
||||
// 1. Direct country relationship
|
||||
if ($this->country_id && $this->country) {
|
||||
return $this->country;
|
||||
}
|
||||
|
||||
// 2. Country from division
|
||||
if ($this->division_id && $this->division && $this->division->country_id) {
|
||||
$this->syncCountryFromDivision();
|
||||
return $this->fresh()->country;
|
||||
}
|
||||
|
||||
// 3. Country from city
|
||||
if ($this->city_id && $this->city && $this->city->country_id) {
|
||||
$this->syncCountryFromCity();
|
||||
return $this->fresh()->country;
|
||||
}
|
||||
|
||||
// 4. Country from district's city (if district exists)
|
||||
if ($this->district_id && $this->district && $this->district->city_id) {
|
||||
// First ensure we have city synced
|
||||
if (!$this->city_id) {
|
||||
$this->syncCityFromDistrict();
|
||||
}
|
||||
|
||||
// Now try to get country from city
|
||||
if ($this->city && $this->city->country_id) {
|
||||
$this->syncCountryFromCity();
|
||||
return $this->fresh()->country;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the location's country_id based on the division's country.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncCountryFromDivision()
|
||||
{
|
||||
if ($this->division && $this->division->country_id) {
|
||||
$this->country_id = $this->division->country_id;
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the location's country_id based on the city's country.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncCountryFromCity()
|
||||
{
|
||||
if ($this->city && $this->city->country_id) {
|
||||
$this->country_id = $this->city->country_id;
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all related divisions.
|
||||
* One-to-many
|
||||
* @return void
|
||||
*/
|
||||
public function division()
|
||||
{
|
||||
return $this->belongsTo(Division::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most appropriate division for this location.
|
||||
* Tries multiple sources in order of preference.
|
||||
* If resolved it syncs the location's missing division_id.
|
||||
*
|
||||
* @return Division|null
|
||||
*/
|
||||
public function getDivision()
|
||||
{
|
||||
// 1. Direct division relationship
|
||||
if ($this->division_id && $this->division) {
|
||||
return $this->division;
|
||||
}
|
||||
|
||||
// 2. Division from city
|
||||
if ($this->city_id && $this->city && $this->city->division_id) {
|
||||
$this->syncDivisionFromCity();
|
||||
return $this->fresh()->division; // Fresh instance to get updated division_id
|
||||
}
|
||||
|
||||
// 3. Division from district's city (if district exists)
|
||||
if ($this->district_id && $this->district && $this->district->city_id) {
|
||||
// First sync city from district if city_id is missing
|
||||
if (!$this->city_id) {
|
||||
$this->syncCityFromDistrict();
|
||||
}
|
||||
|
||||
// Now try to get division from city
|
||||
if ($this->city && $this->city->division_id) {
|
||||
$this->syncDivisionFromCity();
|
||||
return $this->fresh()->division;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the location's country_id based on the division's country.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncCountryFromDistrict()
|
||||
{
|
||||
if ($this->division && $this->division->country_id) {
|
||||
$this->country_id = $this->division->country_id;
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the location's division_id based on the city's division.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncDivisionFromCity()
|
||||
{
|
||||
if ($this->city && $this->city->division_id) {
|
||||
$this->division_id = $this->city->division_id;
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the location's division_id based on the city's division.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function syncCityFromDistrict()
|
||||
{
|
||||
if ($this->district && $this->district->city_id) {
|
||||
$this->city_id = $this->district->city_id;
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return related city.
|
||||
* One-to-many
|
||||
* @return void
|
||||
*/
|
||||
public function city()
|
||||
{
|
||||
return $this->belongsTo(City::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return related district.
|
||||
* One-to-many
|
||||
* @return void
|
||||
*/
|
||||
public function district()
|
||||
{
|
||||
return $this->belongsTo(District::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sync all missing location hierarchy data.
|
||||
* This method will populate all missing IDs based on available relationships.
|
||||
*
|
||||
* @return array Returns what was synced
|
||||
*/
|
||||
public function syncAllLocationData()
|
||||
{
|
||||
$synced = [];
|
||||
|
||||
// Step 1: Sync city from district if missing
|
||||
if (!$this->city_id && $this->district_id) {
|
||||
if ($this->syncCityFromDistrict()) {
|
||||
$synced[] = 'city_from_district';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Sync division from city if missing
|
||||
if (!$this->division_id && $this->city_id) {
|
||||
if ($this->syncDivisionFromCity()) {
|
||||
$synced[] = 'division_from_city';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Sync country from division if missing
|
||||
if (!$this->country_id && $this->division_id) {
|
||||
if ($this->syncCountryFromDivision()) {
|
||||
$synced[] = 'country_from_division';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Fallback - sync country from city if still missing
|
||||
if (!$this->country_id && $this->city_id) {
|
||||
if ($this->syncCountryFromCity()) {
|
||||
$synced[] = 'country_from_city';
|
||||
}
|
||||
}
|
||||
|
||||
return $synced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a complete location hierarchy.
|
||||
* This method ensures all data is synced and returns the complete hierarchy.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCompleteHierarchy()
|
||||
{
|
||||
// Sync all data first
|
||||
$this->syncAllLocationData();
|
||||
|
||||
// Refresh the model to get updated relationships
|
||||
$location = $this->fresh();
|
||||
|
||||
return [
|
||||
'country' => $location->country,
|
||||
'division' => $location->getDivision(),
|
||||
'city' => $location->city,
|
||||
'district' => $location->district,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return related locatable (i.e. user or organization).
|
||||
* One-to-many polymorph
|
||||
* @return void
|
||||
*/
|
||||
public function locatable()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return related meeting.
|
||||
* one-to-many
|
||||
* @return void
|
||||
*/
|
||||
public function meeting()
|
||||
{
|
||||
return $this->hasOne(Meeting::class);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user