ohseesoftware/oh-see-gists

View on GitHub
src/Listeners/HandleContentSaving.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace OhSeeSoftware\OhSeeGists\Listeners;

use GrahamCampbell\GitHub\GitHubManager;
use Illuminate\Support\Facades\Log;
use Ramsey\Uuid\Uuid;
use Statamic\Events\EntrySaving;

class HandleContentSaving
{
    private $github;

    public function __construct(GitHubManager $github)
    {
        $this->github = $github;
    }

    public function handle(EntrySaving $event)
    {
        $githubToken = config('github.connections.main.token', null);
        if (empty($githubToken)) {
            return;
        }

        try {
            $data = $event->entry->data();
            $content = $data->get('content', []);
            $gistBlocks = $this->getGistBlocks($content);

            if (empty($gistBlocks)) {
                return;
            }

            $title = $data->get('title', 'Created by Oh See Gists add-on');
    
            $gistData = $this->buildGistData($gistBlocks, $title);
            $this->saveGist($gistData, $gistBlocks);
    
            $data->put('content', $content);
        } catch (\Throwable $e) {
            Log::error("Error saving gist blocks");
            Log::error($e);
        }
    }

    private function buildGistData(array &$gistBlocks, string $title): array
    {
        $gistData = [
            'public' => true,
            'description' => $title,
            'files' => [],
        ];

        foreach ($gistBlocks as &$gistBlock) {
            $extension = $gistBlock['extension'] ?? 'txt';
            
            $filename = $gistBlock['gist_filename'] ?? null;
            if (!$filename) {
                $filename = Uuid::uuid4() . '.' . $extension;
                $gistBlock['gist_filename'] = $filename;
            }

            $gistData['files'][$filename] = [
                'content' => $gistBlock['code']
            ];
        }

        return $gistData;
    }

    private function saveGist(array $gistData, array &$gistBlocks): void
    {
        if (empty($gistData['files'])) {
            return;
        }

        $gistId = $this->getGistIdFromBlocks($gistBlocks);

        if (empty($gistId)) {
            $response = $this->createGist($gistData);
        } else {
            $response = $this->updateGist($gistId, $gistData);
        }

        $this->updateGistIds($response['id'], $gistBlocks);
    }

    private function getGistIdFromBlocks(array $gistBlocks): ?string
    {
        foreach ($gistBlocks as &$gistBlock) {
            $gistBlockId = $gistBlock['gist_id'] ?? null;

            if ($gistBlockId) {
                return $gistBlockId;
            }
        }

        return null;
    }

    private function createGist(array $gistData): array
    {
        return $this->github->gists()->create($gistData);
    }

    private function updateGist(string $gistId, array $gistData): array
    {
        return $this->github->gists()->update($gistId, $gistData);
    }

    private function updateGistIds(string $gistId, array &$gistBlocks): void
    {
        foreach ($gistBlocks as &$gistBlock) {
            $gistBlock['gist_id'] = $gistId;
        }
    }

    private function getGistBlocks(array &$content): array
    {
        $gistBlocks = [];

        foreach ($content as &$block) {
            $type = $block['type'] ?? null;
            $setType = $block['attrs']['values']['type'] ?? null;

            if ($type !== 'set' || $setType !== 'gist_content') {
                continue;
            }

            $gistBlocks[] = &$block['attrs']['values'];
        }

        return $gistBlocks;
    }
}