From 41431b991f219816d009c9336c157f0a0fe2a459 Mon Sep 17 00:00:00 2001 From: niktest <958190@gmail.com> Date: Tue, 6 Jun 2023 23:37:13 +1000 Subject: [PATCH 1/4] Added support for using PHP array callbacks. Refactored get_mapped_mvc_call Adding support for using PHP array Callbacks / Callables to add_action, add_filter, add_shortcode, remove_action, remove_filter. Simplified the preg_match call with a stripos to optimize performance. --- src/psr4/Bridge.php | 46 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/psr4/Bridge.php b/src/psr4/Bridge.php index bb25370..c1ecc7f 100644 --- a/src/psr4/Bridge.php +++ b/src/psr4/Bridge.php @@ -333,11 +333,11 @@ public function on_admin() * Adds a WordPress action hook. * @since 1.0.3 * - * @param string $hook WordPress hook name. - * @param string $mvc_call Lightweight MVC call. (i.e. 'Controller@method') - * @param mixed $priority Execution priority or MVC params. - * @param mixed $accepted_args Accepted args or priority. - * @param int $args Accepted args. + * @param string $hook WordPress hook name. + * @param string|array $mvc_call Lightweight MVC call. (i.e. 'Controller@method') + * @param mixed $priority Execution priority or MVC params. + * @param mixed $accepted_args Accepted args or priority. + * @param int $args Accepted args. */ public function add_action( $hook, $mvc_call, $priority = 10, $accepted_args = 1, $args = 1 ) { @@ -354,11 +354,11 @@ public function add_action( $hook, $mvc_call, $priority = 10, $accepted_args = 1 * Adds a WordPress filter hook. * @since 1.0.3 * - * @param string $hook WordPress hook name. - * @param string $mvc_call Lightweight MVC call. (i.e. 'Controller@method') - * @param mixed $priority Execution priority or MVC params. - * @param mixed $accepted_args Accepted args or priority. - * @param int $args Accepted args. + * @param string $hook WordPress hook name. + * @param string|array $mvc_call Lightweight MVC call. (i.e. 'Controller@method') + * @param mixed $priority Execution priority or MVC params. + * @param mixed $accepted_args Accepted args or priority. + * @param int $args Accepted args. */ public function add_filter( $hook, $mvc_call, $priority = 10, $accepted_args = 1, $args = 1 ) { @@ -375,8 +375,8 @@ public function add_filter( $hook, $mvc_call, $priority = 10, $accepted_args = 1 * Adds a WordPress shortcode. * @since 1.0.3 * - * @param string $tag WordPress tag name. - * @param string $mvc_call Lightweight MVC call. (i.e. 'Controller@method') + * @param string $tag WordPress tag name. + * @param string|array $mvc_call Lightweight MVC call. (i.e. 'Controller@method') */ public function add_shortcode( $tag, $mvc_call, $mvc_args = null ) { @@ -721,13 +721,13 @@ public function _admin_assets() * @since 3.1.15 * * @param string $hook - * @param string $mvc_handler + * @param string|array $mvc_handler * @param int $priority */ public function remove_action( $hook, $mvc_handler, $priority = 10 ) { remove_action( - $hook, + $hook, [ &$this, $this->get_mapped_mvc_call( $mvc_handler ) ], $priority ); @@ -738,13 +738,13 @@ public function remove_action( $hook, $mvc_handler, $priority = 10 ) * @since 3.1.15 * * @param string $hook - * @param string $mvc_handler + * @param string|array $mvc_handler * @param int $priority */ public function remove_filter( $hook, $mvc_handler, $priority = 10 ) { remove_filter( - $hook, + $hook, [ &$this, $this->get_mapped_mvc_call( $mvc_handler, true ) ], $priority ); @@ -754,13 +754,21 @@ public function remove_filter( $hook, $mvc_handler, $priority = 10 ) * Returns class method call mapped to a mvc engine method. * @since 1.0.3 * + * @param string|array $call + * * @return string */ private function get_mapped_mvc_call( $call, $return = false ) { - return ( preg_match( '/[vV]iew\@/', $call ) ? '_v_' : '_c_' ) - . ( $return ? 'return_' : 'void_' ) - . $call; + if ( is_array( $call ) ) { + $class_prefix = $this->config->get( 'namespace' ) . '\\Controllers\\'; + $call = str_replace( $class_prefix, '', implode( '@', $call ) ); + } + + $type_prefix = stripos( $call, 'view@' ) !== false ? '_v_' : '_c_'; + $return_prefix = $return ? 'return_' : 'void_'; + + return $type_prefix . $return_prefix . $call; } /** From d4e168cd65fbce9f076c8195c836cd087f44c7e1 Mon Sep 17 00:00:00 2001 From: Nikita Alekseev Date: Sat, 8 Jul 2023 19:20:26 +1000 Subject: [PATCH 2/4] Refactor get_mapped_mvc_call upon PR review. Rollback preg_match and remove a Controller hardcoded path. Nikita Alekseev 6 minutes ago --- src/psr4/Bridge.php | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/psr4/Bridge.php b/src/psr4/Bridge.php index c1ecc7f..5a66674 100644 --- a/src/psr4/Bridge.php +++ b/src/psr4/Bridge.php @@ -750,6 +750,24 @@ public function remove_filter( $hook, $mvc_handler, $priority = 10 ) ); } + /** + * Cast MVC call from PHP array Callbacks / Callables to typical string representation + * @since 3.1.18 + * + * @param string|array $mvc_call Lightweight MVC call. (i.e. 'Controller@method', or [Controller::class, 'method']) + * + * @return string + */ + private function cast_mvc_call_to_string( $mvc_call ) + { + if ( is_array( $mvc_call ) && count( $mvc_call ) === 2 ) { + $class_path = explode( '\\', $mvc_call[0] ); + $mvc_call[0] = end( $class_path ); + return implode( '@', $mvc_call ); + } + return $mvc_call; + } + /** * Returns class method call mapped to a mvc engine method. * @since 1.0.3 @@ -760,26 +778,21 @@ public function remove_filter( $hook, $mvc_handler, $priority = 10 ) */ private function get_mapped_mvc_call( $call, $return = false ) { - if ( is_array( $call ) ) { - $class_prefix = $this->config->get( 'namespace' ) . '\\Controllers\\'; - $call = str_replace( $class_prefix, '', implode( '@', $call ) ); - } - - $type_prefix = stripos( $call, 'view@' ) !== false ? '_v_' : '_c_'; - $return_prefix = $return ? 'return_' : 'void_'; - - return $type_prefix . $return_prefix . $call; + $call = $this->cast_mvc_call_to_string( $call ); + return ( preg_match( '/[vV]iew\@/', $call ) ? '_v_' : '_c_' ) + . ( $return ? 'return_' : 'void_' ) + . $call; } /** * Returns valid action filter item. * @since 1.0.3 * - * @param string $hook WordPress hook name. - * @param string $mvc_call Lightweight MVC call. (i.e. 'Controller@method') - * @param mixed $priority Execution priority or MVC params. - * @param mixed $accepted_args Accepted args or priority. - * @param int $args Accepted args. + * @param string $hook WordPress hook name. + * @param string|array $mvc_call Lightweight MVC call. (i.e. 'Controller@method') + * @param mixed $priority Execution priority or MVC params. + * @param mixed $accepted_args Accepted args or priority. + * @param int $args Accepted args. * * @return array */ @@ -787,7 +800,7 @@ private function get_hook( $hook, $mvc_call, $priority = 10, $accepted_args = 1, { return [ 'hook' => $hook, - 'mvc' => $mvc_call, + 'mvc' => $this->cast_mvc_call_to_string( $mvc_call ), 'priority' => is_array( $priority ) ? $accepted_args : $priority, 'args' => is_array( $priority ) ? ( $args ? $args : count( $priority ) ) : $accepted_args, 'mvc_args' => is_array( $priority ) ? $priority : null, From 0248fc12f739b6bd9d4127e64d89792254e49e3e Mon Sep 17 00:00:00 2001 From: Nikita Alekseev Date: Sat, 8 Jul 2023 19:21:00 +1000 Subject: [PATCH 3/4] Extended tests using the new feature of the PHP array Callbacks / Callables --- tests/cases/BridgeTest.php | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/cases/BridgeTest.php b/tests/cases/BridgeTest.php index 4a8c6de..8430126 100644 --- a/tests/cases/BridgeTest.php +++ b/tests/cases/BridgeTest.php @@ -98,11 +98,14 @@ function testControllerParameterOverride() // Prepare global $config; $main = new Main($config); - $main->add_action( 'test', 'TestController@filter', ['override'] ); + $main->add_action( 'test1', 'TestController@filter', ['override'] ); + $main->add_action( 'test2', [\UnitTesting\Controllers\TestController::class, 'filter'], ['override'] ); // Exec - $return = $main->{'_c_return_TestController@filter'}(123); + $return1 = $main->{'_c_return_TestController@filter'}(123); + $return2 = $main->{'_c_return_TestController@filter'}(123); // Assert - $this->assertEquals('override', $return); + $this->assertEquals('override', $return1); + $this->assertEquals('override', $return2); } /** * Tests view parameter override. @@ -169,13 +172,16 @@ function testAddAction() $main = new Main($config); // Run $main->add_action( 'test', 'TestController@testing' ); - $main->add_action( 'test2', 'view@test2' ); + $main->add_action( 'test2', [\UnitTesting\Controllers\TestController::class, 'testing'] ); + $main->add_action( 'test3', 'view@test2' ); $main->add_hooks(); // Assert $this->assertArrayHasKey('test', $hooks['actions']); $this->assertArrayHasKey('test2', $hooks['actions']); + $this->assertArrayHasKey('test3', $hooks['actions']); $this->assertEquals('[{},"_c_void_TestController@testing"]', json_encode($hooks['actions']['test'])); - $this->assertEquals('[{},"_v_void_view@test2"]', json_encode($hooks['actions']['test2'])); + $this->assertEquals('[{},"_c_void_TestController@testing"]', json_encode($hooks['actions']['test2'])); + $this->assertEquals('[{},"_v_void_view@test2"]', json_encode($hooks['actions']['test3'])); } /** * Test method. @@ -191,11 +197,14 @@ function testAddFilter() global $hooks; $main = new Main($config); // Run - $main->add_filter( 'controller', 'FilterController@filtering' ); + $main->add_filter( 'controller1', 'FilterController@filtering' ); + $main->add_filter( 'controller2', [\UnitTesting\Controllers\TestController::class, 'filter'] ); $main->add_hooks(); // Assert - $this->assertArrayHasKey('controller', $hooks['filters']); - $this->assertEquals('[{},"_c_return_FilterController@filtering"]', json_encode($hooks['filters']['controller'])); + $this->assertArrayHasKey('controller1', $hooks['filters']); + $this->assertArrayHasKey('controller2', $hooks['filters']); + $this->assertEquals('[{},"_c_return_FilterController@filtering"]', json_encode($hooks['filters']['controller1'])); + $this->assertEquals('[{},"_c_return_TestController@filter"]', json_encode($hooks['filters']['controller2'])); } /** * Test method. @@ -212,12 +221,17 @@ function testRemoveAction() $main = new Main($config); // Run $main->add_action( 'action1', 'ActionController@to_remove' ); + $main->add_action( 'action2', [\UnitTesting\Controllers\TestController::class, 'action'] ); $main->add_hooks(); $main->remove_action( 'action1', 'ActionController@to_remove' ); + $main->remove_action( 'action2', [\UnitTesting\Controllers\TestController::class, 'action'] ); // Assert $this->assertArrayNotHasKey('action1', $hooks['actions']); $this->assertArrayHasKey('action1', $hooks['removed']); + $this->assertArrayNotHasKey('action2', $hooks['actions']); + $this->assertArrayHasKey('action2', $hooks['removed']); $this->assertEquals('[{},"_c_void_ActionController@to_remove"]', json_encode($hooks['removed']['action1'])); + $this->assertEquals('[{},"_c_void_TestController@action"]', json_encode($hooks['removed']['action2'])); } /** * Test method. @@ -234,11 +248,16 @@ function testRemoveFilter() $main = new Main($config); // Run $main->add_filter( 'filter1', 'FilterController@to_remove' ); + $main->add_filter( 'filter2', [\UnitTesting\Controllers\TestController::class, 'filter'] ); $main->add_hooks(); $main->remove_filter( 'filter1', 'FilterController@to_remove' ); + $main->remove_filter( 'filter2', [\UnitTesting\Controllers\TestController::class, 'filter'] ); // Assert $this->assertArrayNotHasKey('filter1', $hooks['filters']); $this->assertArrayHasKey('filter1', $hooks['removed']); + $this->assertArrayNotHasKey('filter2', $hooks['filters']); + $this->assertArrayHasKey('filter2', $hooks['removed']); $this->assertEquals('[{},"_c_return_FilterController@to_remove"]', json_encode($hooks['removed']['filter1'])); + $this->assertEquals('[{},"_c_return_TestController@filter"]', json_encode($hooks['removed']['filter2'])); } } \ No newline at end of file From 6b2cd587a8bc6e8b8e72f0cd75fd28aca0f81522 Mon Sep 17 00:00:00 2001 From: Nikita Alekseev Date: Sat, 8 Jul 2023 19:26:48 +1000 Subject: [PATCH 4/4] Refactor cast_mvc_call_to_string to avoid loosing performance on implode --- src/psr4/Bridge.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/psr4/Bridge.php b/src/psr4/Bridge.php index 5a66674..e6ab9fe 100644 --- a/src/psr4/Bridge.php +++ b/src/psr4/Bridge.php @@ -762,8 +762,7 @@ private function cast_mvc_call_to_string( $mvc_call ) { if ( is_array( $mvc_call ) && count( $mvc_call ) === 2 ) { $class_path = explode( '\\', $mvc_call[0] ); - $mvc_call[0] = end( $class_path ); - return implode( '@', $mvc_call ); + return end( $class_path ) . '@' . $mvc_call[1]; } return $mvc_call; }