From d7a1d14e1b05f59b769e91db64b602ad82aeb1d1 Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Sun, 9 Aug 2026 21:29:20 +0600 Subject: [PATCH 1/3] fix: evaluate shortcodes in field default value When a field has Allow Shortcodes enabled and a shortcode is set in its Default Value, the shortcode stayed literal in the form until the item was first saved. The per-type allow_shortcode flag was only read in each field's display() method, not in the central PodsForm::default_value() resolver that runs at form render time. Evaluate the shortcode in default_value() when the field type opts in, nested inside the existing default_evaluate_tags block so only the configured default is processed, never request-supplied values. Fixes #7021 --- classes/PodsForm.php | 4 + .../codeception/wpunit/Pods/PodsFormTest.php | 124 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 tests/codeception/wpunit/Pods/PodsFormTest.php diff --git a/classes/PodsForm.php b/classes/PodsForm.php index b4b6a9a5e2..d851ff6e3c 100644 --- a/classes/PodsForm.php +++ b/classes/PodsForm.php @@ -1439,6 +1439,10 @@ public static function default_value( $value, $type = 'text', $name = null, $opt if ( $default !== $default_value && 1 === (int) pods_v( 'default_evaluate_tags', $options, 1 ) ) { $default = pods_evaluate_tags( $default ); + + if ( 1 === (int) pods_v( $type . '_allow_shortcode', $options, 0 ) ) { + $default = do_shortcode( $default ); + } } } diff --git a/tests/codeception/wpunit/Pods/PodsFormTest.php b/tests/codeception/wpunit/Pods/PodsFormTest.php new file mode 100644 index 0000000000..6d7edeab65 --- /dev/null +++ b/tests/codeception/wpunit/Pods/PodsFormTest.php @@ -0,0 +1,124 @@ + '[fooshortcode]', + 'text_allow_shortcode' => 1, + ) + ); + + $this->assertSame( 'foobar', $value ); + } + + /** + * @covers PodsForm::default_value + */ + public function test_default_value_keeps_shortcode_literal_when_allow_shortcode_is_off() { + add_shortcode( 'fooshortcode', static function () { + return 'foobar'; + } ); + + $value = PodsForm::default_value( + '', + 'text', + 'my_field', + array( + 'default' => '[fooshortcode]', + 'text_allow_shortcode' => 0, + ) + ); + + $this->assertSame( '[fooshortcode]', $value ); + } + + /** + * @covers PodsForm::default_value + */ + public function test_default_value_keeps_unknown_shortcode_literal_even_when_allow_shortcode_is_on() { + $value = PodsForm::default_value( + '', + 'text', + 'my_field', + array( + 'default' => 'Hello [unregistered] world', + 'text_allow_shortcode' => 1, + ) + ); + + $this->assertSame( 'Hello [unregistered] world', $value ); + } + + /** + * @covers PodsForm::default_value + */ + public function test_default_value_does_not_evaluate_shortcode_for_field_types_without_allow_shortcode() { + add_shortcode( 'fooshortcode', static function () { + return 'foobar'; + } ); + + $value = PodsForm::default_value( + '', + 'pick', + 'my_field', + array( 'default' => '[fooshortcode]' ) + ); + + $this->assertSame( '[fooshortcode]', $value ); + } + + /** + * @covers PodsForm::default_value + */ + public function test_default_value_keeps_request_supplied_value_literal_even_when_allow_shortcode_is_on() { + add_shortcode( 'fooshortcode', static function () { + return 'foobar'; + } ); + + $_GET['my_param'] = '[fooshortcode]'; + + $value = PodsForm::default_value( + '', + 'text', + 'my_field', + array( + 'default' => 'static default', + 'default_value_parameter' => 'my_param', + 'text_allow_shortcode' => 1, + ) + ); + + unset( $_GET['my_param'] ); + + $this->assertSame( '[fooshortcode]', $value ); + } +} From 3f18fd8fb9484b25835f05c9d2ee0eb40d5445f8 Mon Sep 17 00:00:00 2001 From: Faisal Ahammad Date: Wed, 19 Aug 2026 13:04:04 +0600 Subject: [PATCH 2/3] test: cover shortcode expansion decoupled from magic tag evaluation --- .../codeception/wpunit/Pods/PodsFormTest.php | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/codeception/wpunit/Pods/PodsFormTest.php b/tests/codeception/wpunit/Pods/PodsFormTest.php index 6d7edeab65..1320544f45 100644 --- a/tests/codeception/wpunit/Pods/PodsFormTest.php +++ b/tests/codeception/wpunit/Pods/PodsFormTest.php @@ -121,4 +121,54 @@ public function test_default_value_keeps_request_supplied_value_literal_even_whe $this->assertSame( '[fooshortcode]', $value ); } + + /** + * Shortcode expansion must not be coupled to magic tag evaluation: a default that + * contains a magic tag AND a shortcode must still have both applied. + * + * @covers PodsForm::default_value + */ + public function test_default_value_evaluates_both_magic_tags_and_shortcodes() { + add_shortcode( 'fooshortcode', static function () { + return 'foobar'; + } ); + + $value = PodsForm::default_value( + '', + 'text', + 'my_field', + array( + 'default' => '{@user.ID} [fooshortcode]', + 'text_allow_shortcode' => 1, + ) + ); + + $this->assertStringContainsString( 'foobar', $value ); + $this->assertStringNotContainsString( '[fooshortcode]', $value ); + } + + /** + * default_evaluate_tags only governs magic tags. Turning it off must not silently + * disable shortcode expansion, which is a separate opt-in. + * + * @covers PodsForm::default_value + */ + public function test_default_value_evaluates_shortcode_when_tag_evaluation_disabled() { + add_shortcode( 'fooshortcode', static function () { + return 'foobar'; + } ); + + $value = PodsForm::default_value( + '', + 'text', + 'my_field', + array( + 'default' => '[fooshortcode]', + 'text_allow_shortcode' => 1, + 'default_evaluate_tags' => 0, + ) + ); + + $this->assertSame( 'foobar', $value ); + } } From 0235a1e67e65d9293ba3f4f9af7ab7108c6d1b55 Mon Sep 17 00:00:00 2001 From: faisalahammad Date: Wed, 19 Aug 2026 20:22:11 +0600 Subject: [PATCH 3/3] fix: expand shortcodes in field defaults that contain no magic tags do_shortcode() was nested inside the magic-tag branch, which is only entered when str_replace() actually removed a '{@' or '}' from the default. A default such as 'Today is [current_year]' therefore never reached do_shortcode() and was rendered literally. Shortcode expansion is a separate opt-in ({type}_allow_shortcode) from magic tag evaluation (default_evaluate_tags), so it now runs in a sibling condition. It deliberately still runs before the default_value_parameter override so that request-supplied values are never passed through do_shortcode(). Refs #7021 --- classes/PodsForm.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/classes/PodsForm.php b/classes/PodsForm.php index d851ff6e3c..16e1f0ee15 100644 --- a/classes/PodsForm.php +++ b/classes/PodsForm.php @@ -1439,10 +1439,15 @@ public static function default_value( $value, $type = 'text', $name = null, $opt if ( $default !== $default_value && 1 === (int) pods_v( 'default_evaluate_tags', $options, 1 ) ) { $default = pods_evaluate_tags( $default ); + } - if ( 1 === (int) pods_v( $type . '_allow_shortcode', $options, 0 ) ) { - $default = do_shortcode( $default ); - } + // Shortcode expansion is a separate opt-in from magic tag evaluation, so it must not + // be nested within the magic tag check above -- a default containing only a shortcode + // still needs to be expanded. This intentionally runs before the + // default_value_parameter override below so that request-supplied values are never + // passed through do_shortcode(). + if ( 1 === (int) pods_v( $type . '_allow_shortcode', $options, 0 ) ) { + $default = do_shortcode( $default ); } }