feat: improve polling url rendering with liquid loops. support external liquid renderer

This commit is contained in:
Benjamin Nussbaum 2025-11-14 13:55:55 +01:00
parent 7715fba4c8
commit c02c413987

View file

@ -130,9 +130,10 @@ class Plugin extends Model
} }
} }
// Split URLs by newline and filter out empty lines // Resolve Liquid variables in the entire polling_url field first, then split by newline
$resolvedPollingUrls = $this->resolveLiquidVariables($this->polling_url);
$urls = array_filter( $urls = array_filter(
array_map('trim', explode("\n", $this->polling_url)), array_map('trim', explode("\n", $resolvedPollingUrls)),
fn ($url): bool => ! empty($url) fn ($url): bool => ! empty($url)
); );
@ -147,8 +148,8 @@ class Plugin extends Model
$httpRequest = $httpRequest->withBody($resolvedBody); $httpRequest = $httpRequest->withBody($resolvedBody);
} }
// Resolve Liquid variables in the polling URL // URL is already resolved, use it directly
$resolvedUrl = $this->resolveLiquidVariables($url); $resolvedUrl = $url;
try { try {
// Make the request based on the verb // Make the request based on the verb
@ -183,8 +184,8 @@ class Plugin extends Model
$httpRequest = $httpRequest->withBody($resolvedBody); $httpRequest = $httpRequest->withBody($resolvedBody);
} }
// Resolve Liquid variables in the polling URL // URL is already resolved, use it directly
$resolvedUrl = $this->resolveLiquidVariables($url); $resolvedUrl = $url;
try { try {
// Make the request based on the verb // Make the request based on the verb
@ -241,10 +242,10 @@ class Plugin extends Model
try { try {
// Attempt to parse it into JSON // Attempt to parse it into JSON
$json = $httpResponse->json(); $json = $httpResponse->json();
if($json !== null) { if ($json !== null) {
return $json; return $json;
} }
// Response doesn't seem to be JSON, wrap the response body text as a JSON object // Response doesn't seem to be JSON, wrap the response body text as a JSON object
return ['data' => $httpResponse->body()]; return ['data' => $httpResponse->body()];
} catch (Exception $e) { } catch (Exception $e) {
@ -344,19 +345,48 @@ class Plugin extends Model
return $template; return $template;
} }
/**
* Check if a template contains a Liquid for loop pattern
*
* @param string $template The template string to check
* @return bool True if the template contains a for loop pattern
*/
private function containsLiquidForLoop(string $template): bool
{
return preg_match('/{%-?\s*for\s+/i', $template) === 1;
}
/** /**
* Resolve Liquid variables in a template string using the Liquid template engine * Resolve Liquid variables in a template string using the Liquid template engine
* *
* Uses the external trmnl-liquid renderer when:
* - preferred_renderer is 'trmnl-liquid'
* - External renderer is enabled in config
* - Template contains a Liquid for loop pattern
*
* Otherwise uses the internal PHP-based Liquid renderer.
*
* @param string $template The template string containing Liquid variables * @param string $template The template string containing Liquid variables
* @return string The resolved template with variables replaced with their values * @return string The resolved template with variables replaced with their values
* *
* @throws LiquidException * @throws LiquidException
* @throws Exception
*/ */
public function resolveLiquidVariables(string $template): string public function resolveLiquidVariables(string $template): string
{ {
// Get configuration variables - make them available at root level // Get configuration variables - make them available at root level
$variables = $this->configuration ?? []; $variables = $this->configuration ?? [];
// Check if external renderer should be used
$useExternalRenderer = $this->preferred_renderer === 'trmnl-liquid'
&& config('services.trmnl.liquid_enabled')
&& $this->containsLiquidForLoop($template);
if ($useExternalRenderer) {
// Use external Ruby liquid renderer
return $this->renderWithExternalLiquidRenderer($template, $variables);
}
// Use the Liquid template engine to resolve variables // Use the Liquid template engine to resolve variables
$environment = App::make('liquid.environment'); $environment = App::make('liquid.environment');
$environment->filterRegistry->register(StandardFilters::class); $environment->filterRegistry->register(StandardFilters::class);
@ -404,7 +434,7 @@ class Plugin extends Model
'--context', '--context',
$jsonContext, $jsonContext,
]); ]);
if (! $process->successful()) { if (! $process->successful()) {
$errorOutput = $process->errorOutput() ?: $process->output(); $errorOutput = $process->errorOutput() ?: $process->output();
throw new Exception('External liquid renderer failed: '.$errorOutput); throw new Exception('External liquid renderer failed: '.$errorOutput);