move into sonardesk
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'name' => 'Seo',
|
||||
'enabled' => true,
|
||||
];
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('seo_metadata', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->morphs('seoable');
|
||||
$table->string('title')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->string('canonical_url')->nullable();
|
||||
$table->string('robots')->default('index,follow');
|
||||
$table->string('og_title')->nullable();
|
||||
$table->text('og_description')->nullable();
|
||||
$table->string('og_image')->nullable();
|
||||
$table->string('twitter_card')->default('summary_large_image');
|
||||
$table->string('schema_type')->nullable();
|
||||
$table->json('schema_data')->nullable();
|
||||
$table->boolean('include_in_sitemap')->default(true);
|
||||
$table->decimal('sitemap_priority', 2, 1)->default(0.5);
|
||||
$table->string('sitemap_change_frequency')->default('monthly');
|
||||
$table->timestamps();
|
||||
$table->unique(['seoable_type', 'seoable_id']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('seo_metadata');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Seo\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Settings\Models\Setting;
|
||||
|
||||
final class SeoController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$values = Setting::where('group', 'seo')->pluck('value', 'key');
|
||||
|
||||
return view('seo::index', compact('values'));
|
||||
}
|
||||
|
||||
public function update(Request $request)
|
||||
{
|
||||
$data = $request->validate(['site_title' => ['nullable', 'string', 'max:255'], 'meta_description' => ['nullable', 'string', 'max:500'], 'robots' => ['required', 'string', 'max:100'], 'canonical_base' => ['nullable', 'url', 'max:255']]);
|
||||
foreach ($data as $key => $value) {
|
||||
Setting::updateOrCreate(['group' => 'seo', 'key' => $key], ['value' => $value, 'type' => 'string', 'is_public' => true]);
|
||||
}
|
||||
|
||||
return back()->with('status', 'SEO defaults saved.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Seo\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
final class SeoMetadata extends Model
|
||||
{
|
||||
protected $table = 'seo_metadata';
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return ['schema_data' => 'array', 'include_in_sitemap' => 'boolean', 'sitemap_priority' => 'decimal:1'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Seo\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
final class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
$this->routes(function (): void {
|
||||
Route::middleware('web')->group(module_path('Seo', 'Routes/web.php'));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Seo\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Modules\Seo\Support\ModuleInfo;
|
||||
|
||||
final class SeoServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
$this->mergeConfigFrom(module_path(ModuleInfo::name(), 'Config/config.php'), ModuleInfo::nameLower());
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadMigrationsFrom(module_path(ModuleInfo::name(), 'Database/Migrations'));
|
||||
$this->loadViewsFrom(module_path(ModuleInfo::name(), 'Resources/views'), ModuleInfo::nameLower());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<x-layouts.app :title="__('SEO')"><div class="max-w-3xl space-y-6"><div><h1 class="text-2xl font-semibold">SEO defaults</h1><p class="mt-1 text-sm text-zinc-500">Site-wide metadata used when content does not provide its own values.</p></div>@if(session('status'))<div class="rounded-xl bg-emerald-50 p-3 text-sm text-emerald-800">{{ session('status') }}</div>@endif<form method="POST" action="{{ route('administration.seo.update') }}" class="space-y-5 rounded-xl border border-zinc-200 bg-white p-6 dark:border-zinc-700 dark:bg-zinc-900">@csrf @method('PUT')<flux:input name="site_title" label="Site title" :value="old('site_title',$values['site_title']??'')"/><flux:textarea name="meta_description" label="Default meta description">{{ old('meta_description',$values['meta_description']??'') }}</flux:textarea><flux:input name="robots" label="Robots" :value="old('robots',$values['robots']??'index,follow')" required/><flux:input name="canonical_base" label="Canonical base URL" :value="old('canonical_base',$values['canonical_base']??'')"/><div class="flex justify-end"><flux:button type="submit" variant="primary">Save SEO defaults</flux:button></div></form></div></x-layouts.app>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Seo\Http\Controllers\SeoController;
|
||||
|
||||
Route::middleware(['auth', 'verified'])->prefix('administration/seo')->name('administration.seo.')->group(function (): void {
|
||||
Route::get('/', [SeoController::class, 'index'])->name('index');
|
||||
Route::put('/', [SeoController::class, 'update'])->name('update');
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Seo\Support;
|
||||
|
||||
final class ModuleInfo
|
||||
{
|
||||
public static function name(): string
|
||||
{
|
||||
return 'Seo';
|
||||
}
|
||||
|
||||
public static function nameLower(): string
|
||||
{
|
||||
return 'seo';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
it('boots the Seo module', function (): void {
|
||||
expect(config('seo.name'))->toBe('Seo');
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "absdev/seo-module",
|
||||
"description": "Seo foundation module for the ABSDEV Laravel application platform.",
|
||||
"type": "laravel-module",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Seo\\": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "Seo",
|
||||
"alias": "seo",
|
||||
"version": "1.0.0",
|
||||
"description": "Seo foundation module for the ABSDEV Laravel application platform.",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"modules",
|
||||
"seo"
|
||||
],
|
||||
"priority": 10,
|
||||
"providers": [
|
||||
"Modules\\Seo\\Providers\\SeoServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [],
|
||||
"requires": [
|
||||
"Core"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user