runners refactoring
This commit is contained in:
@@ -32,12 +32,9 @@ require_once('../../../bootstrap.php');
|
|||||||
use Espo\Core\{
|
use Espo\Core\{
|
||||||
Portal\Application,
|
Portal\Application,
|
||||||
Portal\ApplicationRunners\Api,
|
Portal\ApplicationRunners\Api,
|
||||||
|
Portal\Utils\Url,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!empty($_GET['portalId'])) {
|
$portalId = Url::detectPortalIdForApi();
|
||||||
$portalId = $_GET['portalId'];
|
|
||||||
} else {
|
|
||||||
$portalId = explode('/', $_SERVER['REQUEST_URI'])[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
(new Application($portalId))->run(Api::class);
|
(new Application($portalId))->run(Api::class);
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ use Espo\Core\{
|
|||||||
Container\ContainerBuilder,
|
Container\ContainerBuilder,
|
||||||
InjectableFactory,
|
InjectableFactory,
|
||||||
Container,
|
Container,
|
||||||
|
Application\Runner,
|
||||||
|
Application\RunnerParams,
|
||||||
ApplicationUser,
|
ApplicationUser,
|
||||||
Utils\Autoload,
|
Utils\Autoload,
|
||||||
Utils\Config,
|
Utils\Config,
|
||||||
@@ -42,7 +44,6 @@ use Espo\Core\{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use StdClass;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A central access point of the application.
|
* A central access point of the application.
|
||||||
@@ -66,9 +67,12 @@ class Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a specific application runner.
|
* Run an application runner.
|
||||||
|
*
|
||||||
|
* @param $className A runner class name.
|
||||||
|
* @param $params Runner parameters. Will be passed to a runner's constructor.
|
||||||
*/
|
*/
|
||||||
public function run(string $className, ?StdClass $params = null) : void
|
public function run(string $className, ?RunnerParams $params = null) : void
|
||||||
{
|
{
|
||||||
if (!$className || !class_exists($className)) {
|
if (!$className || !class_exists($className)) {
|
||||||
$this->getLog()->error("Application runner '{$className}' does not exist.");
|
$this->getLog()->error("Application runner '{$className}' does not exist.");
|
||||||
@@ -89,9 +93,13 @@ class Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
$runner = $this->getInjectableFactory()->createWith($className, [
|
$runner = $this->getInjectableFactory()->createWith($className, [
|
||||||
'params' => $params,
|
'params' => $params ?? RunnerParams::fromNothing(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (!$runner instanceof Runner) {
|
||||||
|
die("Class should implement Runner interface.");
|
||||||
|
}
|
||||||
|
|
||||||
$runner->run();
|
$runner->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
/************************************************************************
|
||||||
|
* This file is part of EspoCRM.
|
||||||
|
*
|
||||||
|
* EspoCRM - Open Source CRM application.
|
||||||
|
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||||
|
* Website: https://www.espocrm.com
|
||||||
|
*
|
||||||
|
* EspoCRM is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* EspoCRM is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of this program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU General Public License version 3.
|
||||||
|
*
|
||||||
|
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||||
|
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
namespace Espo\Core\Application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for an application runner.
|
||||||
|
*/
|
||||||
|
class RunnerParams
|
||||||
|
{
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
private function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a parameter value.
|
||||||
|
*
|
||||||
|
* @return ?mixed
|
||||||
|
*/
|
||||||
|
public function get(string $name)
|
||||||
|
{
|
||||||
|
return $this->data[$name] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a parameter is set.
|
||||||
|
*/
|
||||||
|
public function has(string $name) : bool
|
||||||
|
{
|
||||||
|
return array_key_exists($name, $this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone with a parameter value.
|
||||||
|
*
|
||||||
|
* @param ?mixed $value
|
||||||
|
*/
|
||||||
|
public function with(string $name, $value) : self
|
||||||
|
{
|
||||||
|
$obj = clone $this;
|
||||||
|
|
||||||
|
$obj->data[$name] = $value;
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create from an array.
|
||||||
|
*/
|
||||||
|
public static function fromArray(array $data) : self
|
||||||
|
{
|
||||||
|
$obj = new self();
|
||||||
|
|
||||||
|
$obj->data = $data;
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty instance.
|
||||||
|
*/
|
||||||
|
public static function fromNothing() : self
|
||||||
|
{
|
||||||
|
return new self();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -107,7 +107,7 @@ class Api implements Runner
|
|||||||
$slim->run();
|
$slim->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addRoute(SlimApp $slim, array $item)
|
private function addRoute(SlimApp $slim, array $item) : void
|
||||||
{
|
{
|
||||||
$method = strtolower($item['method']);
|
$method = strtolower($item['method']);
|
||||||
$route = $item['route'];
|
$route = $item['route'];
|
||||||
@@ -168,8 +168,10 @@ class Api implements Runner
|
|||||||
return $params;
|
return $params;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function processRequest(array $item, RequestWrapper $requestWrapped, ResponseWrapper $responseWrapped)
|
private function processRequest(
|
||||||
{
|
array $item, RequestWrapper $requestWrapped, ResponseWrapper $responseWrapped
|
||||||
|
) : void {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$authRequired = !($item['noAuth'] ?? false);
|
$authRequired = !($item['noAuth'] ?? false);
|
||||||
|
|
||||||
@@ -204,7 +206,8 @@ class Api implements Runner
|
|||||||
|
|
||||||
private function handleException(
|
private function handleException(
|
||||||
Throwable $exception, RequestWrapper $requestWrapped, ResponseWrapper $responseWrapped, string $route
|
Throwable $exception, RequestWrapper $requestWrapped, ResponseWrapper $responseWrapped, string $route
|
||||||
) {
|
) : void {
|
||||||
|
|
||||||
$errorOutput = new ApiErrorOutput($requestWrapped, $route);
|
$errorOutput = new ApiErrorOutput($requestWrapped, $route);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ use Espo\Core\{
|
|||||||
*/
|
*/
|
||||||
class Client implements Runner
|
class Client implements Runner
|
||||||
{
|
{
|
||||||
protected $clientManager;
|
private $clientManager;
|
||||||
|
|
||||||
public function __construct(ClientManager $clientManager)
|
public function __construct(ClientManager $clientManager)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class Command implements Runner
|
|||||||
use Cli;
|
use Cli;
|
||||||
use SetupSystemUser;
|
use SetupSystemUser;
|
||||||
|
|
||||||
protected $commandManager;
|
private $commandManager;
|
||||||
|
|
||||||
public function __construct(ConsoleCommandManager $commandManager)
|
public function __construct(ConsoleCommandManager $commandManager)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Espo\Core\ApplicationRunners;
|
|||||||
|
|
||||||
use Espo\Core\{
|
use Espo\Core\{
|
||||||
Application\Runner,
|
Application\Runner,
|
||||||
|
Application\RunnerParams,
|
||||||
Exceptions\Error,
|
Exceptions\Error,
|
||||||
EntryPoint\EntryPointManager,
|
EntryPoint\EntryPointManager,
|
||||||
ApplicationUser,
|
ApplicationUser,
|
||||||
@@ -52,7 +53,6 @@ use Slim\{
|
|||||||
Psr7\Response,
|
Psr7\Response,
|
||||||
};
|
};
|
||||||
|
|
||||||
use StdClass;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +84,7 @@ class EntryPoint implements Runner
|
|||||||
ApplicationUser $applicationUser,
|
ApplicationUser $applicationUser,
|
||||||
AuthTokenManager $authTokenManager,
|
AuthTokenManager $authTokenManager,
|
||||||
AuthBuilderFactory $authBuilderFactory,
|
AuthBuilderFactory $authBuilderFactory,
|
||||||
?StdClass $params = null
|
?RunnerParams $params = null
|
||||||
) {
|
) {
|
||||||
$this->authenticationFactory = $authenticationFactory;
|
$this->authenticationFactory = $authenticationFactory;
|
||||||
$this->entryPointManager = $entryPointManager;
|
$this->entryPointManager = $entryPointManager;
|
||||||
@@ -94,7 +94,7 @@ class EntryPoint implements Runner
|
|||||||
$this->authTokenManager = $authTokenManager;
|
$this->authTokenManager = $authTokenManager;
|
||||||
$this->authBuilderFactory = $authBuilderFactory;
|
$this->authBuilderFactory = $authBuilderFactory;
|
||||||
|
|
||||||
$this->params = $params ?? (object) [];
|
$this->params = $params ?? RunnerParams::fromNothing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run() : void
|
public function run() : void
|
||||||
@@ -108,9 +108,9 @@ class EntryPoint implements Runner
|
|||||||
throw new Error("Only GET requests allowed for entry points.");
|
throw new Error("Only GET requests allowed for entry points.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$entryPoint = $this->params->entryPoint ?? $requestWrapped->getQueryParam('entryPoint');
|
$entryPoint = $this->params->get('entryPoint') ?? $requestWrapped->getQueryParam('entryPoint');
|
||||||
|
|
||||||
$final = $this->params->final ?? false;
|
$final = $this->params->get('final') ?? false;
|
||||||
|
|
||||||
if (!$entryPoint) {
|
if (!$entryPoint) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@@ -136,7 +136,7 @@ class EntryPoint implements Runner
|
|||||||
(new ResponseEmitter())->emit($responseWrapped->getResponse());
|
(new ResponseEmitter())->emit($responseWrapped->getResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function processRequest(
|
private function processRequest(
|
||||||
string $entryPoint,
|
string $entryPoint,
|
||||||
RequestWrapper $requestWrapped,
|
RequestWrapper $requestWrapped,
|
||||||
ResponseWrapper $responseWrapped,
|
ResponseWrapper $responseWrapped,
|
||||||
@@ -181,7 +181,7 @@ class EntryPoint implements Runner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function detectPortalId(RequestWrapper $requestWrapped) : ?string
|
private function detectPortalId(RequestWrapper $requestWrapped) : ?string
|
||||||
{
|
{
|
||||||
if ($requestWrapped->hasQueryParam('portalId')) {
|
if ($requestWrapped->hasQueryParam('portalId')) {
|
||||||
return $requestWrapped->getQueryParam('portalId');
|
return $requestWrapped->getQueryParam('portalId');
|
||||||
@@ -202,15 +202,17 @@ class EntryPoint implements Runner
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function runThroughPortal(string $portalId, string $entryPoint) : void
|
private function runThroughPortal(string $portalId, string $entryPoint) : void
|
||||||
{
|
{
|
||||||
$app = new PortalApplication($portalId);
|
$app = new PortalApplication($portalId);
|
||||||
|
|
||||||
$app->setClientBasePath($this->clientManager->getBasePath());
|
$app->setClientBasePath($this->clientManager->getBasePath());
|
||||||
|
|
||||||
$app->run(EntryPoint::class, (object) [
|
$params = RunnerParams::fromArray([
|
||||||
'entryPoint' => $entryPoint,
|
'entryPoint' => $entryPoint,
|
||||||
'final' => true,
|
'final' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$app->run(EntryPoint::class, $params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,11 +31,10 @@ namespace Espo\Core\ApplicationRunners;
|
|||||||
|
|
||||||
use Espo\Core\{
|
use Espo\Core\{
|
||||||
Application\Runner,
|
Application\Runner,
|
||||||
|
Application\RunnerParams,
|
||||||
Job\JobManager,
|
Job\JobManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
use StdClass;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a job by ID. A job record should exist in database.
|
* Runs a job by ID. A job record should exist in database.
|
||||||
*/
|
*/
|
||||||
@@ -44,11 +43,11 @@ class Job implements Runner
|
|||||||
use Cli;
|
use Cli;
|
||||||
use SetupSystemUser;
|
use SetupSystemUser;
|
||||||
|
|
||||||
protected $params;
|
private $params;
|
||||||
|
|
||||||
private $jobManager;
|
private $jobManager;
|
||||||
|
|
||||||
public function __construct(JobManager $jobManager, StdClass $params)
|
public function __construct(JobManager $jobManager, RunnerParams $params)
|
||||||
{
|
{
|
||||||
$this->jobManager = $jobManager;
|
$this->jobManager = $jobManager;
|
||||||
|
|
||||||
@@ -57,6 +56,8 @@ class Job implements Runner
|
|||||||
|
|
||||||
public function run() : void
|
public function run() : void
|
||||||
{
|
{
|
||||||
$this->jobManager->runJobById($this->params->id);
|
$id = $this->params->get('id');
|
||||||
|
|
||||||
|
$this->jobManager->runJobById($id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Espo\Core\ApplicationRunners;
|
|||||||
|
|
||||||
use Espo\Core\{
|
use Espo\Core\{
|
||||||
Application\Runner,
|
Application\Runner,
|
||||||
|
Application\RunnerParams,
|
||||||
Exceptions\NotFound,
|
Exceptions\NotFound,
|
||||||
Utils\ClientManager,
|
Utils\ClientManager,
|
||||||
Utils\Config,
|
Utils\Config,
|
||||||
@@ -48,7 +49,6 @@ use Slim\{
|
|||||||
Psr7\Response,
|
Psr7\Response,
|
||||||
};
|
};
|
||||||
|
|
||||||
use StdClass;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,27 +56,27 @@ use Exception;
|
|||||||
*/
|
*/
|
||||||
class PortalClient implements Runner
|
class PortalClient implements Runner
|
||||||
{
|
{
|
||||||
protected $params;
|
private $params;
|
||||||
|
|
||||||
protected $clientManager;
|
private $clientManager;
|
||||||
|
|
||||||
protected $config;
|
private $config;
|
||||||
|
|
||||||
public function __construct(ClientManager $clientManager, Config $config, ?StdClass $params = null)
|
public function __construct(ClientManager $clientManager, Config $config, ?RunnerParams $params = null)
|
||||||
{
|
{
|
||||||
$this->clientManager = $clientManager;
|
$this->clientManager = $clientManager;
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
$this->params = $params ?? (object) [];
|
$this->params = $params ?? RunnerParams::fromNothing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run() : void
|
public function run() : void
|
||||||
{
|
{
|
||||||
$id = $this->params->id ??
|
$id = $this->params->get('id') ??
|
||||||
Url::detectPortalId() ??
|
Url::detectPortalId() ??
|
||||||
$this->config->get('defaultPortalId');
|
$this->config->get('defaultPortalId');
|
||||||
|
|
||||||
$basePath = $this->params->basePath ?? $this->clientManager->getBasePath();
|
$basePath = $this->params->get('basePath') ?? $this->clientManager->getBasePath();
|
||||||
|
|
||||||
$requestWrapped = new RequestWrapper(
|
$requestWrapped = new RequestWrapper(
|
||||||
ServerRequestCreatorFactory::create()->createServerRequestFromGlobals()
|
ServerRequestCreatorFactory::create()->createServerRequestFromGlobals()
|
||||||
@@ -108,7 +108,7 @@ class PortalClient implements Runner
|
|||||||
$application->run(PortalPortalClient::class);
|
$application->run(PortalPortalClient::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function processError(RequestWrapper $request, ResponseWrapper $response, Exception $exception)
|
private function processError(RequestWrapper $request, ResponseWrapper $response, Exception $exception) : void
|
||||||
{
|
{
|
||||||
(new ApiErrorOutput($request))->process($response, $exception, true);
|
(new ApiErrorOutput($request))->process($response, $exception, true);
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Rebuild implements Runner
|
|||||||
{
|
{
|
||||||
use Cli;
|
use Cli;
|
||||||
|
|
||||||
protected $dataManager;
|
private $dataManager;
|
||||||
|
|
||||||
public function __construct(DataManager $dataManager)
|
public function __construct(DataManager $dataManager)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace Espo\Core\Job;
|
|||||||
use Espo\Core\{
|
use Espo\Core\{
|
||||||
Application,
|
Application,
|
||||||
ApplicationRunners\Job as JobRunner,
|
ApplicationRunners\Job as JobRunner,
|
||||||
|
Application\RunnerParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
use Spatie\Async\Task as AsyncTask;
|
use Spatie\Async\Task as AsyncTask;
|
||||||
@@ -55,12 +56,12 @@ class JobTask extends AsyncTask
|
|||||||
{
|
{
|
||||||
$app = new Application();
|
$app = new Application();
|
||||||
|
|
||||||
$data = (object) [
|
$params = RunnerParams::fromArray([
|
||||||
'id' => $this->jobId,
|
'id' => $this->jobId,
|
||||||
];
|
]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$app->run(JobRunner::class, $data);
|
$app->run(JobRunner::class, $params);
|
||||||
}
|
}
|
||||||
catch (Throwable $e) {
|
catch (Throwable $e) {
|
||||||
$GLOBALS['log']->error(
|
$GLOBALS['log']->error(
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ use Espo\Core\{
|
|||||||
*/
|
*/
|
||||||
class Client implements Runner
|
class Client implements Runner
|
||||||
{
|
{
|
||||||
protected $clientManager;
|
private $clientManager;
|
||||||
|
|
||||||
protected $applicationState;
|
private $applicationState;
|
||||||
|
|
||||||
public function __construct(ClientManager $clientManager, ApplicationState $applicationState)
|
public function __construct(ClientManager $clientManager, ApplicationState $applicationState)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,17 @@ namespace Espo\Core\Portal\Utils;
|
|||||||
|
|
||||||
class Url
|
class Url
|
||||||
{
|
{
|
||||||
|
public static function detectPortalIdForApi() : ?string
|
||||||
|
{
|
||||||
|
if (!empty($_GET['portalId'])) {
|
||||||
|
return $_GET['portalId'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = $_SERVER['REQUEST_URI'];
|
||||||
|
|
||||||
|
return explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
public static function detectPortalId() : ?string
|
public static function detectPortalId() : ?string
|
||||||
{
|
{
|
||||||
$portalId = $_SERVER['ESPO_PORTAL_ID'] ?? null;
|
$portalId = $_SERVER['ESPO_PORTAL_ID'] ?? null;
|
||||||
|
|||||||
@@ -39,11 +39,13 @@ $app = new Application();
|
|||||||
|
|
||||||
if (!$app->isInstalled()) {
|
if (!$app->isInstalled()) {
|
||||||
header("Location: install/");
|
header("Location: install/");
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_GET['entryPoint'])) {
|
if (!empty($_GET['entryPoint'])) {
|
||||||
$app->run(EntryPoint::class);
|
$app->run(EntryPoint::class);
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -31,6 +31,7 @@ include "../bootstrap.php";
|
|||||||
|
|
||||||
use Espo\Core\{
|
use Espo\Core\{
|
||||||
Application,
|
Application,
|
||||||
|
Application\RunnerParams,
|
||||||
ApplicationRunners\EntryPoint,
|
ApplicationRunners\EntryPoint,
|
||||||
ApplicationRunners\PortalClient,
|
ApplicationRunners\PortalClient,
|
||||||
Portal\Utils\Url,
|
Portal\Utils\Url,
|
||||||
@@ -58,6 +59,8 @@ if (!empty($_GET['entryPoint'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$app->run(PortalClient::class, (object) [
|
$params = RunnerParams::fromArray([
|
||||||
'basePath' => $basePath,
|
'basePath' => $basePath,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$app->run(PortalClient::class, $params);
|
||||||
|
|||||||
Reference in New Issue
Block a user