diff --git a/app/Services/PluginImportService.php b/app/Services/PluginImportService.php index 06e6092..be69e3e 100644 --- a/app/Services/PluginImportService.php +++ b/app/Services/PluginImportService.php @@ -80,6 +80,9 @@ class PluginImportService $settings['custom_fields'] = []; } + // Normalize options in custom_fields (convert non-named values to named values) + $settings['custom_fields'] = $this->normalizeCustomFieldsOptions($settings['custom_fields']); + // Create configuration template with the custom fields $configurationTemplate = [ 'custom_fields' => $settings['custom_fields'], @@ -206,6 +209,9 @@ class PluginImportService $settings['custom_fields'] = []; } + // Normalize options in custom_fields (convert non-named values to named values) + $settings['custom_fields'] = $this->normalizeCustomFieldsOptions($settings['custom_fields']); + // Create configuration template with the custom fields $configurationTemplate = [ 'custom_fields' => $settings['custom_fields'], @@ -385,6 +391,49 @@ class PluginImportService ]; } + /** + * Normalize options in custom_fields by converting non-named values to named values + * This ensures that options like ["true", "false"] become [["true" => "true"], ["false" => "false"]] + * + * @param array $customFields The custom_fields array from settings + * @return array The normalized custom_fields array + */ + private function normalizeCustomFieldsOptions(array $customFields): array + { + foreach ($customFields as &$field) { + // Only process select fields with options + if (isset($field['field_type']) && $field['field_type'] === 'select' && isset($field['options']) && is_array($field['options'])) { + $normalizedOptions = []; + foreach ($field['options'] as $option) { + // If option is already a named value (array with key-value pair), keep it as is + if (is_array($option)) { + $normalizedOptions[] = $option; + } else { + // Convert non-named value to named value + // Convert boolean to string, use lowercase for label + $value = is_bool($option) ? ($option ? 'true' : 'false') : (string) $option; + $normalizedOptions[] = [$value => $value]; + } + } + $field['options'] = $normalizedOptions; + + // Normalize default value to match normalized option values + if (isset($field['default'])) { + $default = $field['default']; + // If default is boolean, convert to string to match normalized options + if (is_bool($default)) { + $field['default'] = $default ? 'true' : 'false'; + } else { + // Convert to string to ensure consistency + $field['default'] = (string) $default; + } + } + } + } + + return $customFields; + } + /** * Validate that template and context are within command-line argument limits * diff --git a/tests/Feature/PluginImportTest.php b/tests/Feature/PluginImportTest.php index 4bbea15..1b20f93 100644 --- a/tests/Feature/PluginImportTest.php +++ b/tests/Feature/PluginImportTest.php @@ -388,6 +388,45 @@ it('does not set icon_url when importing from URL without iconUrl parameter', fu ->and($plugin->icon_url)->toBeNull(); }); +it('normalizes non-named select options to named values', function (): void { + $user = User::factory()->create(); + + $settingsYaml = <<<'YAML' +name: Test Plugin +refresh_interval: 30 +strategy: static +polling_verb: get +static_data: '{}' +custom_fields: + - keyname: display_incident + field_type: select + options: + - true + - false + default: true +YAML; + + $zipContent = createMockZipFile([ + 'src/settings.yml' => $settingsYaml, + 'src/full.liquid' => getValidFullLiquid(), + ]); + + $zipFile = UploadedFile::fake()->createWithContent('test-plugin.zip', $zipContent); + + $pluginImportService = new PluginImportService(); + $plugin = $pluginImportService->importFromZip($zipFile, $user); + + $customFields = $plugin->configuration_template['custom_fields']; + $displayIncidentField = collect($customFields)->firstWhere('keyname', 'display_incident'); + + expect($displayIncidentField)->not->toBeNull() + ->and($displayIncidentField['options'])->toBe([ + ['true' => 'true'], + ['false' => 'false'], + ]) + ->and($displayIncidentField['default'])->toBe('true'); +}); + // Helper methods function createMockZipFile(array $files): string {