From 8c2be0a8bda026d74c4065a422732784ea38a088 Mon Sep 17 00:00:00 2001 From: Swanand01 <75439077+Swanand01@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:44:28 +0530 Subject: [PATCH] fix: Update SnapWP environment variables (#57) * refactor: update env var names * refactor: replace `NEXT_URL` with `NEXT_PUBLIC_URL` * feat: add commented property to variables * fix: linting errors * fix: remove trailing whitespace * refactor: remove commented from variables, calculate it based on defaults * fix: formatting errors in Admin.php * fix : tests * chore: cleanup * feat: update docs * fix : tests --------- Co-authored-by: Ta5r Co-authored-by: Dovid Levine --- access-functions.php | 12 ++- docs/rest-api.md | 14 +-- src/Modules/Admin.php | 10 +- src/Modules/EnvGenerator/Generator.php | 26 +++-- src/Modules/EnvGenerator/VariableRegistry.php | 22 ++-- tests/Integration/GeneratorTest.php | 101 +++++++++++++----- tests/Integration/RestControllerTest.php | 3 +- 7 files changed, 134 insertions(+), 54 deletions(-) diff --git a/access-functions.php b/access-functions.php index 0bb2a3e..5c16799 100644 --- a/access-functions.php +++ b/access-functions.php @@ -58,11 +58,15 @@ function snapwp_helper_get_env_variables() { return new \WP_Error( 'graphql_not_found', 'WPGraphQL must be installed and activated.', [ 'status' => 500 ] ); } + $upload_dir = wp_get_upload_dir(); + return [ - 'NODE_TLS_REJECT_UNAUTHORIZED' => '', - 'NEXT_URL' => '', - 'HOME_URL' => get_home_url(), - 'GRAPHQL_ENDPOINT' => graphql_get_endpoint(), + 'NODE_TLS_REJECT_UNAUTHORIZED' => '', + 'NEXT_PUBLIC_URL' => '', + 'NEXT_PUBLIC_WORDPRESS_URL' => get_home_url(), + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => graphql_get_endpoint(), + 'NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH' => str_replace( ABSPATH, '', $upload_dir['basedir'] ), + 'NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX' => rest_get_url_prefix(), ]; } } diff --git a/docs/rest-api.md b/docs/rest-api.md index 5bf9d81..a978476 100644 --- a/docs/rest-api.md +++ b/docs/rest-api.md @@ -21,12 +21,14 @@ curl -X GET \ ### Parameters -This endpoint does not require any parameters to be passed in the request body. The .env file content is generated based on WordPress settings. - - - `NEXT_URL` (Required): The headless frontend domain URL. - - `HOME_URL` (Required): The WordPress "frontend" domain URL. - - `GRAPHQL_ENDPOINT`: The WordPress GraphQL endpoint. (Default: `graphql`) - - `NODE_TLS_REJECT_UNAUTHORIZED`: Enable if connecting to a self-signed cert. (Default: commented out) +This endpoint does not require any parameters to be passed in the request body. The .env file content is generated based on WordPress settings. Unchanged variables will be commented out. + + - `NODE_TLS_REJECT_UNAUTHORIZED`: Enable if connecting to a self-signed cert. (Default: `0`) + - `NEXT_PUBLIC_URL` (Required): The headless frontend domain URL. (Default: `http://localhost:3000`) + - `NEXT_PUBLIC_WORDPRESS_URL` (Required): The WordPress "frontend" domain URL. + - `NEXT_PUBLIC_GRAPHQL_ENDPOINT`: The WordPress GraphQL endpoint. (Default: `graphql`) + - `NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH`: The WordPress Uploads directory path. (Default: `wp-content/uploads`) + - `NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX`: The WordPress REST URL Prefix. (Default: `wp-json`) Note: This endpoint requires authentication with administrator privileges. diff --git a/src/Modules/Admin.php b/src/Modules/Admin.php index 11f3845..b4c8619 100644 --- a/src/Modules/Admin.php +++ b/src/Modules/Admin.php @@ -128,12 +128,12 @@ public function render_menu(): void { $value ) : ?> - + %s', $value ) ); ?> @@ -164,8 +164,8 @@ public function render_menu(): void { NEXT_URL' + esc_html__( 'Then update the %s variable with the URL for your headless frontend.', 'snapwp-helper' ), + 'NEXT_PUBLIC_URL' ); ?>

@@ -180,7 +180,7 @@ public function render_menu(): void { npm run dev', 'npm run build && npm run start' ); diff --git a/src/Modules/EnvGenerator/Generator.php b/src/Modules/EnvGenerator/Generator.php index bee8082..9cec7f9 100644 --- a/src/Modules/EnvGenerator/Generator.php +++ b/src/Modules/EnvGenerator/Generator.php @@ -59,9 +59,16 @@ protected function prepare_variables( array $variables ): ?string { foreach ( $variables as $name => $value ) { $variable_output = $this->prepare_variable( $name, $value ); - if ( null !== $variable_output ) { - $output .= $variable_output; + if ( empty( $variable_output ) ) { + continue; } + + // Add a newline if there's already content. + if ( ! empty( $output ) ) { + $output .= "\n"; + } + + $output .= $variable_output; } return $output ?: null; @@ -94,13 +101,16 @@ protected function prepare_variable( string $name, ?string $value ): ?string { // Determine the final value to output. $resolved_value = ! empty( $value ) ? $value : $default; - if ( empty( $resolved_value ) ) { - $resolved_value = null; - } - $comment = ! empty( $description ) ? sprintf( "\n# %s\n", $description ) : ''; - $output = null !== $resolved_value ? sprintf( '%s=%s\n', $name, $resolved_value ) : sprintf( '# %s=\'0\'\n', $name ); + // Prepare the output. + $comment = ! empty( $description ) ? sprintf( "\n# %s\n", $description ) : ''; + $env_output = sprintf( '%s=%s', $name, $resolved_value ); + + // Comment out variables if they're not required and have the default value. + if ( ! $required && $resolved_value === $default ) { + $env_output = '# ' . $env_output; + } - return $comment . $output; + return $comment . $env_output; } } diff --git a/src/Modules/EnvGenerator/VariableRegistry.php b/src/Modules/EnvGenerator/VariableRegistry.php index 5a2c876..1992853 100644 --- a/src/Modules/EnvGenerator/VariableRegistry.php +++ b/src/Modules/EnvGenerator/VariableRegistry.php @@ -19,26 +19,36 @@ class VariableRegistry { * @var array */ private const VARIABLES = [ - 'NODE_TLS_REJECT_UNAUTHORIZED' => [ + 'NODE_TLS_REJECT_UNAUTHORIZED' => [ 'description' => 'Enable if connecting to a self-signed cert', - 'default' => '', + 'default' => '0', 'required' => false, ], - 'NEXT_URL' => [ + 'NEXT_PUBLIC_URL' => [ 'description' => 'The headless frontend domain URL', - 'default' => '', + 'default' => 'http://localhost:3000', 'required' => false, ], - 'HOME_URL' => [ + 'NEXT_PUBLIC_WORDPRESS_URL' => [ 'description' => 'The WordPress "frontend" domain URL', 'default' => '', 'required' => true, ], - 'GRAPHQL_ENDPOINT' => [ + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => [ 'description' => 'The WordPress GraphQL endpoint', 'default' => 'graphql', 'required' => false, ], + 'NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH' => [ + 'description' => 'The WordPress Uploads directory path', + 'default' => 'wp-content/uploads', + 'required' => false, + ], + 'NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX' => [ + 'description' => 'The WordPress REST URL Prefix', + 'default' => 'wp-json', + 'required' => false, + ], ]; /** diff --git a/tests/Integration/GeneratorTest.php b/tests/Integration/GeneratorTest.php index f513889..259fdce 100644 --- a/tests/Integration/GeneratorTest.php +++ b/tests/Integration/GeneratorTest.php @@ -7,9 +7,9 @@ namespace SnapWP\Helper\Tests\Integration; -use lucatume\WPBrowser\TestCase\WPTestCase; use SnapWP\Helper\Modules\EnvGenerator\Generator; use SnapWP\Helper\Modules\EnvGenerator\VariableRegistry; +use lucatume\WPBrowser\TestCase\WPTestCase; /** * Class GeneratorTest @@ -24,10 +24,12 @@ public function testGeneratorInitialization(): void { $registry = new VariableRegistry(); $values = [ - 'NODE_TLS_REJECT_UNAUTHORIZED' => '', - 'NEXT_URL' => 'http://localhost:3000', - 'HOME_URL' => 'https://headless-demo.local', - 'GRAPHQL_ENDPOINT' => '', + 'NODE_TLS_REJECT_UNAUTHORIZED' => '', + 'NEXT_PUBLIC_URL' => 'http://localhost:3000', + 'NEXT_PUBLIC_WORDPRESS_URL' => 'https://headless-demo.local', + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => '', + 'NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH' => '', + 'NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX' => '', ]; $generator = new Generator( $values, $registry ); @@ -41,11 +43,13 @@ public function testGeneratorInitialization(): void { public function testGenerateEnvContent(): void { $registry = new VariableRegistry(); $values = [ - 'NODE_TLS_REJECT_UNAUTHORIZED' => '5', - 'NEXT_URL' => 'http://localhost:3000', - 'HOME_URL' => 'https://headless-demo.local', - 'GRAPHQL_ENDPOINT' => '/test_endpoint', - 'INVALID_VARIABLE' => 'should-not-be-included', // This should not be included in the output. + 'NODE_TLS_REJECT_UNAUTHORIZED' => '5', + 'NEXT_PUBLIC_URL' => 'http://localhost:3000', + 'NEXT_PUBLIC_WORDPRESS_URL' => 'https://headless-demo.local', + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => '/test_endpoint', + 'NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH' => 'uploads', + 'NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX' => 'api', + 'INVALID_VARIABLE' => 'should-not-be-included', // This should not be included in the output. ]; $generator = new Generator( $values, $registry ); @@ -53,7 +57,24 @@ public function testGenerateEnvContent(): void { // Generate the .env content. $content = $generator->generate(); - $expectedContent = "\n# Enable if connecting to a self-signed cert\nNODE_TLS_REJECT_UNAUTHORIZED=5\\n\n# The headless frontend domain URL\nNEXT_URL=http://localhost:3000\\n\n# The WordPress \"frontend\" domain URL\nHOME_URL=https://headless-demo.local\\n\n# The WordPress GraphQL endpoint\nGRAPHQL_ENDPOINT=/test_endpoint\\n"; + $expectedContent = ' +# Enable if connecting to a self-signed cert +NODE_TLS_REJECT_UNAUTHORIZED=5 + +# The headless frontend domain URL +# NEXT_PUBLIC_URL=http://localhost:3000 + +# The WordPress "frontend" domain URL +NEXT_PUBLIC_WORDPRESS_URL=https://headless-demo.local + +# The WordPress GraphQL endpoint +NEXT_PUBLIC_GRAPHQL_ENDPOINT=/test_endpoint + +# The WordPress Uploads directory path +NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH=uploads + +# The WordPress REST URL Prefix +NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX=api'; $this->assertSame( $expectedContent, $content ); } @@ -64,10 +85,12 @@ public function testGenerateEnvContent(): void { public function testMissingRequiredValuesEnvContent(): void { $registry = new VariableRegistry(); $values = [ - 'NODE_TLS_REJECT_UNAUTHORIZED' => '', - 'NEXT_URL' => '', - 'HOME_URL' => '', - 'GRAPHQL_ENDPOINT' => '', + 'NODE_TLS_REJECT_UNAUTHORIZED' => '', + 'NEXT_PUBLIC_URL' => '', + 'NEXT_PUBLIC_WORDPRESS_URL' => '', + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => '', + 'NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH' => '', + 'NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX' => '', ]; $generator = new Generator( $values, $registry ); @@ -88,10 +111,12 @@ public function testDefaultValuesForEnvContent(): void { // CASE : For NODE_TLS_REJECT_UNAUTHORIZED with no default value, Generator class should comment out the variable in .ENV content. $values = [ - 'NODE_TLS_REJECT_UNAUTHORIZED' => '', - 'NEXT_URL' => 'http://localhost:3000', - 'HOME_URL' => 'https://headless-demo.local', - 'GRAPHQL_ENDPOINT' => '/test_endpoint', + 'NODE_TLS_REJECT_UNAUTHORIZED' => '', + 'NEXT_PUBLIC_URL' => '', + 'NEXT_PUBLIC_WORDPRESS_URL' => 'https://headless-demo.local', + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => '/test_endpoint', + 'NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH' => '', + 'NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX' => '', ]; $generator = new Generator( $values, $registry ); @@ -100,16 +125,33 @@ public function testDefaultValuesForEnvContent(): void { $content = $generator->generate(); // Define expected content. - $expectedContent = "\n# Enable if connecting to a self-signed cert\n# NODE_TLS_REJECT_UNAUTHORIZED='0'\\n\n# The headless frontend domain URL\nNEXT_URL=http://localhost:3000\\n\n# The WordPress \"frontend\" domain URL\nHOME_URL=https://headless-demo.local\\n\n# The WordPress GraphQL endpoint\nGRAPHQL_ENDPOINT=/test_endpoint\\n"; + $expectedContent = ' +# Enable if connecting to a self-signed cert +# NODE_TLS_REJECT_UNAUTHORIZED=0 + +# The headless frontend domain URL +# NEXT_PUBLIC_URL=http://localhost:3000 + +# The WordPress "frontend" domain URL +NEXT_PUBLIC_WORDPRESS_URL=https://headless-demo.local + +# The WordPress GraphQL endpoint +NEXT_PUBLIC_GRAPHQL_ENDPOINT=/test_endpoint + +# The WordPress Uploads directory path +# NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH=wp-content/uploads + +# The WordPress REST URL Prefix +# NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX=wp-json'; $this->assertSame( $expectedContent, $content ); // CASE : For GRAPHQL_ENDPOINT, Generator should use the default value of the variable. $values = [ 'NODE_TLS_REJECT_UNAUTHORIZED' => '', - 'NEXT_URL' => 'http://localhost:3000', - 'HOME_URL' => 'https://headless-demo.local', - 'GRAPHQL_ENDPOINT' => '', + 'NEXT_PUBLIC_URL' => 'http://localhost:3000', + 'NEXT_PUBLIC_WORDPRESS_URL' => 'https://headless-demo.local', + 'NEXT_PUBLIC_GRAPHQL_ENDPOINT' => '', ]; $generator = new Generator( $values, $registry ); @@ -117,7 +159,18 @@ public function testDefaultValuesForEnvContent(): void { // Generate the .env content. $content = $generator->generate(); - $expectedContent = "\n# Enable if connecting to a self-signed cert\n# NODE_TLS_REJECT_UNAUTHORIZED='0'\\n\n# The headless frontend domain URL\nNEXT_URL=http://localhost:3000\\n\n# The WordPress \"frontend\" domain URL\nHOME_URL=https://headless-demo.local\\n\n# The WordPress GraphQL endpoint\nGRAPHQL_ENDPOINT=graphql\\n"; + $expectedContent = ' +# Enable if connecting to a self-signed cert +# NODE_TLS_REJECT_UNAUTHORIZED=0 + +# The headless frontend domain URL +# NEXT_PUBLIC_URL=http://localhost:3000 + +# The WordPress "frontend" domain URL +NEXT_PUBLIC_WORDPRESS_URL=https://headless-demo.local + +# The WordPress GraphQL endpoint +# NEXT_PUBLIC_GRAPHQL_ENDPOINT=graphql'; $this->assertSame( $expectedContent, $content ); } diff --git a/tests/Integration/RestControllerTest.php b/tests/Integration/RestControllerTest.php index 57b7093..1c73ed8 100644 --- a/tests/Integration/RestControllerTest.php +++ b/tests/Integration/RestControllerTest.php @@ -64,6 +64,7 @@ public function testRegisterRoutes(): void { /** * Tests if the endpoint is accessible, and the env content in response is correct. + * Assuming standard default values. */ public function testGenerateEnvEndpoint(): void { @@ -86,7 +87,7 @@ public function testGenerateEnvEndpoint(): void { $this->assertNotEmpty( $actual_data['content'] ); $search = '\n'; $replace = ''; - $expected = "\n# Enable if connecting to a self-signed cert\n# NODE_TLS_REJECT_UNAUTHORIZED='0'\n# The headless frontend domain URL\n# NEXT_URL='0'\n# The WordPress \"frontend\" domain URL\nHOME_URL=" . get_home_url() . "\n# The WordPress GraphQL endpoint\nGRAPHQL_ENDPOINT=" . graphql_get_endpoint(); + $expected = "\n# Enable if connecting to a self-signed cert\n# NODE_TLS_REJECT_UNAUTHORIZED=0\n\n# The headless frontend domain URL\n# NEXT_PUBLIC_URL=http://localhost:3000\n\n# The WordPress \"frontend\" domain URL\nNEXT_PUBLIC_WORDPRESS_URL=" . get_home_url() . "\n\n# The WordPress GraphQL endpoint\n# NEXT_PUBLIC_GRAPHQL_ENDPOINT=" . graphql_get_endpoint() . "\n\n# The WordPress Uploads directory path\n# NEXT_PUBLIC_WORDPRESS_UPLOADS_PATH=" . str_replace( ABSPATH, '', wp_get_upload_dir()['basedir'] ) . "\n\n# The WordPress REST URL Prefix\n# NEXT_PUBLIC_WORDPRESS_REST_URL_PREFIX=" . rest_get_url_prefix(); $this->assertEquals( $expected, str_replace( $search, $replace, $actual_data['content'] ) );