Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 121 additions & 1 deletion src/Attrs.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

namespace spaf\simputils;

use Attribute;
use Closure;
use Exception;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionClassConstant;
use ReflectionException;
use ReflectionMethod;
use ReflectionObject;
use Reflector;
use spaf\simputils\models\Box;
use TypeError;
use function class_exists;
Expand Down Expand Up @@ -47,7 +52,7 @@ static function collectMethodReflections(mixed $instance, string $attr): Box|arr
$reflection = new ReflectionClass($instance);
} else {
throw new TypeError(
'$instance is not Object or Class String or Class does not exist'
'$instance is not Object or Class String or Class does not exist',
);
}
if (!is_string($attr) || !class_exists($attr)) {
Expand All @@ -65,4 +70,119 @@ static function collectMethodReflections(mixed $instance, string $attr): Box|arr
return $res;
}

/**
* @param string|object $instance
* @param null|Box|array $attrs
* @param int $target
* @param null|callable $callback Must return true, false or null. If null returned, then
* no further attributes are checked.
* params (
* $attr_instance
* ReflectionAttribute $attr,
* Reflector $item,
* string|object $instance,
* $all_attrs
* )
* @param bool $find_first Find first matching Spell
*
* @return array|Box
* @throws ReflectionException
*/
static function findSpells(
string|object $instance,
null|Box|array $attrs = null,
int $target = Attribute::TARGET_ALL,
?callable $callback = null,
bool $find_first = false,
) {

$target = Attribute::TARGET_ALL | $target;

$r = new ReflectionClass($instance);
$res = PHP::box();

$attrs = PHP::box($attrs);

if (Boolean::isBitFlagOn($target, $t = Attribute::TARGET_CLASS)) {
static::_processAttributes($res, $r, $t, $attrs, $callback, $instance, $find_first);
if ($find_first && $res->size > 0) {
return $res;
}
}

if (Boolean::isBitFlagOn($target, $t = Attribute::TARGET_PROPERTY)) {
foreach ($r->getProperties() as $ref_item) {
static::_processAttributes($res, $ref_item, $t, $attrs, $callback, $instance, $find_first);
if ($find_first && $res->size > 0) {
return $res;
}
}
}

if (Boolean::isBitFlagOn($target, $t = Attribute::TARGET_METHOD)) {
foreach ($r->getMethods() as $ref_item) {
static::_processAttributes($res, $ref_item, $t, $attrs, $callback, $instance, $find_first);
if ($find_first && $res->size > 0) {
return $res;
}
}
}

if (Boolean::isBitFlagOn($target, $t = Attribute::TARGET_CLASS_CONSTANT)) {
foreach ($r->getConstants() as $key => $val) {
$ref_item = new ReflectionClassConstant($instance, $key);
static::_processAttributes($res, $ref_item, $t, $attrs, $callback, $instance, $find_first);
}
}

return $res;
}

static protected function _processAttributes(
&$res,
Reflector $ref_item,
int $target,
Box $attrs,
?callable $callback,
$instance,
$find_first,
) {
foreach ($sub_attrs = $ref_item->getAttributes() as $at) {
/** @var ReflectionAttribute $at */
if (!$attrs->size || $attrs->containsValue($at->getName())) {
if (!$callback) {
$res->append([
'instance' => $instance,
'target' => $target,
'item_reflection' => $ref_item,
'attr' => $at->newInstance(),
'attr_reflection' => $at,
]);
if ($find_first) {
return;
}
} else {
$at_instance = $at->newInstance();
$cbk_res = $callback($at_instance, $at, $ref_item, $instance, $sub_attrs);
if ($cbk_res === false) {
continue;
}
$res->append([
'instance' => $instance,
'target' => $target,
'item_reflection' => $ref_item,
'attr' => $at_instance,
'attr_reflection' => $at,
]);
if ($find_first) {
return;
}
if ($cbk_res === null) {
break;
}
}
}
}
}

}
15 changes: 15 additions & 0 deletions src/Boolean.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,19 @@ static function from(mixed $val, bool $strict = false): ?bool {
static function to(mixed $val): mixed {
return static::from($val)?static::$to_yes:static::$to_no;
}

/**
* Checks whether a bit-flag is on
*
* Basically a shortcut for bit operation "AND" mask
*
* @param int $value
* @param int $flags
*
* @return bool
*/
static function isBitFlagOn(int $value, int $flags): bool {
$res = $value & $flags;
return $res;
}
}
4 changes: 4 additions & 0 deletions src/attributes/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,8 @@ public static function methodAccessType($ref, \ReflectionAttribute $attr, $args

return $method_type;
}

function getFinalType() {

}
}
12 changes: 10 additions & 2 deletions src/attributes/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Attribute;
use spaf\simputils\components\RenderedWrapper;
use spaf\simputils\generic\Spell;
use spaf\simputils\Html;
use spaf\simputils\traits\BaseHtmlTrait;
use spaf\simputils\traits\StaticRendererTrait;
Expand All @@ -17,12 +18,19 @@
* and methods must return either `null` or {@see RenderedWrapper}.
*
* @see RenderedWrapper Stringifiable object for
* {@see \spaf\simputils\traits\StaticRendererTrait::render()}
* {@see StaticRendererTrait::render()}
* @see StaticRendererTrait Trait containing `render` method/functionality.
* @see Html Really minimal HTML static class to create/render tags.
* @see BaseHtmlTrait Trait containing minimal HTML create/render tag(s)
*/
#[Attribute(Attribute::TARGET_METHOD)]
class Renderer {
class Renderer extends Spell {

static function getName(): string {
return 'renderer';
}

static function invoke(callable $target, ...$spell): mixed {
// TODO: Implement invoke() method.
}
}
16 changes: 16 additions & 0 deletions src/attributes/spells/Serialize.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace spaf\simputils\attributes\spells;


use Attribute;
use spaf\simputils\generic\Spell;

#[Attribute(Attribute::TARGET_METHOD)]
class Serialize extends Spell {

static function getName(): string {
return 'serialize';
}

}
32 changes: 32 additions & 0 deletions src/generic/Spell.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace spaf\simputils\generic;

use Attribute;

/**
* Meta-Magic Spell BaseClass
*/
#[Attribute]
abstract class Spell extends BasicAttribute {

/**
* Name of the spell class.
*
* Basically a short string name of the Spell
*
* @return mixed
*/
abstract static function getName(): string;

/**
* The method that will be invoked for this spell
*
* @param callable $target
* @param mixed ...$spell
*
* @return mixed
*/
abstract static function invoke(callable $target, ...$spell): mixed;

}
12 changes: 6 additions & 6 deletions src/traits/PropertiesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ trait PropertiesTrait {
* @param string $name Name of the property
*
* @return mixed
* @throws \spaf\simputils\exceptions\PropertyDoesNotExist Property does not exist
* @throws \spaf\simputils\exceptions\PropertyIsReadOnly Property is read-only
* @throws \spaf\simputils\exceptions\PropertyIsWriteOnly Property is write-only
* @throws PropertyDoesNotExist Property does not exist
* @throws PropertyIsReadOnly Property is read-only
* @throws PropertyIsWriteOnly Property is write-only
*/
public function __get($name) {
$ref = static::class.'#'.$name.'#'.Property::TYPE_GET;
Expand Down Expand Up @@ -185,9 +185,9 @@ private function getAllTheLastMethodsAndProperties() {
* relevant only for {@see __isset()})
*
* @return bool
* @throws \spaf\simputils\exceptions\PropertyDoesNotExist Property does not exist
* @throws \spaf\simputils\exceptions\PropertyIsReadOnly Property is read-only
* @throws \spaf\simputils\exceptions\PropertyIsWriteOnly Property is write-only
* @throws PropertyDoesNotExist Property does not exist
* @throws PropertyIsReadOnly Property is read-only
* @throws PropertyIsWriteOnly Property is write-only
*/
private function _simpUtilsPrepareProperty(
string $name,
Expand Down
19 changes: 17 additions & 2 deletions src/traits/StaticRendererTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace spaf\simputils\traits;

use ReflectionMethod;
use spaf\simputils\attributes\markers\Shortcut;
use spaf\simputils\attributes\Renderer;
use spaf\simputils\Attrs;
use spaf\simputils\components\RenderedWrapper;
Expand Down Expand Up @@ -44,8 +45,7 @@ static function render(mixed ...$params): string {

try {
$res = $method_reflection->invoke($instance, ...$params);
}
catch (TypeError) {
} catch (TypeError) {
$res = null;
}

Expand All @@ -69,6 +69,21 @@ static function render(mixed ...$params): string {
return $res;
}

/**
* Shortcut for render method
*
* @param mixed ...$params
*
* @return string
* @throws \Exception
* @see Renderer
* @see RenderedWrapper
*/
#[Shortcut('static::render()')]
static function r(mixed ...$params): string {
return static::render(...$params);
}

#[Renderer]
static private function defaultRenderer($arg = null): RenderedWrapper {
return new RenderedWrapper($arg);
Expand Down