From 28bafaf18b05920b35d6c787231e3412d441fa26 Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Fri, 25 Sep 2026 11:39:26 +0530 Subject: [PATCH 1/3] fix: elementor global color handling for not-found errors --- inc/compatibility/elementor.php | 3 +- tests/test-elementor-compatibility.php | 80 +++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/inc/compatibility/elementor.php b/inc/compatibility/elementor.php index 1b4f945956..e4d224e52a 100644 --- a/inc/compatibility/elementor.php +++ b/inc/compatibility/elementor.php @@ -140,7 +140,8 @@ public function enqueue() { * @return \WP_REST_Response|\WP_Error */ public function alter_global_colors_front_end( $response, $handler, \WP_REST_Request $request ) { - if ( is_wp_error( $response ) ) { + // Elementor never knows Neve IDs, so not-found is expected here. + if ( is_wp_error( $response ) && 'global_not_found' !== $response->get_error_code() ) { return $response; } diff --git a/tests/test-elementor-compatibility.php b/tests/test-elementor-compatibility.php index 845d0246ba..7ff1d52023 100644 --- a/tests/test-elementor-compatibility.php +++ b/tests/test-elementor-compatibility.php @@ -20,24 +20,46 @@ class TestElementorCompatibility extends WP_UnitTestCase { */ const COLOR_ROUTE = self::GLOBALS_ROUTE . '/colors/nvprimaryaccent'; + /** + * Reset the static custom colors so they don't leak into other tests. + */ + public function tearDown(): void { + $custom_colors = new ReflectionProperty( \Neve\Compatibility\Elementor::class, 'custom_global_colors' ); + $custom_colors->setAccessible( true ); + $custom_colors->setValue( null, null ); + + parent::tearDown(); + } + /** * Build a compatibility instance in a post-init state. * * Avoids ::init(), which needs ELEMENTOR_VERSION defined and would leak that * constant plus its hooks into the rest of the suite. * + * @param array $custom_global_colors Custom global colors theme mod value. + * * @return \Neve\Compatibility\Elementor */ - private function get_elementor_compat() { + private function get_elementor_compat( $custom_global_colors = [] ) { $elementor = new \Neve\Compatibility\Elementor(); $custom_colors = new ReflectionProperty( $elementor, 'custom_global_colors' ); $custom_colors->setAccessible( true ); - $custom_colors->setValue( $elementor, [] ); + $custom_colors->setValue( $elementor, $custom_global_colors ); return $elementor; } + /** + * Elementor's error for a global ID missing from its kit. + * + * @return WP_Error + */ + private function get_global_not_found_error() { + return new WP_Error( 'global_not_found', 'The Global value you are trying to use is not available.', [ 'status' => 404 ] ); + } + /** * Errored responses should be passed through untouched. */ @@ -89,4 +111,58 @@ public function test_global_colors_front_end_overrides_color() { $this->assertSame( 'nvprimaryaccent', $data['id'] ); $this->assertArrayHasKey( 'value', $data ); } + + /** + * Elementor's not-found error for a Neve color should resolve to the palette color. + */ + public function test_global_colors_front_end_resolves_neve_color_on_not_found() { + $elementor = $this->get_elementor_compat(); + $request = new WP_REST_Request( 'GET', self::COLOR_ROUTE ); + + $filtered = $elementor->alter_global_colors_front_end( $this->get_global_not_found_error(), [], $request ); + + $this->assertInstanceOf( WP_REST_Response::class, $filtered ); + + $palettes = neve_get_global_colors_default( true ); + $expected = $palettes['palettes'][ $palettes['activePalette'] ]['colors']['nv-primary-accent']; + $data = $filtered->get_data(); + + $this->assertSame( 'nvprimaryaccent', $data['id'] ); + $this->assertSame( neve_sanitize_colors( $expected ), $data['value'] ); + } + + /** + * Elementor's not-found error for a custom Neve color should resolve to that color. + */ + public function test_global_colors_front_end_resolves_custom_color_on_not_found() { + $elementor = $this->get_elementor_compat( + [ + 'custom' => [ + 'label' => 'Custom', + 'val' => '#123456', + ], + ] + ); + $request = new WP_REST_Request( 'GET', self::GLOBALS_ROUTE . '/colors/custom' ); + + $filtered = $elementor->alter_global_colors_front_end( $this->get_global_not_found_error(), [], $request ); + + $this->assertInstanceOf( WP_REST_Response::class, $filtered ); + + $data = $filtered->get_data(); + + $this->assertSame( 'custom', $data['id'] ); + $this->assertSame( '#123456', $data['value'] ); + } + + /** + * Elementor's not-found error for a non-Neve color should be passed through untouched. + */ + public function test_global_colors_front_end_passes_through_not_found_for_unknown_color() { + $elementor = $this->get_elementor_compat(); + $request = new WP_REST_Request( 'GET', self::GLOBALS_ROUTE . '/colors/primary' ); + $error = $this->get_global_not_found_error(); + + $this->assertSame( $error, $elementor->alter_global_colors_front_end( $error, [], $request ) ); + } } From f0e2250e78ef4b8ee17dd15c5eb978ee6598f52d Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Fri, 25 Sep 2026 12:07:40 +0530 Subject: [PATCH 2/3] fix: reflect static colors consistently --- tests/test-elementor-compatibility.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-elementor-compatibility.php b/tests/test-elementor-compatibility.php index 7ff1d52023..845a97526d 100644 --- a/tests/test-elementor-compatibility.php +++ b/tests/test-elementor-compatibility.php @@ -44,9 +44,9 @@ public function tearDown(): void { private function get_elementor_compat( $custom_global_colors = [] ) { $elementor = new \Neve\Compatibility\Elementor(); - $custom_colors = new ReflectionProperty( $elementor, 'custom_global_colors' ); + $custom_colors = new ReflectionProperty( \Neve\Compatibility\Elementor::class, 'custom_global_colors' ); $custom_colors->setAccessible( true ); - $custom_colors->setValue( $elementor, $custom_global_colors ); + $custom_colors->setValue( null, $custom_global_colors ); return $elementor; } From 83f6cdff4ad68b61d363f9c403b1e46eb5f8fa04 Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Fri, 25 Sep 2026 12:38:33 +0530 Subject: [PATCH 3/3] fix: handle not-found errors for non-color routes --- inc/compatibility/elementor.php | 11 ++++++--- tests/test-elementor-compatibility.php | 34 ++++++++++++++++++++------ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/inc/compatibility/elementor.php b/inc/compatibility/elementor.php index e4d224e52a..45f0d4b352 100644 --- a/inc/compatibility/elementor.php +++ b/inc/compatibility/elementor.php @@ -140,12 +140,17 @@ public function enqueue() { * @return \WP_REST_Response|\WP_Error */ public function alter_global_colors_front_end( $response, $handler, \WP_REST_Request $request ) { - // Elementor never knows Neve IDs, so not-found is expected here. - if ( is_wp_error( $response ) && 'global_not_found' !== $response->get_error_code() ) { + $route = $request->get_route(); + + // Elementor never knows Neve IDs, so not-found is expected on the colors route. + $is_color_not_found = is_wp_error( $response ) + && 'global_not_found' === $response->get_error_code() + && 0 === strpos( $route, '/elementor/v1/globals/colors/' ); + + if ( is_wp_error( $response ) && ! $is_color_not_found ) { return $response; } - $route = $request->get_route(); $rest_to_slugs = [ 'nvprimaryaccent' => 'nv-primary-accent', 'nvsecondaryaccent' => 'nv-secondary-accent', diff --git a/tests/test-elementor-compatibility.php b/tests/test-elementor-compatibility.php index 845a97526d..6dc7d7b69a 100644 --- a/tests/test-elementor-compatibility.php +++ b/tests/test-elementor-compatibility.php @@ -24,29 +24,36 @@ class TestElementorCompatibility extends WP_UnitTestCase { * Reset the static custom colors so they don't leak into other tests. */ public function tearDown(): void { - $custom_colors = new ReflectionProperty( \Neve\Compatibility\Elementor::class, 'custom_global_colors' ); - $custom_colors->setAccessible( true ); - $custom_colors->setValue( null, null ); + $this->set_custom_global_colors( null ); parent::tearDown(); } + /** + * Set the static custom global colors on the compatibility class. + * + * @param array|null $colors Custom global colors, or null for the unloaded default. + */ + private function set_custom_global_colors( ?array $colors ): void { + $custom_colors = new ReflectionProperty( \Neve\Compatibility\Elementor::class, 'custom_global_colors' ); + $custom_colors->setAccessible( true ); + $custom_colors->setValue( null, $colors ); + } + /** * Build a compatibility instance in a post-init state. * * Avoids ::init(), which needs ELEMENTOR_VERSION defined and would leak that * constant plus its hooks into the rest of the suite. * - * @param array $custom_global_colors Custom global colors theme mod value. + * @param array $custom_global_colors Custom global colors theme mod value. * * @return \Neve\Compatibility\Elementor */ - private function get_elementor_compat( $custom_global_colors = [] ) { + private function get_elementor_compat( array $custom_global_colors = [] ) { $elementor = new \Neve\Compatibility\Elementor(); - $custom_colors = new ReflectionProperty( \Neve\Compatibility\Elementor::class, 'custom_global_colors' ); - $custom_colors->setAccessible( true ); - $custom_colors->setValue( null, $custom_global_colors ); + $this->set_custom_global_colors( $custom_global_colors ); return $elementor; } @@ -165,4 +172,15 @@ public function test_global_colors_front_end_passes_through_not_found_for_unknow $this->assertSame( $error, $elementor->alter_global_colors_front_end( $error, [], $request ) ); } + + /** + * Elementor's not-found error on a non-color route should be passed through for a Neve ID. + */ + public function test_global_colors_front_end_passes_through_not_found_on_typography_route() { + $elementor = $this->get_elementor_compat(); + $request = new WP_REST_Request( 'GET', self::GLOBALS_ROUTE . '/typography/nvprimaryaccent' ); + $error = $this->get_global_not_found_error(); + + $this->assertSame( $error, $elementor->alter_global_colors_front_end( $error, [], $request ) ); + } }