CornyPhoenix/tex-tools

View on GitHub
src/JobProcessBuilder.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php /** File containing class JobProcessBuilder */

/*
 * This file is part of the TeX Tools for PHP component.
 *
 * (c) Konstantin S. M. Möllers <ksm.moellers@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CornyPhoenix\Tex;

use CornyPhoenix\Tex\Executables\ExecutableInterface;
use CornyPhoenix\Tex\Jobs\Job;
use Symfony\Component\Process\ProcessBuilder;

/**
 * ProcessBuilder for TeX Jobs.
 *
 * @package CornyPhoenix\Tex
 */
class JobProcessBuilder extends ProcessBuilder
{
    const OPTION_JOBNAME = 'jobname';
    const OPTION_INTERACTION_MODE = 'interaction';
    const OPTION_SYNC_TEX = 'synctex';
    const OPTION_OUTPUT_FORMAT = 'output-format';
    const OPTION_OUTPUT_DIRECTORY = 'output-directory';
    const OPTION_SHELL_ESCAPE = 'shell-escape';
    const OPTION_NO_SHELL_ESCAPE = 'no-shell-escape';
    const OPTION_DRAFT_MODE = 'draftmode';

    /**
     * The executable operating this process builder.
     *
     * @var ExecutableInterface
     */
    private $executable;

    /**
     * Creates a new TeX Job Process Builder.
     *
     * @param Executables\ExecutableInterface $executable
     */
    public function __construct(ExecutableInterface $executable)
    {
        parent::__construct();

        // Set application to execute
        $this->setExecutable($executable);
    }

    /**
     * Sets the processed TeX Job.
     *
     * @param Job $job
     * @return $this
     */
    public function setJob(Job $job)
    {
        // Clear the job
        $this->clearArguments();

        // Set values
        $this->setArgumentValue(self::OPTION_JOBNAME, $job->getJobname());
        $this->setArgumentValue(self::OPTION_INTERACTION_MODE, $job->getInteractionMode());
        $this->setArgumentValue(self::OPTION_SYNC_TEX, $job->getSyncTex());
        $this->setArgumentValue(self::OPTION_OUTPUT_DIRECTORY, $job->getOutputDirectory());

        // Set bool arguments
        $this->setArgumentBool(self::OPTION_SHELL_ESCAPE, $job->isShellEscape());
        $this->setArgumentBool(self::OPTION_NO_SHELL_ESCAPE, !$job->isShellEscape());
        $this->setArgumentBool(self::OPTION_DRAFT_MODE, $job->isDraftMode());

        $this->setOutputFormat();

        // Set input file
        $this->setInputFile($job);
        $this->setTexInputSources($job);

        return $this;
    }

    /**
     * Returns the executable operating this process builder.
     *
     * @return ExecutableInterface
     */
    public function getExecutable()
    {
        return $this->executable;
    }

    /**
     * Sets the executable operating this process builder.
     *
     * @param ExecutableInterface $executable
     * @return $this
     */
    public function setExecutable(ExecutableInterface $executable)
    {
        $this->executable = $executable;
        $this->setPrefix($executable->getPath());

        return $this;
    }

    /**
     * Sets the output format argument.
     *
     * @return $this
     */
    private function setOutputFormat()
    {
        if (in_array($this->executable->getOutputFormats(), [FileFormat::PDF, FileFormat::DVI])) {
            $this->setArgumentValue(self::OPTION_OUTPUT_FORMAT, $this->executable->getOutputFormats());
        }

        return $this;
    }

    /**
     * Sets the environment variables to support additional tex inputs.
     *
     * @return $this
     */
    private function setTexInputSources(Job $job)
    {
        if (empty($job->getAdditionalTexInputs())) {
            return;
        }

        // All source directories are separated by colon. The last empty value references the default sources.
        $sources = implode(':', array_merge($job->getAdditionalTexInputs(), ['']));

        $this->addEnvironmentVariables([
            'TEXINPUTS' => $sources,
            'TTFONTS' => $sources,
            'OPENTYPEFONTS' => $sources,
        ]);

        return $this;
    }

    /**
     * Sets the input file processed.
     *
     * @param Job $job
     */
    private function setInputFile(Job $job)
    {
        $this->setWorkingDirectory($job->getDirectory());
        $this->add($job->getName() . '.' . $this->executable->getInputFormat());
    }

    /**
     * Sets an option in the arguments, like <pre>--$option=$value</pre>
     * If <code>$value</code> is <code>null</code>, no option will be added.
     *
     * @param string $option
     * @param mixed|null $value
     * @return JobProcessBuilder
     */
    private function setArgumentValue($option, $value)
    {
        if (null !== $value) {
            $this->add(sprintf('%s%s=%s', $this->executable->getOptionPrefix(), $option, strval($value)));
        }
        return $this;
    }

    /**
     * Sets a an bool option in the arguments, like <pre>--$option</pre>.
     *
     * @param string $option
     * @param bool $bool
     * @return JobProcessBuilder
     */
    private function setArgumentBool($option, $bool)
    {
        if ($bool) {
            $this->add(sprintf('%s%s', $this->executable->getOptionPrefix(), $option));
        }
        return $this;
    }

    /**
     * Clears all arguments. The prefix remains.
     */
    private function clearArguments()
    {
        $this->setArguments(array());
    }
}