Skip to content

Commit e4cdfe3

Browse files
authored
Improve PHP in antlers meta handling (#379)
* Add test coverage for people trying to get extra clever. * Implement improvements to pass failing tests. * Do simple string checks to early for performance/etc, because why not.
1 parent 80d6f9e commit e4cdfe3

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

src/Cascade.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22

33
namespace Statamic\SeoPro;
44

5+
use Exception;
56
use Illuminate\Support\Collection;
7+
use Statamic\Facades\Antlers;
68
use Statamic\Facades\Blink;
79
use Statamic\Facades\Config;
810
use Statamic\Facades\Entry;
9-
use Statamic\Facades\Parse;
1011
use Statamic\Facades\Site;
1112
use Statamic\Facades\URL;
13+
use Statamic\Fields\Field;
1214
use Statamic\Fields\Value;
15+
use Statamic\Fieldtypes\Text;
1316
use Statamic\Support\Arr;
1417
use Statamic\Support\Str;
1518
use Statamic\View\Cascade as ViewCascade;
@@ -381,13 +384,29 @@ protected function parseImageField($value)
381384

382385
protected function parseAntlers($item)
383386
{
384-
if (Str::contains($item, ['{{?', '{{$'])) {
387+
// Simplistically prevent php in antlers.
388+
if (Str::contains($item, ['{{?', '{{$', '@{'])) {
385389
return $item;
386390
}
387391

388-
$viewCascade = app(ViewCascade::class)->toArray();
392+
// Also, the parser has extra runtime protections around `Value` objects
393+
// when `antlers: true` is set on a blueprint field. While this may be
394+
// improved in future, we'll give custom seo fields same treatment.
395+
try {
396+
$textFieldType = new Text;
397+
$textFieldType->setField(new Field('___tmpValue', ['antlers' => true]));
398+
$value = new Value($item, '___tmpValue', $textFieldType);
389399

390-
return (string) Parse::template($item, array_merge($viewCascade, $this->current));
400+
$viewCascade = array_merge(
401+
app(ViewCascade::class)->toArray(),
402+
$this->current,
403+
['___tmpValue' => $value],
404+
);
405+
406+
return (string) Antlers::parse('{{ ___tmpValue }}', $viewCascade);
407+
} catch (Exception $exception) {
408+
return $item;
409+
}
391410
}
392411

393412
protected function humans()

tests/CascadeTest.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
class CascadeTest extends TestCase
1212
{
13-
public function tearDown(): void
13+
protected function tearDown(): void
1414
{
1515
if ($this->files->exists($path = base_path('custom_seo.yaml'))) {
1616
$this->files->delete($path);
@@ -126,6 +126,49 @@ public function it_parses_antlers()
126126
$this->assertEquals('RED', $data['description']);
127127
}
128128

129+
public static function phpInAntlersProvider()
130+
{
131+
return [
132+
[
133+
'{{? echo "php used" ?}}',
134+
'{{? echo "php used" ?}}',
135+
],
136+
[
137+
'{{$ "php used" $}}',
138+
'{{$ "php used" $}}',
139+
],
140+
[
141+
"{{ _php_used = '@{@{' + '? echo \"php used\" ?' + '@}}'; _php_used | antlers /}}",
142+
"{{ _php_used = '@{@{' + '? echo \"php used\" ?' + '@}}'; _php_used | antlers /}}",
143+
],
144+
[
145+
"{{ _php_used = (['' => ''] | json); _open = (_php_used | at(0)); _close = (_php_used | at(6)); _antlers_modified = _open + _open + '? echo \"php used\" ?' + _close + _close; _antlers_modified | antlers /}}",
146+
'{{? echo "php used" ?}}',
147+
],
148+
];
149+
}
150+
151+
/**
152+
* @test
153+
*
154+
* @dataProvider phpInAntlersProvider
155+
*/
156+
public function it_doesnt_parse_php_in_antlers($antlers, $output)
157+
{
158+
$entry = Entry::findByUri('/about')->entry();
159+
160+
$data = (new Cascade)
161+
->with(SiteDefaults::load()->all())
162+
->with([
163+
'description' => $antlers,
164+
])
165+
->withCurrent($entry)
166+
->get();
167+
168+
$this->assertNotEquals('hello', $data['description']);
169+
$this->assertEquals($output, $data['description']);
170+
}
171+
129172
/** @test */
130173
public function it_parses_field_references()
131174
{

0 commit comments

Comments
 (0)