translation/laravel

View on GitHub
src/Service/SourceEditSync.php

Summary

Maintainability
A
3 hrs
Test Coverage
D
67%
<?php

namespace Tio\Laravel\Service;

use Tio\Laravel\SourceSaver;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;

class SourceEditSync
{
    private $config;

    /**
     * @var Application
     */
    private $application;
    /**
     * @var Filesystem
     */
    private $filesystem;
    /**
     * @var SourceSaver
     */
    private $sourceSaver;

    public function __construct(
        Application $application,
        Filesystem $filesystem,
        SourceSaver $sourceSaver
    ) {
        $this->config = $application['config']['translation'];
        $this->application = $application;
        $this->filesystem = $filesystem;
        $this->sourceSaver = $sourceSaver;
    }

    public function call($command)
    {
        $client = new Client(['base_uri' => $this->url() ]);
        $body = $this->createBody($command);
        $responseData = $this->makeRequest($client, $body, $command);

        foreach ($responseData['source_edits'] as $sourceEdit) {
            $this->sourceSaver->call(
                $sourceEdit,
                $this->sourceLocale()
            );
        }

        $this->updateMetadataTimestamp();
    }

    private function createBody($command)
    {
        $locale = $this->sourceLocale();

        $formData = [
            'client' => 'laravel',
            'version' => '1.23',
            'timestamp' => $this->metadataTimestamp($command),
            'source_language' => $locale
        ];

        $body = http_build_query($formData);

        foreach ($this->targetLocales() as $locale) {
            $body = $body . "&target_languages[]=$locale";
        }

        return $body;
    }

    private function makeRequest($client, $body, $command)
    {
        try {
            $response = $client->request(
                'POST', '', [
                'headers' => [
                    'Content-Type' => 'application/x-www-form-urlencoded'
                ],
                'body' => $body
                ]
            );

            return json_decode($response->getBody()->getContents(), true);
        } catch (RequestException $e) {
            if ($e->hasResponse()) {
                $responseData = json_decode($e->getResponse()->getBody()->getContents(), true);
                $this->displayErrorAndExit($responseData['error'], $command);
            }
            else {
                $this->displayErrorAndExit($e->getMessage(), $command);
            }
        }
    }

    private function sourceLocale()
    {
        return $this->config['source_locale'];
    }

    private function targetLocales()
    {
        return $this->config['target_locales'];
    }

    private function url()
    {
        return 'https://translation.io/api/projects/' . $this->config['key'] . '/source_edits';
    }

    private function metadataFilePath()
    {
        return $this->application['path.lang'] . DIRECTORY_SEPARATOR . '.translation_io';
    }

    private function metadataTimestamp($command)
    {
        $metadataFilePath = $this->metadataFilePath();

        if ($this->filesystem->exists($metadataFilePath)) {
            $metadataContent = $this->filesystem->get($metadataFilePath);

            return $this->timestampFromMetadataContent($metadataContent, $command);
        }
        else {
            return 0;
        }
    }

    private function timestampFromMetadataContent($metadataContent, $command)
    {
        $this->displayMetadataErrorAndExit($metadataContent, $command);

        $json = json_decode($metadataContent, true);

        if (is_null($json)) {
            return 0;
        }
        else {
            return $json['timestamp'];
        }
    }

    private function displayMetadataErrorAndExit($metadataContent, $command)
    {
        if (Str::contains($metadataContent, ['>>>>', '<<<<'])) {
            $metadataFilePath = $this->metadataFilePath();

            $command->line("----------");
            $command->error("Error: " . $metadataFilePath . " file seems to have unresolved versioning conflicts. Please fix them and try again.");
            $command->line("----------");

            exit(1);
        }
    }

    private function updateMetadataTimestamp()
    {
        $data = json_encode([ "timestamp" => Carbon::now()->timestamp ]);
        $metadataFilePath = $this->metadataFilePath();

        $this->filesystem->put($metadataFilePath, $data);
    }

    private function displayErrorAndExit($error, $command)
    {
        $command->line("----------");
        $command->error("Error: {$error}");
        $command->line("----------");

        throw new \Exception($error);
    }
}