diff --git a/app/Console/Commands/ImportHtmlTemplates.php b/app/Console/Commands/ImportHtmlTemplates.php index 9aeb840..886010c 100644 --- a/app/Console/Commands/ImportHtmlTemplates.php +++ b/app/Console/Commands/ImportHtmlTemplates.php @@ -143,41 +143,82 @@ class ImportHtmlTemplates extends Command // A. Header Özel Alanları if ($templateType === 'header') { + // Navbar sınıfını kontrol et + $navbar = $xpath->query('.//*[contains(@class, "navbar")]', $node)->item(0); + $isNavbarLight = $navbar && str_contains($navbar->getAttribute('class'), 'navbar-light'); + $isNavbarDark = $navbar && str_contains($navbar->getAttribute('class'), 'navbar-dark'); + // Logo $brands = $xpath->query('.//*[contains(@class, "navbar-brand")]//img', $node); foreach ($brands as $img) { $src = $this->fixAssetPath($img->getAttribute('src')); $class = $img->getAttribute('class'); + $settingKey = 'setting.logo'; + if (str_contains($class, 'logo-dark')) { - $data['setting.logo_dark'] = $src; - $img->setAttribute('src', '{setting.logo_dark}'); + $settingKey = 'setting.logo_dark'; } elseif (str_contains($class, 'logo-light')) { - $data['setting.logo_light'] = $src; - $img->setAttribute('src', '{setting.logo_light}'); - } else { - $data['setting.logo'] = $src; - $img->setAttribute('src', '{setting.logo}'); + $settingKey = 'setting.logo_light'; + } elseif ($isNavbarLight) { + // Navbar light ise (açık zemin), koyu logo gerekir + $settingKey = 'setting.logo_dark'; + } elseif ($isNavbarDark) { + // Navbar dark ise (koyu zemin), açık logo gerekir + $settingKey = 'setting.logo_light'; + } + + $data[$settingKey] = $src; + $img->setAttribute('src', '{' . $settingKey . '}'); + } + + // Menu ({custom.menu}) + $navs = $xpath->query('.//*[contains(@class, "navbar-nav")]', $node); + foreach ($navs as $nav) { + // Sadece ana menüyü hedefle (genellikle navbar-collapse içinde olur) + // İçeriği tamamen temizle ve yerine placeholder koy + $parent = $nav->parentNode; + if ($parent) { + // Eğer parent offcanvas-body veya navbar-collapse ise + $textNode = $node->ownerDocument->createTextNode('___CUSTOM_MENU___'); + $parent->replaceChild($textNode, $nav); } } - // Menu - $navs = $xpath->query('.//*[contains(@class, "navbar-nav")]', $node); - foreach ($navs as $nav) { - if (!$nav->parentNode) continue; - // İçini temizle - while ($nav->hasChildNodes()) { - $nav->removeChild($nav->firstChild); + // Navbar Other ({custom.navbar}) + $others = $xpath->query('.//*[contains(@class, "navbar-other")]', $node); + foreach ($others as $other) { + $parent = $other->parentNode; + if ($parent) { + // Navbar other genellikle butonları içerir, bunu custom.navbar ile değiştiriyoruz + // Ancak dil seçici de bunun içinde olabilir. + // Kullanıcı örneğinde {custom.navbar} ve {custom.language-selector} yan yana. + // Biz şimdilik navbar-other'ı komple custom.navbar yapalım. + // Dil seçici için ayrıca bir mantık kuralım. + + // Dil seçiciyi kontrol et, eğer varsa onu çıkarıp yanına ekleyebiliriz ama + // genellikle navbar-other kapsayıcıdır. + + $textNode = $node->ownerDocument->createTextNode('___CUSTOM_NAVBAR___'); + $parent->replaceChild($textNode, $other); + + // Hemen sonrasına language selector ekleyelim (varsayım) + // Veya kullanıcı manuel eklesin. + // Kullanıcının isteği: {custom.navbar} {custom.language-selector} + $langNode = $node->ownerDocument->createTextNode('___CUSTOM_LANGUAGE___'); + $parent->appendChild($langNode); } - // Placeholder metni ekle - Token olarak - $nav->nodeValue = '___SPECIAL_MENU___'; } - // Dil Seçici - $langs = $xpath->query('.//*[contains(@class, "language")]', $node); - foreach ($langs as $lang) { - $lang->nodeValue = '___SETTING_LANGUAGES___'; - } + // Dil Seçici ({custom.language-selector}) - Eğer navbar-other dışında varsa + $langs = $xpath->query('.//*[contains(@class, "language-select") or contains(@class, "dropdown-language")]', $node); + foreach ($langs as $lang) { + $parent = $lang->parentNode; + if ($parent) { + $textNode = $node->ownerDocument->createTextNode('___CUSTOM_LANGUAGE___'); + $parent->replaceChild($textNode, $lang); + } + } } // B. Genel İşlemler @@ -250,8 +291,11 @@ class ImportHtmlTemplates extends Command // SPECIAL TOKENS FIX if ($templateType === 'header') { - $html = str_replace('___SPECIAL_MENU___', '{special.menu}', $html); - $html = str_replace('___SETTING_LANGUAGES___', '{setting.available_languages}', $html); + $html = str_replace('___SPECIAL_MENU___', '{custom.menu}', $html); // Geriye dönük uyumluluk + $html = str_replace('___CUSTOM_MENU___', '{custom.menu}', $html); + $html = str_replace('___CUSTOM_NAVBAR___', '{custom.navbar}', $html); + $html = str_replace('___CUSTOM_LANGUAGE___', '{custom.language-selector}', $html); + $html = str_replace('___SETTING_LANGUAGES___', '{custom.language-selector}', $html); } return ['html' => $html, 'data' => $data]; diff --git a/app/Filament/Admin/Resources/Settings/Pages/EditSetting.php b/app/Filament/Admin/Resources/Settings/Pages/EditSetting.php index 57a47ae..be7cd98 100644 --- a/app/Filament/Admin/Resources/Settings/Pages/EditSetting.php +++ b/app/Filament/Admin/Resources/Settings/Pages/EditSetting.php @@ -51,7 +51,7 @@ class EditSetting extends EditRecord protected function getRedirectUrl(): string { - return $this->getResource()::getUrl('index'); + return $this->getResource()::getUrl('edit', ['record' => $this->getRecord()]); } protected function getSavedNotificationTitle(): ?string diff --git a/app/Filament/Admin/Resources/Settings/Schemas/SettingForm.php b/app/Filament/Admin/Resources/Settings/Schemas/SettingForm.php index e70976b..a3163be 100644 --- a/app/Filament/Admin/Resources/Settings/Schemas/SettingForm.php +++ b/app/Filament/Admin/Resources/Settings/Schemas/SettingForm.php @@ -116,12 +116,6 @@ class SettingForm ->required() ->visible(fn (Get $get) => in_array($get('type'), ['string', 'text', 'json'])) ->rows(fn (Get $get) => $get('type') === 'text' ? 5 : 3) - ->formatStateUsing(function ($state, $record) { - if ($record && in_array($record->type, ['string', 'text', 'json'])) { - return $record->value; - } - return $state; - }) ->columnSpanFull(), Toggle::make('value_boolean') @@ -129,12 +123,6 @@ class SettingForm ->helperText(__('settings.value_helper')) ->required() ->visible(fn (Get $get) => $get('type') === 'boolean') - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'boolean') { - return filter_var($record->value, FILTER_VALIDATE_BOOLEAN); - } - return false; - }) ->columnSpanFull(), FileUpload::make('value_file') @@ -146,12 +134,6 @@ class SettingForm ->directory('settings') ->acceptedFileTypes(['image/*', 'application/pdf', 'text/*']) ->maxSize(10240) // 10MB - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'file') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), DatePicker::make('value_date') @@ -161,12 +143,6 @@ class SettingForm ->visible(fn (Get $get) => $get('type') === 'date') ->displayFormat('d/m/Y') ->format('Y-m-d') - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'date') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), DateTimePicker::make('value_datetime') @@ -177,12 +153,6 @@ class SettingForm ->displayFormat('d/m/Y H:i') ->format('Y-m-d H:i:s') ->seconds(false) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'datetime') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), Repeater::make('value_array') @@ -213,13 +183,6 @@ class SettingForm ->reorderable() ->collapsible() ->itemLabel(fn (array $state): ?string => $state['key'] ?? null) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'array') { - $decoded = json_decode($record->value, true); - return is_array($decoded) ? $decoded : []; - } - return is_array($state) ? $state : []; - }) ->columnSpanFull(), ColorPicker::make('value_color_picker') @@ -227,12 +190,6 @@ class SettingForm ->helperText(__('settings.value_helper')) ->required() ->visible(fn (Get $get) => $get('type') === 'color_picker') - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'color_picker') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), CodeEditor::make('value_code_editor') @@ -241,12 +198,6 @@ class SettingForm ->required() ->visible(fn (Get $get) => $get('type') === 'code_editor') ->language(CodeEditorLanguage::Php) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'code_editor') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), RichEditor::make('value_rich_editor') @@ -272,12 +223,6 @@ class SettingForm 'underline', 'undo', ]) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'rich_editor') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), MarkdownEditor::make('value_markdown_editor') @@ -285,12 +230,6 @@ class SettingForm ->helperText(__('settings.value_helper')) ->required() ->visible(fn (Get $get) => $get('type') === 'markdown_editor') - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'markdown_editor') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), TagsInput::make('value_tags_input') @@ -299,13 +238,6 @@ class SettingForm ->required() ->visible(fn (Get $get) => $get('type') === 'tags_input') ->separator(',') - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'tags_input') { - $decoded = json_decode($record->value, true); - return is_array($decoded) ? $decoded : []; - } - return is_array($state) ? $state : []; - }) ->columnSpanFull(), CheckboxList::make('value_checkbox_list') @@ -318,13 +250,6 @@ class SettingForm 'option2' => __('settings.checkbox_option_2'), 'option3' => __('settings.checkbox_option_3'), ]) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'checkbox_list') { - $decoded = json_decode($record->value, true); - return is_array($decoded) ? $decoded : []; - } - return is_array($state) ? $state : []; - }) ->columnSpanFull(), Radio::make('value_radio') @@ -337,12 +262,6 @@ class SettingForm 'option2' => __('settings.radio_option_2'), 'option3' => __('settings.radio_option_3'), ]) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'radio') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), ToggleButtons::make('value_toggle_buttons') @@ -355,12 +274,6 @@ class SettingForm 'option2' => __('settings.toggle_option_2'), 'option3' => __('settings.toggle_option_3'), ]) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'toggle_buttons') { - return $record->value; - } - return $state; - }) ->columnSpanFull(), Slider::make('value_slider') @@ -370,12 +283,6 @@ class SettingForm ->visible(fn (Get $get) => $get('type') === 'slider') ->range(minValue: 0, maxValue: 100) ->step(1) - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'slider') { - return (int) $record->value; - } - return $state ?? 0; - }) ->columnSpanFull(), KeyValue::make('value_key_value') @@ -383,13 +290,6 @@ class SettingForm ->helperText(__('settings.value_helper')) ->required() ->visible(fn (Get $get) => $get('type') === 'key_value') - ->formatStateUsing(function ($state, $record) { - if ($record && $record->type === 'key_value') { - $decoded = json_decode($record->value, true); - return is_array($decoded) ? $decoded : []; - } - return is_array($state) ? $state : []; - }) ->columnSpanFull(), Toggle::make('is_active') diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 4ad7442..1b38656 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -69,7 +69,12 @@ class Setting extends Model */ public function setValueFileAttribute($value) { - $this->attributes['value'] = $value; + // Filament bazen dosya yolunu array olarak döndürebilir, bu durumda ilk elemanı alıyoruz + if (is_array($value)) { + $this->attributes['value'] = array_values($value)[0] ?? null; + } else { + $this->attributes['value'] = $value; + } } /** @@ -176,6 +181,134 @@ class Setting extends Model $this->attributes['value'] = is_array($value) ? json_encode($value) : $value; } + /** + * Get value for text field + */ + public function getValueTextAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for boolean field + */ + public function getValueBooleanAttribute() + { + return isset($this->attributes['value']) ? filter_var($this->attributes['value'], FILTER_VALIDATE_BOOLEAN) : false; + } + + /** + * Get value for file field + */ + public function getValueFileAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for date field + */ + public function getValueDateAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for datetime field + */ + public function getValueDatetimeAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for array field + */ + public function getValueArrayAttribute() + { + return isset($this->attributes['value']) ? json_decode($this->attributes['value'], true) : []; + } + + /** + * Get value for color picker field + */ + public function getValueColorPickerAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for code editor field + */ + public function getValueCodeEditorAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for rich editor field + */ + public function getValueRichEditorAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for markdown editor field + */ + public function getValueMarkdownEditorAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for tags input field + */ + public function getValueTagsInputAttribute() + { + return isset($this->attributes['value']) ? json_decode($this->attributes['value'], true) : []; + } + + /** + * Get value for checkbox list field + */ + public function getValueCheckboxListAttribute() + { + return isset($this->attributes['value']) ? json_decode($this->attributes['value'], true) : []; + } + + /** + * Get value for radio field + */ + public function getValueRadioAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for toggle buttons field + */ + public function getValueToggleButtonsAttribute() + { + return $this->attributes['value'] ?? null; + } + + /** + * Get value for slider field + */ + public function getValueSliderAttribute() + { + return isset($this->attributes['value']) ? (int) $this->attributes['value'] : 0; + } + + /** + * Get value for key value field + */ + public function getValueKeyValueAttribute() + { + return isset($this->attributes['value']) ? json_decode($this->attributes['value'], true) : []; + } + /** * Get setting by key */ diff --git a/app/Services/TemplateService.php b/app/Services/TemplateService.php index 3701a91..bd5b036 100644 --- a/app/Services/TemplateService.php +++ b/app/Services/TemplateService.php @@ -50,6 +50,11 @@ class TemplateService if (str_starts_with($placeholder, 'special.')) { continue; } + + // Skip setting.* placeholders - they are global settings managed via Settings module + if ($type === 'setting') { + continue; + } // Skip custom.* placeholders - they are blade components, not form fields if ($type === 'custom') { @@ -282,7 +287,7 @@ class TemplateService public static function parsePlaceholders(string $html): array { // Pattern: {type.field} or {special.type.field} or {type.field.field2} etc. - preg_match_all('/\{([a-z]+(?:\.[a-z][a-z_-]*)+)\}/i', $html, $matches); + preg_match_all('/\{([a-z]+(?:\.[a-z][a-z0-9_-]*)+)\}/i', $html, $matches); return array_unique($matches[1] ?? []); } @@ -410,7 +415,7 @@ class TemplateService // Also supports {special.page.title} format (special.* prefix) // Exclude custom.* from this regex to avoid double processing // Pattern: {type.field} or {special.type.field} or {type.field.field2} etc. - preg_match_all('/\{([a-z]+(?:\.[a-z][a-z_-]*)+)\}/i', $html, $matches); + preg_match_all('/\{([a-z]+(?:\.[a-z][a-z0-9_-]*)+)\}/i', $html, $matches); $placeholders = array_unique($matches[1] ?? []); // Filter out custom.* placeholders as they're already handled above diff --git a/database/seeders/SettingSeeder.php b/database/seeders/SettingSeeder.php index 3aa6b93..bbb80cf 100644 --- a/database/seeders/SettingSeeder.php +++ b/database/seeders/SettingSeeder.php @@ -587,7 +587,7 @@ class SettingSeeder extends Seeder ], [ 'key' => 'logo_light', - 'value' => 'assets/img/logo-light.png', + 'value' => '', 'type' => 'file', 'group' => 'theme', 'label' => 'Light Logo', @@ -597,7 +597,7 @@ class SettingSeeder extends Seeder ], [ 'key' => 'logo_dark', - 'value' => 'assets/img/logo-dark.png', + 'value' => '', 'type' => 'file', 'group' => 'theme', 'label' => 'Dark Logo',