diff --git a/app/Liquid/Filters/StandardFilters.php b/app/Liquid/Filters/StandardFilters.php
new file mode 100644
index 0000000..4db86a0
--- /dev/null
+++ b/app/Liquid/Filters/StandardFilters.php
@@ -0,0 +1,20 @@
+filterRegistry->register(StandardFilters::class);
$liquidTemplate = $environment->parseString($template);
$context = $environment->newRenderContext(data: $variables);
@@ -285,7 +288,7 @@ class Plugin extends Model
$inlineFileSystem = new InlineTemplatesFileSystem();
$environment = new \Keepsuit\Liquid\Environment(
fileSystem: $inlineFileSystem,
- extensions: [new StandardExtension()]
+ extensions: [new StandardExtension(), new LaravelLiquidExtension()]
);
// Register all custom filters
diff --git a/resources/views/livewire/catalog/index.blade.php b/resources/views/livewire/catalog/index.blade.php
index 4725e68..92bd5a9 100644
--- a/resources/views/livewire/catalog/index.blade.php
+++ b/resources/views/livewire/catalog/index.blade.php
@@ -2,6 +2,7 @@
use App\Services\PluginImportService;
use Livewire\Volt\Component;
+use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
@@ -26,21 +27,40 @@ new class extends Component {
$catalogContent = $response->body();
$catalog = Yaml::parse($catalogContent);
- return collect($catalog)->map(function ($plugin, $key) {
- return [
- 'id' => $key,
- 'name' => $plugin['name'] ?? 'Unknown Plugin',
- 'description' => $plugin['author_bio']['description'] ?? '',
- 'author' => $plugin['author']['name'] ?? 'Unknown Author',
- 'github' => $plugin['author']['github'] ?? null,
- 'license' => $plugin['license'] ?? null,
- 'zip_url' => $plugin['trmnlp']['zip_url'] ?? null,
- 'repo_url' => $plugin['trmnlp']['repo'] ?? null,
- 'logo_url' => $plugin['logo_url'] ?? null,
- 'screenshot_url' => $plugin['screenshot_url'] ?? null,
- 'learn_more_url' => $plugin['author_bio']['learn_more_url'] ?? null,
- ];
- })->toArray();
+ $currentVersion = config('app.version');
+
+ return collect($catalog)
+ ->filter(function ($plugin) use ($currentVersion) {
+ // Check if Laravel compatibility is true
+ if (!Arr::get($plugin, 'byos.byos_laravel.compatibility', false)) {
+ return false;
+ }
+
+ // Check minimum version if specified
+ $minVersion = Arr::get($plugin, 'byos.byos_laravel.min_version');
+ if ($minVersion && $currentVersion && version_compare($currentVersion, $minVersion, '<')) {
+ return false;
+ }
+
+ return true;
+ })
+ ->map(function ($plugin, $key) {
+ return [
+ 'id' => $key,
+ 'name' => Arr::get($plugin, 'name', 'Unknown Plugin'),
+ 'description' => Arr::get($plugin, 'author_bio.description', ''),
+ 'author' => Arr::get($plugin, 'author.name', 'Unknown Author'),
+ 'github' => Arr::get($plugin, 'author.github'),
+ 'license' => Arr::get($plugin, 'license'),
+ 'zip_url' => Arr::get($plugin, 'trmnlp.zip_url'),
+ 'repo_url' => Arr::get($plugin, 'trmnlp.repo'),
+ 'logo_url' => Arr::get($plugin, 'logo_url'),
+ 'screenshot_url' => Arr::get($plugin, 'screenshot_url'),
+ 'learn_more_url' => Arr::get($plugin, 'author_bio.learn_more_url'),
+ ];
+ })
+ ->sortBy('name')
+ ->toArray();
} catch (\Exception $e) {
Log::error('Failed to load catalog from URL: ' . $e->getMessage());
return [];
diff --git a/resources/views/livewire/plugins/index.blade.php b/resources/views/livewire/plugins/index.blade.php
index 828e051..bcecfc9 100644
--- a/resources/views/livewire/plugins/index.blade.php
+++ b/resources/views/livewire/plugins/index.blade.php
@@ -38,10 +38,7 @@ new class extends Component {
public function refreshPlugins(): void
{
- $userPlugins = auth()->user()?->plugins?->map(function ($plugin) {
- return $plugin->toArray();
- })->toArray();
-
+ $userPlugins = auth()->user()?->plugins?->makeHidden(['render_markup', 'data_payload'])->toArray();
$this->plugins = array_merge($this->native_plugins, $userPlugins ?? []);
}
diff --git a/resources/views/livewire/plugins/recipe.blade.php b/resources/views/livewire/plugins/recipe.blade.php
index 9226af6..3a8e7cc 100644
--- a/resources/views/livewire/plugins/recipe.blade.php
+++ b/resources/views/livewire/plugins/recipe.blade.php
@@ -133,7 +133,7 @@ new class extends Component {
$this->addError('polling_url', 'The polling URL must be a valid URL after resolving configuration variables.');
}
} catch (\Exception $e) {
- $this->addError('polling_url', 'Error resolving Liquid variables: ' . $e->getMessage());
+ $this->addError('polling_url', 'Error resolving Liquid variables: ' . $e->getMessage() . $e->getPrevious()?->getMessage());
}
}
}
@@ -148,7 +148,7 @@ new class extends Component {
$this->data_payload_updated_at = $this->plugin->data_payload_updated_at;
} catch (\Exception $e) {
- $this->dispatch('data-update-error', message: $e->getMessage());
+ $this->dispatch('data-update-error', message: $e->getMessage() . $e->getPrevious()?->getMessage());
}
}
}
@@ -690,7 +690,10 @@ HTML;
@endforeach
@else
-
+ @php
+ $key = mb_strtolower(str_replace(' ', '_', $option));
+ @endphp
+
@endif
@endforeach
@endif
diff --git a/tests/Feature/Livewire/Catalog/IndexTest.php b/tests/Feature/Livewire/Catalog/IndexTest.php
index 7defd78..5964588 100644
--- a/tests/Feature/Livewire/Catalog/IndexTest.php
+++ b/tests/Feature/Livewire/Catalog/IndexTest.php
@@ -38,6 +38,11 @@ it('loads plugins from catalog URL', function () {
'trmnlp' => [
'zip_url' => 'https://example.com/plugin.zip',
],
+ 'byos' => [
+ 'byos_laravel' => [
+ 'compatibility' => true,
+ ]
+ ],
'logo_url' => 'https://example.com/logo.png',
],
];
diff --git a/tests/Feature/PluginLiquidWhereFilterTest.php b/tests/Feature/PluginLiquidFilterTest.php
similarity index 76%
rename from tests/Feature/PluginLiquidWhereFilterTest.php
rename to tests/Feature/PluginLiquidFilterTest.php
index c165109..fb429ae 100644
--- a/tests/Feature/PluginLiquidWhereFilterTest.php
+++ b/tests/Feature/PluginLiquidFilterTest.php
@@ -2,7 +2,9 @@
declare(strict_types=1);
+use App\Liquid\Filters\StandardFilters;
use App\Models\Plugin;
+use Keepsuit\Liquid\Environment;
/**
* Tests for the Liquid where filter functionality
@@ -92,3 +94,31 @@ LIQUID
// Should not contain the low tide data
$this->assertStringNotContainsString('"type":"L"', $result);
});
+
+it('encodes arrays for url_encode as JSON with spaces after commas and then percent-encodes', function () {
+ /** @var Environment $env */
+ $env = app('liquid.environment');
+ $env->filterRegistry->register(StandardFilters::class);
+
+ $template = $env->parseString('{{ categories | url_encode }}');
+
+ $output = $template->render($env->newRenderContext([
+ 'categories' => ['common', 'obscure'],
+ ]));
+
+ expect($output)->toBe('%5B%22common%22%2C%22obscure%22%5D');
+});
+
+it('keeps scalar url_encode behavior intact', function () {
+ /** @var Environment $env */
+ $env = app('liquid.environment');
+ $env->filterRegistry->register(StandardFilters::class);
+
+ $template = $env->parseString('{{ text | url_encode }}');
+
+ $output = $template->render($env->newRenderContext([
+ 'text' => 'hello world',
+ ]));
+
+ expect($output)->toBe('hello+world');
+});