diff --git a/app/Models/CampaignImport.php b/app/Models/CampaignImport.php index a4b00db1b9..ea315a3de0 100644 --- a/app/Models/CampaignImport.php +++ b/app/Models/CampaignImport.php @@ -55,4 +55,9 @@ public function user() { return $this->belongsTo(User::class); } + + public function isFailed(): bool + { + return $this->status_id == CampaignImportStatus::FAILED; + } } diff --git a/app/Models/Entity.php b/app/Models/Entity.php index 9008786ee0..d5f5ceadbb 100644 --- a/app/Models/Entity.php +++ b/app/Models/Entity.php @@ -469,7 +469,7 @@ public function export(): array // Entity relations $relations = [ - 'entityTags', 'relationships', 'posts', 'abilities', 'events', 'entityAttributes', 'assets', 'mentions' + 'entityTags', 'relationships', 'posts', 'abilities', 'events', 'entityAttributes', 'assets', 'mentions', 'inventories' ]; foreach ($relations as $relation) { foreach ($this->$relation as $model) { diff --git a/app/Renderers/Layouts/Campaign/CampaignImport.php b/app/Renderers/Layouts/Campaign/CampaignImport.php index f69b58ce83..25a7c60078 100644 --- a/app/Renderers/Layouts/Campaign/CampaignImport.php +++ b/app/Renderers/Layouts/Campaign/CampaignImport.php @@ -32,22 +32,22 @@ public function columns(): array return __('campaigns/import.status.' . $key); }, ], - 'created_by' => [ + 'user_id' => [ 'key' => 'user.name', 'label' => 'campaigns.members.fields.name', 'render' => function ($model) { - if (!$model->created_by) { + if (!$model->user_id) { return ''; } $html = '' . $model->user->name . ''; return $html; }, ], - 'created_at' => [ - 'key' => 'created_at', - 'label' => 'campaigns.invites.fields.created', + 'updated_at' => [ + 'key' => 'updated_at', + 'label' => 'campaigns/import.fields.updated', 'render' => function ($model) { - $html = '' . $model->created_at->diffForHumans() . ''; + $html = '' . $model->updated_at->diffForHumans() . ''; return $html; }, ], diff --git a/app/Services/Campaign/Import/ImportIdMapper.php b/app/Services/Campaign/Import/ImportIdMapper.php index 909cd3b110..c06ecf5e3a 100644 --- a/app/Services/Campaign/Import/ImportIdMapper.php +++ b/app/Services/Campaign/Import/ImportIdMapper.php @@ -63,6 +63,10 @@ public function getGallery(string $old): string { return $this->gallery[$old]; } + public function hasGallery(string $old): bool + { + return !empty($this->gallery[$old]); + } public function getPost(int $old): int { diff --git a/app/Services/Campaign/Import/ImportMentions.php b/app/Services/Campaign/Import/ImportMentions.php index 99339a7d1e..9732162b33 100644 --- a/app/Services/Campaign/Import/ImportMentions.php +++ b/app/Services/Campaign/Import/ImportMentions.php @@ -3,17 +3,21 @@ namespace App\Services\Campaign\Import; use App\Facades\ImportIdMapper; +use App\Jobs\Campaigns\Import; +use App\Models\ImageMention; +use App\Models\Post; use Illuminate\Support\Str; trait ImportMentions { + protected array $imageMentions = []; protected function mentions(string|null $text): string|null { if (empty($text)) { return $text; } - return preg_replace_callback( + $text = preg_replace_callback( '`\[([a-z_]+):(.*?)\]`i', function ($matches) { $segments = explode('|', $matches[2]); @@ -26,11 +30,60 @@ function ($matches) { $entityID = ImportIdMapper::getEntity($oldEntityID); if (Str::contains($matches[2], '|')) { - return '[' . $entityType . ':' . Str::replace($oldEntityID . '|', $entityID . '|', $matches[2]); + return '[' . $entityType . ':' . Str::replace($oldEntityID . '|', $entityID . '|', $matches[2] . ']'); } return '[' . $entityType . ':' . $entityID . ']'; }, $text ); + + $images = []; + preg_match_all('/data-gallery-id="[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"/i', $text, $segments); + foreach ($segments[0] as $key => $type) { + $id = mb_substr($type, 17, -1); + if (!in_array($id, $images)) { + $images[$key] = $id; + } + } + $this->imageMentions = []; + foreach ($images as $uuid) { + if (!ImportIdMapper::hasGallery($uuid)) { + continue; + } + $newUuid = ImportIdMapper::getGallery($uuid); + $text = Str::replace($uuid, $newUuid, $text); + $text = Str::replace( + '/campaigns/' . $this->data['campaign_id'] . '/', + '/campaigns/' . $this->campaign->id . '/', + $text + ); + $this->imageMentions[] = $newUuid; + } + + return $text; + } + + public function imageMentions(): array + { + return $this->imageMentions; + } + + protected function mapImageMentions(mixed $model): self + { + if (empty($this->imageMentions)) { + return $this; + } + + foreach ($this->imageMentions as $uuid) { + $men = new ImageMention(); + $men->entity_id = $this->entity->id; + $men->image_id = $uuid; + if ($model instanceof Post) { + $men->post_id = $model->id; + } + + $men->save(); + } + return $this; } } diff --git a/app/Services/Campaign/Import/ImportService.php b/app/Services/Campaign/Import/ImportService.php index 4acfb60b83..80e68dcda1 100644 --- a/app/Services/Campaign/Import/ImportService.php +++ b/app/Services/Campaign/Import/ImportService.php @@ -4,6 +4,7 @@ use App\Enums\CampaignImportStatus; use App\Models\CampaignImport; +use App\Notifications\Header; use App\Services\Campaign\Import\Mappers\AbilityMapper; use App\Services\Campaign\Import\Mappers\CalendarMapper; use App\Services\Campaign\Import\Mappers\CampaignMapper; @@ -49,6 +50,8 @@ class ImportService protected array $mappers; + protected array $logs = []; + public function __construct(EntityMappingService $entityMappingService) { $this->entityMappingService = $entityMappingService; @@ -102,7 +105,7 @@ protected function mappers(): self 'characters' => CharacterMapper::class, ]; foreach ($setup as $model => $mapperClass) { - dump('Init mapper ' . $model); + $this->logs[] = 'Init mapper ' . $model; $mapper = app()->make($mapperClass); $this->mappers[$model] = $mapper ->campaign($this->campaign) @@ -146,26 +149,47 @@ protected function extract(): void protected function process() { - //try { + try { $this->importCampaign() ->gallery() ->entities() ->secondCampaign() ; $this->job->status_id = CampaignImportStatus::FINISHED; - /*} catch (Exception $e) { + } catch (Exception $e) { dump($e->getMessage()); Log::error('Import', ['error' => $e->getMessage()]); $this->job->status_id = CampaignImportStatus::FAILED; - }*/ + } return $this; } protected function cleanup(): self { - Storage::deleteDirectory(storage_path('/app/' . $this->dataPath)); + Storage::disk('local')->deleteDirectory($this->dataPath); + $config = $this->job->config; + $config['logs'] = $this->logs; + $this->job->config = $config; $this->job->save(); + + $key = 'failed'; + $colour = 'red'; + if (!$this->job->isFailed()) { + $key = 'success'; + $colour = 'green'; + } + $this->campaign->notifyAdmins( + new Header( + 'campaign.import.' . $key, + 'upload', + $colour, + [ + 'campaign' => $this->campaign->name, + 'link' => route('dashboard', $this->campaign), + ] + ) + ); return $this; } @@ -192,7 +216,8 @@ protected function gallery(): self $path = $this->dataPath . '/gallery'; if (!Storage::disk('local')->exists($path)) { - dd('no gallery'); + $this->logs[] = 'No gallery'; + return $this; } $files = Storage::disk('local')->files($path); @@ -218,7 +243,7 @@ protected function gallery(): self protected function entities(): self { foreach ($this->mappers as $model => $mapper) { - dump('Processing ' . $model); + $this->logs[] = 'Processing ' . $model; $count = 0; foreach ($this->files($model) as $file) { if (!Str::endsWith($file, '.json')) { @@ -234,7 +259,7 @@ protected function entities(): self $count++; unset($data); } - dump('- ' . $count . ' ' . $model); + $this->logs[] = $count; $mapper->tree()->fixTree()->clear(); } @@ -243,7 +268,7 @@ protected function entities(): self if (!method_exists($mapper, 'second')) { continue; } - dump('Second round ' . $model); + $this->logs[] = 'Second round ' . $model; $count = 0; foreach ($this->files($model) as $file) { if (!Str::endsWith($file, '.json')) { @@ -259,14 +284,14 @@ protected function entities(): self $count++; unset($data); } - dump('- ' . $count . ' ' . $model); + $this->logs[] = $count; } foreach ($this->mappers as $model => $mapper) { if (!method_exists($mapper, 'third')) { continue; } - dump('Third round ' . $model); + $this->logs[] = 'Third round ' . $model; $count = 0; foreach ($this->files($model) as $file) { if (!Str::endsWith($file, '.json')) { @@ -285,7 +310,7 @@ protected function entities(): self $count++; unset($data); } - dump('- ' . $count . ' ' . $model); + $this->logs[] = '- ' . $count; } return $this; @@ -295,7 +320,7 @@ protected function files(string $model): array { $path = $this->dataPath . '/' . $model; if (!Storage::disk('local')->exists($path)) { - dump('No ' . $model); + $this->logs[] = 'No ' . $model; return []; } @@ -306,7 +331,8 @@ protected function open(string $file): array { $path = $this->dataPath . '/' . $file; if (!Storage::disk('local')->exists($path)) { - dd('file ' . $path . ' doesnt exist'); + $this->logs[] = 'file ' . $path . ' doesnt exist'; + return []; } $fullpath = Storage::disk('local')->path($path); diff --git a/app/Services/Campaign/Import/Mappers/EntityMapper.php b/app/Services/Campaign/Import/Mappers/EntityMapper.php index fd03997829..9dbfb207d6 100644 --- a/app/Services/Campaign/Import/Mappers/EntityMapper.php +++ b/app/Services/Campaign/Import/Mappers/EntityMapper.php @@ -10,6 +10,7 @@ use App\Models\EntityEvent; use App\Models\EntityMention; use App\Models\EntityTag; +use App\Models\Inventory; use App\Models\Post; use App\Models\Relation; use App\Services\EntityMappingService; @@ -217,6 +218,7 @@ protected function posts(): self $post->save(); ImportIdMapper::putPost($data['id'], $post->id); + $this->mapImageMentions($post); } return $this; @@ -343,7 +345,7 @@ protected function saveModel(): self { $this->model->entry = $this->mentions($this->model->entry); $this->model->save(); - + $this->mapImageMentions($this->model); return $this; } @@ -438,8 +440,32 @@ protected function inventory(): self if (empty($this->data['entity']['inventories'])) { return $this; } - - dd('inventories, uh oh'); + $fields = [ + 'name', + 'amount', + 'position', + 'description', + 'visibility_id', + 'is_equipped', + 'copy_item_entry', + ]; + foreach ($this->data['entity']['inventories'] as $data) { + + $inv = new Inventory(); + $inv->entity_id = $this->entity->id; + if (!empty($data['item_id'])) { + $itemID = ImportIdMapper::get('items', $data['item_id']); + if (empty($itemID)) { + continue; + } + $inv->item_id = $itemID; + } + $inv->created_by = $this->user->id; + foreach ($fields as $field) { + $inv->$field = $data[$field]; + } + $inv->save(); + } return $this; } diff --git a/lang/en/campaigns/import.php b/lang/en/campaigns/import.php index 52dbcaa705..443ff43a83 100644 --- a/lang/en/campaigns/import.php +++ b/lang/en/campaigns/import.php @@ -7,6 +7,7 @@ 'title' => 'Import', 'fields' => [ 'file' => 'Export ZIP file', + 'updated' => 'Last updated', ], 'status' => [ 'running' => 'Running', diff --git a/lang/en/notifications.php b/lang/en/notifications.php index bc9332a6ec..e46375efd6 100644 --- a/lang/en/notifications.php +++ b/lang/en/notifications.php @@ -38,6 +38,10 @@ 'troubleshooting' => [ 'joined' => 'The Kanka team-member :user joined the campaign :campaign.', ], + 'import' => [ + 'success' => 'Campaign :campaign finished importing.', + 'fail' => 'Campaign :campaign failed to import.', + ] ], 'clear' => [ 'action' => 'Clear all',