Created
June 22, 2017 14:35
-
-
Save geerteltink/9a0f13b759e4581f4e69571fda764c7f to your computer and use it in GitHub Desktop.
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
<?php | |
namespace App\Application\Console; | |
class CreateMiddleware | |
{ | |
/** | |
* @var string Template for middleware class. | |
*/ | |
const MIDDLEWARE_SKELETON = <<< 'EOS' | |
<?php | |
declare(strict_types=1); | |
namespace %namespace%; | |
use Interop\Http\ServerMiddleware\DelegateInterface; | |
use Interop\Http\ServerMiddleware\MiddlewareInterface; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\ServerRequestInterface; | |
class %class% implements MiddlewareInterface | |
{ | |
public function __construct() | |
{ | |
} | |
public function process(ServerRequestInterface $request, DelegateInterface $delegate): ResponseInterface | |
{ | |
// Do something (with the request) first | |
// Call the next middleware and wait for the response | |
$response = $delegate->process($request); | |
// Do something (with the response) before returning the response | |
// Return the response | |
return $response; | |
} | |
} | |
EOS; | |
/** | |
* @var string Template for middleware class. | |
*/ | |
const ACTION_SKELETON = <<< 'EOS' | |
<?php | |
declare(strict_types=1); | |
namespace %namespace%; | |
use App\Infrastructure\View\StreamRenderer; | |
use Interop\Http\ServerMiddleware\DelegateInterface; | |
use Interop\Http\ServerMiddleware\MiddlewareInterface; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\ServerRequestInterface; | |
use Zend\Diactoros\Response\HtmlResponse; | |
class %class% implements MiddlewareInterface | |
{ | |
/** | |
* @var StreamRenderer | |
*/ | |
private $renderer; | |
public function __construct(StreamRenderer $renderer) | |
{ | |
$this->renderer = $renderer; | |
} | |
public function process(ServerRequestInterface $request, DelegateInterface $delegate): ResponseInterface | |
{ | |
return new HtmlResponse($this->renderer->render($request, '%path%::%template%')); | |
} | |
} | |
EOS; | |
/** | |
* @var string Template for middleware class. | |
*/ | |
const API_SKELETON = <<< 'EOS' | |
<?php | |
declare(strict_types=1); | |
namespace %namespace%; | |
use Interop\Http\ServerMiddleware\DelegateInterface; | |
use Interop\Http\ServerMiddleware\MiddlewareInterface; | |
use Psr\Http\Message\ResponseInterface; | |
use Psr\Http\Message\ServerRequestInterface; | |
use Zend\Diactoros\Response\JsonResponse; | |
class %class% implements MiddlewareInterface | |
{ | |
public function __construct() | |
{ | |
} | |
public function process(ServerRequestInterface $request, DelegateInterface $delegate): ResponseInterface | |
{ | |
return new JsonResponse([]); | |
} | |
} | |
EOS; | |
const TEMPLATE_SKELETON = <<< 'EOS' | |
<?php $this->layout('layout::%path%', ['title' => '%template%']); ?> | |
<h1>%template%</h1> | |
EOS; | |
/** | |
* @param string $class | |
* @param string|null $projectRoot | |
* | |
* @return string | |
* @throws CreateMiddlewareException | |
*/ | |
public function process($class, $projectRoot = null): string | |
{ | |
$templatePath = $templateNamespace = $templateName = null; | |
$projectRoot = $projectRoot ?: getcwd(); | |
$path = $this->getClassPath($class, $projectRoot); | |
$templateData = $this->getTemplateNamespaceAndName($class); | |
[$namespace, $class] = $this->getNamespaceAndClass($class); | |
$api = strpos($namespace, '\\Api'); | |
// Middleware | |
$skeleton = self::MIDDLEWARE_SKELETON; | |
// HtmlResponse Action | |
if ($api === false && substr($class, -6) === 'Action') { | |
$skeleton = self::ACTION_SKELETON; | |
[$templateNamespace, $templatePath, $templateName] = $templateData; | |
} | |
// JsonResponse API Action | |
if ($api !== false) { | |
$skeleton = self::API_SKELETON; | |
} | |
$content = str_replace( | |
['%namespace%', '%class%', '%path%', '%template%'], | |
[$namespace, $class, $templateNamespace, $templatePath . $templateName], | |
$skeleton | |
); | |
if (is_file($path)) { | |
throw CreateMiddlewareException::unableToCreatePath($path, $class); | |
} | |
// Create middleware class | |
file_put_contents($path, $content); | |
if ($templatePath !== null) { | |
// Create template | |
$content = str_replace( | |
['%namespace%', '%class%', '%path%', '%template%'], | |
[$namespace, $class, $templateNamespace, $templatePath . $templateName], | |
self::TEMPLATE_SKELETON | |
); | |
file_put_contents(sprintf( | |
'resources/templates/%s/%s%s.phtml', | |
$templateNamespace, | |
$templatePath, | |
$templateName | |
), $content); | |
} | |
return $path; | |
} | |
/** | |
* @param string $class | |
* @param string $projectRoot | |
* | |
* @return string | |
* @throws CreateMiddlewareException | |
*/ | |
private function getClassPath($class, $projectRoot): string | |
{ | |
$autoloaders = $this->getComposerAutoloaders($projectRoot); | |
[$namespace, $path] = $this->discoverNamespaceAndPath($class, $autoloaders); | |
// Absolute path to namespace | |
$path = implode([$projectRoot, DIRECTORY_SEPARATOR, $path]); | |
$parts = explode('\\', $class); | |
$className = array_pop($parts); | |
// Create absolute path to subnamespace, if required | |
//$nsParts = explode('\\', trim($namespace, '\\')); | |
$subNsParts = array_slice($parts, substr_count(trim($namespace, '\\'), '\\') + 1); | |
if (0 < count($subNsParts)) { | |
$subNsPath = implode(DIRECTORY_SEPARATOR, $subNsParts); | |
$path = implode([$path, DIRECTORY_SEPARATOR, $subNsPath]); | |
} | |
// Create path if it does not exist | |
if (! @mkdir($path, 0755, true) && ! is_dir($path)) { | |
throw CreateMiddlewareException::unableToCreatePath($path, $class); | |
} | |
return $path . DIRECTORY_SEPARATOR . $className . '.php'; | |
} | |
/** | |
* @param string $projectRoot | |
* | |
* @return array Associative array of namespace/path pairs | |
* @throws CreateMiddlewareException | |
*/ | |
private function getComposerAutoloaders($projectRoot): array | |
{ | |
$composerPath = sprintf('%s/composer.json', $projectRoot); | |
if (! file_exists($composerPath)) { | |
throw CreateMiddlewareException::missingComposerJson(); | |
} | |
$composer = json_decode(file_get_contents($composerPath), true); | |
if (json_last_error() !== \JSON_ERROR_NONE) { | |
throw CreateMiddlewareException::invalidComposerJson(json_last_error_msg()); | |
} | |
if (! isset($composer['autoload']['psr-4'])) { | |
throw CreateMiddlewareException::missingComposerAutoloaders(); | |
} | |
if (! is_array($composer['autoload']['psr-4'])) { | |
throw CreateMiddlewareException::missingComposerAutoloaders(); | |
} | |
return $composer['autoload']['psr-4']; | |
} | |
/** | |
* @param string $class | |
* @param array $autoloaders | |
* | |
* @return array [namespace, path] | |
* @throws CreateMiddlewareException | |
*/ | |
private function discoverNamespaceAndPath($class, array $autoloaders): array | |
{ | |
$discoveredPath = false; | |
foreach ($autoloaders as $namespace => $path) { | |
if (0 === strpos($class, $namespace)) { | |
$path = trim( | |
str_replace( | |
['/', '\\'], | |
DIRECTORY_SEPARATOR, | |
$path | |
), | |
DIRECTORY_SEPARATOR | |
); | |
return [$namespace, $path]; | |
} | |
} | |
throw CreateMiddlewareException::autoloaderNotFound($class); | |
} | |
/** | |
* @param string $class | |
* | |
* @return array [namespace, class] | |
*/ | |
private function getNamespaceAndClass($class): array | |
{ | |
$parts = explode('\\', $class); | |
$className = array_pop($parts); | |
$namespace = implode('\\', $parts); | |
return [$namespace, $className]; | |
} | |
private function getTemplateNamespaceAndName($class): array | |
{ | |
$parts = explode('\\', $class); | |
if ($parts[0] = 'App') { | |
unset($parts[0]); | |
} | |
if ($parts[1] = 'Application') { | |
unset($parts[1]); | |
} | |
$namespace = strtolower(array_shift($parts)); | |
$template = strtolower(array_pop($parts)); | |
$template = preg_replace('/action$/', '', $template); | |
$path = sprintf('%s/', strtolower(implode('/', $parts))); | |
$realPath = sprintf('resources/templates/%s/%s/', $namespace, strtolower(implode('/', $parts))); | |
// Create path if it does not exist | |
if (! @mkdir($realPath, 0755, true) && ! is_dir($realPath)) { | |
throw CreateMiddlewareException::unableToCreatePath($realPath, $class); | |
} | |
return [$namespace, $path, $template]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment