* Drag-and-drop section ordering with automatic saving.
* Add existing reusable documents to regions.
* Remove placements without deleting documents.
* Create independent page-specific copies.
* Shared-document usage warnings.
* Document creation, duplication, deletion protection and filtering.
* Draft and published document states.
* Document and placement scheduling.
* Authenticated homepage preview.
* Draft sections displayed in preview with a clear draft marker.
* Content Composer added to the administration sidebar.
* Public rendering now respects:
* Publication status
* Future publication dates
* Expiry dates
* Placement start and end dates
* Enabled state
* Original Saasland homepage remains as the fallback when no composition exists.
65 lines
6.2 KiB
PHP
65 lines
6.2 KiB
PHP
<?php
|
|
namespace Modules\Content\Console;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Modules\Content\Models\ContentDocument;
|
|
use Modules\Content\Models\ContentType;
|
|
use Modules\Content\Models\PageContent;
|
|
|
|
final class InstallSaaslandContent extends Command
|
|
{
|
|
protected $signature = 'content:install-saasland {--force : Replace the existing home composition}';
|
|
protected $description = 'Install editable Saasland header, body and footer content documents.';
|
|
|
|
public function handle(): int
|
|
{
|
|
$requiredTables = ['content_types', 'content_documents', 'page_content'];
|
|
$missingTables = array_values(array_filter(
|
|
$requiredTables,
|
|
static fn (string $table): bool => ! Schema::hasTable($table),
|
|
));
|
|
|
|
if ($missingTables !== []) {
|
|
$this->components->error('Content composition tables are missing: '.implode(', ', $missingTables).'.');
|
|
$this->components->info('Run php artisan migrate before installing the Saasland composition.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
DB::transaction(function (): void {
|
|
if ($this->option('force')) PageContent::query()->where('page_key','home')->delete();
|
|
$definitions = $this->definitions();
|
|
$order = ['site-header'=>['header',10], 'hero'=>['body',10], 'feature-grid'=>['body',20], 'product-feed'=>['body',30], 'testimonial-feed'=>['body',40], 'team-feed'=>['body',50], 'blog-feed'=>['body',60], 'news-feed'=>['body',70], 'faq-feed'=>['body',80], 'newsletter-form'=>['body',90], 'call-to-action'=>['body',100], 'site-footer'=>['footer',10]];
|
|
foreach ($definitions as $key => $definition) {
|
|
$type = ContentType::query()->updateOrCreate(['key'=>$key], $definition['type']);
|
|
$document = ContentDocument::query()->updateOrCreate(['slug'=>'saasland-'.$key], ['content_type_id'=>$type->id,'title'=>$definition['title'],'data'=>$definition['data'],'status'=>'published','published_at'=>now()]);
|
|
[$region,$sort] = $order[$key];
|
|
PageContent::query()->updateOrCreate(['page_key'=>'home','region'=>$region,'sort_order'=>$sort], ['content_document_id'=>$document->id,'is_enabled'=>true]);
|
|
}
|
|
});
|
|
$this->components->info('Saasland content composition installed.');
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function definitions(): array
|
|
{
|
|
$type = fn(string $name,string $renderer,array $regions) => ['name'=>$name,'renderer'=>$renderer,'allowed_regions'=>$regions,'is_system'=>true,'is_active'=>true,'schema'=>[]];
|
|
return [
|
|
'site-header'=>['title'=>'Main website header','type'=>$type('Site header','site-header',['header']),'data'=>['show_login'=>true,'show_registration'=>true,'sticky'=>true]],
|
|
'hero'=>['title'=>'Homepage hero','type'=>$type('Hero','hero',['body']),'data'=>['eyebrow'=>'A better way to run your business','heading'=>'Transform Your Business With Our SaaS Solution','description'=>'Streamline operations, boost productivity, and improve customer satisfaction with one connected platform built for modern teams.','primary_label'=>'Get started free','primary_url'=>'/register','secondary_label'=>'Book demo','secondary_url'=>'#contact','show_metrics'=>true]],
|
|
'feature-grid'=>['title'=>'Core features','type'=>$type('Feature grid','feature-grid',['body']),'data'=>['eyebrow'=>'Powerful features','heading'=>'Everything your team needs to grow','description'=>'Planning, collaboration, reporting, publishing, commerce and customer insight in one extensible platform.','items'=>[['title'=>'Smart automation','description'=>'Remove repetitive work and delays.'],['title'=>'Real-time analytics','description'=>'Turn activity into useful business insight.'],['title'=>'Content operations','description'=>'Create, review and publish confidently.'],['title'=>'Secure by design','description'=>'Protect users and data with dependable controls.'],['title'=>'Flexible integrations','description'=>'Connect the tools your organisation already uses.'],['title'=>'Modular architecture','description'=>'Activate only the capabilities each site needs.']]]],
|
|
'product-feed'=>['title'=>'Pricing plans','type'=>$type('Product feed','product-feed',['body']),'data'=>['eyebrow'=>'Simple pricing','heading'=>'Choose a plan that fits','description'=>'Plans are managed from Products & Pricing in the CMS.','limit'=>6]],
|
|
'testimonial-feed'=>['title'=>'Customer stories','type'=>$type('Testimonial feed','testimonial-feed',['body']),'data'=>['eyebrow'=>'Customer stories','heading'=>'Trusted by ambitious teams','limit'=>6]],
|
|
'team-feed'=>['title'=>'Team','type'=>$type('Team feed','team-feed',['body']),'data'=>['eyebrow'=>'Our team','heading'=>'People behind the platform','limit'=>8]],
|
|
'blog-feed'=>['title'=>'Latest blog posts','type'=>$type('Blog feed','blog-feed',['body']),'data'=>['eyebrow'=>'Insights','heading'=>'Latest from the blog','limit'=>3]],
|
|
'news-feed'=>['title'=>'Latest news','type'=>$type('News feed','news-feed',['body']),'data'=>['eyebrow'=>'Newsroom','heading'=>'Latest news','limit'=>3]],
|
|
'faq-feed'=>['title'=>'Frequently asked questions','type'=>$type('FAQ feed','faq-feed',['body']),'data'=>['eyebrow'=>'FAQ','heading'=>'Answers before you begin','limit'=>12]],
|
|
'newsletter-form'=>['title'=>'Newsletter signup','type'=>$type('Newsletter form','newsletter-form',['body']),'data'=>['eyebrow'=>'Newsletter','heading'=>'Useful updates, no noise','description'=>'Receive product news, publishing guidance, and practical platform updates.','button_label'=>'Subscribe']],
|
|
'call-to-action'=>['title'=>'Homepage final call to action','type'=>$type('Call to action','call-to-action',['body']),'data'=>['heading'=>'Ready to transform your business?','description'=>'Start building a faster, more connected operation today.','button_label'=>'Get started free','button_url'=>'/register']],
|
|
'site-footer'=>['title'=>'Main website footer','type'=>$type('Site footer','site-footer',['footer']),'data'=>['description'=>'One connected platform for modern teams.','show_social_links'=>true,'show_back_to_top'=>true]],
|
|
];
|
|
}
|
|
}
|