From 8f1ed0d07f45420e4ed1762371abbc1550819e5c Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Sat, 3 Jun 2023 21:42:51 +0200 Subject: [PATCH 01/12] Added @codeCoverageIgnore comments --- src/Core/Cache/CacheState/TransformedCacheState.php | 2 ++ src/Core/DI.php | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Core/Cache/CacheState/TransformedCacheState.php b/src/Core/Cache/CacheState/TransformedCacheState.php index da0dff0..ecc5483 100644 --- a/src/Core/Cache/CacheState/TransformedCacheState.php +++ b/src/Core/Cache/CacheState/TransformedCacheState.php @@ -54,7 +54,9 @@ public function isFresh(): bool } if (filemtime($transformerFilePath) > $this->modificationTime) { + // @codeCoverageIgnoreStart return false; + // @codeCoverageIgnoreEnd } } diff --git a/src/Core/DI.php b/src/Core/DI.php index 0b9f728..3c75b78 100644 --- a/src/Core/DI.php +++ b/src/Core/DI.php @@ -30,7 +30,7 @@ class DI implements ServiceInterface private ContainerBuilder $containerBuilder; /** - * Reg + * Register the dependency injection container. * * @return void * @@ -93,6 +93,8 @@ public static function get(string $class) * @param $value * * @return void + * + * @codeCoverageIgnore */ public static function set(string $class, $value): void { From f3784fe2bb9b648679c047c409effcf08088ce4f Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Mon, 5 Jun 2023 17:40:38 +0200 Subject: [PATCH 02/12] Updated README.md --- README.md | 133 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 05957e6..2d50595 100644 --- a/README.md +++ b/README.md @@ -59,15 +59,19 @@ composer require okapi/code-transformer ## 📖 List of contents -- [Create a kernel](#create-a-kernel) -- [Create a transformer](#create-a-transformer) -- [Initialize the kernel](#initialize-the-kernel) +- [Create a Kernel](#create-a-kernel) +- [Create a Transformer](#create-a-transformer) +- [Target Class](#target-class) +- [Initialize the Kernel](#initialize-the-kernel) +- [Target Class (transformed)](#target-class-transformed) - [Result](#result) - [Limitations](#limitations) +- [How it works](#how-it-works) +- [Testing](#testing) -## Create a kernel +## Create a Kernel ```php getStringContentsText() === 'Hello World!' ) { // Replace it with 'Hello from Code Transformer!' - // Edit method accepts a Token class + // Edit method accepts a Token or Node class $code->edit( $node->children, "'Hello from Code Transformer!'", @@ -184,59 +196,43 @@ class UnPrivateTransformer extends Transformer ``` -## Initialize the kernel +## Target Class ```php -// Initialize the kernel early in the application lifecycle - myPrivateProperty; // You can't get me! -$myTargetClass->myPrivateMethod(); // Hello from Code Transformer! -``` +myPrivateProperty; // You can't get me! +$myTargetClass->myPrivateMethod(); // Hello from Code Transformer! +``` + + + # Limitations - Normally xdebug will point to the original source code, not the transformed @@ -263,36 +273,47 @@ $iAmAppended = true; # How it works -- The `Kernel` registers multiple services +- The `CodeTransformerKernel` registers multiple services - - The `TransformerContainer` service stores the list of transformers and their configuration + - The `TransformerManager` service stores the list of transformers and their + configuration - The `CacheStateManager` service manages the cache state - - The `StreamFilter` service registers a [PHP Stream Filter](https://www.php.net/manual/wrappers.php.php#wrappers.php.filter) + - The `StreamFilter` service registers a + [PHP Stream Filter](https://www.php.net/manual/wrappers.php.php#wrappers.php.filter) which allows to modify the source code before it is loaded by PHP - - The `AutoloadInterceptor` service overloads the Composer autoloader, which handles the loading of classes + - The `AutoloadInterceptor` service overloads the Composer autoloader, + which handles the loading of classes ## General workflow when a class is loaded - The `AutoloadInterceptor` service intercepts the loading of a class - - It expects a class file path -- The `TransformerContainer` matches the class name with the list of transformer target classes +- The `TransformerMatcher` matches the class name with the list of transformer + target classes + +- If the class is matched, query the cache state to see if the transformed + source code is already cached -- If the class is matched, we query the cache state to see if the transformed source code is already cached - Check if the cache is valid: - - Modification time of the caching process is less than the modification time of the source file or the transformers + - Modification time of the caching process is less than the modification + time of the source file or the transformers - Check if the cache file, the source file and the transformers exist - - Check if the number of transformers is the same as the number of transformers in the cache - - If the cache is valid, we load the transformed source code from the cache - - If not, we convert the class file path to a stream filter path - -- The `StreamFilter` modifies the source code by applying the matching transformers - - If the modified source code is different from the original source code, we cache the transformed source code - - If not, we cache it anyway, but without a cached source file path, so that the transformation process is not repeated + - Check if the number of transformers is the same as the number of + transformers in the cache + + - If the cache is valid, load the transformed source code from the cache + - If not, return a stream filter path to the `AutoloadInterceptor` service + +- The `StreamFilter` modifies the source code by applying the matching + transformers + - If the modified source code is different from the original source code, + cache the transformed source code + - If not, cache it anyway, but without a cached source file path, + so that the transformation process is not repeated From e6ad19ae1a589fe1829acaa3dc0f6a205289b6f1 Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Mon, 5 Jun 2023 18:17:21 +0200 Subject: [PATCH 03/12] Updated PhpDocs --- src/CodeTransformerKernel.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/CodeTransformerKernel.php b/src/CodeTransformerKernel.php index 0b0a364..7f41e60 100644 --- a/src/CodeTransformerKernel.php +++ b/src/CodeTransformerKernel.php @@ -31,6 +31,7 @@ abstract class CodeTransformerKernel #[Inject] private Options $options; + /** @internal */ #[Inject] protected TransformerManager $transformerManager; @@ -44,7 +45,10 @@ abstract class CodeTransformerKernel private AutoloadInterceptor $autoloadInterceptor; /** - * Make the constructor public to allow the DI container to instantiate the class. + * Make the constructor public to allow the DI container to instantiate the + * class. + * + * @internal */ public function __construct() {} @@ -70,7 +74,7 @@ public function __construct() {} /** * Enable debug mode. This will disable the cache. - *
Default: false
+ *
Default: {@link false}
* * @var bool */ From 478f0eff9e8fd492e7fb1c742868adecbcd402e9 Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Mon, 5 Jun 2023 19:57:10 +0200 Subject: [PATCH 04/12] Removed TODO.md --- TODO.md | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 TODO.md diff --git a/TODO.md b/TODO.md deleted file mode 100644 index ed313f3..0000000 --- a/TODO.md +++ /dev/null @@ -1,32 +0,0 @@ -# 1. Class Name matching -Optimize the class name matching by using efficient data structures or -algorithms (e.g. trie-based matching or regular expressions). - -# 2. Cache management -More sophisticated cache management strategy, such as Least Recently Used (LRU) -or Time-To-Live (TTL) based eviction, to ensure that cache remains up-to-date -and efficient. - -# 3. Parallelization -Parallelize the process of matching and transforming classes and methods to -reduce the overall processing time. - -# 4. Incremental updates -Incremental update mechanism to process only new or changed classes and methods. - -# 5. Monitoring -Monitor the performance of the library to identify bottlenecks and areas that -need optimization (e.g. Profilers or benchmarking suites). - -# 6. Documentation -- Document how to use xdebug with php-unit tests that use the - `#[RunTestsInSeparateProcesses]` attribute (PhpStorm) -- Create a flowchart - -# 7. Testing -- Add tests for the `order` property of the `Transformer` class - -# 8. Production/Development support -- Add support for production/development environments: - - Production: Cache will not be checked for updates (better performance). - - Development: Cache will be checked for updates (better debugging experience). From 6100236bef5138a7a9c3e6cbd1a453160a794006 Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Mon, 5 Jun 2023 20:30:07 +0200 Subject: [PATCH 05/12] Added a thanks section to README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 2d50595..0d12536 100644 --- a/README.md +++ b/README.md @@ -331,6 +331,15 @@ Give a ⭐ if this project helped you! +## 🙏 Thanks + +- Big thanks to [lisachenko](https://github.com/lisachenko) for their pioneering + work on the [Go! Aspect-Oriented Framework for PHP](https://github.com/goaop/framework). + This project drew inspiration from their innovative approach and served as a + foundation for this project. + + + ## 📝 License Copyright © 2023 [Valentin Wotschel](https://github.com/WalterWoshid).
From 54077ec4811b900b7bde67491403adfc09465a7e Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Mon, 5 Jun 2023 20:41:11 +0200 Subject: [PATCH 06/12] Added TODO to README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 0d12536..a0a0ac1 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ composer require okapi/code-transformer - [Limitations](#limitations) - [How it works](#how-it-works) - [Testing](#testing) +- [TODO](#todo) @@ -331,6 +332,18 @@ Give a ⭐ if this project helped you! +## TODO + +- Add support for Production/Development environments: + - Production: Cache will not be checked for updates (better performance) + - Development: Cache will be checked for updates (better debugging experience) + +- Create a flowchart (WIP) + +- Cache lifetime + + + ## 🙏 Thanks - Big thanks to [lisachenko](https://github.com/lisachenko) for their pioneering From 91923652f23f0603fc436da57a35698fa6805f52 Mon Sep 17 00:00:00 2001 From: Valentin Wotschel Date: Sun, 3 Sep 2023 15:49:20 +0200 Subject: [PATCH 07/12] Added "throw exception on double initialization" option to kernel --- src/CodeTransformerKernel.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/CodeTransformerKernel.php b/src/CodeTransformerKernel.php index 7f41e60..54ae496 100644 --- a/src/CodeTransformerKernel.php +++ b/src/CodeTransformerKernel.php @@ -80,6 +80,17 @@ public function __construct() {} */ protected bool $debug = false; + /** + * Throw an exception if the kernel is initialized twice. + *
Default: {@link false}
+ * + * If {@link false}, any subsequent call to {@link init()} will be + * ignored. + * + * @var bool + */ + protected bool $throwExceptionOnDoubleInitialization = false; + // endregion /** @@ -115,7 +126,12 @@ public static function init(): void static::ensureNotKernelNamespace(); $instance = static::getInstance(); - $instance->ensureNotInitialized(); + + if ($instance->throwExceptionOnDoubleInitialization) { + $instance->ensureNotInitialized(); + } elseif ($instance->initialized) { + return; + } // Initialize the services $instance->preInit(); From f960f223039233b6f4cd955649150f3decbc0327 Mon Sep 17 00:00:00 2001 From: Valentin Wotschel Date: Sun, 3 Sep 2023 15:50:47 +0200 Subject: [PATCH 08/12] Added test cases for "already initialized kernel" --- .../AlreadyInitializedKernelTest.php | 34 +++++++++++++++++++ tests/Stubs/Kernel/EmptyKernel.php | 13 +++++++ .../ExceptionOnDoubleInitializationKernel.php | 23 +++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 tests/Functional/AlreadyInitializedKernelTest.php create mode 100644 tests/Stubs/Kernel/EmptyKernel.php create mode 100644 tests/Stubs/Kernel/ExceptionOnDoubleInitializationKernel.php diff --git a/tests/Functional/AlreadyInitializedKernelTest.php b/tests/Functional/AlreadyInitializedKernelTest.php new file mode 100644 index 0000000..d59d468 --- /dev/null +++ b/tests/Functional/AlreadyInitializedKernelTest.php @@ -0,0 +1,34 @@ +assertTrue(true); + } + + public function testInitializeKernelTwiceWithExceptionOnDoubleInitializationOption(): void + { + Util::clearCache(); + + $this->expectException(AlreadyInitializedException::class); + + ExceptionOnDoubleInitializationKernel::init(); + ExceptionOnDoubleInitializationKernel::init(); + } +} diff --git a/tests/Stubs/Kernel/EmptyKernel.php b/tests/Stubs/Kernel/EmptyKernel.php new file mode 100644 index 0000000..d5ae497 --- /dev/null +++ b/tests/Stubs/Kernel/EmptyKernel.php @@ -0,0 +1,13 @@ +initCount++; + + if ($this->initCount > 1) { + throw new Exception('I should not be initialized twice!'); + } + + parent::preInit(); + } +} From 1f7e6ac35d70e41c571736fd2262477774cc0d27 Mon Sep 17 00:00:00 2001 From: Valentin Wotschel Date: Sun, 3 Sep 2023 15:51:07 +0200 Subject: [PATCH 09/12] Bumped Composer version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 62c5241..638b3c8 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "okapi/code-transformer", "description": "PHP Code Transformer is a PHP library that allows you to modify and transform the source code of a loaded PHP class.", - "version": "1.3.1", + "version": "1.3.2", "type": "library", "homepage": "https://github.com/okapi-web/php-code-transformer", "license": "MIT", From 93c4dbe98beb108cc9dc8f3541b806611085938e Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Sun, 3 Sep 2023 15:49:20 +0200 Subject: [PATCH 10/12] Added "throw exception on double initialization" option to kernel --- src/CodeTransformerKernel.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/CodeTransformerKernel.php b/src/CodeTransformerKernel.php index 7f41e60..54ae496 100644 --- a/src/CodeTransformerKernel.php +++ b/src/CodeTransformerKernel.php @@ -80,6 +80,17 @@ public function __construct() {} */ protected bool $debug = false; + /** + * Throw an exception if the kernel is initialized twice. + *
Default: {@link false}
+ * + * If {@link false}, any subsequent call to {@link init()} will be + * ignored. + * + * @var bool + */ + protected bool $throwExceptionOnDoubleInitialization = false; + // endregion /** @@ -115,7 +126,12 @@ public static function init(): void static::ensureNotKernelNamespace(); $instance = static::getInstance(); - $instance->ensureNotInitialized(); + + if ($instance->throwExceptionOnDoubleInitialization) { + $instance->ensureNotInitialized(); + } elseif ($instance->initialized) { + return; + } // Initialize the services $instance->preInit(); From 71416e090df910264087176e3d20bcdd975d71b3 Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Sun, 3 Sep 2023 15:50:47 +0200 Subject: [PATCH 11/12] Added test cases for "already initialized kernel" --- .../AlreadyInitializedKernelTest.php | 34 +++++++++++++++++++ tests/Stubs/Kernel/EmptyKernel.php | 13 +++++++ .../ExceptionOnDoubleInitializationKernel.php | 23 +++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 tests/Functional/AlreadyInitializedKernelTest.php create mode 100644 tests/Stubs/Kernel/EmptyKernel.php create mode 100644 tests/Stubs/Kernel/ExceptionOnDoubleInitializationKernel.php diff --git a/tests/Functional/AlreadyInitializedKernelTest.php b/tests/Functional/AlreadyInitializedKernelTest.php new file mode 100644 index 0000000..d59d468 --- /dev/null +++ b/tests/Functional/AlreadyInitializedKernelTest.php @@ -0,0 +1,34 @@ +assertTrue(true); + } + + public function testInitializeKernelTwiceWithExceptionOnDoubleInitializationOption(): void + { + Util::clearCache(); + + $this->expectException(AlreadyInitializedException::class); + + ExceptionOnDoubleInitializationKernel::init(); + ExceptionOnDoubleInitializationKernel::init(); + } +} diff --git a/tests/Stubs/Kernel/EmptyKernel.php b/tests/Stubs/Kernel/EmptyKernel.php new file mode 100644 index 0000000..d5ae497 --- /dev/null +++ b/tests/Stubs/Kernel/EmptyKernel.php @@ -0,0 +1,13 @@ +initCount++; + + if ($this->initCount > 1) { + throw new Exception('I should not be initialized twice!'); + } + + parent::preInit(); + } +} From efc0a1cbbcfef7dfdfe7d6c41cd194d7a6b6ed4c Mon Sep 17 00:00:00 2001 From: WalterWoshid Date: Sun, 3 Sep 2023 15:51:07 +0200 Subject: [PATCH 12/12] Bumped Composer version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 62c5241..638b3c8 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "okapi/code-transformer", "description": "PHP Code Transformer is a PHP library that allows you to modify and transform the source code of a loaded PHP class.", - "version": "1.3.1", + "version": "1.3.2", "type": "library", "homepage": "https://github.com/okapi-web/php-code-transformer", "license": "MIT",