mirror of
https://gh.wpcy.net/https://github.com/fairpm/aspirecloud.git
synced 2026-06-20 02:22:28 +08:00
94 lines
3 KiB
PHP
94 lines
3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Actions\Admin\API\V1;
|
|
|
|
use App\Http\JsonLines;
|
|
use App\Http\JsonResponses;
|
|
use App\Models\WpOrg\ClosedPlugin;
|
|
use App\Models\WpOrg\Plugin;
|
|
use App\Models\WpOrg\Theme;
|
|
use Exception;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Pipeline\Pipeline;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
use function Safe\ini_set;
|
|
|
|
class BulkImport
|
|
{
|
|
use JsonResponses;
|
|
use JsonLines;
|
|
|
|
public function __invoke(Request $request, Pipeline $pipeline): JsonResponse
|
|
{
|
|
ini_set('memory_limit', '2G');
|
|
ini_set('max_execution_time', '300');
|
|
|
|
$currentLine = 0;
|
|
$imported = 0;
|
|
$errors = [];
|
|
|
|
$request_info = ['userid' => auth()->user()?->id, 'ip' => $request->ip()];
|
|
|
|
Log::info("Beginning bulk import", $request_info);
|
|
|
|
foreach ($this->lazyJsonLines($request) as $metadata) {
|
|
$currentLine++;
|
|
try {
|
|
$model = DB::transaction(fn() => $this->loadOne($metadata));
|
|
assert($model instanceof Model); // strip 'mixed' type from DB::transaction
|
|
Log::debug(
|
|
"Imported {$model->slug}",
|
|
['slug' => $model->slug, 'version' => $model->version, 'type' => $model->getMorphClass()],
|
|
);
|
|
$imported++;
|
|
} catch (Exception $e) {
|
|
$errors[$currentLine] = $e->getMessage();
|
|
}
|
|
}
|
|
|
|
Log::info("Bulk import complete", [...$request_info, 'imported' => $imported, 'errors' => $errors]);
|
|
|
|
return $errors ? $this->error(compact('errors', 'imported')) : $this->success(['imported' => $imported]);
|
|
}
|
|
|
|
/** @param array<string, mixed> $metadata */
|
|
private function loadOne(array $metadata): Plugin|ClosedPlugin|Theme
|
|
{
|
|
$sync_meta = $metadata['aspiresync_meta'];
|
|
$type = $sync_meta['type'];
|
|
$status = $sync_meta['status'];
|
|
|
|
$class = match ($type) {
|
|
'plugin' => match ($status) {
|
|
'open' => Plugin::class,
|
|
'closed' => ClosedPlugin::class,
|
|
default => throw new Exception("Unknown plugin status: {$status}"),
|
|
},
|
|
'theme' => match ($status) {
|
|
'open' => Theme::class,
|
|
// Closed themes don't seem to be a thing, they're just 404 in the API
|
|
default => throw new Exception("Unknown theme status: {$status}"),
|
|
},
|
|
default => throw new Exception("Unknown plugin type: {$type}"),
|
|
};
|
|
|
|
$slug = $metadata['slug'];
|
|
|
|
assert(is_a($class, Model::class, true)); // @phpstan-ignore function.alreadyNarrowedType (that's the POINT!)
|
|
|
|
if ($type === 'plugin') {
|
|
Plugin::where('slug', $slug)->delete();
|
|
ClosedPlugin::where('slug', $slug)->delete();
|
|
} elseif ($type === 'theme') {
|
|
Theme::where('slug', $slug)->delete();
|
|
}
|
|
|
|
return $class::fromSyncMetadata($metadata);
|
|
}
|
|
}
|