Skip to content
Snippets Groups Projects
process.php 2.17 KiB
Newer Older
Pavel Piligrimov's avatar
Pavel Piligrimov committed
<?php

namespace Mail\Mjml\Mjml\Process;

use Mail\Mjml\Exception\ProcessException;

/**
 * Подготовка и запуск рендера шаблона
 */
class Process
{
    private $sCommand;
    private $sInput;
    private $sOutput;
    private $sErrorMessage = '';

    public const STDIN = 0;
    public const STDOUT = 1;
    public const STDERR = 2;

    private static $aDescriptors = [
        self::STDIN => ['pipe', 'r'],
        self::STDOUT => ['pipe', 'w'],
        self::STDERR => ['pipe', 'w']
    ];

    public function __construct(string $command, string $input)
    {
        $this->sCommand = $command;
        $this->sInput   = $input;
    }

    /**
     * @throws ProcessException
     */
    public function run(): void
    {
        $this->initialize();

        $pipes = [];
        $process = $this->createProcess($pipes);

        $this->setInput($pipes);
        $this->setOutput($pipes);
        $this->setErrorMessage($pipes);

        if (0 !== proc_close($process)) {
            throw new ProcessException($this->sErrorMessage);
        }
    }

    public function getOutput()
    {
        return $this->sOutput;
    }

    private function initialize(): void
    {
        $this->sOutput       = null;
        $this->sErrorMessage = '';
    }

    /**
     * @return resource
     * 
     * @throws ProcessException
     */
    private function createProcess(array &$pipes)
    {
        $process = proc_open($this->sCommand, self::$aDescriptors, $pipes);

        if (!is_resource($process)) {
            throw new ProcessException('Unable to create a process.');
        }

        return $process;
    }

    private function setInput(array $pipes): void
    {
        $stdin = $pipes[self::STDIN];
        fwrite($stdin, $this->sInput);
        fclose($stdin);
    }

    private function setOutput(array $pipes): void
    {
        $stdout        = $pipes[self::STDOUT];
        $this->sOutput = stream_get_contents($stdout);
        fclose($stdout);
    }

    private function setErrorMessage(array $pipes): void
    {
        $stderr              = $pipes[self::STDERR];
        $this->sErrorMessage = stream_get_contents($stderr);
        fclose($stderr);
    }
}