PHP code example of giorgigrdzelidze / laravel-stringer

1. Go to this page and download the library: Download giorgigrdzelidze/laravel-stringer library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

giorgigrdzelidze / laravel-stringer example snippets


// 3. Bind two adapters in any service provider
$this->app->bind(\Stringer\Laravel\Contracts\ContentTarget::class, ArticleTarget::class);
$this->app->bind(\Stringer\Laravel\Contracts\ContextBuilder::class, PublicContextBuilder::class);

// 4. Register the Filament plugin
->plugin(\Stringer\Laravel\Filament\StringerPlugin::make())

// app/Models/Article.php
public function registerMediaConversions(?Media $media = null): void
{
    $this->addMediaConversion('og')->fit(Fit::Crop, 1200, 630)->performOnCollections('cover');
    $this->addMediaConversion('twitter')->fit(Fit::Crop, 1200, 675)->performOnCollections('cover');
    $this->addMediaConversion('thumb')->fit(Fit::Crop, 400, 225)->performOnCollections('cover');
}

$article->getFirstMediaUrl('cover');            // 1792x1024 master
$article->getFirstMediaUrl('cover', 'og');      // 1200x630
$article->getFirstMediaUrl('cover', 'twitter'); // 1200x675
$article->getFirstMediaUrl('cover', 'thumb');   // 400x225

// app/Providers/Filament/AdminPanelProvider.php
use Stringer\Laravel\Filament\StringerPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(StringerPlugin::make());
}

// app/Stringer/Adapters/ArticleTarget.php

use App\Models\Article;
use App\Models\ArticleCategory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Spatie\Tags\Tag;
use Stringer\Laravel\Contracts\ContentTarget;
use Stringer\Laravel\DataObjects\LocalizedDraft;
use Stringer\Laravel\Enums\FieldType;
use Stringer\Laravel\Models\BlogTopic;
use Stringer\Laravel\Models\StringerContentField;

final class ArticleTarget implements ContentTarget
{
    public function __construct(
        private readonly Article $articles,
        private readonly ArticleCategory $categories,
    ) {}

    public function write(LocalizedDraft $draft, ?BlogTopic $topic = null): Article
    {
        $article = $this->articles->newInstance();
        $fields = StringerContentField::query()->where('is_active', true)->get()->keyBy('name');
        $pendingTags = [];

        foreach ($draft->fields as $name => $value) {
            $field = $fields->get($name);
            if (! $field) { continue; }

            match ($field->type) {
                FieldType::TranslatableString => $article->setTranslations($name, is_array($value) ? $value : []),
                FieldType::TranslatableMarkdown => $article->setTranslations(
                    $name,
                    is_array($value) ? array_map(fn ($v) => is_string($v) ? (string) Str::markdown($v) : $v, $value) : [],
                ),
                FieldType::Markdown => $article->{$name} = is_string($value) ? (string) Str::markdown($value) : $value,
                FieldType::TagList => $pendingTags[$name] = $value,
                FieldType::Category => $this->assignCategory($article, $value),
                FieldType::Integer => $article->{$name} = (int) $value,
                default => $article->{$name} = $value,
            };
        }

        // G1: per-topic auto-publish opt-in. Default writes a draft.
        $article->status = $topic?->target_status ?? 'draft';
        $article->publish_at = ($topic && $topic->auto_publish) ? now() : null;

        $article->save();
        foreach ($pendingTags as $tagValue) { $this->syncTags($article, $tagValue); }

        return $article;
    }

    public function editUrl(Model $record): string
    {
        return \App\Filament\Resources\ArticleResource::getUrl('edit', ['record' => $record]);
    }

    public function attachCover(Model $record, \Stringer\Laravel\DataObjects\GeneratedImage $image): void
    {
        if (! $record instanceof Article) {
            return;
        }

        $record
            ->addMediaFromString($image->bytes)
            ->usingFileName('cover-'.$record->getKey().'.'.$image->extension())
            ->withCustomProperties([
                'generator' => $image->sourceDriver,
                'prompt' => $image->prompt,
                'attribution' => $image->attribution,
            ])
            ->toMediaCollection('cover');
    }
}

// app/Stringer/Adapters/PublicContextBuilder.php

use App\Models\{Article, ArticleCategory, Project, Repository};
use Stringer\Laravel\Contracts\ContextBuilder;

final class PublicContextBuilder implements ContextBuilder
{
    public function __construct(
        private readonly Article $articles,
        private readonly Project $projects,
        private readonly Repository $repositories,
        private readonly ArticleCategory $categories,
    ) {}

    public function build(): array
    {
        return [
            'articles' => /* recent published articles, projected to {title, excerpt} */,
            'projects' => /* recent visible projects */,
            'repositories' => /* recent visible repositories */,
            'categories' => /* all categories, projected to {name, slug, description} */,
        ];
    }
}

$this->app->bind(\Stringer\Laravel\Contracts\ContentTarget::class, ArticleTarget::class);
$this->app->bind(\Stringer\Laravel\Contracts\ContextBuilder::class, PublicContextBuilder::class);
bash
# 1. Install
composer rtisan db:seed --class="Stringer\Laravel\Database\Seeders\StringerDefaultPromptsSeeder"
php artisan db:seed --class="Stringer\Laravel\Database\Seeders\StringerDefaultContentFieldsSeeder"
bash
# 5. Trigger your first draft
php artisan queue:work &
php artisan tinker --execute="\$t = app(Stringer\Laravel\Services\TopicQueue::class)->enqueue('write about laravel queue retries', Stringer\Laravel\Enums\TopicSource::Manual); Stringer\Laravel\Jobs\GenerateDraftJob::dispatch(\$t->id);"
bash
php artisan db:seed --class="Stringer\Laravel\Database\Seeders\StringerDefaultPromptsSeeder"
php artisan db:seed --class="Stringer\Laravel\Database\Seeders\StringerDefaultContentFieldsSeeder"
bash
php artisan stringer:images:backfill                          # everything eligible
php artisan stringer:images:backfill --driver=unsplash         # one-off driver override
php artisan stringer:images:backfill --limit=10                # cap the batch
php artisan stringer:images:backfill --sync                    # run inline, no queue