Changeset View
Changeset View
Standalone View
Standalone View
src/app/Http/Controllers/Controller.php
<?php | <?php | ||||
namespace App\Http\Controllers; | namespace App\Http\Controllers; | ||||
use Illuminate\Foundation\Bus\DispatchesJobs; | use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
use Illuminate\Routing\Controller as BaseController; | use Illuminate\Routing\Controller as BaseController; | ||||
use Illuminate\Foundation\Validation\ValidatesRequests; | use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | ||||
use Illuminate\Support\Facades\Auth; | use Illuminate\Support\Facades\Auth; | ||||
class Controller extends BaseController | class Controller extends BaseController | ||||
{ | { | ||||
use AuthorizesRequests; | use AuthorizesRequests; | ||||
use DispatchesJobs; | use DispatchesJobs; | ||||
use ValidatesRequests; | use ValidatesRequests; | ||||
/** @var array Common object properties in the API response */ | |||||
protected static $objectProps = []; | |||||
/** | /** | ||||
* Common error response builder for API (JSON) responses | * Common error response builder for API (JSON) responses | ||||
* | * | ||||
* @param int $code Error code | * @param int $code Error code | ||||
* @param string $message Error message | * @param string $message Error message | ||||
* @param array $data Additional response data | * @param array $data Additional response data | ||||
* | * | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | class Controller extends BaseController | ||||
* Get the guard to be used during authentication. | * Get the guard to be used during authentication. | ||||
* | * | ||||
* @return \Illuminate\Contracts\Auth\Guard | * @return \Illuminate\Contracts\Auth\Guard | ||||
*/ | */ | ||||
protected function guard() | protected function guard() | ||||
{ | { | ||||
return Auth::guard(); | return Auth::guard(); | ||||
} | } | ||||
/** | |||||
* Object status' process information. | |||||
* | |||||
* @param object $object The object to process | |||||
* @param array $steps The steps definition | |||||
* | |||||
* @return array Process state information | |||||
*/ | |||||
protected static function processStateInfo($object, array $steps): array | |||||
{ | |||||
$process = []; | |||||
// Create a process check list | |||||
foreach ($steps as $step_name => $state) { | |||||
$step = [ | |||||
'label' => $step_name, | |||||
'title' => \trans("app.process-{$step_name}"), | |||||
]; | |||||
if (is_array($state)) { | |||||
$step['link'] = $state[1]; | |||||
$state = $state[0]; | |||||
} | |||||
$step['state'] = $state; | |||||
$process[] = $step; | |||||
} | |||||
// Add domain specific steps | |||||
if (method_exists($object, 'domain')) { | |||||
$domain = $object->domain(); | |||||
// If that is not a public domain | |||||
if ($domain && !$domain->isPublic()) { | |||||
$domain_status = API\V4\DomainsController::statusInfo($domain); | |||||
$process = array_merge($process, $domain_status['process']); | |||||
} | |||||
} | |||||
$all = count($process); | |||||
$checked = count(array_filter($process, function ($v) { | |||||
return $v['state']; | |||||
})); | |||||
$state = $all === $checked ? 'done' : 'running'; | |||||
// After 180 seconds assume the process is in failed state, | |||||
// this should unlock the Refresh button in the UI | |||||
if ($all !== $checked && $object->created_at->diffInSeconds(\Carbon\Carbon::now()) > 180) { | |||||
$state = 'failed'; | |||||
} | |||||
return [ | |||||
'process' => $process, | |||||
'processState' => $state, | |||||
'isReady' => $all === $checked, | |||||
]; | |||||
} | |||||
/** | |||||
* Object status' process information update. | |||||
* | |||||
* @param object $object The object to process | |||||
* | |||||
* @return array Process state information | |||||
*/ | |||||
protected function processStateUpdate($object): array | |||||
{ | |||||
$response = $this->statusInfo($object); // @phpstan-ignore-line | |||||
if (!empty(request()->input('refresh'))) { | |||||
$updated = false; | |||||
$async = false; | |||||
$last_step = 'none'; | |||||
foreach ($response['process'] as $idx => $step) { | |||||
$last_step = $step['label']; | |||||
if (!$step['state']) { | |||||
$exec = $this->execProcessStep($object, $step['label']); // @phpstan-ignore-line | |||||
if (!$exec) { | |||||
if ($exec === null) { | |||||
$async = true; | |||||
} | |||||
break; | |||||
} | |||||
$updated = true; | |||||
} | |||||
} | |||||
if ($updated) { | |||||
$response = $this->statusInfo($object); // @phpstan-ignore-line | |||||
} | |||||
$success = $response['isReady']; | |||||
$suffix = $success ? 'success' : 'error-' . $last_step; | |||||
$response['status'] = $success ? 'success' : 'error'; | |||||
$response['message'] = \trans('app.process-' . $suffix); | |||||
if ($async && !$success) { | |||||
$response['processState'] = 'waiting'; | |||||
$response['status'] = 'success'; | |||||
$response['message'] = \trans('app.process-async'); | |||||
} | |||||
} | |||||
return $response; | |||||
} | |||||
/** | |||||
* Prepare an object for the UI. | |||||
* | |||||
* @param object $object An object | |||||
* @param bool $full Include all object properties | |||||
* | |||||
* @return array Object information | |||||
*/ | |||||
protected static function objectToClient($object, bool $full = false): array | |||||
mollekopf: Personally I would prefer passing $objectProps as argument instead of $full, unless… | |||||
Done Inline ActionsYes, but this way we define the common props once (per object type), so we don't have to pass them all the time as an argument. This makes also the API responses unified "automatically", i.e. reseller, admin, user end-points, all of them return the same set of object properties. machniak: Yes, but this way we define the common props once (per object type), so we don't have to pass… | |||||
{ | |||||
if ($full) { | |||||
$result = $object->toArray(); | |||||
} else { | |||||
$result = ['id' => $object->id]; | |||||
foreach (static::$objectProps as $prop) { | |||||
$result[$prop] = $object->{$prop}; | |||||
} | |||||
} | |||||
$result = array_merge($result, static::objectState($object)); // @phpstan-ignore-line | |||||
return $result; | |||||
} | |||||
} | } |
Personally I would prefer passing $objectProps as argument instead of $full, unless $objectProps becomes useful for other functions as well.
It would make it a bit clearer IMO what's going on: Either you serialize everything, or just the requested $objectProps.
That's not a blocker though.