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',