mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 23:18:10 +00:00
feat: set icon url on import
This commit is contained in:
parent
e427932dd0
commit
471340ac16
4 changed files with 73 additions and 14 deletions
|
|
@ -139,11 +139,13 @@ class PluginImportService
|
||||||
* @param string $zipUrl The URL to the ZIP file
|
* @param string $zipUrl The URL to the ZIP file
|
||||||
* @param User $user The user importing the plugin
|
* @param User $user The user importing the plugin
|
||||||
* @param string|null $zipEntryPath Optional path to specific plugin in monorepo
|
* @param string|null $zipEntryPath Optional path to specific plugin in monorepo
|
||||||
|
* @param string|null $preferredRenderer Optional preferred renderer (e.g., 'trmnl-liquid')
|
||||||
|
* @param string|null $iconUrl Optional icon URL to set on the plugin
|
||||||
* @return Plugin The created plugin instance
|
* @return Plugin The created plugin instance
|
||||||
*
|
*
|
||||||
* @throws Exception If the ZIP file is invalid or required files are missing
|
* @throws Exception If the ZIP file is invalid or required files are missing
|
||||||
*/
|
*/
|
||||||
public function importFromUrl(string $zipUrl, User $user, ?string $zipEntryPath = null, $preferredRenderer = null): Plugin
|
public function importFromUrl(string $zipUrl, User $user, ?string $zipEntryPath = null, $preferredRenderer = null, ?string $iconUrl = null): Plugin
|
||||||
{
|
{
|
||||||
// Download the ZIP file
|
// Download the ZIP file
|
||||||
$response = Http::timeout(60)->get($zipUrl);
|
$response = Http::timeout(60)->get($zipUrl);
|
||||||
|
|
@ -233,6 +235,7 @@ class PluginImportService
|
||||||
'configuration_template' => $configurationTemplate,
|
'configuration_template' => $configurationTemplate,
|
||||||
'data_payload' => json_decode($settings['static_data'] ?? '{}', true),
|
'data_payload' => json_decode($settings['static_data'] ?? '{}', true),
|
||||||
'preferred_renderer' => $preferredRenderer,
|
'preferred_renderer' => $preferredRenderer,
|
||||||
|
'icon_url' => $iconUrl,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (! $plugin_updated) {
|
if (! $plugin_updated) {
|
||||||
|
|
@ -388,7 +391,6 @@ class PluginImportService
|
||||||
* @param string $template The liquid template string
|
* @param string $template The liquid template string
|
||||||
* @param string $jsonContext The JSON-encoded context
|
* @param string $jsonContext The JSON-encoded context
|
||||||
* @param string $liquidPath The path to the liquid renderer executable
|
* @param string $liquidPath The path to the liquid renderer executable
|
||||||
* @return void
|
|
||||||
*
|
*
|
||||||
* @throws Exception If the template or context exceeds argument limits
|
* @throws Exception If the template or context exceeds argument limits
|
||||||
*/
|
*/
|
||||||
|
|
@ -400,14 +402,14 @@ class PluginImportService
|
||||||
$maxTotalArgLength = $this->getMaxArgumentLength();
|
$maxTotalArgLength = $this->getMaxArgumentLength();
|
||||||
|
|
||||||
// Check individual argument sizes (template and context are the largest)
|
// Check individual argument sizes (template and context are the largest)
|
||||||
if (strlen($template) > $maxIndividualArgLength || strlen($jsonContext) > $maxIndividualArgLength) {
|
if (mb_strlen($template) > $maxIndividualArgLength || mb_strlen($jsonContext) > $maxIndividualArgLength) {
|
||||||
throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.');
|
throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total size of all arguments (path + flags + template + context)
|
// Calculate total size of all arguments (path + flags + template + context)
|
||||||
// Add overhead for path, flags, and separators (conservative estimate: ~200 bytes)
|
// Add overhead for path, flags, and separators (conservative estimate: ~200 bytes)
|
||||||
$totalArgSize = strlen($liquidPath) + strlen('--template') + strlen($template)
|
$totalArgSize = mb_strlen($liquidPath) + mb_strlen('--template') + mb_strlen($template)
|
||||||
+ strlen('--context') + strlen($jsonContext) + 200;
|
+ mb_strlen('--context') + mb_strlen($jsonContext) + 200;
|
||||||
|
|
||||||
if ($totalArgSize > $maxTotalArgLength) {
|
if ($totalArgSize > $maxTotalArgLength) {
|
||||||
throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.');
|
throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.');
|
||||||
|
|
@ -425,8 +427,8 @@ class PluginImportService
|
||||||
$argMax = null;
|
$argMax = null;
|
||||||
if (function_exists('shell_exec')) {
|
if (function_exists('shell_exec')) {
|
||||||
$result = @shell_exec('getconf ARG_MAX 2>/dev/null');
|
$result = @shell_exec('getconf ARG_MAX 2>/dev/null');
|
||||||
if ($result !== null && is_numeric(trim($result))) {
|
if ($result !== null && is_numeric(mb_trim($result))) {
|
||||||
$argMax = (int) trim($result);
|
$argMax = (int) mb_trim($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,13 @@ new class extends Component {
|
||||||
$this->installingPlugin = $pluginId;
|
$this->installingPlugin = $pluginId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$importedPlugin = $pluginImportService->importFromUrl($plugin['zip_url'], auth()->user(), $plugin['zip_entry_path'] ?? null);
|
$importedPlugin = $pluginImportService->importFromUrl(
|
||||||
|
$plugin['zip_url'],
|
||||||
|
auth()->user(),
|
||||||
|
$plugin['zip_entry_path'] ?? null,
|
||||||
|
null,
|
||||||
|
$plugin['logo_url'] ?? null
|
||||||
|
);
|
||||||
|
|
||||||
$this->dispatch('plugin-installed');
|
$this->dispatch('plugin-installed');
|
||||||
Flux::modal('import-from-catalog')->close();
|
Flux::modal('import-from-catalog')->close();
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,14 @@ new class extends Component {
|
||||||
try {
|
try {
|
||||||
$zipUrl = "https://usetrmnl.com/api/plugin_settings/{$recipeId}/archive";
|
$zipUrl = "https://usetrmnl.com/api/plugin_settings/{$recipeId}/archive";
|
||||||
|
|
||||||
|
$recipe = collect($this->recipes)->firstWhere('id', $recipeId);
|
||||||
|
|
||||||
$plugin = $pluginImportService->importFromUrl(
|
$plugin = $pluginImportService->importFromUrl(
|
||||||
$zipUrl,
|
$zipUrl,
|
||||||
auth()->user(),
|
auth()->user(),
|
||||||
preferredRenderer: config('services.trmnl.liquid_enabled') ? 'trmnl-liquid' : null
|
null,
|
||||||
|
config('services.trmnl.liquid_enabled') ? 'trmnl-liquid' : null,
|
||||||
|
$recipe['icon_url'] ?? null
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->dispatch('plugin-installed');
|
$this->dispatch('plugin-installed');
|
||||||
|
|
|
||||||
|
|
@ -341,6 +341,53 @@ it('imports specific plugin from monorepo zip with zip_entry_path parameter', fu
|
||||||
->and($plugin->render_markup)->toContain('<div class="plugin2-content">Plugin 2 content</div>');
|
->and($plugin->render_markup)->toContain('<div class="plugin2-content">Plugin 2 content</div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sets icon_url when importing from URL with iconUrl parameter', function (): void {
|
||||||
|
$user = User::factory()->create();
|
||||||
|
|
||||||
|
$zipContent = createMockZipFile([
|
||||||
|
'src/settings.yml' => getValidSettingsYaml(),
|
||||||
|
'src/full.liquid' => getValidFullLiquid(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Http::fake([
|
||||||
|
'https://example.com/plugin.zip' => Http::response($zipContent, 200),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$pluginImportService = new PluginImportService();
|
||||||
|
$plugin = $pluginImportService->importFromUrl(
|
||||||
|
'https://example.com/plugin.zip',
|
||||||
|
$user,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'https://example.com/icon.png'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($plugin)->toBeInstanceOf(Plugin::class)
|
||||||
|
->and($plugin->icon_url)->toBe('https://example.com/icon.png');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not set icon_url when importing from URL without iconUrl parameter', function (): void {
|
||||||
|
$user = User::factory()->create();
|
||||||
|
|
||||||
|
$zipContent = createMockZipFile([
|
||||||
|
'src/settings.yml' => getValidSettingsYaml(),
|
||||||
|
'src/full.liquid' => getValidFullLiquid(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Http::fake([
|
||||||
|
'https://example.com/plugin.zip' => Http::response($zipContent, 200),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$pluginImportService = new PluginImportService();
|
||||||
|
$plugin = $pluginImportService->importFromUrl(
|
||||||
|
'https://example.com/plugin.zip',
|
||||||
|
$user
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($plugin)->toBeInstanceOf(Plugin::class)
|
||||||
|
->and($plugin->icon_url)->toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
function createMockZipFile(array $files): string
|
function createMockZipFile(array $files): string
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue