Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Changelog
* [Feature] **PHP 8.1+ enum interception** — instance and static methods on both unit (pure) and backed enums can now be intercepted by aspects. The enum body is extracted into a trait (`Foo__AopProxied`); a proxy enum re-declares the cases and dispatches intercepted methods via per-method `static $__joinPoint` caching. Built-in enum methods (`cases`, `from`, `tryFrom`) and initialization joinpoints are never woven.
* [Feature] `self::` in proxied classes now resolves to the proxy class naturally (via PHP trait semantics), removing the need for `SelfValueTransformer`.
* [Feature] **First-class callable syntax** — generated proxy code and invocation constructors use PHP 8.1+ first-class callable syntax (`$this->__aop__method(...)`, `parent::method(...)`, `\func(...)`) to reference original method and function bodies, eliminating the need for `Closure::bind` at construction time.
* [BC BREAK] Removed `Features::PARAMETER_WIDENING` and the parameter-widening code path in the proxy generators. The feature was a PHP 7.0/7.1 compatibility aid (parameter type widening, wiki.php.net/rfc/parameter-no-type-variance) that has been a no-op concern since the PHP 7.2 baseline: generated proxies always keep the original parameter types. Remove the flag from `AspectKernel::configureAop()` options if you passed it.
* [BC BREAK] Removed DeclareError support, including the `DeclareError` attribute, `DeclareErrorInterceptor`, and `PointcutBuilder::declareError()`. Use `Before` or `Around` interceptors to emit user warnings or throw exceptions instead.
* [BC BREAK] Removed support for the "dynamic" pointcut (`dynamic(public Foo->method*(*))`), including `MagicMethodDynamicPointcut`, `DynamicInvocationMatcherInterceptor`, the `Pointcut::KIND_DYNAMIC` constant and the `$instanceOrScope`/`$arguments` parameters of `Pointcut::matches()`. Use a traditional execution pointcut for the magic methods instead, e.g. `execution(public Foo->__call(*))` or `execution(public Foo::__callStatic(*))`, and check the invoked method name from `$invocation->getArguments()[0]` inside the advice.
* [Removed] `SelfValueTransformer` and `SelfValueVisitor` — no longer needed with the trait-based engine.
Expand Down
1 change: 0 additions & 1 deletion src/Aop/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,3 @@ Proxy generators use TypeGenerator::renderTypeForPhpDoc() to emit V as 2nd gener
Interface with bitmask constants:
- INTERCEPT_FUNCTIONS=1, INTERCEPT_INITIALIZATIONS=2, INTERCEPT_INCLUDES=4
- PREBUILT_CACHE=64 — assume cache already prepared, skip freshness checks
- PARAMETER_WIDENING=128 — enable parameter widening for PHP>=7.2
15 changes: 4 additions & 11 deletions src/Aop/Features.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ interface Features
* Enables interception of system function.
* By default this feature is disabled, because this option is very expensive.
*/
public const INTERCEPT_FUNCTIONS = 1;
public const int INTERCEPT_FUNCTIONS = 1;

/**
* Enables interception of "new" operator in the source code
* By default this feature is disabled, because it's very tricky
*/
public const INTERCEPT_INITIALIZATIONS = 2;
public const int INTERCEPT_INITIALIZATIONS = 2;

/**
* Enables interception of "include"/"require" operations in legacy code
* By default this feature is disabled, because only composer should be used
*/
public const INTERCEPT_INCLUDES = 4;
public const int INTERCEPT_INCLUDES = 4;

/**
* Trust the cache built at deploy time (`bin/aspect cache:warmup:aop`) unconditionally
Expand All @@ -44,12 +44,5 @@ interface Features
* rebuild the cache on every deployment. Also usable for read-only file systems
* (GAE, phar, etc).
*/
public const PREBUILT_CACHE = 64;

/**
* Enables usage of parameter widening for PHP>=7.2.0
*
* @see https://wiki.php.net/rfc/parameter-no-type-variance
*/
public const PARAMETER_WIDENING = 128;
public const int PREBUILT_CACHE = 64;
}
18 changes: 9 additions & 9 deletions src/Aop/Pointcut.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@
*/
interface Pointcut
{
public const KIND_METHOD = 1;
public const KIND_PROPERTY = 2;
public const KIND_CLASS = 4;
public const KIND_TRAIT = 8;
public const KIND_FUNCTION = 16;
public const KIND_INIT = 32;
public const KIND_STATIC_INIT = 64;
public const KIND_ALL = 127;
public const KIND_INTRODUCTION = 512;
public const int KIND_METHOD = 1;
public const int KIND_PROPERTY = 2;
public const int KIND_CLASS = 4;
public const int KIND_TRAIT = 8;
public const int KIND_FUNCTION = 16;
public const int KIND_INIT = 32;
public const int KIND_STATIC_INIT = 64;
public const int KIND_ALL = 127;
public const int KIND_INTRODUCTION = 512;

/**
* Returns the kind of point filter
Expand Down
3 changes: 0 additions & 3 deletions src/Bridge/Doctrine/MetadataLoadInterceptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
*/
final class MetadataLoadInterceptor implements EventSubscriber
{
/**
* {@inheritdoc}
*/
public function getSubscribedEvents(): array
{
return [
Expand Down
3 changes: 0 additions & 3 deletions src/Console/Command/BaseAspectCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ class BaseAspectCommand extends Command
*/
protected AspectKernel $aspectKernel;

/**
* {@inheritDoc}
*/
protected function configure(): void
{
$this->addArgument('loader', InputArgument::REQUIRED, 'Path to the aspect loader file');
Expand Down
6 changes: 0 additions & 6 deletions src/Console/Command/CacheWarmupCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
*/
class CacheWarmupCommand extends BaseAspectCommand
{
/**
* {@inheritDoc}
*/
protected function configure(): void
{
parent::configure();
Expand All @@ -43,9 +40,6 @@ protected function configure(): void
;
}

/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->loadAspectKernel($input, $output);
Expand Down
6 changes: 0 additions & 6 deletions src/Console/Command/DebugAdvisorCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
*/
class DebugAdvisorCommand extends BaseAspectCommand
{
/**
* {@inheritDoc}
*/
protected function configure(): void
{
parent::configure();
Expand All @@ -51,9 +48,6 @@ protected function configure(): void
;
}

/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->loadAspectKernel($input, $output);
Expand Down
6 changes: 0 additions & 6 deletions src/Console/Command/DebugAspectCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
*/
class DebugAspectCommand extends BaseAspectCommand
{
/**
* {@inheritDoc}
*/
protected function configure(): void
{
parent::configure();
Expand All @@ -45,9 +42,6 @@ protected function configure(): void
;
}

/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->loadAspectKernel($input, $output);
Expand Down
6 changes: 0 additions & 6 deletions src/Console/Command/DebugWeavingCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@
*/
class DebugWeavingCommand extends BaseAspectCommand
{
/**
* {@inheritDoc}
*/
protected function configure(): void
{
parent::configure();
Expand All @@ -49,9 +46,6 @@ protected function configure(): void
;
}

/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->loadAspectKernel($input, $output);
Expand Down
18 changes: 9 additions & 9 deletions src/Core/AspectContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,47 @@ interface AspectContainer
/**
* Prefix for function interceptor
*/
public const FUNCTION_PREFIX = 'func';
public const string FUNCTION_PREFIX = 'func';

/**
* Prefix for properties interceptor
*/
public const PROPERTY_PREFIX = 'prop';
public const string PROPERTY_PREFIX = 'prop';

/**
* Prefix for method interceptor
*/
public const METHOD_PREFIX = 'method';
public const string METHOD_PREFIX = 'method';

/**
* Prefix for static method interceptor
*/
public const STATIC_METHOD_PREFIX = 'static';
public const string STATIC_METHOD_PREFIX = 'static';

/**
* Trait introduction prefix
*/
public const INTRODUCTION_TRAIT_PREFIX = 'trait';
public const string INTRODUCTION_TRAIT_PREFIX = 'trait';

/**
* Interface introduction prefix
*/
public const INTRODUCTION_INTERFACE_PREFIX = 'interface';
public const string INTRODUCTION_INTERFACE_PREFIX = 'interface';

/**
* Initialization prefix, is used for initialization pointcuts
*/
public const INIT_PREFIX = 'init';
public const string INIT_PREFIX = 'init';

/**
* Initialization prefix, is used for initialization pointcuts
*/
public const STATIC_INIT_PREFIX = 'staticinit';
public const string STATIC_INIT_PREFIX = 'staticinit';

/**
* Suffix, that will be added to all proxied class names
*/
public const AOP_PROXIED_SUFFIX = '__AopProxied';
public const string AOP_PROXIED_SUFFIX = '__AopProxied';

/**
* Returns a service from the container.
Expand Down
22 changes: 5 additions & 17 deletions src/Instrument/ClassLoading/AopComposerLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,6 @@
*/
class AopComposerLoader
{
/**
* Instance of original autoloader
*/
protected ClassLoader $original;

/**
* AOP kernel options
*
* @phpstan-var KernelOptions
*/
protected array $options;

/**
* File enumerator
*/
Expand Down Expand Up @@ -79,11 +67,11 @@ class AopComposerLoader
*
* @phpstan-param KernelOptions $options Configuration options
*/
public function __construct(ClassLoader $original, AspectContainer $container, array $options)
{
$this->options = $options;
$this->original = $original;

public function __construct(
protected readonly ClassLoader $original,
AspectContainer $container,
protected readonly array $options
) {
$prefixes = $original->getPrefixes();
$excludePaths = $options['excludePaths'];

Expand Down
12 changes: 3 additions & 9 deletions src/Instrument/ClassLoading/CachePathManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,16 @@ class CachePathManager
/**
* Name of the file with full transformation metadata (build-time data, loaded lazily)
*/
private const CACHE_FILE_NAME = '/_transformation.cache';
private const string CACHE_FILE_NAME = '/_transformation.cache';

/**
* Name of the file with the minimal runtime include map (originalPath => cacheUri|null)
*/
private const INCLUDE_MAP_FILE_NAME = '/_include.cache';
private const string INCLUDE_MAP_FILE_NAME = '/_include.cache';

/** @phpstan-var KernelOptions */
protected array $options;

/**
* Aspect kernel instance
*/
protected AspectKernel $kernel;

protected ?string $cacheDir = null;

/**
Expand Down Expand Up @@ -99,9 +94,8 @@ class CachePathManager
*/
protected array $newCacheState = [];

public function __construct(AspectKernel $kernel)
public function __construct(protected readonly AspectKernel $kernel)
{
$this->kernel = $kernel;
$options = $kernel->getOptions();
$this->options = $options;
$this->appDir = $options['appDir'];
Expand Down
7 changes: 2 additions & 5 deletions src/Instrument/ClassLoading/SourceTransformingLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ class SourceTransformingLoader extends PhpStreamFilter
/**
* Php filter definition
*/
public const PHP_FILTER_READ = 'php://filter/read=';
public const string PHP_FILTER_READ = 'php://filter/read=';

/**
* Default PHP filter name for registration
*/
public const FILTER_IDENTIFIER = 'go.source.transforming.loader';
public const string FILTER_IDENTIFIER = 'go.source.transforming.loader';

/**
* String buffer
Expand Down Expand Up @@ -140,9 +140,6 @@ public static function getId(): string
return self::$filterId;
}

/**
* {@inheritdoc}
*/
public function filter($in, $out, &$consumed, $closing): int
{
while ($bucket = stream_bucket_make_writeable($in)) {
Expand Down
35 changes: 8 additions & 27 deletions src/Instrument/FileSystem/Enumerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,18 @@
*/
class Enumerator
{
/**
* Path to the root directory, where enumeration should start
*/
private string $rootDirectory;

/**
* List of additional include paths, should be below rootDirectory
*
* @var string[]
*/
private array $includePaths;

/**
* List of additional exclude paths, should be below rootDirectory
*
* @var string[]
*/
private array $excludePaths;

/**
* Initializes an enumerator
*
* @param string $rootDirectory Path to the root directory
* @param string[] $includePaths List of additional include paths
* @param string[] $excludePaths List of additional exclude paths
* @param string $rootDirectory Path to the root directory, where enumeration should start
* @param string[] $includePaths List of additional include paths, should be below rootDirectory
* @param string[] $excludePaths List of additional exclude paths, should be below rootDirectory
*/
public function __construct(string $rootDirectory, array $includePaths = [], array $excludePaths = [])
{
$this->rootDirectory = $rootDirectory;
$this->includePaths = $includePaths;
$this->excludePaths = $excludePaths;
public function __construct(
private readonly string $rootDirectory,
private readonly array $includePaths = [],
private readonly array $excludePaths = []
) {
}

/**
Expand Down
8 changes: 1 addition & 7 deletions src/Instrument/Transformer/BaseSourceTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ abstract class BaseSourceTransformer implements SourceTransformer
*/
protected array $options;

/**
* Aspect kernel instance
*/
protected AspectKernel $kernel;

/**
* Aspect container instance
*/
Expand All @@ -42,9 +37,8 @@ abstract class BaseSourceTransformer implements SourceTransformer
/**
* Default constructor for transformer
*/
public function __construct(AspectKernel $kernel)
public function __construct(protected readonly AspectKernel $kernel)
{
$this->kernel = $kernel;
$this->container = $kernel->getContainer();
$this->options = $kernel->getOptions();
}
Expand Down
Loading