-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from softonic/feature/Extract-classes-to-library
Extracted classes to library
- Loading branch information
Showing
11 changed files
with
466 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
* @<AUTHOR> | ||
* @xaviapa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
|
||
namespace Softonic\RestApiNestedResources\Http\Middleware; | ||
|
||
use Illuminate\Http\Request; | ||
use Illuminate\Support\Arr; | ||
use Softonic\RestApiNestedResources\Http\Traits\PathParameters; | ||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException; | ||
|
||
/** | ||
* Middleware that checks if model does not exist. | ||
*/ | ||
class EnsureModelDoesNotExist | ||
{ | ||
use PathParameters; | ||
|
||
public function handle(Request $request, callable $next, string $modelClass, ...$fieldsToCheck) | ||
{ | ||
$parametersToCheck = $this->getParametersToCheck($request, $fieldsToCheck); | ||
|
||
$found = (bool)($modelClass)::where($parametersToCheck) | ||
->count(); | ||
|
||
if ($found) { | ||
throw new ConflictHttpException( | ||
"{$modelClass} resource already exists for " . json_encode($parametersToCheck, JSON_THROW_ON_ERROR) | ||
); | ||
} | ||
|
||
return $next($request); | ||
} | ||
|
||
private function getParametersToCheck(Request $request, array $fieldsToCheck): array | ||
{ | ||
$pathParameters = $this->getPathParameters($request); | ||
|
||
$parameters = array_merge($request->all(), $pathParameters); | ||
|
||
return Arr::only($parameters, $fieldsToCheck); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
namespace Softonic\RestApiNestedResources\Http\Middleware; | ||
|
||
use Illuminate\Http\Request; | ||
use Softonic\RestApiNestedResources\Http\Traits\PathParameters; | ||
use Softonic\RestApiNestedResources\PreProcessors\EnsureModelExists as EnsureModelExistsProcessor; | ||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException; | ||
|
||
/** | ||
* Middleware that checks if model exists. | ||
*/ | ||
class EnsureModelExists | ||
{ | ||
use PathParameters; | ||
|
||
public function __construct(private EnsureModelExistsProcessor $ensureModelExists) | ||
{ | ||
} | ||
|
||
/** | ||
* @throws ConflictHttpException | ||
*/ | ||
public function handle(Request $request, callable $next, string $modelClass, ...$fieldsToCheck) | ||
{ | ||
$pathParameters = $this->getPathParameters($request); | ||
|
||
$parameters = array_merge($request->all(), $pathParameters); | ||
|
||
$this->ensureModelExists->process($modelClass, $fieldsToCheck, $parameters); | ||
|
||
return $next($request); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<?php | ||
|
||
namespace Softonic\RestApiNestedResources\Http\Middleware; | ||
|
||
use Closure; | ||
use Illuminate\Container\Container; | ||
use Illuminate\Contracts\Routing\Registrar; | ||
use Illuminate\Contracts\Routing\UrlRoutable; | ||
use Illuminate\Database\Eloquent\ModelNotFoundException; | ||
use Illuminate\Http\Request; | ||
use Illuminate\Routing\Route; | ||
use Illuminate\Support\Str; | ||
use Softonic\RestApiNestedResources\Models\MultiKeyModel; | ||
|
||
class SubstituteBindings | ||
{ | ||
/** | ||
* The router instance. | ||
*/ | ||
protected Registrar $router; | ||
|
||
/** | ||
* The IoC container instance. | ||
*/ | ||
protected Container $container; | ||
|
||
/** | ||
* Create a new bindings substitutor. | ||
* | ||
* @return void | ||
*/ | ||
public function __construct(Registrar $router, Container $container = null) | ||
{ | ||
$this->router = $router; | ||
$this->container = $container ?: new Container; | ||
} | ||
|
||
/** | ||
* Handle an incoming request. | ||
* | ||
* @return mixed | ||
*/ | ||
public function handle(Request $request, Closure $next) | ||
{ | ||
$this->router->substituteBindings($route = $request->route()); | ||
|
||
$this->substituteImplicitBindings($route); | ||
|
||
return $next($request); | ||
} | ||
|
||
/** | ||
* Substitute the implicit Eloquent model bindings for the route. | ||
*/ | ||
protected function substituteImplicitBindings(Route $route): void | ||
{ | ||
$this->resolveForRoute($route); | ||
} | ||
|
||
/** | ||
* Resolve the implicit route bindings for the given route. | ||
*/ | ||
protected function resolveForRoute(Route $route): void | ||
{ | ||
$parameters = $route->parameters(); | ||
|
||
foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) { | ||
if (!$pathParameters = static::getPathParameters($parameter->name, $parameters)) { | ||
continue; | ||
} | ||
|
||
if ($pathParameters instanceof UrlRoutable) { | ||
continue; | ||
} | ||
|
||
$instance = $this->container->make($parameter->getType()->getName()); | ||
|
||
try { | ||
$id = ($instance instanceof MultiKeyModel) | ||
? $instance::generateIdForField($instance->getKeyName(), $pathParameters) | ||
: $pathParameters[$instance->getKeyName()]; | ||
$model = $instance::findOrFail($id); | ||
} catch (ModelNotFoundException $e) { | ||
throw new ModelNotFoundException( | ||
"{$e->getModel()} resource not found for " . json_encode($pathParameters, JSON_THROW_ON_ERROR) | ||
); | ||
} | ||
|
||
foreach (array_keys($parameters) as $parameterName) { | ||
$route->forgetParameter($parameterName); | ||
} | ||
$route->setParameter($parameter->name, $model); | ||
} | ||
} | ||
|
||
/** | ||
* Return the path parameters prepending the "id_" string to them. | ||
*/ | ||
protected static function getPathParameters(string $name, array $parameters): array | ||
{ | ||
$pathParameters = []; | ||
$snakeName = Str::snake($name); | ||
|
||
foreach ($parameters as $parameter => $value) { | ||
$pathParameters['id_' . $parameter] = $value; | ||
|
||
$snakeName = Str::after($snakeName, $parameter); | ||
|
||
$snakeName = Str::after($snakeName, '_'); | ||
} | ||
|
||
return $pathParameters; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace Softonic\RestApiNestedResources\Http\Traits; | ||
|
||
use Illuminate\Http\Request; | ||
|
||
trait PathParameters | ||
{ | ||
public function getPathParameters(Request $request): array | ||
{ | ||
$pathParameters = $request->route() | ||
->parameters(); | ||
|
||
$pathParametersKeys = array_map( | ||
fn($key) => 'id_' . $key, | ||
array_keys($pathParameters) | ||
); | ||
|
||
return array_combine($pathParametersKeys, $pathParameters); | ||
} | ||
} |
Oops, something went wrong.