-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug Fixes: Refined logic for managing execution depth and interception state #9
Conversation
Improve code readability and maintainability by using the Z_OBJ macro for object access. This change ensures a more consistent approach to handling object instances within the code. Additionally, remove redundant call to prepare_intercept_params for cleaner execution logic.
This commit enhances debugging capabilities by wrapping key debug print statements with #ifdef RAYAOP_DEBUG preprocessor directives, ensuring they are only executed when debugging is enabled. Additionally, a minor type casting correction was made to the string length print statement for clarity.
WalkthroughThe changes in the Changes
Possibly related PRs
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
rayaop.c (1)
Line range hint
116-452
: Consider implementing granular debug levelsThe current implementation uses a simple debug flag, but the various types of debug information (execution depth, interception, state changes) could benefit from different debug levels. This would allow more fine-grained control over debugging output.
Consider implementing different debug levels:
- RAYAOP_DEBUG_LEVEL_BASIC: State changes only
- RAYAOP_DEBUG_LEVEL_EXECUTION: Include execution depth
- RAYAOP_DEBUG_LEVEL_VERBOSE: Include all debug information
This would allow users to focus on specific aspects during debugging.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
rayaop.c
(7 hunks)
🔇 Additional comments (6)
rayaop.c (6)
116-118
: LGTM: Debug print statement properly implemented
The debug print statement is correctly wrapped in the RAYAOP_DEBUG conditional and provides useful debugging information.
133-138
: LGTM: Improved object validation with better error handling
The change improves object validation by using Z_OBJ
directly and adds proper error handling for NULL object cases.
188-190
: LGTM: Added execution depth tracking debug information
The debug print statement helps track the execution depth, which is crucial for debugging potential recursion issues.
198-200
: LGTM: Added interception execution debug information
The debug print statement provides visibility into which methods are being intercepted.
316-318
: LGTM: Added method interception state change debug information
The debug print statements clearly indicate when method interception is enabled or disabled.
Also applies to: 321-323
452-452
: LGTM: Improved string debug print format
The debug print format for strings now properly includes both length and content.
The code has been significantly refactored to enhance error handling and simplify interception logic. New error codes have been introduced for more precise error messages, and numerous debug functions were removed to streamline the code. Additionally, the mutex handling was simplified, and function prototypes were rearranged for better readability.
Refactor the interception logic in `rayaop_execute_ex` by consolidating exception handling conditions to streamline the execution flow. The changes remove redundant checks, ensuring cleaner and more efficient code while maintaining functionality. These updates help improve readability and reduce complexity by minimizing the pathways through which the function could execute.
Refactored `rayaop_execute_ex` to ensure execution data and function validity, improving robustness. Added detailed error handling using try-catch equivalence for reliable cleanup in case of exceptions. This change helps maintain code integrity and prevents potential execution issues.
Renamed `php_rayaop_original_execute_ex` to `original_zend_execute_ex` and made `php_rayaop_should_intercept` a static function called `rayaop_should_intercept`. This refactoring improves code readability and ensures naming consistency throughout the module. Additionally, removed the `PHP_RAYAOP_API` declaration from `php_rayaop_should_intercept` as it is now intended for internal use only.
Refactor variable naming for clarity and adjust exception handling in interception logic to prevent unnecessary intercept attempts if an exception is present. Enhance handler update process by ensuring proper cleanup of previous handlers and adding new ones only when interception info exists. This improves the robustness and maintainability of the aspect-oriented programming functionality.
Modified the build script to include debug flags, enabling better debugging capabilities. This change sets the CFLAGS to "-g -O0" during the configure step to provide more detailed debugging information. This will help in identifying and resolving issues more effectively during development.
Added a line to activate method interception in the '001-rayaop-basic.phpt' test to ensure that interceptors properly modify method execution. This change ensures the test accurately reflects expected behavior when interception is enabled and helps validate interceptor functionality.
Renamed the variable $result to $res in test loop for clarity and consistency with the rest of the code. This change ensures uniformity in variable names and improves readability without altering the test's logic or output. The redundant PHP closing tag was also removed to align with PSR-2 coding standards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (5)
build.sh (1)
12-12
: Consider making debug flags configurableWhile debug symbols and disabled optimizations are helpful during development, they may impact performance in production. Consider making these flags configurable based on the environment.
- ./configure CFLAGS="-g -O0" + CFLAGS=${CFLAGS:="-g -O0"} + ./configure CFLAGS="$CFLAGS"tests/001-rayaop-basic.phpt (1)
35-36
: LGTM! Consider adding edge casesThe explicit enable call fixes the verification issue. Consider adding test cases for:
- Multiple enable/disable toggles
- Nested method calls
- Error cases when enable is called with invalid parameters
tests/008-rayaop-thread-safety.phpt (1)
34-39
: Maintain consistent variable namingThe variable was renamed from
$result
to$res
. For consistency, consider using descriptive variable names throughout the codebase.- $res = method_intercept( + $interceptResult = method_intercept(php_rayaop.h (1)
37-42
: Consider using an enum for error codes.While the current #define approach works, using an enum would provide better type safety and IDE support.
-#define RAYAOP_E_MEMORY_ALLOCATION 1 -#define RAYAOP_E_HASH_UPDATE 2 -#define RAYAOP_E_INVALID_HANDLER 3 -#define RAYAOP_E_MAX_DEPTH_EXCEEDED 4 -#define RAYAOP_E_NULL_POINTER 5 -#define RAYAOP_E_INVALID_STATE 6 +typedef enum { + RAYAOP_E_MEMORY_ALLOCATION = 1, + RAYAOP_E_HASH_UPDATE = 2, + RAYAOP_E_INVALID_HANDLER = 3, + RAYAOP_E_MAX_DEPTH_EXCEEDED = 4, + RAYAOP_E_NULL_POINTER = 5, + RAYAOP_E_INVALID_STATE = 6 +} rayaop_error_code_t;rayaop.c (1)
299-329
: Consider adding transaction-like error handling for atomic operations.The memory management and hash table updates could benefit from a more atomic approach to prevent resource leaks in edge cases.
+ zend_bool success = 0; RAYAOP_G_LOCK(); + do { php_rayaop_intercept_info *existing = zend_hash_str_find_ptr(RAYAOP_G(intercept_ht), key, key_len); if (existing) { /* Update existing entry */ if (!zval_ptr_dtor_safe(&existing->handler)) { + break; } ZVAL_COPY(&existing->handler, interceptor); zend_string_release(existing->class_name); zend_string_release(existing->method_name); existing->class_name = info->class_name; existing->method_name = info->method_name; efree(info); } else { if (zend_hash_str_update_ptr(RAYAOP_G(intercept_ht), key, key_len, info) == NULL) { + break; } } + success = 1; + } while (0); RAYAOP_G_UNLOCK(); + + if (!success) { + efree(key); + zval tmp_zv; + ZVAL_PTR(&tmp_zv, info); + php_rayaop_free_intercept_info(&tmp_zv); + php_rayaop_handle_error(RAYAOP_E_HASH_UPDATE, "Failed to update intercept hash table"); + RETURN_FALSE; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
build.sh
(1 hunks)php_rayaop.h
(2 hunks)rayaop.c
(7 hunks)tests/001-rayaop-basic.phpt
(2 hunks)tests/008-rayaop-thread-safety.phpt
(2 hunks)
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (6)
tests/008-rayaop-thread-safety.phpt (1)
Line range hint 48-54
: LGTM! Robust error handling implementation
The addition of try-catch properly handles the error condition and prevents test failures when exceptions are expected. This improves the test's reliability and coverage.
php_rayaop.h (2)
22-29
: LGTM: Well-structured export macros for cross-platform compatibility.
The export macros are correctly defined for Windows and GCC platforms, ensuring proper symbol visibility.
45-46
: LGTM: Thread-safe mutex implementation.
The mutex implementation is correctly guarded by ZTS (Zend Thread Safety) macro.
rayaop.c (3)
46-73
: LGTM: Comprehensive error handling with clear error types and levels.
The error handling implementation is well-structured with appropriate error levels and descriptive messages.
🧰 Tools
🪛 cppcheck (2.10-2)
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
151-159
: LGTM: Proper exception handling with early returns.
The code correctly checks for existing exceptions before proceeding with interception.
214-226
: Verify argument handling for edge cases.
The argument processing code should be tested with various edge cases:
- Maximum number of arguments
- Arguments containing circular references
- Arguments with complex types
Replaced echo with var_dump for clearer output of non-intercepted method results. Added a success check evaluating the outputs against expected values, reporting success or failure at script completion, and setting appropriate exit codes.
Add a call to `ts_free_id(rayaop_globals_id)` immediately after allocating the globals. This ensures proper resource cleanup and prevents potential memory leaks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
smoke.php (1)
46-53
: Consider enhancing test verification with descriptive messagesWhile the success verification is good, it could be more descriptive to help debug failures.
Consider this improvement:
-$success = $result1 === 'Result: test' && $result2 === 'Non-intercepted result: test'; -echo $success ? 'Test Success.' : 'Test Failure.'; +$success = true; +$expected1 = 'Result: test'; +$expected2 = 'Non-intercepted result: test'; + +if ($result1 !== $expected1) { + echo "Intercepted method test failed.\n"; + echo "Expected: $expected1\n"; + echo "Got: $result1\n"; + $success = false; +} + +if ($result2 !== $expected2) { + echo "Non-intercepted method test failed.\n"; + echo "Expected: $expected2\n"; + echo "Got: $result2\n"; + $success = false; +} + +echo $success ? "All tests passed successfully.\n" : "Test suite failed.\n";rayaop.c (2)
47-73
: Improved error handling with clear error types and levelsThe error handling implementation is well-structured with clear error types and appropriate error levels. However, consider adding debug logging for non-critical errors.
Consider adding debug logging:
PHP_RAYAOP_API void php_rayaop_handle_error(int error_code, const char *message) { int error_level = E_ERROR; const char *error_type = "Unknown Error"; + if (RAYAOP_G(debug_level) > 0) { + php_error_docref(NULL, E_NOTICE, "[RayAOP Debug] Handling error code: %d", error_code); + } switch (error_code) {🧰 Tools
🪛 cppcheck (2.10-2)
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
308-329
: Enhanced duplicate handler managementThe code now properly handles duplicate interceptors by cleaning up the old handler before installing the new one. However, consider adding debug logging for handler replacements.
Add debug logging for handler replacements:
if (existing) { + if (RAYAOP_G(debug_level) > 0) { + php_error_docref(NULL, E_NOTICE, "[RayAOP Debug] Replacing existing handler for %s", key); + } /* 上書き: 前のhandlerを解放して新しいhandlerを登録 */ zval_ptr_dtor(&existing->handler);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
rayaop.c
(7 hunks)smoke.php
(2 hunks)tests/001-rayaop-basic.phpt
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/001-rayaop-basic.phpt
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (3)
rayaop.c (3)
134-137
: Improved exception handling with proper cleanup
The code now properly handles exceptions at multiple points, preventing resource leaks and ensuring clean execution paths.
Also applies to: 151-159, 194-197, 228-231
371-374
:
Critical: Fix potential memory leak in thread safety initialization
The ts_free_id
is called immediately after allocation, which could lead to a memory leak or crash.
Apply this fix:
ts_allocate_id(&rayaop_globals_id, sizeof(zend_rayaop_globals), NULL, NULL);
rayaop_mutex = tsrm_mutex_alloc();
-ts_free_id(rayaop_globals_id);
if (!rayaop_mutex) {
+ ts_free_id(rayaop_globals_id);
php_error_docref(NULL, E_ERROR, "Failed to allocate mutex for RayAOP");
return FAILURE;
}
Likely invalid or redundant comment.
214-226
: Verify argument handling in intercepted methods
The argument processing code looks correct, but we should verify it handles all PHP types properly.
✅ Verification successful
Let me gather more information about the argument handling by checking the interceptor implementations.
Based on the gathered information, I can now provide the final response:
Argument handling in intercepted methods is implemented correctly
The implementation correctly and safely handles PHP arguments:
- Proper reference counting with
Z_TRY_ADDREF_P
- Undefined value checks with
Z_ISUNDEF_P
- Type safety checks for objects and handlers
- Test coverage includes:
- Methods with and without parameters
- Multiple interceptors handling same arguments
- Memory management verification
- Thread safety validation
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for potential type handling issues in intercepted methods
ast-grep --pattern 'function testMethod($_) {
$$$
}'
# Look for test cases with different argument types
rg -A 5 'testMethod.*\(' tests/
Length of output: 4124
Script:
#!/bin/bash
# Check interceptor implementations to see how they handle different argument types
rg -A 10 "implements.*MethodInterceptorInterface" tests/
# Look for any type-related assertions or checks in test files
rg -A 5 "(assertInstanceOf|gettype|is_\w+)" tests/
# Check for any type-related error handling in the extension
rg -A 5 "Z_(TYPE|IS)" rayaop.c
Length of output: 6241
Modified the condition to propagate explicit return values and handle cases where the return type is void or undefined. This ensures that the return value is appropriately set to NULL when no explicit return value is provided, preventing potential errors during execution.
Add a call to `method_intercept_enable(true);` in the thread-safety test script. This ensures that the method interception is activated during the test executions, allowing accurate evaluations of thread safety conditions.
This test ensures that the interception works correctly with methods that have no explicit return statement and those with an empty return. It validates that the interceptor processes both void and empty return methods as expected, returning null in each case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (3)
tests/010-rayaop-void-return.phpt (1)
17-17
: Consider translating Japanese comments to English.The comments
// 明示的なreturnなし
and// 明示的な空return
should be translated to English for better maintainability and collaboration.- // 明示的なreturnなし + // No explicit return- // 明示的な空return + // Explicit empty returnAlso applies to: 22-22
rayaop.c (2)
151-159
: Redundant exception checks could be consolidated.There are multiple similar exception checks that could be consolidated to improve code readability and maintainability.
Consider consolidating the exception checks at the beginning of the function:
static void rayaop_execute_ex(zend_execute_data *execute_data) { if (EG(exception)) { if (php_rayaop_original_execute_ex) { php_rayaop_original_execute_ex(execute_data); } else { zend_execute_ex(execute_data); } return; } - /* Remove redundant checks */ - if (EG(exception)) { - goto fallback; - } - - if (EG(exception)) { - efree(key); - goto fallback; - }Also applies to: 173-175, 194-197
315-322
: Consider extracting handler update logic to a separate function.The handler update logic in the
method_intercept
function could be extracted to improve readability and reusability.Consider creating a helper function:
static void update_existing_handler(php_rayaop_intercept_info *existing, php_rayaop_intercept_info *new_info) { zval_ptr_dtor(&existing->handler); ZVAL_COPY(&existing->handler, &new_info->handler); zend_string_release(existing->class_name); zend_string_release(existing->method_name); existing->class_name = new_info->class_name; existing->method_name = new_info->method_name; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
rayaop.c
(7 hunks)tests/008-rayaop-thread-safety.phpt
(1 hunks)tests/010-rayaop-void-return.phpt
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/008-rayaop-thread-safety.phpt
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (2)
tests/010-rayaop-void-return.phpt (2)
5-12
: LGTM! Well-structured interceptor implementation.
The VoidTestInterceptor
correctly implements the MethodInterceptorInterface
and properly handles the method invocation lifecycle.
14-24
: LGTM! Clear test cases for void returns.
The TestClass
effectively demonstrates both scenarios of void returns:
- Implicit void return (no return statement)
- Explicit void return (return;)
Add explicit error handling when interceptor call fails but doesn't raise an exception. The change separates error conditions between call failure and exceptions, providing more detailed error reporting through php_rayaop_handle_error. - Split call_user_function result check into separate variable - Add specific error handling for call failures - Report errors with RAYAOP_E_INVALID_HANDLER code Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…zation Move ts_free_id call after mutex allocation failure check to ensure proper cleanup sequence. The original placement could cause resource cleanup in incorrect order when mutex allocation fails. - Move ts_free_id inside failure condition block - Ensure resources are cleaned up in correct order on error Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (2)
rayaop.c (2)
46-73
: Consider adding error code documentation.The error handling implementation is solid with appropriate error levels and clear messages. However, it would be helpful to add documentation about these error codes in the header file.
Consider adding documentation in
php_rayaop.h
:/** * Error codes for RayAOP * * RAYAOP_E_MEMORY_ALLOCATION: Memory allocation failure * RAYAOP_E_HASH_UPDATE: Hash table update failure * RAYAOP_E_INVALID_HANDLER: Invalid or missing handler * RAYAOP_E_MAX_DEPTH_EXCEEDED: Maximum interception depth exceeded * RAYAOP_E_NULL_POINTER: Null pointer error * RAYAOP_E_INVALID_STATE: Invalid state error */🧰 Tools
🪛 cppcheck (2.10-2)
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
Line range hint
151-263
: Consider adding memory leak prevention in error paths.While the cleanup section is thorough, there are paths where memory leaks could occur if exceptions are thrown during parameter preparation.
Apply this diff:
if (arg_count > 0 && !EG(exception)) { zval *args = ZEND_CALL_ARG(execute_data, 1); if (args && !EG(exception)) { for (uint32_t i = 0; i < arg_count; i++) { zval *arg = &args[i]; if (!Z_ISUNDEF_P(arg)) { + if (EG(exception)) { + /* Clean up already added parameters */ + zend_hash_clean(Z_ARRVAL(params[2])); + goto cleanup; + } Z_TRY_ADDREF_P(arg); add_next_index_zval(¶ms[2], arg); } } } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
rayaop.c
(7 hunks)
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (4)
rayaop.c (4)
11-26
: LGTM: Well-defined argument information and global variable initialization.
The argument information is properly defined with correct type hints and the global variable is explicitly initialized.
35-44
: LGTM: Well-defined interface method declarations.
The interface method declarations are properly defined with correct return and parameter types.
125-144
: LGTM: Comprehensive interception checks.
The function properly checks all necessary conditions before proceeding with interception, including:
- Method interception enabled state
- Execution depth limits
- Exception state
- Required data availability
- Recursive interception prevention
377-385
:
Remove duplicate mutex check.
There's a duplicate check for mutex allocation failure.
Apply this diff:
ts_allocate_id(&rayaop_globals_id, sizeof(zend_rayaop_globals), NULL, NULL);
rayaop_mutex = tsrm_mutex_alloc();
if (!rayaop_mutex) {
ts_free_id(rayaop_globals_id);
php_error_docref(NULL, E_ERROR, "Failed to allocate mutex for RayAOP");
return FAILURE;
}
- if (!rayaop_mutex) {
- php_error_docref(NULL, E_ERROR, "Failed to allocate mutex for RayAOP");
- return FAILURE;
- }
Likely invalid or redundant comment.
This update introduces two new functions, demo and debug, to the build.sh script. The demo function executes a demo script with specific PHP settings, while the debug function runs the demo script using lldb for debugging purposes. These additions enhance the script's functionality, providing more options for testing and debugging.
This update enhances the PHP extension with comprehensive error handling and debugging capabilities, improving resource management and error reporting. Additionally, documentation in the README files has been expanded to include API references, performance considerations, and known limitations for better user understanding.
Introduce a PHP demo project to showcase Ray.Aop, implementing the RealBillingService interface with weekend blocking functionality. The demo includes class implementations, matchers, interceptors, and the necessary configuration for testing the functionality. Update files include `RealBillingService`, `BillingService`, `WeekendBlocker`, `IsContainsMatcher`, and the necessary autoload configurations.
This commit introduces a new GitHub Actions step to test the demo directory by installing dependencies and running tests. It also updates the workflow to include Valgrind memory checks on the demo directory to ensure better reliability and logs these checks for later inspection.
This update expands the PHP testing matrix by including version 8.4, ensuring compatibility with the latest PHP release. It helps maintain forward compatibility and prepares the codebase for adopting newer PHP features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Outside diff range and nitpick comments (10)
demo/src/RealBillingService.php (1)
9-15
: Add documentation and consider making the message configurableThe implementation could benefit from proper documentation and more flexibility.
+/** + * Concrete implementation of BillingService + */ class RealBillingService implements BillingService { + private string $successMessage; + + public function __construct(string $successMessage = 'Charged.') + { + $this->successMessage = $successMessage; + } + + /** + * {@inheritdoc} + */ public function chargeOrder(): string { - return 'Charged.' . PHP_EOL; + return $this->successMessage . PHP_EOL; } }.gitignore (1)
36-37
: Consider adding more PHP-specific patternsThe additions are good, but consider including other common PHP patterns:
/demo/vendor/ /demo/tmp/ +/demo/composer.lock +*.cache +.phpunit.result.cache +.php-cs-fixer.cachedemo/aop.php (1)
22-29
: Consider moving method_intercept_enable() callThe
method_intercept_enable()
call should ideally be placed before object instantiation to ensure proper interception.Consider this restructuring:
+ method_intercept_enable(true); try { $billingService = new RealBillingService(); - method_intercept_enable(true); echo $billingService->chargeOrder(); } catch (RuntimeException $e) { echo $e->getMessage() . PHP_EOL; exit(1); }.github/workflows/build.yml (1)
77-80
: Consider using a more descriptive path for Valgrind logs.While the Valgrind check for the demo directory is correctly configured, the log file path could be more descriptive.
- valgrind --suppressions=../valgrind.supp --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-demo-out.txt php -n -dextension=../modules/rayaop.so aop.php + valgrind --suppressions=../valgrind.supp --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-demo-aop-out.txt php -n -dextension=../modules/rayaop.so aop.phpREADME.ja.md (1)
164-165
: Fix list indentation for consistency.The unordered list items are indented with 4 spaces instead of the standard 2 spaces used elsewhere in the document.
- - 新しいインターセプターを登録すると、以前のものは自動的に解除されます - - この設計により、予測可能な動作と最適なパフォーマンスを確保 + - 新しいインターセプターを登録すると、以前のものは自動的に解除されます + - この設計により、予測可能な動作と最適なパフォーマンスを確保🧰 Tools
🪛 Markdownlint (0.35.0)
164-164: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
165-165: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
README.md (1)
164-165
: Fix list indentation for consistency.The unordered list items are indented with 4 spaces instead of the standard 2 spaces used elsewhere in the document.
- - When registering a new interceptor for a method, the previous one is automatically unregistered - - This design ensures predictable behavior and optimal performance + - When registering a new interceptor for a method, the previous one is automatically unregistered + - This design ensures predictable behavior and optimal performance🧰 Tools
🪛 Markdownlint (0.35.0)
164-164: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
165-165: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
demo/README.md (4)
3-3
: Fix hyphenation in compound adjectiveThe term "Aspect Oriented" should be hyphenated when used as a compound adjective.
-This is a demonstration of [Ray.Aop](https://github.com/ray-di/Ray.Aop), an Aspect Oriented Programming (AOP) framework for PHP. +This is a demonstration of [Ray.Aop](https://github.com/ray-di/Ray.Aop), an Aspect-Oriented Programming (AOP) framework for PHP.🧰 Tools
🪛 LanguageTool
[uncategorized] ~3-~3: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...(https://github.com/ray-di/Ray.Aop), an Aspect Oriented Programming (AOP) framework for PHP. #...(EN_COMPOUND_ADJECTIVE_INTERNAL)
8-8
: Improve extension path documentationThe hard-coded path
../modules/rayaop.so
might not be applicable for all installations. Consider providing more flexible installation instructions.-- rayaop.so PHP extension (must be in ../modules/rayaop.so) ++ rayaop.so PHP extension (typically found in PHP's extension directory)Also consider adding instructions for:
- How to find PHP's extension directory
- How to configure the extension path in php.ini
- Installation steps for different operating systems
14-27
: Enhance running instructions with additional contextWhile the commands are clear, users would benefit from:
- Explanation of when to use each method
- Description of expected output
- Warning about production vs development settings
Consider adding sections like:
### Method 1: Quick Start Use this method for a simple demonstration: ```bash php run.phpExpected output: [describe what users should see]
Method 2: Manual Extension Loading
Use this method when testing different extension configurations:
php -dextension=../modules/rayaop.so aop.phpMethod 3: Debugging Mode
⚠️ For development only. Do not use these settings in production:php -dextension=../modules/rayaop.so -dzend_extension=xdebug.so -dxdebug.mode=debug aop.php--- `31-32`: **Enhance project structure documentation** The current structure description is minimal. Consider adding: - Detailed explanation of contents in `src/` - Description of example classes and their purpose - Tree view of the project structure Example enhancement: ```markdown ## Project Structure ```bash . ├── aop.php # Main demo file showcasing AOP functionality └── src/ # Source code directory ├── Interceptors/ # Example interceptors │ └── [List interceptor classes with descriptions] └── Target/ # Example target classes └── [List target classes with descriptions]
Key Components
aop.php
: Demonstrates how to:
- Set up method interception
- Apply aspects to target classes
- Handle intercepted method calls
src/Interceptors/
: Contains example interceptors that demonstrate:
- Logging
- Caching
- Authorization
[Add actual interceptor examples]src/Target/
: Contains example target classes that demonstrate:
- Different method types
- Various use cases
[Add actual target class examples]<details> <summary>🧰 Tools</summary> <details> <summary>🪛 LanguageTool</summary> [uncategorized] ~31-~31: Loose punctuation mark. Context: ...p ``` ## Project Structure - `aop.php`: Main demo file that showcases AOP funct... (UNLIKELY_OPENING_PUNCTUATION) </details> </details> </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used: CodeRabbit UI** **Review profile: CHILL** <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between c1397d64ae617253e848958caa8ed6403298963c and e93e0542ff49287306239b9f34f7a44e82150145. </details> <details> <summary>📒 Files selected for processing (13)</summary> * `.github/workflows/build.yml` (3 hunks) * `.gitignore` (1 hunks) * `README.ja.md` (1 hunks) * `README.md` (4 hunks) * `build.sh` (3 hunks) * `demo/README.md` (1 hunks) * `demo/aop.php` (1 hunks) * `demo/composer.json` (1 hunks) * `demo/run.php` (1 hunks) * `demo/src/BillingService.php` (1 hunks) * `demo/src/IsContainsMatcher.php` (1 hunks) * `demo/src/RealBillingService.php` (1 hunks) * `demo/src/WeekendBlocker.php` (1 hunks) </details> <details> <summary>✅ Files skipped from review due to trivial changes (2)</summary> * demo/run.php * demo/composer.json </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary> * build.sh </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>🪛 LanguageTool</summary> <details> <summary>README.md</summary> [misspelling] ~91-~91: This word is normally spelled as one. Context: ...te - Safe initialization and cleanup in multi-threaded environments When using in multi-threa... (EN_COMPOUNDS_MULTI_THREADED) --- [misspelling] ~93-~93: This word is normally spelled as one. Context: ...ti-threaded environments When using in multi-threaded environments (e.g., PHP-FPM): - Ensure ... (EN_COMPOUNDS_MULTI_THREADED) --- [uncategorized] ~104-~104: Loose punctuation mark. Context: ...des: - `RAYAOP_E_MEMORY_ALLOCATION (1)`: Memory allocation failure - `RAYAOP_E_H... (UNLIKELY_OPENING_PUNCTUATION) --- [grammar] ~111-~111: The verb ‘reporting’ is used with the gerund form. Context: ...'s error reporting system. Enable error reporting to catch and handle these errors. ## Debug Mode... (ADMIT_ENJOY_VB) </details> <details> <summary>README.ja.md</summary> [uncategorized] ~174-~174: 文法ミスがあります。"を軽蔑する"の間違いです。 Context: ...y-di/Ray.Aop)は高レベルのAOP機能を提供します: Ray.Aopの提供する機能: - Matchersを使用した条件付きインターセプション - メソッドあ... (NO_SURU) </details> <details> <summary>demo/README.md</summary> [uncategorized] ~3-~3: If this is a compound adjective that modifies the following noun, use a hyphen. Context: ...(https://github.com/ray-di/Ray.Aop), an Aspect Oriented Programming (AOP) framework for PHP. #... (EN_COMPOUND_ADJECTIVE_INTERNAL) --- [uncategorized] ~31-~31: Loose punctuation mark. Context: ...p ``` ## Project Structure - `aop.php`: Main demo file that showcases AOP funct... (UNLIKELY_OPENING_PUNCTUATION) </details> </details> <details> <summary>🪛 Markdownlint (0.35.0)</summary> <details> <summary>README.md</summary> 164-164: Expected: 2; Actual: 4 Unordered list indentation (MD007, ul-indent) --- 165-165: Expected: 2; Actual: 4 Unordered list indentation (MD007, ul-indent) </details> <details> <summary>README.ja.md</summary> 164-164: Expected: 2; Actual: 4 Unordered list indentation (MD007, ul-indent) --- 165-165: Expected: 2; Actual: 4 Unordered list indentation (MD007, ul-indent) </details> </details> </details> <details> <summary>🔇 Additional comments (3)</summary> <details> <summary>.github/workflows/build.yml (2)</summary> `84-93`: **LGTM! Robust implementation of Valgrind results check.** The loop implementation properly handles multiple log files with appropriate existence checks and clear error messaging. --- `53-60`: **LGTM! Verify composer.json existence.** The demo directory test step is well-structured with proper error handling and extension loading. <details> <summary>✅ Verification successful</summary> **Composer configuration is present and correctly set up** The demo directory contains all necessary files including `composer.json`, `aop.php`, and the required directory structure. The workflow step is properly configured to work with this setup. </details> <details> <summary>🏁 Scripts executed</summary> The following scripts were executed for the analysis: Script: ```shell #!/bin/bash # Verify composer.json exists in demo directory if [ ! -f "demo/composer.json" ]; then echo "Warning: composer.json not found in demo directory" exit 1 fi
Length of output: 35
Script:
#!/bin/bash # Let's check if the demo directory exists and list its contents ls -la demo/ 2>/dev/null || echo "Demo directory not found" # Also search for any composer files in the repository fd composer.jsonLength of output: 505
README.ja.md (1)
133-133
: Verify consistency of technical values between README.md and README.ja.md
Ensure that technical values (execution depth, performance metrics) are consistent between both README files.
Also applies to: 149-151
✅ Verification successful
Technical values are consistent between README.md and README.ja.md
The verification confirms that both files maintain consistency in critical technical values:
- MAX_EXECUTION_DEPTH is set to 100 in both files
- Performance metrics are accurately translated and maintain the same values:
- Direct method calls: 0.1-0.2μs
- Intercepted calls: 1-2μs
- Complex interceptors behavior description matches
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check consistency of technical values between README files
echo "Checking MAX_EXECUTION_DEPTH..."
grep -A1 "MAX_EXECUTION_DEPTH" README.md README.ja.md
echo "Checking performance metrics..."
grep -A3 "Method interception adds minimal overhead" README.md
grep -A3 "メソッドインターセプションによるオーバーヘッド" README.ja.md
Length of output: 1068
Enhance the error handling by providing detailed context in failure messages of the interceptor calls. Error reports now include both the class and method names where the failure occurred, aiding in quicker diagnostics and debugging.
The removed code contained a duplicate check for the mutex allocation, which was unnecessary as the error handling for this condition already exists. This cleanup helps streamline the code and avoid redundant error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (3)
rayaop.c (3)
47-73
: Consider standardizing error levels based on error severity.While the error handling is comprehensive, some error types that could be recoverable are set to E_ERROR. Consider adjusting error levels based on severity:
- RAYAOP_E_NULL_POINTER could be E_WARNING if the operation can be retried
- RAYAOP_E_INVALID_STATE could be E_WARNING if the state can be recovered
case RAYAOP_E_NULL_POINTER: error_type = "Null Pointer Error"; + error_level = E_WARNING; break; case RAYAOP_E_INVALID_STATE: error_type = "Invalid State"; + error_level = E_WARNING; break;🧰 Tools
🪛 cppcheck (2.10-2)
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
125-147
: Consider restructuring with early returns for better readability.The function could be more readable with early returns instead of nested conditions.
PHP_RAYAOP_API zend_bool php_rayaop_should_intercept(zend_execute_data *execute_data) { if (!RAYAOP_G(method_intercept_enabled)) { return 0; } if (RAYAOP_G(execution_depth) >= MAX_EXECUTION_DEPTH) { return 0; } if (EG(exception)) { return 0; } - if (!execute_data || !execute_data->func || !execute_data->func->common.scope || !execute_data->func->common.function_name) { + if (!execute_data || !execute_data->func) { + return 0; + } + if (!execute_data->func->common.scope || !execute_data->func->common.function_name) { return 0; } if (RAYAOP_G(is_intercepting)) { return 0; } return 1; }
383-387
: Enhance error message for mutex allocation failure.Consider providing more detailed error information when mutex allocation fails.
if (!rayaop_mutex) { ts_free_id(rayaop_globals_id); - php_error_docref(NULL, E_ERROR, "Failed to allocate mutex for RayAOP"); + php_error_docref(NULL, E_ERROR, "Failed to allocate mutex for RayAOP: Memory allocation error (errno: %d)", errno); return FAILURE; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
.github/workflows/build.yml
(4 hunks)rayaop.c
(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/build.yml
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (4)
rayaop.c (4)
11-44
: LGTM! Well-structured declarations and initializations.
The global variables are properly initialized, and the argument information is well-defined with appropriate type safety.
151-159
: LGTM! Good exception handling at entry point.
The early check for exceptions and proper fallback to original execution is a good practice.
103-112
:
Add error handling for spprintf failure.
The key generation function should handle the case where spprintf fails (returns -1).
char *key;
int len = spprintf(&key, 0, "%s::%s", ZSTR_VAL(class_name), ZSTR_VAL(method_name));
+if (len < 0) {
+ return NULL;
+}
if (key_len) {
*key_len = (size_t)len;
}
Likely invalid or redundant comment.
83-83
: 🛠️ Refactor suggestion
Ensure proper cleanup on partial initialization failure.
The ZVAL_UNDEF initialization is correct, but consider adding cleanup code if subsequent allocations fail.
RAYAOP_G(is_intercepting) = 1; | ||
int call_result = call_user_function(NULL, &info->handler, &method_name, &retval, 3, params); | ||
if (call_result == SUCCESS && !EG(exception)) { | ||
if (execute_data->return_value) { | ||
if (!Z_ISUNDEF(retval)) { | ||
ZVAL_COPY(execute_data->return_value, &retval); // Propagate explicit return values | ||
} else { | ||
ZVAL_NULL(execute_data->return_value); // Handle void or empty returns | ||
} | ||
} | ||
} else if (call_result != SUCCESS) { | ||
char error_msg[256]; | ||
snprintf(error_msg, sizeof(error_msg), | ||
"Interceptor call failed for %s::%s", | ||
ZSTR_VAL(info->class_name), | ||
ZSTR_VAL(info->method_name)); | ||
php_rayaop_handle_error(RAYAOP_E_INVALID_HANDLER, error_msg); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider using a cleanup macro for consistent resource management.
The error handling and cleanup paths are complex. Consider using a macro to ensure consistent cleanup.
+#define CLEANUP_AND_RETURN(status) do { \
+ zval_ptr_dtor(&retval); \
+ zval_ptr_dtor(&method_name); \
+ zval_ptr_dtor(¶ms[1]); \
+ zval_ptr_dtor(¶ms[2]); \
+ zval_ptr_dtor(¶ms[0]); \
+ RAYAOP_G(is_intercepting) = 0; \
+ efree(key); \
+ RAYAOP_G(execution_depth)--; \
+ return status; \
+} while(0)
Committable suggestion skipped: line range outside the PR's diff.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
demo/src/BillingService.php (1)
1-19
: LGTM! Consider separating technical concerns from business interface.The interface is well-structured with proper documentation and type declarations. However, consider if the
#[WeekendBlock]
attribute should be moved to the implementation class instead of the interface to maintain better separation between business contract and technical implementation details.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
demo/src/BillingService.php
(1 hunks)
🔇 Additional comments (1)
demo/src/BillingService.php (1)
17-17
: Missing WeekendBlock attribute class definition
The codebase contains a WeekendBlocker
interceptor class that implements the blocking logic, but there's no corresponding PHP attribute class definition for WeekendBlock
. This is required for proper attribute registration in PHP 8+.
#!/bin/bash
# Search for WeekendBlock attribute definition
rg -p "attribute.*WeekendBlock|Attribute.*WeekendBlock" --type php
# Check if there are any Ray AOP attribute configurations
rg -p "Ray\\\\Aop.*Attribute" --type php
# Verify the attribute usage
ast-grep --pattern '#[WeekendBlock]'
@coderabbitai review again |
@koriym: I will redo the entire review of the PR as requested. ✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (14)
demo/src/RealBillingService.php (1)
1-15
: Add class and method documentation for consistency.While the implementation is correct, consider adding PHPDoc documentation to maintain consistency with the interface.
<?php declare(strict_types=1); namespace Demo; use const PHP_EOL; +/** + * Concrete implementation of BillingService + */ class RealBillingService implements BillingService { + /** + * {@inheritdoc} + */ public function chargeOrder(): string { return 'Charged.' . PHP_EOL; } }demo/composer.json (1)
17-19
: Add PHP version requirement.Consider adding PHP version requirement to ensure compatibility:
"require": { + "php": ">=8.0", "ray/aop": "^2.17" }
demo/README.md (2)
3-3
: Minor grammatical improvement neededConsider hyphenating "Aspect-Oriented Programming" as it's a compound adjective.
-This is a demonstration of [Ray.Aop](https://github.com/ray-di/Ray.Aop), an Aspect Oriented Programming (AOP) framework for PHP. +This is a demonstration of [Ray.Aop](https://github.com/ray-di/Ray.Aop), an Aspect-Oriented Programming (AOP) framework for PHP.🧰 Tools
🪛 LanguageTool
[uncategorized] ~3-~3: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...(https://github.com/ray-di/Ray.Aop), an Aspect Oriented Programming (AOP) framework for PHP. #...(EN_COMPOUND_ADJECTIVE_INTERNAL)
31-32
: Consider expanding project structure documentationThe project structure section could benefit from more detailed descriptions of the demo classes in the
src/
directory and their purposes.🧰 Tools
🪛 LanguageTool
[uncategorized] ~31-~31: Loose punctuation mark.
Context: ...p ``` ## Project Structure -aop.php
: Main demo file that showcases AOP funct...(UNLIKELY_OPENING_PUNCTUATION)
build.sh (2)
12-12
: Consider making debug flags configurableThe debug flags
-g -O0
are hardcoded. Consider making these configurable through environment variables for flexibility.- ./configure CFLAGS="-g -O0" + CFLAGS="${CFLAGS:--g -O0}" + ./configure CFLAGS="$CFLAGS"
Line range hint
69-71
: Update usage help messageThe usage message doesn't include the new
demo
anddebug
commands.- echo "Usage: $0 {clean|prepare|build|install|run|all}" + echo "Usage: $0 {clean|prepare|build|install|run|demo|debug|all}"tests/001-rayaop-basic.phpt (1)
Line range hint
13-18
: Consider adding more test cases for interceptorThe TestInterceptor implementation could benefit from additional test cases covering edge cases and error conditions.
Consider adding tests for:
- Null parameters
- Exception handling
- Return type validation
Would you like me to help generate additional test cases?
tests/010-rayaop-void-return.phpt (2)
14-24
: Consider adding PHPDoc comments for better documentationThe test class methods would benefit from PHPDoc comments explaining their purpose and return types, especially since they demonstrate different void return scenarios.
class TestClass { + /** + * Method without explicit return statement + * @return void + */ public function voidMethod() { echo "Executing void method\n"; // 明示的なreturnなし } + /** + * Method with explicit return statement + * @return void + */ public function emptyReturnMethod() { echo "Executing empty return method\n"; return; // 明示的な空return } }
41-52
: Consider adding negative test casesThe expected output covers the happy path, but consider adding test cases for:
- Interceptor throwing an exception
- Multiple interceptors in chain
- Edge cases with different PHP versions
smoke.php (1)
10-10
: Consider adding parameter validationThe interceptor should validate parameters before invoking the method.
- return call_user_func_array([$object, $method], $params); + if (!method_exists($object, $method)) { + throw new \InvalidArgumentException("Method {$method} does not exist"); + } + return call_user_func_array([$object, $method], $params);.github/workflows/build.yml (1)
77-79
: Consider adding timeout for Valgrind demo testThe Valgrind test on the demo directory might benefit from a timeout to prevent hanging in case of issues.
cd demo -valgrind --suppressions=../valgrind.supp --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-demo-out.txt php -n -dextension=../modules/rayaop.so aop.php +timeout 300s valgrind --suppressions=../valgrind.supp --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-demo-out.txt php -n -dextension=../modules/rayaop.so aop.phpREADME.ja.md (1)
163-166
: Fix list indentationThe nested list items under "メソッドあたり1つのインターセプター" are indented with 4 spaces instead of the standard 2 spaces.
- メソッドあたり1つのインターセプター:最後に登録されたインターセプターが優先されます - - 新しいインターセプターを登録すると、以前のものは自動的に解除されます - - この設計により、予測可能な動作と最適なパフォーマンスを確保 + メソッドあたり1つのインターセプター:最後に登録されたインターセプターが優先されます + - 新しいインターセプターを登録すると、以前のものは自動的に解除されます + - この設計により、予測可能な動作と最適なパフォーマンスを確保🧰 Tools
🪛 Markdownlint (0.35.0)
164-164: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
165-165: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
README.md (2)
164-165
: Fix list indentationThe nested list items under "One interceptor per method" are indented with 4 spaces instead of the standard 2 spaces.
- One interceptor per method: The extension supports a single active interceptor per method, with the last registered interceptor taking precedence - - When registering a new interceptor for a method, the previous one is automatically unregistered - - This design ensures predictable behavior and optimal performance + One interceptor per method: The extension supports a single active interceptor per method, with the last registered interceptor taking precedence + - When registering a new interceptor for a method, the previous one is automatically unregistered + - This design ensures predictable behavior and optimal performance🧰 Tools
🪛 Markdownlint (0.35.0)
164-164: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
165-165: Expected: 2; Actual: 4
Unordered list indentation(MD007, ul-indent)
89-96
: Fix hyphenation in compound wordsFor consistency, "multi-threaded" should be written as "multithreaded" throughout the documentation.
- - Safe initialization and cleanup in multi-threaded environments + - Safe initialization and cleanup in multithreaded environments - When using in multi-threaded environments (e.g., PHP-FPM): + When using in multithreaded environments (e.g., PHP-FPM):🧰 Tools
🪛 LanguageTool
[misspelling] ~91-~91: This word is normally spelled as one.
Context: ...te - Safe initialization and cleanup in multi-threaded environments When using in multi-threa...(EN_COMPOUNDS_MULTI_THREADED)
[misspelling] ~93-~93: This word is normally spelled as one.
Context: ...ti-threaded environments When using in multi-threaded environments (e.g., PHP-FPM): - Ensure ...(EN_COMPOUNDS_MULTI_THREADED)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (19)
.github/workflows/build.yml
(4 hunks).gitignore
(1 hunks)README.ja.md
(1 hunks)README.md
(4 hunks)build.sh
(3 hunks)demo/README.md
(1 hunks)demo/aop.php
(1 hunks)demo/composer.json
(1 hunks)demo/run.php
(1 hunks)demo/src/BillingService.php
(1 hunks)demo/src/IsContainsMatcher.php
(1 hunks)demo/src/RealBillingService.php
(1 hunks)demo/src/WeekendBlocker.php
(1 hunks)php_rayaop.h
(2 hunks)rayaop.c
(7 hunks)smoke.php
(2 hunks)tests/001-rayaop-basic.phpt
(2 hunks)tests/008-rayaop-thread-safety.phpt
(1 hunks)tests/010-rayaop-void-return.phpt
(1 hunks)
🧰 Additional context used
📓 Learnings (4)
demo/src/BillingService.php (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#9
File: demo/src/BillingService.php:17-17
Timestamp: 2024-12-09T07:06:47.709Z
Learning: In the `ext-rayaop` project, attributes like `#[WeekendBlock]` used with Ray AOP do not necessarily require a corresponding PHP attribute class definition, as Ray AOP handles the binding internally.
demo/src/IsContainsMatcher.php (2)
Learnt from: koriym
PR: ray-di/ext-rayaop#9
File: demo/src/IsContainsMatcher.php:17-22
Timestamp: 2024-12-09T07:03:50.648Z
Learning: In PHP sample code files like 'demo/src/IsContainsMatcher.php' in the Ray.Aop project, strict argument validation and case-insensitive matching options are not necessary.
Learnt from: koriym
PR: ray-di/ext-rayaop#9
File: demo/src/IsContainsMatcher.php:27-32
Timestamp: 2024-12-09T07:03:49.562Z
Learning: For sample code in `demo/src/IsContainsMatcher.php`, strict matching logic is not required; simpler implementations are acceptable.
demo/aop.php (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#9
File: demo/aop.php:14-20
Timestamp: 2024-12-09T07:04:27.602Z
Learning: When reviewing sample code in `demo/aop.php`, avoid suggesting strict error handling enhancements, as less strict code is acceptable for demonstration purposes.
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 LanguageTool
demo/README.md
[uncategorized] ~3-~3: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...(https://github.com/ray-di/Ray.Aop), an Aspect Oriented Programming (AOP) framework for PHP. #...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
[uncategorized] ~31-~31: Loose punctuation mark.
Context: ...p ``` ## Project Structure - aop.php
: Main demo file that showcases AOP funct...
(UNLIKELY_OPENING_PUNCTUATION)
README.ja.md
[uncategorized] ~174-~174: 文法ミスがあります。"を軽蔑する"の間違いです。
Context: ...y-di/Ray.Aop)は高レベルのAOP機能を提供します: Ray.Aopの提供する機能: - Matchersを使用した条件付きインターセプション - メソッドあ...
(NO_SURU)
README.md
[misspelling] ~91-~91: This word is normally spelled as one.
Context: ...te - Safe initialization and cleanup in multi-threaded environments When using in multi-threa...
(EN_COMPOUNDS_MULTI_THREADED)
[misspelling] ~93-~93: This word is normally spelled as one.
Context: ...ti-threaded environments When using in multi-threaded environments (e.g., PHP-FPM): - Ensure ...
(EN_COMPOUNDS_MULTI_THREADED)
[uncategorized] ~104-~104: Loose punctuation mark.
Context: ...des: - RAYAOP_E_MEMORY_ALLOCATION (1)
: Memory allocation failure - `RAYAOP_E_H...
(UNLIKELY_OPENING_PUNCTUATION)
[grammar] ~111-~111: The verb ‘reporting’ is used with the gerund form.
Context: ...'s error reporting system. Enable error reporting to catch and handle these errors. ## Debug Mode...
(ADMIT_ENJOY_VB)
🪛 Markdownlint (0.35.0)
README.ja.md
164-164: Expected: 2; Actual: 4
Unordered list indentation
(MD007, ul-indent)
165-165: Expected: 2; Actual: 4
Unordered list indentation
(MD007, ul-indent)
README.md
164-164: Expected: 2; Actual: 4
Unordered list indentation
(MD007, ul-indent)
165-165: Expected: 2; Actual: 4
Unordered list indentation
(MD007, ul-indent)
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (21)
demo/aop.php (2)
14-20
: Aspect Binding and Weaving Configured Correctly
The aspect is properly set up with the matcher and interceptor, and the weaving is correctly applied to the source directory.
22-29
: Method Interception Enabled and Runtime Execution Handled Appropriately
The code enables method interception and handles exceptions from chargeOrder()
effectively within the try-catch block.
php_rayaop.h (2)
93-93
: Consistent Use of zend_bool
for Boolean Return Type
The function php_rayaop_should_intercept
now returns zend_bool
instead of bool
, ensuring consistency with Zend Engine types.
61-61
: Verify Definition of ZEND_BEGIN_MODULE_GLOBALS
Macro
At line 61, the ZEND_BEGIN_MODULE_GLOBALS
macro is used, but ensure that all necessary headers are included so this macro is properly defined to prevent compilation issues.
Run the following script to verify that the macro ZEND_BEGIN_MODULE_GLOBALS
is defined:
✅ Verification successful
No Issues with ZEND_BEGIN_MODULE_GLOBALS
Usage
The code correctly uses the ZEND_BEGIN_MODULE_GLOBALS
macro with proper header inclusions. The file includes all necessary Zend headers (zend.h
, zend_API.h
, zend_types.h
) that would provide the macro definition, and the macro is used correctly to define the module globals structure with appropriate member variables. The structure follows the standard PHP extension pattern for module globals.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if 'ZEND_BEGIN_MODULE_GLOBALS' is defined in included headers.
# List of header files included in php_rayaop.h
headers=(
"php.h"
"zend.h"
"zend_API.h"
"zend_types.h"
"zend_ini.h"
"php_ini.h"
"ext/standard/info.h"
"zend_exceptions.h"
"zend_interfaces.h"
"TSRM.h"
)
# Search for the macro definition
for header in "${headers[@]}"; do
if [ -f "$header" ]; then
grep -H 'ZEND_BEGIN_MODULE_GLOBALS' "$header"
fi
done
Length of output: 723
Script:
#!/bin/bash
# Let's try a different approach by checking the actual content of php_rayaop.h
# to verify the includes and macro usage
# First, let's see the includes in php_rayaop.h
echo "=== Checking includes in php_rayaop.h ==="
rg -A 10 "#include" php_rayaop.h
# Then, let's check for ZEND_BEGIN_MODULE_GLOBALS usage
echo -e "\n=== Checking ZEND_BEGIN_MODULE_GLOBALS usage ==="
rg "ZEND_BEGIN_MODULE_GLOBALS" -A 3 php_rayaop.h
# Let's also check if this macro might be defined in Zend headers
echo -e "\n=== Looking for ZEND_BEGIN_MODULE_GLOBALS definition in the codebase ==="
rg "ZEND_BEGIN_MODULE_GLOBALS" --type hpp --type h
Length of output: 1296
Script:
#!/bin/bash
# Let's check if the macro is defined in the PHP core headers that are typically installed
# First, let's check if we can find the PHP development headers
echo "=== Checking for PHP development headers ==="
fd -g "zend_modules.h"
# Let's also check the content of config.h which might include system paths
echo -e "\n=== Checking config.h content ==="
cat config.h
# Finally, let's verify the complete module globals structure
echo -e "\n=== Checking complete module globals structure ==="
rg -B 2 -A 5 "ZEND_BEGIN_MODULE_GLOBALS" php_rayaop.h
Length of output: 849
rayaop.c (3)
125-147
: Ensure Accurate Interception Conditions in php_rayaop_should_intercept
The conditions in the php_rayaop_should_intercept
function correctly check for:
- Interception enabled status.
- Maximum execution depth not exceeded.
- No existing exceptions.
- Valid
execute_data
and function details. - Not currently intercepting to prevent recursion.
233-267
: Robust Parameter Preparation and Cleanup in rayaop_execute_ex
The updated interception execution:
- Checks for exceptions before proceeding.
- Prepares parameters carefully, adding references where necessary.
- Handles cleanup meticulously, even in error scenarios.
108-110
:
Add Error Handling for spprintf
Failure
The spprintf
function may fail and return a negative value. It's important to check if len < 0
and handle the failure to prevent potential issues.
Apply this diff to add error handling:
int len = spprintf(&key, 0, "%s::%s", ZSTR_VAL(class_name), ZSTR_VAL(method_name));
+if (len < 0) {
+ return NULL;
+}
if (key_len) {
*key_len = (size_t)len;
}
demo/run.php (1)
3-3
: Execution Command Configured Correctly
The passthru
function correctly executes the ao.php
script with the rayaop.so
extension loaded.
demo/src/BillingService.php (1)
1-19
: LGTM! Well-structured interface with proper documentation.
The interface is well-implemented with:
- Strict type declaration
- Clear PHPDoc documentation
- Proper return type specification
- Correct attribute usage
demo/composer.json (1)
17-19
: Verify compatibility with ray/aop version.
Let's check if version ^2.17 of ray/aop is the latest stable version and verify its compatibility.
✅ Verification successful
Let me gather more specific information about the stable versions.
The specified version ^2.17 is compatible and up-to-date
The project is using the latest stable version (2.17.0) released on November 15, 2024. The caret operator (^) in the version constraint allows for compatible updates within the same major version, which is appropriate for this package.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check latest version and release date of ray/aop
curl -s https://packagist.org/packages/ray/aop.json | jq -r '.package.versions | to_entries | map(select(.key | startswith("2."))) | max_by(.key) | {version: .key, time: .value.time}'
Length of output: 251
Script:
#!/bin/bash
# Get all stable versions (excluding dev versions) and their release dates
curl -s https://packagist.org/packages/ray/aop.json | jq -r '.package.versions | to_entries | map(select(.key | test("^\\d+\\.\\d+\\.\\d+$"))) | sort_by(.key) | .[] | "\(.key) (\(.value.time))"'
Length of output: 2837
.gitignore (1)
36-37
: LGTM! Appropriate additions to .gitignore
The new entries properly exclude vendor dependencies and temporary files from version control.
demo/src/WeekendBlocker.php (1)
1-29
: LGTM! Clear demonstration of method interception
The implementation provides a good example of how to use method interception in Ray AOP, with clear error messages and logging.
demo/src/IsContainsMatcher.php (1)
1-33
: LGTM! Appropriate implementation for demonstration purposes
The matcher implementation clearly demonstrates the concept of AOP matching with simple, easy-to-understand logic. The code structure and documentation are well-organized.
tests/001-rayaop-basic.phpt (1)
35-36
: LGTM: Explicit interception control improves test clarity
The addition of explicit interception control makes the test behavior more predictable and easier to understand.
tests/010-rayaop-void-return.phpt (2)
5-12
: LGTM: Interceptor implementation follows best practices
The VoidTestInterceptor
correctly implements the MethodInterceptorInterface
and properly handles the method invocation chain.
26-29
: Verify initialization order and error handling
The initialization sequence looks correct, but we should verify error handling for failed interceptions.
✅ Verification successful
Error handling is properly implemented in the codebase
Based on the code analysis:
method_intercept()
returns boolean values (true/false) to indicate success/failure as documented in README.md- The initialization sequence in the test is correct:
method_intercept_init()
- Initializes and returns boolean statusmethod_intercept()
calls - Each returns boolean for validationmethod_intercept_enable(true)
- Enables interception globally
The error handling is implemented through return values rather than exceptions, which is appropriate for this low-level extension. The test can detect failures through these return values.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for error handling patterns in method_intercept calls
rg -A 5 "method_intercept\(" | grep -E "try|catch|if.*false"
Length of output: 62
Script:
#!/bin/bash
# Let's search for method_intercept implementation and usage patterns
ast-grep --pattern 'function method_intercept($$$)'
# Also search for any error handling or return value checks
rg "method_intercept" -B 2 -A 2
Length of output: 14953
smoke.php (1)
51-54
: LGTM: Improved test verification
Good addition of explicit success/failure checking and appropriate exit codes.
tests/008-rayaop-thread-safety.phpt (2)
Line range hint 50-56
: LGTM: Proper exception handling
Good implementation of try-catch block for handling error conditions.
45-46
: Verify method_intercept_enable placement
The enable call's placement is correct, but we should verify it's not called redundantly elsewhere.
✅ Verification successful
Multiple method_intercept_enable calls found across test files
The method_intercept_enable(true)
call appears in multiple test files, but this is expected and correct because:
- Each test file needs to independently enable interception for its own test cases
- The calls in README.md and README.ja.md are documentation examples
- The call in demo/aop.php is a demonstration file
- All other occurrences are in separate test files that need to run in isolation
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for multiple enable calls
rg "method_intercept_enable\(true\)"
Length of output: 496
.github/workflows/build.yml (2)
53-60
: LGTM: Demo directory test step properly integrated
The new test step correctly:
- Changes to demo directory
- Installs dependencies
- Loads the extension
84-93
: LGTM: Robust Valgrind log checking
The log checking logic properly:
- Handles multiple log files
- Verifies each log's existence
- Checks for error summary
Add a check for negative length returned by spprintf to ensure key generation doesn't proceed with invalid data. This prevents potential issues or crashes that could occur if the function fails and returns an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (5)
rayaop.c (5)
11-11
: Consider adding NULL check in MINIT.The global variable initialization is good, but consider adding a NULL check after registering the interface in MINIT to ensure proper initialization.
zend_class_entry ce; INIT_NS_CLASS_ENTRY(ce, "Ray\\Aop", "MethodInterceptorInterface", ray_aop_method_interceptor_interface_methods); ray_aop_method_interceptor_interface_ce = zend_register_internal_interface(&ce); +if (!ray_aop_method_interceptor_interface_ce) { + php_error_docref(NULL, E_ERROR, "Failed to register MethodInterceptorInterface"); + return FAILURE; +}
47-73
: Consider using snprintf for error messages.The error handling structure is good, but consider using snprintf for the error message to prevent potential buffer overflow in future modifications.
- php_error_docref(NULL, error_level, "[RayAOP] %s: %s", error_type, message); + char error_msg[512]; + snprintf(error_msg, sizeof(error_msg), "[RayAOP] %s: %s", error_type, message); + php_error_docref(NULL, error_level, "%s", error_msg);🧰 Tools
🪛 cppcheck (2.10-2)
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
128-150
: Consider adding scope validation.The interception checks are comprehensive, but consider adding validation for the scope type to prevent potential issues with internal functions.
if (!execute_data || !execute_data->func || !execute_data->func->common.scope || !execute_data->func->common.function_name) { return 0; } +/* Ensure we're not trying to intercept internal functions */ +if (execute_data->func->type == ZEND_INTERNAL_FUNCTION) { + return 0; +} + if (RAYAOP_G(is_intercepting)) { return 0; }
323-344
: Consider using atomic operations for handler updates.The current implementation has a potential race condition where another thread could modify the handler between the find and update operations.
Consider implementing a compare-and-swap mechanism or using a more fine-grained locking strategy for handler updates.
386-392
: Consider reordering initialization steps.The current order of operations could lead to a brief window where the mutex is not available but the globals are allocated.
#ifdef ZTS - ts_allocate_id(&rayaop_globals_id, sizeof(zend_rayaop_globals), NULL, NULL); rayaop_mutex = tsrm_mutex_alloc(); - if (!rayaop_mutex) { - ts_free_id(rayaop_globals_id); php_error_docref(NULL, E_ERROR, "Failed to allocate mutex for RayAOP"); return FAILURE; } + ts_allocate_id(&rayaop_globals_id, sizeof(zend_rayaop_globals), NULL, NULL); #endif
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
rayaop.c
(7 hunks)
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
- Add exception check during parameter array population - Handle failed array insertion by removing reference - Add break on failure to prevent further processing This fixes memory leaks that could occur if exceptions or failures happen while preparing parameters for method interception.
Add a check to ensure that internal functions are not intercepted by the AOP mechanism. This prevents potential issues or undefined behavior when manipulating internal PHP functions. The change enhances stability and reliability of the interception logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (1)
rayaop.c (1)
47-73
: Consider standardizing error levels across error types.While the error handling is more granular now, some error types use E_ERROR while others use E_WARNING without clear justification. Consider documenting the criteria for choosing error levels.
🧰 Tools
🪛 cppcheck (2.10-2)
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
rayaop.c
(7 hunks)
🧰 Additional context used
📓 Learnings (1)
rayaop.c (1)
Learnt from: koriym
PR: ray-di/ext-rayaop#7
File: rayaop.c:250-274
Timestamp: 2024-11-12T14:02:45.946Z
Learning: In `rayaop.c`, when cleaning up `php_rayaop_intercept_info` structures upon failure, we can use `php_rayaop_free_intercept_info` by passing a temporary `zval` containing the pointer to `info`.
🪛 cppcheck (2.10-2)
rayaop.c
[error] 60-60: There is an unknown macro here somewhere. Configuration is required. If ZEND_BEGIN_MODULE_GLOBALS is a macro then please configure it.
(unknownMacro)
🔇 Additional comments (5)
rayaop.c (5)
11-11
: LGTM: Explicit NULL initialization adds clarity.
The explicit NULL initialization of ray_aop_method_interceptor_interface_ce
helps prevent undefined behavior.
103-116
: LGTM: Robust key generation with proper error handling.
The function now properly handles:
- NULL input validation
- spprintf failure
- Memory management
207-264
: Consider using a cleanup macro for better maintainability.
The cleanup logic is repeated in multiple places. A cleanup macro would reduce code duplication and ensure consistent resource cleanup.
394-401
: LGTM: Proper initialization with error handling.
The mutex allocation and cleanup sequence is well-implemented with proper error handling.
128-152
: Verify the MAX_EXECUTION_DEPTH constant.
The execution depth check is good, but we should verify if MAX_EXECUTION_DEPTH is properly defined.
✅ Verification successful
Let me check the actual definition of MAX_EXECUTION_DEPTH to verify its value.
MAX_EXECUTION_DEPTH is properly defined and documented
The constant is well-defined in php_rayaop.h
with a value of 100, which is a reasonable limit to prevent infinite recursion. This value is also properly documented in both English and Japanese README files.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if MAX_EXECUTION_DEPTH is defined in header files
rg -l "define.*MAX_EXECUTION_DEPTH"
Length of output: 73
Script:
#!/bin/bash
# Get the definition of MAX_EXECUTION_DEPTH and surrounding context
rg "define.*MAX_EXECUTION_DEPTH" -B 2 -A 2
Length of output: 549
@coderabbitai We will release this PR. Would you like to add release notes? |
Tip For best results, initiate chat on the files or code changes. @koriym, certainly! Here are the release notes for this PR: Release Notes Bug Fixes and Enhancements
These changes enhance the reliability, efficiency, and documentation of the Ray AOP extension, providing a solid foundation for aspect-oriented programming in PHP. Let me know if you'd like any adjustments or additional details! |
Summary by CodeRabbit
New Features
RealBillingService
,WeekendBlocker
, andIsContainsMatcher
.Bug Fixes
Documentation