Skip to content

Commit 704c521

Browse files
chiragchhatralaJonBons
authored andcommitted
Enhance redirect URL handling and MentionParser functionality (JhumanJ#639)
- Updated the `redirect_url` validation in `UserFormRequest` to accept strings instead of just max length. - Modified `MentionParser` to include a `urlFriendlyOutput` method, allowing for URL encoding of special characters in parsed values. - Adjusted the `PublicFormController` to utilize the new `urlFriendlyOutput` method for redirect URLs. - Created a migration to change the `redirect_url` field type in the database from string to text, accommodating longer URLs. - Added tests to ensure proper handling of long redirect URLs and the functionality of the new URL-friendly output feature in `MentionParser`. This update improves the flexibility and robustness of form handling and URL processing.
1 parent 33f2caa commit 704c521

File tree

6 files changed

+115
-4
lines changed

6 files changed

+115
-4
lines changed

api/app/Http/Controllers/Forms/PublicFormController.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ private function getRedirectData($form, $submissionData)
116116
return ['id' => $key, 'value' => $value];
117117
})->values()->all();
118118

119-
$redirectUrl = ($form->redirect_url) ? (new MentionParser($form->redirect_url, $formattedData))->parseAsText() : null;
119+
$redirectUrl = ($form->redirect_url) ? (new MentionParser($form->redirect_url, $formattedData))->urlFriendlyOutput()->parseAsText() : null;
120120

121121
if ($redirectUrl && !filter_var($redirectUrl, FILTER_VALIDATE_URL)) {
122122
$redirectUrl = null;

api/app/Http/Requests/UserFormRequest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function rules()
5555
're_fillable' => 'boolean',
5656
're_fill_button_text' => 'string|min:1|max:50',
5757
'submitted_text' => 'string|max:2000',
58-
'redirect_url' => 'nullable|max:255',
58+
'redirect_url' => 'nullable|string',
5959
'database_fields_update' => 'nullable|array',
6060
'max_submissions_count' => 'integer|nullable|min:1',
6161
'max_submissions_reached_text' => 'string|nullable',

api/app/Open/MentionParser.php

+15-2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,20 @@ class MentionParser
99
{
1010
private $content;
1111
private $data;
12+
private $urlFriendly = false;
1213

1314
public function __construct($content, $data)
1415
{
1516
$this->content = $content;
1617
$this->data = $data;
1718
}
1819

20+
public function urlFriendlyOutput(bool $enable = true): self
21+
{
22+
$this->urlFriendly = $enable;
23+
return $this;
24+
}
25+
1926
public function parse()
2027
{
2128
$doc = new DOMDocument();
@@ -40,7 +47,7 @@ public function parse()
4047
$value = $this->getData($fieldId);
4148

4249
if ($value !== null) {
43-
$textNode = $doc->createTextNode(is_array($value) ? implode(', ', $value) : $value);
50+
$textNode = $doc->createTextNode(is_array($value) ? implode($this->urlFriendly ? ',+' : ', ', $value) : $value);
4451
$element->parentNode->replaceChild($textNode, $element);
4552
} elseif ($fallback) {
4653
$textNode = $doc->createTextNode($fallback);
@@ -127,7 +134,13 @@ private function getData($fieldId)
127134
$value = collect($this->data)->firstWhere('id', $fieldId)['value'] ?? null;
128135

129136
if (is_object($value)) {
130-
return (array) $value;
137+
$value = (array) $value;
138+
}
139+
140+
if ($this->urlFriendly && $value !== null) {
141+
return is_array($value)
142+
? array_map('urlencode', $value)
143+
: urlencode($value);
131144
}
132145

133146
return $value;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class () extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::table('forms', function (Blueprint $table) {
14+
$table->text('redirect_url')->nullable()->change();
15+
});
16+
}
17+
18+
/**
19+
* Reverse the migrations.
20+
*/
21+
public function down(): void
22+
{
23+
Schema::table('forms', function (Blueprint $table) {
24+
$table->string('redirect_url')->nullable()->change();
25+
});
26+
}
27+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
test('form accepts long redirect urls', function () {
4+
$this->withoutExceptionHandling();
5+
$user = $this->actingAsUser();
6+
$workspace = $this->createUserWorkspace($user);
7+
$form = $this->createForm($user, $workspace);
8+
9+
// Create a very long URL (more than 255 characters)
10+
$longUrl = 'https://example.com/?' . str_repeat('very-long-parameter=value&', 50);
11+
12+
$this->putJson(route('open.forms.update', $form->id), array_merge($form->toArray(), [
13+
'redirect_url' => $longUrl
14+
]))->assertStatus(200);
15+
16+
expect($form->fresh()->redirect_url)->toBe($longUrl);
17+
});
18+
19+
test('form accepts null redirect url', function () {
20+
$user = $this->actingAsUser();
21+
$workspace = $this->createUserWorkspace($user);
22+
$form = $this->createForm($user, $workspace);
23+
24+
$this->putJson(route('open.forms.update', $form->id), array_merge($form->toArray(), [
25+
'redirect_url' => null
26+
]))->assertStatus(200);
27+
28+
expect($form->fresh()->redirect_url)->toBeNull();
29+
});

api/tests/Unit/Service/Forms/MentionParserTest.php

+42
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,46 @@
173173

174174
expect($result)->toBe('some text replaced text dewde');
175175
});
176+
177+
describe('urlFriendlyOutput', function () {
178+
test('it encodes special characters in values', function () {
179+
$content = '<p>Test: <span mention mention-field-id="123">Placeholder</span></p>';
180+
$data = [['id' => '123', 'value' => 'Hello & World']];
181+
182+
$parser = new MentionParser($content, $data);
183+
$result = $parser->urlFriendlyOutput()->parse();
184+
185+
expect($result)->toBe('<p>Test: Hello+%26+World</p>');
186+
});
187+
188+
test('it encodes spaces in values', function () {
189+
$content = '<p>Name: <span mention mention-field-id="123">Placeholder</span></p>';
190+
$data = [['id' => '123', 'value' => 'John Doe']];
191+
192+
$parser = new MentionParser($content, $data);
193+
$result = $parser->urlFriendlyOutput()->parse();
194+
195+
expect($result)->toBe('<p>Name: John+Doe</p>');
196+
});
197+
198+
test('it encodes array values', function () {
199+
$content = '<p>Tags: <span mention mention-field-id="123">Placeholder</span></p>';
200+
$data = [['id' => '123', 'value' => ['Web & Mobile', 'PHP/Laravel']]];
201+
202+
$parser = new MentionParser($content, $data);
203+
$result = $parser->urlFriendlyOutput()->parse();
204+
205+
expect($result)->toBe('<p>Tags: Web+%26+Mobile,+PHP%2FLaravel</p>');
206+
});
207+
208+
test('it can be disabled explicitly', function () {
209+
$content = '<p>Test: <span mention mention-field-id="123">Placeholder</span></p>';
210+
$data = [['id' => '123', 'value' => 'Hello & World']];
211+
212+
$parser = new MentionParser($content, $data);
213+
$result = $parser->urlFriendlyOutput(false)->parse();
214+
215+
expect($result)->toBe('<p>Test: Hello & World</p>');
216+
});
217+
});
176218
});

0 commit comments

Comments
 (0)