Skip to content
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

All work towards first release #2

Merged
merged 40 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
2b5791c
Add rayaop extension and configuration setup
koriym Jun 30, 2024
94dd518
Replace and rename php_rayaop.h files
koriym Jun 30, 2024
a43b209
Add clean-tests and mrproper to Makefile
koriym Jun 30, 2024
cd48704
Add 'clean' and 'make' run configurations
koriym Jun 30, 2024
6f92479
Update PHP version in GitHub workflow
koriym Jun 30, 2024
a83bc59
Uncomment code to release class and method names
koriym Jun 30, 2024
e373bd3
Adjust return value cleanup and hash table initialization
koriym Jun 30, 2024
b8f2d47
Uncomment debug definition in rayaop.c
koriym Jun 30, 2024
e324283
Update rayaop.c with enhanced debugging and error handling
koriym Jun 30, 2024
23ed5ce
Add 'cmake-build-debug' to .gitignore
koriym Jun 30, 2024
f72bd3a
Add test.php with TestClass and Intercepted classes
koriym Jun 30, 2024
747999f
Add script to generate package.xml for pecl extensions
koriym Jun 30, 2024
fda5c27
Update link formatting and variable definitions
koriym Jun 30, 2024
d919ea5
Update source files and set CMP0115 policy in CMakeLists.txt
koriym Jun 30, 2024
935de3a
Update memory management for intercept hash table
koriym Jul 1, 2024
4cc134e
Change script name in run function
koriym Jul 1, 2024
4e935ca
Update PHP command in GitHub workflow
koriym Jul 1, 2024
4cc434a
fixup! Update PHP command in GitHub workflow
koriym Jul 1, 2024
29a4a16
Refactor hash table allocation and shutdown functions in rayaop.c
koriym Jul 4, 2024
959503f
Enable RAYAOP_DEBUG for debugging
koriym Jul 4, 2024
62b0e71
Update build workflow with memory check and test enhancements
koriym Jul 6, 2024
e0135b6
Update PROGRAM_PARAMS in make.xml
koriym Jul 6, 2024
e2fbca1
Refactor rayaop_zend_execute_ex for better maintainability
koriym Jul 6, 2024
ac47076
Update RayAop PHP extension header
koriym Jul 6, 2024
ca13b0d
Refactor rayaop.c for better management of intercept info
koriym Jul 6, 2024
ce44306
Refactor rayaop.c for improved organization and readability
koriym Jul 6, 2024
2c44bf4
Rename class and implement interface in PHP and C
koriym Jul 6, 2024
9fb75a7
Add basic tests for RayAOP extension
koriym Jul 6, 2024
7859d29
Add RED test for multiple interceptors in RayAOP
koriym Jul 6, 2024
abaacdc
Refactor error handling in rayaop.c
koriym Jul 6, 2024
4585a1f
Add comments and improve function descriptions in rayaop.c
koriym Jul 6, 2024
f0c96bd
Update and translate Ray Aop PECL extension documentation
koriym Jul 6, 2024
a0d109d
Update expected test output in multiple interceptors test
koriym Jul 6, 2024
71b72fd
Update database connection configuration
koriym Jul 6, 2024
8d9518f
Update README with enhanced installation guide and test execution det…
koriym Jul 6, 2024
ca46f7e
Add Ray.Aop InterceptHandler to spec.md
koriym Jul 6, 2024
108a87f
Update README.md with extension functionalities and usage details
koriym Jul 6, 2024
6de1ec4
Improve indentation in documentation file
koriym Jul 6, 2024
6af1949
Improve README.md formatting
koriym Jul 6, 2024
3c7990e
Remove unsupported features from README
koriym Jul 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 69 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ on:
workflow_dispatch:

jobs:
build:
build-and-test:
runs-on: ubuntu-latest

strategy:
matrix:
php-version: ['8.0', '8.1', '8.2', '8.3']
php-version: ['8.1', '8.2', '8.3']

steps:
- name: Checkout code
Expand All @@ -23,8 +23,10 @@ jobs:
php-version: ${{ matrix.php-version }}
extensions: mbstring, intl

- name: Install build tools
run: sudo apt-get update && sudo apt-get install -y autoconf automake libtool bison re2c
- name: Install build tools and Valgrind
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake libtool bison re2c valgrind

- name: Prepare build
run: |
Expand All @@ -33,9 +35,69 @@ jobs:
make

- name: Run tests
id: run_tests
run: make test
continue-on-error: true

- name: Run demo with debug logging
id: run_demo
run: |
php -dextension=./modules/rayaop.so -i | grep rayaop
timeout 60s php -n -dextension=./modules/rayaop.so -dmemory_limit=128M -dreport_memleaks=1 -dzend.assertions=1 -dassert.exception=1 smoke.php
continue-on-error: true

- name: Run Valgrind memory check
if: steps.run_tests.outcome == 'failure' || steps.run_demo.outcome == 'failure'
run: |
cat << EOF > valgrind.supp
{
<insert_a_suppression_name_here>
Memcheck:Leak
match-leak-kinds: reachable
...
fun:php_module_startup
...
}
EOF
valgrind --suppressions=valgrind.supp --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt php -n -dextension=./modules/rayaop.so smoke.php

- name: Check Valgrind results
if: steps.run_tests.outcome == 'failure' || steps.run_demo.outcome == 'failure'
run: |
if [ -f valgrind-out.txt ]; then
echo "Valgrind log found:"
cat valgrind-out.txt
if ! grep -q "ERROR SUMMARY: 0 errors from 0 contexts" valgrind-out.txt; then
echo "Valgrind found errors"
exit 1
fi
else
echo "Valgrind log not found. This is unexpected."
exit 1
fi

- name: Upload Valgrind log file
if: (steps.run_tests.outcome == 'failure' || steps.run_demo.outcome == 'failure') && always()
uses: actions/upload-artifact@v2
with:
name: valgrind-log
path: valgrind-out.txt
if-no-files-found: warn

- name: Upload test logs
if: failure()
uses: actions/upload-artifact@v2
with:
name: test-logs
path: |
tests/*.log
tests/*.sh
if-no-files-found: warn

- name: Run demo
- name: Final status check
if: always()
run: |
php -d extension=./modules/rayaop.so -i | grep rayaop
timeout 60s php -d extension=./modules/rayaop.so -d memory_limit=128M -d report_memleaks=1 -d zend.assertions=1 -d assert.exception=1 rayaop.php 2> php_stderr.log || true
if [ "${{ steps.run_tests.outcome }}" == "failure" ] || [ "${{ steps.run_demo.outcome }}" == "failure" ]; then
echo "Tests or demo run failed. Please check the logs for more information."
exit 1
fi
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@

# Ignore directories and its content
/Makefile.fragments
/Makefile.objects
/Makefile.objects
/cmake-build-debug
7 changes: 7 additions & 0 deletions .idea/runConfigurations/clean.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/runConfigurations/make.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 必要なCMakeのバージョンを指定
# link https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html
cmake_minimum_required(VERSION 3.8)

# プロジェクトの名前と使用する言語を指定
# link https://cmake.org/cmake/help/latest/command/project.html
project(rayaop C)

# コンパイル時に定義するシンボルを指定
# link https://cmake.org/cmake/help/latest/command/add_compile_definitions.html
add_compile_definitions(HAVE_RAYAOP)


# `php-config` コマンドを使ってPHPのインクルードディレクトリを取得
# link https://cmake.org/cmake/help/latest/command/execute_process.html
execute_process (
COMMAND php-config --include-dir
OUTPUT_VARIABLE PHP_SOURCE
)

# 取得したディレクトリの末尾にある改行を削除
# link https://cmake.org/cmake/help/latest/command/string.html
string(REGEX REPLACE "\n$" "" PHP_SOURCE "${PHP_SOURCE}")

# 使用するソースディレクトリをメッセージとして表示
# link https://cmake.org/cmake/help/latest/command/message.html
message("Using source directory: ${PHP_SOURCE}")

# インクルードディレクトリを追加
# link https://cmake.org/cmake/help/latest/command/include_directories.html
include_directories(${PHP_SOURCE})
include_directories(${PHP_SOURCE}/main)
include_directories(${PHP_SOURCE}/Zend)
include_directories(${PHP_SOURCE}/TSRM)
include_directories(${PROJECT_SOURCE_DIR})

# カスタムターゲット `configure` を追加
# `phpize` と `./configure` を実行し、ソースファイルに依存させる
# link https://cmake.org/cmake/help/latest/command/add_custom_target.html
add_custom_target(configure
COMMAND phpize && ./configure
DEPENDS ${SOURCE_FILES}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})

# ソースファイルのリストを指定
# link https://cmake.org/cmake/help/latest/command/set.html
set(SOURCE_FILES php_rayaop.h rayaop.c)

# ソースファイルからライブラリを作成(ただし、ALLビルドからは除外)
# link https://cmake.org/cmake/help/latest/command/add_library.html
add_library(___ EXCLUDE_FROM_ALL ${SOURCE_FILES})

# CMakeの CMP0115 ポリシーの振る舞いを設定。新しいポリシーでは、ソースファイルが存在しない場合でも
# add_executable() または add_library() を実行しますが、生成されたビルドがそのファイルを見つけられない場合にはエラーを生成します。
# link https://cmake.org/cmake/help/latest/policy/CMP0115.html
cmake_policy(SET CMP0115 NEW)

16 changes: 16 additions & 0 deletions Makefile.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
clean-tests:
rm -f tests/*.diff tests/*.exp tests/*.log tests/*.out tests/*.php tests/*.sh

mrproper: clean clean-tests
rm -rf autom4te.cache build modules vendor
rm -f acinclude.m4 aclocal.m4 config.guess config.h config.h.in config.log config.nice config.status config.sub \
configure configure.ac install-sh libtool ltmain.sh Makefile Makefile.fragments Makefile.global \
Makefile.objects missing mkinstalldirs run-tests.php *~

info: $(all_targets)
"$(PHP_EXECUTABLE)" -d "extension=$(phplibdir)/$(PHP_PECL_EXTENSION).so" --re "$(PHP_PECL_EXTENSION)"

package.xml: php_$(PHP_PECL_EXTENSION).h
$(PHP_EXECUTABLE) build-packagexml.php

.PHONY: all clean install distclean test prof-gen prof-clean prof-use clean-tests mrproper info
103 changes: 70 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,50 @@

<img src="https://ray-di.github.io/images/logo.svg" alt="ray-di logo" width="150px;">

A PHP extension that provides Aspect-Oriented Programming (AOP) functionality for method interception.
A PHP extension that provides Aspect-Oriented Programming (AOP) functionality for method interception, designed to complement Ray.Aop.

## Features

- Intercept method calls on specific classes
- Efficient method interception for specific classes
- Apply custom logic before and after method execution
- Modify method arguments and return values
- Works with `final` classes and methods

## Requirements

- PHP 8.0 or higher
- php-dev package installed
- PHP 8.1 or higher

## Installation

2.Compile the extension:
1. Clone the repository:

```
phpize
./configure
make
git clone https://github.com/ray-di/ext-rayaop.git
cd ext-rayaop
```

3. Install the extension:
2. Build and install the extension:

```
sudo make install
phpize
./configure
make
make install
```

4. Add the following line to your php.ini file:
3. Add the following line to your php.ini file:

```
extension=rayaop.so
```

## About this Extension

This PECL extension is designed to enhance the performance of Ray.Aop by eliminating the need for CodeGen, resulting in faster execution speeds. While it is primarily created for Ray.Aop, it can also be used to implement custom AOP solutions independently of Ray.Aop.
This PECL extension is designed to enhance Ray.Aop by providing method interception capabilities at a lower level. While it can be used independently, it's primarily intended to be used in conjunction with Ray.Aop for optimal functionality.

By using this extension, developers can achieve high-performance method interception without the overhead of generating and compiling additional code.
Key points:
- The extension intentionally binds only one interceptor per method for simplicity and performance.
- Multiple interceptor chaining should be implemented in PHP code, either using Ray.Aop or custom implementation.
- The main advantages are the ability to intercept `final` classes/methods and unrestricted use of the `new` keyword.

## Usage

Expand All @@ -63,14 +67,9 @@ class MyInterceptor implements Ray\Aop\MethodInterceptorInterface
{
public function intercept(object $object, string $method, array $params): mixed
{
echo "Intercepted: " . get_class($object) . "::{$method}\n";
echo "Arguments: " . json_encode($params) . "\n";

// Call the original method
echo "Before method execution\n";
$result = call_user_func_array([$object, $method], $params);

echo "Method execution completed.\n";

echo "After method execution\n";
return $result;
}
}
Expand All @@ -85,7 +84,7 @@ $interceptor = new MyInterceptor();
method_intercept('TestClass', 'testMethod', $interceptor);
```

### Example
### Complete Example

```php
class TestClass
Expand All @@ -97,22 +96,47 @@ class TestClass
}
}

$interceptor = new MyInterceptor();
method_intercept('TestClass', 'testMethod', $interceptor);

$test = new TestClass();
$result = $test->testMethod("test");
echo "Result: $result\n";
echo "Final result: $result\n";
```

## Running Tests

To run the tests, use the following command:

Output:
```
php -dextension=./modules/rayaop.so test/rayaop_test.php
Before method execution
TestClass::testMethod(test) called
After method execution
Final result: Result: test
```

## Integration with Ray.Aop

For more complex AOP scenarios, it's recommended to use this extension in combination with [Ray.Aop](https://github.com/ray-di/Ray.Aop). Ray.Aop provides a higher-level API for managing multiple interceptors and more advanced AOP features.

## The Power of AOP

Aspect-Oriented Programming (AOP) is a powerful paradigm that complements Object-Oriented Programming (OOP) in building more flexible and maintainable software systems. By using AOP:

1. **Separation of Concerns**: You can cleanly separate cross-cutting concerns (like logging, security, or transaction management) from your core business logic.

2. **Enhanced Modularity**: AOP allows you to modularize system-wide concerns that would otherwise be scattered across multiple classes.

3. **Improved Code Reusability**: Aspects can be reused across different parts of your application, reducing code duplication.

4. **Easier Maintenance**: By centralizing certain behaviors, AOP can make your codebase easier to maintain and evolve over time.

5. **Non-invasive Changes**: You can add new behaviors to existing code without modifying the original classes, adhering to the Open/Closed Principle.

6. **Dynamic Behavior Modification**: With this PECL extension, you can even apply aspects to final classes and methods, providing unprecedented flexibility in your system design.

By combining the strengths of OOP and AOP, developers can create more robust, flexible, and easier-to-maintain software architectures. This PECL extension, especially when used in conjunction with Ray.Aop, opens up new possibilities for structuring your PHP applications, allowing you to tackle complex problems with elegance and efficiency.

## Build Script

You can use the build.sh script for various build operations:
The `build.sh` script provides various operations for building and managing the extension:

```sh
./build.sh clean # Clean the build environment
Expand All @@ -122,10 +146,23 @@ You can use the build.sh script for various build operations:
./build.sh all # Execute all the above steps
```

## Contributing
Use `./build.sh all` for a complete build and installation process.

## Running Tests

To run the tests for this extension, use the following command:

```sh
make test
```

This command will execute the PHP extension's test suite, which is the standard method for testing PHP extensions.

If you need to run specific tests or want more verbose output, you can use:

Contributions are welcome! Please feel free to submit a Pull Request.
```sh
make test TESTS="-v tests/your_specific_test.phpt"
```

## License
Replace `your_specific_test.phpt` with the actual test file you want to run.

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Loading
Loading