diff --git a/src/Uplink/Admin/Fields/Field.php b/src/Uplink/Admin/Fields/Field.php index 160d4baf..c91fac69 100644 --- a/src/Uplink/Admin/Fields/Field.php +++ b/src/Uplink/Admin/Fields/Field.php @@ -5,12 +5,13 @@ use StellarWP\Uplink\Admin\License_Field; use StellarWP\Uplink\Uplink; use StellarWP\Uplink\Config; -use StellarWP\Uplink\Resources\Collection; +use StellarWP\Uplink\View\Contracts\View; use StellarWP\Uplink\Resources\Resource; +use StellarWP\Uplink\Components\Controller; // Use function statement is problematic with Strauss. use StellarWP\Uplink as UplinkNamespace; -class Field { +class Field extends Controller{ public const STELLARWP_UPLINK_GROUP = 'stellarwp_uplink_group'; /** @@ -48,21 +49,19 @@ class Field { */ protected bool $show_heading = false; + /** + * @var string + */ + protected const VIEW = 'fields/field'; + /** * Constructor! * - * @param string $slug Field slug. + * @param View $view The View Engine to render views. + * @param Resource $resource The resource. */ - public function __construct( string $slug ) { - $this->slug = $slug; - - $collection = Config::get_container()->get( Collection::class ); - $resource = $collection->get( $slug ); - - if ( ! $resource instanceof Resource ) { - throw new \InvalidArgumentException( sprintf( 'Resource with slug "%s" does not exist.', $slug ) ); - } - + public function __construct( View $view, Resource $resource ) { + $this->view = $view; $this->resource = $resource; } @@ -184,7 +183,7 @@ public function get_product_slug(): string { * @return string */ public function get_slug(): string { - return $this->slug; + return $this->resource->get_slug(); } /** @@ -193,15 +192,24 @@ public function get_slug(): string { * @return string */ public function get_classes(): string { - return 'stellarwp-uplink-license-key-field'; + return $this->classes( ['stellarwp-uplink-license-key-field' ] ); } /** * Renders the field. * + * @return void + */ + public function render( array $args = [] ): void { + echo $this->get_render_html(); + } + + /** + * Returns the field. + * * @return string */ - public function render(): string { + public function get_render_html(): string { Config::get_container()->get( License_Field::class )->enqueue_assets(); if ( $this->resource->is_using_oauth() ) { @@ -214,9 +222,12 @@ public function render(): string { $field = $this; $group = Config::get_container()->get( License_Field::class )->get_group_name( $this->get_slug() ); - ob_start(); - include Config::get_container()->get( Uplink::UPLINK_ADMIN_VIEWS_PATH ) . '/fields/field.php'; - $html = ob_get_clean(); + $args = [ + 'field' => $field, + 'group' => $group, + ]; + + $html = $this->view->render( self::VIEW, $args, true ); /** * Filters the field HTML. diff --git a/src/Uplink/Admin/Fields/Form.php b/src/Uplink/Admin/Fields/Form.php index b1ed7deb..2290c37a 100644 --- a/src/Uplink/Admin/Fields/Form.php +++ b/src/Uplink/Admin/Fields/Form.php @@ -4,8 +4,9 @@ use StellarWP\Uplink\Config; use StellarWP\Uplink\Uplink; +use StellarWP\Uplink\Components\Controller; -class Form { +class Form extends Controller{ /** * @var array */ @@ -26,6 +27,11 @@ class Form { */ protected string $button_text = ''; + /** + * @var string + */ + protected const VIEW = 'fields/form'; + /** * Adds a field to the form. * @@ -61,16 +67,23 @@ public function get_fields(): array { return $this->fields; } + /** + * Renders the form. + * + * @return void + */ + public function render( array $args = [] ): void { + echo $this->get_render_html(); + } + /** * Renders the form. * * @return string */ - public function render(): string { - $form = $this; - ob_start(); - include Config::get_container()->get( Uplink::UPLINK_ADMIN_VIEWS_PATH ) . '/fields/form.php'; - $html = ob_get_clean(); + public function get_render_html(): string { + $args = [ 'form' => $this ]; + $html = $this->view->render( self::VIEW, $args, true ); return apply_filters( 'stellarwp/uplink/' . Config::get_hook_prefix() . '/license_form_html', $html ); } diff --git a/src/Uplink/View/Contracts/View.php b/src/Uplink/View/Contracts/View.php index adbc2dac..b4fa9565 100644 --- a/src/Uplink/View/Contracts/View.php +++ b/src/Uplink/View/Contracts/View.php @@ -16,10 +16,12 @@ interface View { * * @param mixed[] $args Arguments to be extracted and passed to the view. * + * @param bool $is_admin Whether to load the view from the admin directory. + * * @throws FileNotFoundException If the view file cannot be found. * * @return string */ - public function render( string $name, array $args = [] ): string; + public function render( string $name, array $args = [], bool $is_admin = false ): string; } diff --git a/src/Uplink/View/Provider.php b/src/Uplink/View/Provider.php index a5ecfdc9..fa791c2b 100644 --- a/src/Uplink/View/Provider.php +++ b/src/Uplink/View/Provider.php @@ -13,7 +13,7 @@ final class Provider extends Abstract_Provider { public function register() { $this->container->singleton( WordPress_View::class, - new WordPress_View( __DIR__ . '/../../views' ) + new WordPress_View( __DIR__ . '/../../views', '.php', __DIR__ . '/../../admin-views' ) ); $this->container->bind( View::class, $this->container->get( WordPress_View::class ) ); diff --git a/src/Uplink/View/WordPress_View.php b/src/Uplink/View/WordPress_View.php index 5432a3cf..fa315197 100644 --- a/src/Uplink/View/WordPress_View.php +++ b/src/Uplink/View/WordPress_View.php @@ -20,6 +20,15 @@ final class WordPress_View implements Contracts\View { */ private $directory; + /** + * The server path to the admin-views folder. + * + * @var string + * + * @example /app/views/ + */ + private $admin_directory; + /** * The file extension of view files. * @@ -32,10 +41,12 @@ final class WordPress_View implements Contracts\View { /** * @param string $directory The server path to the views folder. * @param string $extension The file extension of view files. + * @param string $admin_directory The server path to the admin-views folder. */ - public function __construct( string $directory, string $extension = '.php' ) { - $this->directory = trailingslashit( realpath( $directory ) ); - $this->extension = $extension; + public function __construct( string $directory, string $extension = '.php', string $admin_directory = '' ) { + $this->directory = trailingslashit( realpath( $directory ) ); + $this->admin_directory = trailingslashit( realpath( $admin_directory ) ); + $this->extension = $extension; } /** @@ -48,12 +59,14 @@ public function __construct( string $directory, string $extension = '.php' ) { * * @param mixed[] $args Arguments to be extracted and passed to the view. * + * @param bool $is_admin Whether to load the view from the admin directory. + * * @throws FileNotFoundException If the view file cannot be found. * * @return string */ - public function render( string $name, array $args = [] ): string { - $file = $this->get_path( $name ); + public function render( string $name, array $args = [], bool $is_admin = false ): string { + $file = $this->get_path( $name, $is_admin ); try { $level = ob_get_level(); @@ -77,12 +90,14 @@ public function render( string $name, array $args = [] ): string { * * @param string $name The relative view path/name, e.g. `admin/notice`. * + * @param bool $is_admin Whether to load the view from the admin directory. + * * @throws FileNotFoundException If the view file cannot be found. * * @return string The absolute path to the view file. */ - private function get_path( string $name ): string { - $file = $this->directory . $name . $this->extension; + private function get_path( string $name, bool $is_admin = false ): string { + $file = ( $is_admin ? $this->admin_directory : $this->directory ) . $name . $this->extension; $path = realpath( $file ); if( $path === false ) { diff --git a/src/admin-views/fields/form.php b/src/admin-views/fields/form.php index 9dc6fc41..4248d297 100644 --- a/src/admin-views/fields/form.php +++ b/src/admin-views/fields/form.php @@ -19,7 +19,7 @@
get_fields() as $field ) : ?> - render(); ?> + render(); ?> should_show_button() ) : ?> get_button_text() );?> diff --git a/tests/wpunit/Admin/Fields/FieldTest.php b/tests/wpunit/Admin/Fields/FieldTest.php index 488f75ba..a0cae3c1 100644 --- a/tests/wpunit/Admin/Fields/FieldTest.php +++ b/tests/wpunit/Admin/Fields/FieldTest.php @@ -11,6 +11,7 @@ use StellarWP\Uplink\Tests\TestUtils; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; use StellarWP\Uplink\Tests\Traits\With_Uopz; +use StellarWP\Uplink\View\WordPress_View; class FieldTest extends UplinkTestCase { @@ -18,14 +19,16 @@ class FieldTest extends UplinkTestCase { use SnapshotAssertions; use With_Uopz; - /** - * @test - */ - public function it_should_fail_with_invalid_slug() { - $slug = 'Invalid Slug'; - $this->expectException( InvalidArgumentException::class ); - $this->expectExceptionMessage( sprintf( 'Resource with slug "%s" does not exist.', $slug ) ); - new Field( $slug ); + protected $view; + + protected $collection; + + public function setUp(): void { + parent::setUp(); + + $this->view = $this->container->get( WordPress_View::class ); + + $this->collection = $this->container->get( Collection::class ); } public function resourceProvider() { @@ -57,7 +60,7 @@ public function setup_container_get_slug( $resource ) { public function it_should_get_fields_with_slug( $resource ) { $current_resource = $this->setup_container_get_slug( $resource ); $slug = $current_resource->get_slug(); - $field = new Field( $slug ); + $field = new Field( $this->view, $current_resource ); $license_key = 'license_key' . $slug; $option_name = $current_resource->get_license_object()->get_key_option_name(); @@ -87,7 +90,7 @@ public function it_should_get_fields_with_slug( $resource ) { public function it_should_render_fields_correctly( $resource ) { $current_resource = $this->setup_container_get_slug( $resource ); $slug = $current_resource->get_slug(); - $field = new Field( $slug ); + $field = new Field( $this->view, $current_resource ); $license_key = 'license_key' . $slug; $option_name = $current_resource->get_license_object()->get_key_option_name(); $this->set_fn_return( 'wp_create_nonce', '123456789', false ); @@ -100,7 +103,7 @@ public function it_should_render_fields_correctly( $resource ) { $field_name = 'field-' . $slug; $field->set_field_name( $field_name ); - $test = $field->render(); + $test = $field->get_render_html(); $this->assertMatchesHtmlSnapshot( $test ); } @@ -110,7 +113,7 @@ public function it_should_render_fields_correctly( $resource ) { * @dataProvider resourceProvider */ public function it_should_set_and_get_field_id( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $field_id = 'custom-field-id'; $field->set_field_id( $field_id ); @@ -123,7 +126,7 @@ public function it_should_set_and_get_field_id( $resource ) { * @dataProvider resourceProvider */ public function it_should_set_and_get_field_label( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $label = 'Custom Label'; $field->set_label( $label ); @@ -136,7 +139,7 @@ public function it_should_set_and_get_field_label( $resource ) { * @dataProvider resourceProvider */ public function it_should_get_placeholder( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $this->assertEquals( 'License key', $field->get_placeholder() ); } @@ -146,7 +149,7 @@ public function it_should_get_placeholder( $resource ) { * @dataProvider resourceProvider */ public function it_should_get_nonce_action_and_field( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $nonce_action = Config::get_container()->get( License_Field::class )->get_group_name(); $nonce_field = $field->get_nonce_field(); @@ -168,7 +171,7 @@ public function it_should_get_nonce_action_and_field( $resource ) { * @dataProvider resourceProvider */ public function it_should_show_and_hide_label_and_heading( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $field->show_label( true ); $this->assertTrue( $field->should_show_label() ); @@ -188,9 +191,9 @@ public function it_should_show_and_hide_label_and_heading( $resource ) { * @dataProvider resourceProvider */ public function it_should_render_correct_html( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); - $html = $field->render(); + $html = $field->get_render_html(); $this->assertStringContainsString( 'stellarwp-uplink-license-key-field', $html ); $this->assertStringContainsString( $field->get_slug(), $html ); } @@ -200,7 +203,7 @@ public function it_should_render_correct_html( $resource ) { * @dataProvider resourceProvider */ public function it_should_handle_empty_field_name( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $this->assertEmpty( $field->get_field_name(), 'Field name should be empty by default' ); } @@ -210,7 +213,7 @@ public function it_should_handle_empty_field_name( $resource ) { * @dataProvider resourceProvider */ public function it_should_handle_empty_field_id( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $this->assertNotEmpty( $field->get_field_id(), 'Field ID should not be empty even if not set' ); } @@ -220,7 +223,7 @@ public function it_should_handle_empty_field_id( $resource ) { * @dataProvider resourceProvider */ public function it_should_handle_empty_label( $resource ) { - $field = new Field( $this->setup_container_get_slug( $resource )->get_slug() ); + $field = new Field( $this->view, $this->setup_container_get_slug( $resource ) ); $this->assertEmpty( $field->get_label(), 'Label should be empty by default' ); } diff --git a/tests/wpunit/Admin/Fields/FormTest.php b/tests/wpunit/Admin/Fields/FormTest.php index 3357f974..b3299a1c 100644 --- a/tests/wpunit/Admin/Fields/FormTest.php +++ b/tests/wpunit/Admin/Fields/FormTest.php @@ -9,6 +9,7 @@ use StellarWP\Uplink\Tests\TestUtils; use tad\Codeception\SnapshotAssertions\SnapshotAssertions; use StellarWP\Uplink\Tests\Traits\With_Uopz; +use StellarWP\Uplink\View\WordPress_View; class FormTest extends UplinkTestCase { @@ -16,6 +17,18 @@ class FormTest extends UplinkTestCase { use SnapshotAssertions; use With_Uopz; + protected $view; + + protected $collection; + + public function setUp(): void { + parent::setUp(); + + $this->view = $this->container->get( WordPress_View::class ); + + $this->collection = $this->container->get( Collection::class ); + } + public function setup_container_get_slug( $resource ) { $collection = Config::get_container()->get( Collection::class ); @@ -46,11 +59,11 @@ public function it_should_add_field_to_form( $resource ) { $current_resource = $this->setup_container_get_slug( $resource ); $slug = $current_resource->get_slug(); - $field = new Field( $slug ); + $field = new Field( $this->view, $current_resource ); $field->set_field_name( 'field-' . $slug ); $field->show_label( true ); - $form = new Form(); + $form = new Form( $this->view ); $form->add_field( $field ); $fields = $form->get_fields(); @@ -64,7 +77,7 @@ public function it_should_add_field_to_form( $resource ) { */ public function it_should_set_and_get_button_text( $resource ) { $button_text = 'Submit'; - $form = new Form(); + $form = new Form( $this->view ); $form->set_button_text( $button_text ); $this->assertEquals( $button_text, $form->get_button_text() ); @@ -78,10 +91,10 @@ public function it_should_render_form( $resource ) { $current_resource = $this->setup_container_get_slug( $resource ); $slug = $current_resource->get_slug(); - $field = new Field( $slug ); + $field = new Field( $this->view, $current_resource ); $field->set_field_name( 'field-' . $slug ); - $form = new Form(); + $form = new Form( $this->view ); $form->add_field( $field ); $license_key = 'license_key' . $slug; @@ -94,7 +107,7 @@ public function it_should_render_form( $resource ) { $this->assertEquals( $option_value, $license_key ); // Render the form and assert the HTML snapshot - $form_html = $form->render(); + $form_html = $form->get_render_html(); // Assert the HTML snapshot $this->assertMatchesHtmlSnapshot( $form_html ); @@ -105,7 +118,7 @@ public function it_should_render_form( $resource ) { * @dataProvider resourceProvider */ public function it_should_get_button_text( $resource ) { - $form = new Form(); + $form = new Form( $this->view ); $this->assertEquals( 'Save Changes', $form->get_button_text() ); } @@ -114,7 +127,7 @@ public function it_should_get_button_text( $resource ) { * @dataProvider resourceProvider */ public function it_should_show_and_hide_button( $resource ) { - $form = new Form(); + $form = new Form( $this->view ); $this->assertTrue( $form->should_show_button() ); $form->show_button( false ); @@ -126,13 +139,13 @@ public function it_should_show_and_hide_button( $resource ) { */ public function it_should_add_multiple_fields_to_form() { $resources = $this->get_test_resources(); - $form = new Form(); + $form = new Form( $this->view ); $expected_field_count = count( $resources ); foreach ( $resources as $resource ) { $current_resource = $this->setup_container_get_slug( $resource ); $slug = $current_resource->get_slug(); - $field = new Field( $slug ); + $field = new Field( $this->view, $current_resource ); $field->set_field_name( 'field-' . $slug ); $form->add_field( $field ); @@ -155,13 +168,13 @@ public function it_should_add_multiple_fields_to_form() { */ public function it_should_render_form_with_multiple_fields() { $resources = $this->get_test_resources(); - $form = new Form(); + $form = new Form( $this->view ); $expected_field_count = count( $resources ); foreach ( $resources as $resource ) { $current_resource = $this->setup_container_get_slug( $resource ); $slug = $current_resource->get_slug(); - $field = new Field( $slug ); + $field = new Field( $this->view, $current_resource ); $field->set_field_name( 'field-' . $slug ); $form->add_field( $field ); @@ -176,7 +189,7 @@ public function it_should_render_form_with_multiple_fields() { $this->set_fn_return( 'wp_create_nonce', '123456789', false ); // Render the form and assert the HTML snapshot - $form_html = $form->render(); + $form_html = $form->get_render_html(); // Assert the HTML snapshot $this->assertMatchesHtmlSnapshot( $form_html );