Skip to content

Commit

Permalink
Built basic Renderer system
Browse files Browse the repository at this point in the history
Signed-off-by: Tom Wright <[email protected]>
  • Loading branch information
betterthanclay committed Jun 19, 2024
1 parent 81484f9 commit 27adc3c
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 43 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
## v0.1.0 (2024-06-19)
* Built initial implementation
* Built initial Verifier implementation
* Built basic Renderer system
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
"decodelabs/archetype": "^0.3.5",
"decodelabs/coercion": "^0.2.8",
"decodelabs/compass": "^0.1.7",
"decodelabs/dictum": "^0.6.2",
"decodelabs/exceptional": "^0.4.5",
"decodelabs/glitch-support": "^0.4.6",
"decodelabs/hydro": "^0.1.3",
"decodelabs/slingshot": "^0.1.9",
"decodelabs/tagged": "^0.15.0",
"decodelabs/veneer": "^0.10.25",

"symfony/polyfill-php82": "^1.29"
Expand Down
150 changes: 119 additions & 31 deletions src/Scrutiny/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@

namespace DecodeLabs\Scrutiny;

use Closure;
use DecodeLabs\Dovetail;
use DecodeLabs\Dovetail\Config\Scrutiny as ScrutinyConfig;
use DecodeLabs\Exceptional;
use DecodeLabs\Scrutiny;
use DecodeLabs\Scrutiny\Renderer\Custom as CustomRenderer;
use DecodeLabs\Scrutiny\Renderer\Generic as GenericRenderer;
use DecodeLabs\Slingshot;
use DecodeLabs\Tagged\Element;
use DecodeLabs\Tagged\Markup;
use DecodeLabs\Veneer;
use ReflectionClass;

class Context
{
Expand All @@ -25,6 +31,11 @@ class Context

protected ?Config $config = null;

/**
* @var array<string, Renderer>
*/
protected array $renderers = [];

/**
* Set config
*/
Expand Down Expand Up @@ -52,50 +63,133 @@ class_exists(Dovetail::class)
/**
* Load verifier
*
* @param array<string, mixed> $config
* @param array<string, mixed> $settings
*/
public function loadVerifier(
string $name,
?array $config = null
?string $name = null,
?array $settings = null
): Verifier {
if ($config === null) {
$config = $this->getConfig()?->getSettingsFor($name) ?? [];
if (!$verifier = $this->tryLoadVerifier($name, $settings)) {
throw Exceptional::NotFound(
'Verifier ' . $name . ' is not enabled'
);
}

return $verifier;
}

/**
* Try load verifier
*
* @param array<string, mixed> $settings
*/
public function tryLoadVerifier(
?string $name = null,
?array $settings = null
): ?Verifier {
$config = $this->getConfig();

if ($name === null) {
$name = $config?->getFirstEnabledVerifier();

if ($name === null) {
return null;
}
}

if ($settings === null) {
$settings = $config?->getSettingsFor($name) ?? [];
}

if (
isset($config['enabled']) &&
$config['enabled'] === false
isset($settings['enabled']) &&
$settings['enabled'] === false
) {
throw Exceptional::NotFound(
'Verifier ' . $name . ' is not enabled'
);
return null;
}

return (new Slingshot())
->addType($this)
->resolveNamedInstance(Verifier::class, $name, $config);
->resolveNamedInstance(Verifier::class, $name, $settings);
}


/**
* Load default verifier
* Render inline
*/
public function loadDefaultVerifier(): Verifier
{
$config = $this->getConfig();
$name = $config?->getFirstEnabledVerifier();
public function renderInline(
?string $verifierName = null,
?string $nonce = null
): ?Markup {
return $this->tryLoadVerifier($verifierName)
?->renderInline($nonce);
}

if ($name === null) {
throw Exceptional::NotFound(
'No verifiers are enabled'
);
/**
* Render component
*/
public function render(
?string $verifierName = null
): ?Element {
if (!$verifier = $this->tryLoadVerifier($verifierName)) {
return null;
}

return $this->loadVerifier(
$name,
$config?->getSettingsFor($name) ?? []
);
$verifierName = (new ReflectionClass($verifier))->getShortName();
return $this->getRenderer($verifierName)->render($verifier);
}

/**
* Register renderer
*/
public function registerRenderer(
string $verifierName,
Renderer $renderer
): void {
$this->renderers[$verifierName] = $renderer;
}

/**
* Register custom renderer
*/
public function registerCustomRenderer(
string $verifierName,
Closure $renderer,
): void {
$this->registerRenderer($verifierName, new CustomRenderer($renderer));
}

/**
* Register default renderer
*/
public function registerDefaultRenderer(
Renderer $renderer
): void {
$this->registerRenderer('Default', $renderer);
}

/**
* Get renderer
*/
public function getRenderer(
string $verifierName
): Renderer {
return
$this->renderers[$verifierName] ??
$this->renderers['Default'] ??
new GenericRenderer();
}

/**
* Remove renderer
*/
public function removeRenderer(
string $verifierName
): void {
unset($this->renderers[$verifierName]);
}


/**
* Create payload and verify
*
Expand Down Expand Up @@ -127,13 +221,7 @@ public function verifyPayload(
): Result {
$name = $payload->getVerifierName();

try {
if ($name === null) {
$verifier = $this->loadDefaultVerifier();
} else {
$verifier = $this->loadVerifier($name);
}
} catch (NotFoundException $e) {
if (!$verifier = $this->tryLoadVerifier($name)) {
return new Result(
payload: $payload,
errors: [
Expand Down
19 changes: 19 additions & 0 deletions src/Scrutiny/Renderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

/**
* @package Scrutiny
* @license http://opensource.org/licenses/MIT
*/

declare(strict_types=1);

namespace DecodeLabs\Scrutiny;

use DecodeLabs\Tagged\Element;

interface Renderer
{
public function render(
Verifier $verifier
): Element;
}
38 changes: 38 additions & 0 deletions src/Scrutiny/Renderer/Custom.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/**
* @package Scrutiny
* @license http://opensource.org/licenses/MIT
*/

declare(strict_types=1);

namespace DecodeLabs\Scrutiny\Renderer;

use Closure;
use DecodeLabs\Scrutiny\Renderer;
use DecodeLabs\Scrutiny\Verifier;
use DecodeLabs\Tagged\Element;

class Custom implements Renderer
{
/**
* @var Closure(Verifier):Element
*/
protected Closure $renderer;

/**
* @param Closure(Verifier):Element $renderer
*/
public function __construct(
Closure $renderer
) {
$this->renderer = $renderer;
}

public function render(
Verifier $verifier
): Element {
return ($this->renderer)($verifier);
}
}
36 changes: 36 additions & 0 deletions src/Scrutiny/Renderer/Generic.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/**
* @package Scrutiny
* @license http://opensource.org/licenses/MIT
*/

declare(strict_types=1);

namespace DecodeLabs\Scrutiny\Renderer;

use DecodeLabs\Dictum;
use DecodeLabs\Scrutiny\Renderer;
use DecodeLabs\Scrutiny\Verifier;
use DecodeLabs\Tagged;
use DecodeLabs\Tagged\Element;
use ReflectionClass;

class Generic implements Renderer
{
public function render(
Verifier $verifier
): Element {
$name = strtolower(
(new ReflectionClass($verifier))->getShortName()
);

$attributes = [];

foreach ($verifier->getComponentData() as $key => $value) {
$attributes[Dictum::slug($key)] = $value;
}

return Tagged::{'scrutiny-' . $name}(null, $attributes);
}
}
11 changes: 11 additions & 0 deletions src/Scrutiny/Verifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,19 @@

namespace DecodeLabs\Scrutiny;

use DecodeLabs\Tagged\Markup;

interface Verifier
{
public function renderInline(
?string $nonce = null
): Markup;

/**
* @return array<string, mixed>
*/
public function getComponentData(): array;

public function verify(
Payload $payload
): Result;
Expand Down
2 changes: 1 addition & 1 deletion src/Scrutiny/Verifier/HCaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class HCaptcha extends SiteVerify
{
public const VERIFY_URL = 'https://api.hcaptcha.com/siteverify';
public const API_URL = 'https://hcaptcha.com/1/api.js';
public const CLIENT_FIELD_NAME = 'h-captcha';
public const CLIENT_KEY_NAME = 'h-captcha';
public const RESPONSE_FIELD_NAME = 'h-captcha-response';

protected function createResponse(
Expand Down
2 changes: 1 addition & 1 deletion src/Scrutiny/Verifier/Recaptcha.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Recaptcha extends SiteVerify
{
public const VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
public const API_URL = 'https://www.google.com/recaptcha/api.js';
public const CLIENT_FIELD_NAME = 'g-recaptcha';
public const CLIENT_KEY_NAME = 'g-recaptcha';
public const RESPONSE_FIELD_NAME = 'g-recaptcha-response';

protected function createResponse(
Expand Down
Loading

0 comments on commit 27adc3c

Please sign in to comment.