Skip to content

Commit

Permalink
pint and phpstan
Browse files Browse the repository at this point in the history
  • Loading branch information
markhuot committed Oct 27, 2023
1 parent a529bc2 commit fd8b1b0
Show file tree
Hide file tree
Showing 23 changed files with 331 additions and 123 deletions.
13 changes: 8 additions & 5 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ parameters:
paths:
- src
scanFiles:
- %currentWorkingDirectory%/vendor/yiisoft/yii2/Yii.php
- %currentWorkingDirectory%/vendor/craftcms/cms/src/Craft.php
- %currentWorkingDirectory%/vendor/craftcms/cms/src/behaviors/CustomFieldBehavior.php.template
- %currentWorkingDirectory%/vendor/yiisoft/yii2/Yii.php
- %currentWorkingDirectory%/vendor/craftcms/cms/src/Craft.php
- %currentWorkingDirectory%/vendor/craftcms/cms/src/behaviors/CustomFieldBehavior.php.template
excludePaths:
- %currentWorkingDirectory%/src/phpstan/ThrowIfTypeSpecifyingExtension.php
- %currentWorkingDirectory%/src/phpstan/AbortIfFunctionTypeSpecifyingExtension.php
- %currentWorkingDirectory%/src/phpstan/ThrowIfTypeSpecifyingExtension.php
- %currentWorkingDirectory%/src/phpstan/AbortIfFunctionTypeSpecifyingExtension.php
ignoreErrors:
- '#Unable to resolve the template type TMapValue in call to method#'
- '#Unable to resolve the template type T in call to method craft\\services\\Elements::getElementById\(\)#'
41 changes: 28 additions & 13 deletions src/actions/MakeModelFromArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

namespace markhuot\keystone\actions;

use craft\base\ElementInterface;
use craft\base\FieldInterface;
use craft\base\Model;
use markhuot\keystone\db\ActiveRecord;
use yii\base\ModelEvent;

use function markhuot\keystone\helpers\base\app;

/**
* Recursively create models from an array.
*
Expand Down Expand Up @@ -50,6 +54,10 @@ public function handle(string $className, mixed $data, $validate = true, $errorO
if (count($condition)) {
$model = $className::findOne($condition);
}
} elseif ($className === ElementInterface::class) {
$model = app()->getElements()->getElementById($data);
} elseif ($className === FieldInterface::class) {
$model = app()->getFields()->getFieldById($data);
}

if (empty($model) && $createOnMissing) {
Expand All @@ -64,17 +72,31 @@ public function handle(string $className, mixed $data, $validate = true, $errorO
return null;
}

$this->load($model, $data);

if ($validate) {
$this->validate($model);
}

return $model;
}

protected function load(\yii\base\Model $model, mixed $data): void
{
if (! is_array($data)) {
return;
}

$reflect = new \ReflectionClass($model);

// if (is_array($data)) {
foreach ($data as $key => &$value) {
if ($reflect->hasProperty($key)) {
$property = $reflect->getProperty($key);
$type = $property->getType()->getName();

if (enum_exists($type)) {
$value = $type::from($value);
} elseif (class_exists($type)) {
} elseif (class_exists($type) || interface_exists($type)) {
$value = (new static)
->handle(
className: $type,
Expand All @@ -86,7 +108,6 @@ className: $type,
}
}
}
// }

$reflect = new \ReflectionClass($model);
foreach ($reflect->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
Expand All @@ -95,12 +116,12 @@ className: $type,
unset($data[$property->getName()]);
}
}
if ($model instanceof \markhuot\keystone\models\http\MoveComponentRequest) {
// \markhuot\craftpest\helpers\test\dd(array_keys($data));
}

$model->load($data, '');
}

protected function validate(\yii\base\Model $model): void
{
$catch = function (ModelEvent $event) {
$reflect = new \ReflectionClass($event->sender);
foreach ($reflect->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
Expand All @@ -112,14 +133,8 @@ className: $type,

$model->on(Model::EVENT_BEFORE_VALIDATE, $catch);

if ($validate && ! $model->validate()) {
if ($errorOnMissing) {
throw new \RuntimeException('oh no!');
}
}
$model->validate();

$model->off(Model::EVENT_BEFORE_VALIDATE, $catch);

return $model;
}
}
1 change: 1 addition & 0 deletions src/attributes/Background.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function getInputHtml(): string
public function getCssRules(): Collection
{
return collect($this->value)
->forgetWhen(['color', 'image'], fn ($value) => (bool) $value)
->mapWithKeys(fn ($value, $key) => match ($key) {
'image' => ['background-image' => 'url('.Asset::find()->id($value)->one()?->getUrl().')'],
'color' => ['background-color' => '#'.$value],
Expand Down
1 change: 1 addition & 0 deletions src/attributes/Border.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function getCssRules(): Collection
{
return collect($this->value)
->mapWithKeys(fn ($value, $key) => match ($key) {
'color' => ['border-'.$key => '#'.$value],
'width' => (new MapExpandedAttributeValue)->handle($value, 'border-width', 'border-&-width'),
default => ['border-'.$key => $value],
});
Expand Down
13 changes: 11 additions & 2 deletions src/base/AttributeBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class AttributeBag
{
/** @var Collection<class-string<Attribute>, mixed> */
protected Collection $attributes;

public function __construct(Collection|array|null $attributes = [])
Expand Down Expand Up @@ -35,9 +36,12 @@ public function mergeDefaults(array $defaults = []): self
return $this;
}

public function toHtml()
/**
* @return array<string>
*/
public function toArray(): array
{
$attributes = $this->attributes
return $this->attributes
->map(function ($value, $key) {
if (class_exists($key)) {
return (new $key($value))->toAttributeArray();
Expand All @@ -46,6 +50,11 @@ public function toHtml()
return [$key => $value];
})
->reduce(fn ($attr, $carry) => array_merge_recursive($carry, $attr), []);
}

public function toHtml()
{
$attributes = $this->toArray();

return collect($attributes)
->map(function ($value, $key) {
Expand Down
3 changes: 3 additions & 0 deletions src/base/FieldDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use craft\fields\Lightswitch;
use craft\fields\PlainText;

/**
* @method self handle(string $handle)
*/
class FieldDefinition
{
public function __construct(
Expand Down
2 changes: 1 addition & 1 deletion src/base/InlineEditData.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class InlineEditData
public function __construct(
protected Component $component,
protected FieldInterface $field,
protected string $value
protected ?string $value
) {
}

Expand Down
1 change: 1 addition & 0 deletions src/controllers/ComponentsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public function actionAdd()
public function actionStore()
{
$data = $this->request->getBodyParamObject(AddComponentRequest::class);

(new AddComponent)->handle(
elementId: $data->element->id,
fieldId: $data->field->id,
Expand Down
10 changes: 10 additions & 0 deletions src/helpers/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
namespace markhuot\keystone\helpers\base;

use Craft;
use craft\helpers\App;

function app(): \craft\web\Application|\craft\console\Application
{
return Craft::$app;
}

function parseEnv(string $alias): string
{
$result = App::parseEnv($alias);

throw_if(! $result || ! is_string($result) || $result === $alias, 'The alias '.$alias.' could not be resolved');

return $result;
}

/**
* @template T
*
Expand Down
14 changes: 8 additions & 6 deletions src/listeners/DiscoverSiteComponentTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

namespace markhuot\keystone\listeners;

use craft\helpers\App;
use markhuot\keystone\events\RegisterComponentTypes;

use function markhuot\keystone\helpers\base\parseEnv;

class DiscoverSiteComponentTypes
{
public function handle(RegisterComponentTypes $event)
public function handle(RegisterComponentTypes $event): void
{
$componentsDirectory = App::parseEnv('@templates/components');
$templatesPath = parseEnv('@templates/');
$componentsDirectory = $templatesPath.'components/';
$templates = [
...glob($componentsDirectory.'/*.twig'),
...glob($componentsDirectory.'/**/*.twig'),
...(glob($componentsDirectory.'*.twig') ?: []),
...(glob($componentsDirectory.'**/*.twig') ?: []),
];

foreach ($templates as $template) {
$start = mb_strlen(App::parseEnv('@templates/'));
$start = mb_strlen($templatesPath);
$localPath = 'site:'.substr($template, $start);
$key = 'site/'.substr($template, $start, -5);
$event->registerTwigTemplate($key, $localPath);
Expand Down
13 changes: 7 additions & 6 deletions src/listeners/MarkClassesSafeForTwig.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace markhuot\keystone\listeners;

use Craft;
use craft\base\Event;
use craft\web\View;
use markhuot\keystone\base\AttributeBag;
Expand All @@ -12,24 +11,26 @@
use markhuot\keystone\models\Component;
use Twig\Extension\EscaperExtension;

use function markhuot\keystone\helpers\base\app;

class MarkClassesSafeForTwig
{
public function handle(Event $event)
public function handle(Event $event): void
{
// Bit of a hack but we need to make sure that the AttributeBag is marked as safe in
// both the CP and the Site mode because we render templates out of both modes during
// a regular request. This is what allows plugins to ship default components out of
// their "cp" templates and use them on the front-end "site".
$oldTemplateMode = Craft::$app->getView()->getTemplateMode();
$oldTemplateMode = app()->getView()->getTemplateMode();
foreach ([View::TEMPLATE_MODE_CP, View::TEMPLATE_MODE_SITE] as $mode) {
Craft::$app->getView()->setTemplateMode($mode);
$escaper = Craft::$app->getView()->getTwig()->getExtension(EscaperExtension::class);
app()->getView()->setTemplateMode($mode);
$escaper = app()->getView()->getTwig()->getExtension(EscaperExtension::class);
$escaper->addSafeClass(AttributeBag::class, ['all']);
$escaper->addSafeClass(Component::class, ['all']);
$escaper->addSafeClass(SlotCollection::class, ['all']);
$escaper->addSafeClass(SlotDefinition::class, ['all']);
$escaper->addSafeClass(InlineEditData::class, ['all']);
}
Craft::$app->getView()->setTemplateMode($oldTemplateMode);
app()->getView()->setTemplateMode($oldTemplateMode);
}
}
41 changes: 11 additions & 30 deletions src/listeners/RegisterCollectionMacros.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,39 @@

class RegisterCollectionMacros
{
public function handle()
public function handle(): void
{
Collection::macro('filterRecursive', function (callable $callback = null) {
/** @var Collection<array-key, mixed> $this */
if (! $callback) {
$callback = fn ($value) => ! empty($value);
}

return $this
->filter(fn ($value, $key) => $callback($value, $key))
->map(fn ($value, $key) => is_array($value) ?
collect($value)->filterRecursive($callback)->toArray() :
$value);
->map(function ($value, $key) use ($callback) {
return is_array($value) ?
collect($value)->filterRecursive($callback)->toArray() : // @phpstan-ignore-line because filterRecursive is unknown
$value;
});
});

Collection::macro('mapIntoSpread', function (string $className) {
/** @var Collection<array-key, mixed> $this */
return $this->map(function ($item) use ($className) {
return new $className(...$item);
});
});

Collection::macro('mapKey', function (string $givenKey, callable $callback) {
/** @var Collection<array-key, mixed> $this */
return $this->map(function ($item, $key) use ($givenKey, $callback) {
return $givenKey === $key ? $callback($item, $key) : $item;
});
});

Collection::macro('forgetWhen', function (mixed $keys, mixed $condition) {
/** @var Collection<array-key, mixed> $this */
$keysToCheck = is_array($keys) ? $keys : [$keys];

return $this->filter(function ($value, $key) use ($keysToCheck, $condition) {
Expand All @@ -48,33 +54,8 @@ public function handle()
});
});

// Collection::macro('load', function (array $data) {
// foreach ($data as $key => $value) {
// $this->set($key, $value);
// }
//
// return $this;
// });

// Collection::macro('loadWhenMissing', function (array $data) {
// return $this->loadWhen($data, fn ($value, $key, $collection) => ! $collection->has($key));
// });

// Collection::macro('loadWhenEmpty', function (array $data) {
// return $this->loadWhen($data, fn ($value, $key, $collection) => empty($collection->get($key)));
// });

// Collection::macro('loadWhen', function ($data, $callback) {
// foreach ($data as $key => $value) {
// if ($callback($value, $key, $this)) {
// $this->set($key, $value);
// }
// }
//
// return $this;
// });

Collection::macro('mergeKeys', function ($callback) {
/** @var Collection<array-key, mixed> $this */
$values = [];
$reflect = new \ReflectionFunction($callback);

Expand Down
2 changes: 1 addition & 1 deletion src/listeners/RegisterCpUrlRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class RegisterCpUrlRules
{
public function handle(RegisterUrlRulesEvent $event)
public function handle(RegisterUrlRulesEvent $event): void
{
$routes = include __DIR__.'/../../src/config/routes.php';

Expand Down
2 changes: 1 addition & 1 deletion src/listeners/RegisterDefaultAttributeTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class RegisterDefaultAttributeTypes
{
public function handle(RegisterAttributeType $event)
public function handle(RegisterAttributeType $event): void
{
$event->add(\markhuot\keystone\attributes\Alignment::class);
$event->add(\markhuot\keystone\attributes\Background::class);
Expand Down
2 changes: 1 addition & 1 deletion src/listeners/RegisterDefaultComponentTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class RegisterDefaultComponentTypes
{
public function handle(RegisterComponentTypes $event)
public function handle(RegisterComponentTypes $event): void
{
$event->registerTwigTemplate('keystone/fragment', 'cp:keystone/components/fragment.twig');
$event->registerTwigTemplate('keystone/section', 'cp:keystone/components/section.twig');
Expand Down
Loading

0 comments on commit fd8b1b0

Please sign in to comment.