Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organisations can now have multiple locations #855

Merged
merged 4 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions app/Console/Commands/Migrations/MigrateOrganisationLocations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace App\Console\Commands\Migrations;

use App\Models\Organisation;
use App\Models\OrganisationLocation;
use Illuminate\Console\Command;

class MigrateOrganisationLocations extends Command
{
public $count = 0;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'organisation:locations';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate organisation location to locations';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
OrganisationLocation::truncate();
Organisation::whereNotNull('location_id')->chunk(1000, function ($organisations) {
$this->info('1000 Chunk...');
foreach ($organisations as $organisation) {
$organisation->locations()->attach($organisation->location_id);
$this->count++;
}
});

$this->info('Migrated ' . $this->count . ' organisations');
return 0;
}
}
1 change: 1 addition & 0 deletions app/Datagrids/Bulks/CreatureBulk.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class CreatureBulk extends Bulk
'name',
'type',
'creature_id',
'locations',
'tags',
'private_choice',
'extinct_choice',
Expand Down
2 changes: 1 addition & 1 deletion app/Datagrids/Bulks/OrganisationBulk.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class OrganisationBulk extends Bulk
protected array $fields = [
'name',
'type',
'location_id',
'locations',
'organisation_id',
'tags',
'private_choice',
Expand Down
1 change: 1 addition & 0 deletions app/Datagrids/Bulks/RaceBulk.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class RaceBulk extends Bulk
'name',
'type',
'race_id',
'locations',
'tags',
'private_choice',
'entity_image',
Expand Down
1 change: 1 addition & 0 deletions app/Http/Controllers/Api/v1/OrganisationApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function store(Request $request, Campaign $campaign)
$data['campaign_id'] = $campaign->id;
$model = Organisation::create($data);
$this->crudSave($model);
$model->refresh();
return new Resource($model);
}

Expand Down
2 changes: 2 additions & 0 deletions app/Http/Requests/StoreCreature.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public function rules()
'image' => 'mimes:jpeg,png,jpg,gif,webp|max:' . Limit::upload(),
'image_url' => 'nullable|url|active_url',
'template_id' => 'nullable',
'locations' => 'array',
'locations.*' => 'distinct|exists:locations,id',
];

/** @var Creature $self */
Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/StoreOrganisation.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ public function rules()
'entry' => 'nullable|string',
'type' => 'nullable|string|max:191',
'image' => 'mimes:jpeg,png,jpg,gif,webp|max:' . Limit::upload(),
'location_id' => 'nullable|integer|exists:locations,id',
spitfire305 marked this conversation as resolved.
Show resolved Hide resolved
'organisation_id' => 'nullable|exists:organisations,id',
'image_url' => 'nullable|url|active_url',
'template_id' => 'nullable',
'locations' => 'array',
'locations.*' => 'distinct|exists:locations,id',
];

/** @var Organisation $self */
Expand Down
2 changes: 2 additions & 0 deletions app/Http/Requests/StoreRace.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public function rules()
'image' => 'mimes:jpeg,png,jpg,gif,webp|max:' . Limit::upload(),
'image_url' => 'nullable|url|active_url',
'template_id' => 'nullable',
'locations' => 'array',
'locations.*' => 'distinct|exists:locations,id',
];

/** @var Race $self */
Expand Down
4 changes: 3 additions & 1 deletion app/Http/Resources/OrganisationResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ public function toArray($request)
{
/** @var Organisation $model */
$model = $this->resource;
$locationIDs = $model->locations()->pluck('locations.id');
return $this->entity([
'type' => $model->type,
'organisation_id' => $model->organisation_id,
'is_defunct' => (bool) $model->is_defunct,
'members' => OrganisationMemberResource::collection($model->members()->has('character')->with('character')->get())
'members' => OrganisationMemberResource::collection($model->members()->has('character')->with('character')->get()),
'locations' => $locationIDs
]);
}
}
61 changes: 54 additions & 7 deletions app/Models/Organisation.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* @property Collection|OrganisationMember[] $members
* @property Collection|Organisation[] $descendants
* @property Collection|Organisation[] $organisations
* @property Collection|Location[] $locations
* @property bool $is_defunct
*/
class Organisation extends MiscModel
Expand All @@ -43,7 +44,6 @@ class Organisation extends MiscModel
'name',
'slug',
'entry',
'location_id',
'organisation_id',
'type',
'is_private',
Expand All @@ -66,7 +66,6 @@ class Organisation extends MiscModel
* Fields that can be sorted on
*/
protected array $sortableColumns = [
'location.name',
'is_defunct',
];

Expand All @@ -75,11 +74,11 @@ class Organisation extends MiscModel
*/
protected array $foreignExport = [
'members',
'pivotLocations',
];

protected array $exportFields = [
'base',
'location_id',
'is_defunct',
];

Expand All @@ -90,7 +89,6 @@ class Organisation extends MiscModel
* @var string[]
*/
public array $nullableForeignKeys = [
'location_id',
'organisation_id'
];

Expand All @@ -105,8 +103,9 @@ public function scopePreparedWith(Builder $query): Builder
->with([
'entity',
'entity.image',
'location',
'location.entity',
'locations' => function ($sub) {
$sub->select('id', 'name');
},
ilestis marked this conversation as resolved.
Show resolved Hide resolved
'parent' => function ($sub) {
$sub->select('id', 'name');
},
Expand All @@ -121,6 +120,40 @@ public function scopePreparedWith(Builder $query): Builder
]);
}

/**
* Filter on organisations in specific locations
*/
public function scopeLocation(Builder $query, int|null $location, FilterOption $filter): Builder
{
if ($filter === FilterOption::NONE) {
if (!empty($location)) {
return $query;
}
return $query
->whereRaw('(select count(*) from organisation_location as ol where ol.organisation_id = ' .
$this->getTable() . '.id and ol.location_id = ' . ((int) $location) . ') = 0');
} elseif ($filter === FilterOption::EXCLUDE) {
return $query
->whereRaw('(select count(*) from organisation_location as ol where ol.organisation_id = ' .
$this->getTable() . '.id and ol.location_id = ' . ((int) $location) . ') = 0');
}

$ids = [$location];
if ($filter === FilterOption::CHILDREN) {
/** @var Location|null $model */
$model = Location::find($location);
if (!empty($model)) {
$ids = [...$model->descendants->pluck('id')->toArray(), $model->id];
}
}
return $query
->select($this->getTable() . '.*')
->leftJoin('organisation_location as ol', function ($join) {
$join->on('ol.organisation_id', '=', $this->getTable() . '.id');
})
->whereIn('ol.location_id', $ids)->distinct();
}

/**
* Filter for organisations with specific member
*/
Expand Down Expand Up @@ -204,6 +237,20 @@ public function location()
return $this->belongsTo('App\Models\Location', 'location_id', 'id');
}

/**
* Organisations have multiple locations
*/
public function locations()
{
return $this->belongsToMany('App\Models\Location', 'organisation_location')
->with('entity');
}

public function pivotLocations()
{
return $this->hasMany('App\Models\OrganisationLocation');
}

/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
Expand Down Expand Up @@ -281,7 +328,7 @@ public function entityTypeId(): int
*/
public function showProfileInfo(): bool
{
return !empty($this->type) || !empty($this->location) || !$this->entity->elapsedEvents->isEmpty();
return !empty($this->type) || !empty($this->location) || !$this->entity->elapsedEvents->isEmpty() || $this->locations->isNotEmpty();
}

/**
Expand Down
48 changes: 48 additions & 0 deletions app/Models/OrganisationLocation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\Models;

use App\Models\Concerns\Paginatable;
use Illuminate\Database\Eloquent\Relations\Pivot;

/**
* Class OrganisationLocation
* @package App\Models
*
* @property int $organisation_id
* @property int $location_id
* @property Organisation $organisation
* @property Location $location
*/
class OrganisationLocation extends Pivot
{
use Paginatable;

/**
* @var string
*/
public $table = 'organisation_location';

protected $fillable = ['organisation_id', 'location_id'];

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function organisation()
{
return $this->belongsTo('App\Models\Organisation', 'organisation_id', 'id');
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function location()
{
return $this->belongsTo('App\Models\Location', 'location_id', 'id');
}

public function exportFields(): array
{
return ['location_id'];
}
}
12 changes: 7 additions & 5 deletions app/Observers/Concerns/HasLocations.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ trait HasLocations
{
/**
*/
public function saveLocations(MiscModel|Creature $model)
public function saveLocations(MiscModel|Creature $model, array $locations = [])
{
/** @var Creature $model */
$existing = $unique = $recreate = [];
Expand All @@ -28,11 +28,13 @@ public function saveLocations(MiscModel|Creature $model)
if (!empty($recreate)) {
$model->locations()->attach($recreate);
}

$locations = request()->get('locations', []);
if (!$locations) {
$locations = request()->get('locations', []);
$detach = true;
}
$newLocations = [];
foreach ($locations as $id) {
// Existing race, do nothing
// Existing location, do nothing
if (!empty($existing[$id])) {
unset($existing[$id]);
continue;
Expand All @@ -51,7 +53,7 @@ public function saveLocations(MiscModel|Creature $model)
$model->locations()->attach($newLocations);

// Detach the remaining
if (!empty($existing)) {
if (!empty($existing) && isset($detach)) {
$model->locations()->detach($existing);
}
}
Expand Down
13 changes: 13 additions & 0 deletions app/Observers/OrganisationObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,27 @@
use App\Models\Character;
use App\Models\Organisation;
use App\Models\OrganisationMember;
use App\Observers\Concerns\HasLocations;

class OrganisationObserver extends MiscObserver
{
use HasLocations;

public function saved(Organisation $organisation)
{
$this->saveMembers($organisation);
}

/**
*/
public function crudSaved(Organisation $organisation)
{
if (!request()->has('save_locations') && !request()->has('locations')) {
return;
}
$this->saveLocations($organisation);
}

/**
*/
public function deleting(Organisation $organisation)
Expand Down
Loading
Loading