CornyPhoenix/tex-tools

View on GitHub
src/Repositories/AbstractRepository.php

Summary

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

/*
 * 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\Repositories;

use CornyPhoenix\Tex\Exceptions\RepositoryException;
use CornyPhoenix\Tex\FileFormat;
use CornyPhoenix\Tex\Jobs\Job;

/**
 * An abstract implementation of the RepositoryInterface.
 *
 * @package CornyPhoenix\Tex\Repositories
 * @date 04.09.14
 * @author moellers
 */
abstract class AbstractRepository implements RepositoryInterface
{
    const TEMP_FILE_PREFIX = 'job';

    /**
     * The tree directory of the repository.
     *
     * @var string
     */
    private $directory;

    /**
     * The jobs contained by this repository.
     *
     * @var Job[]
     */
    private $jobs;

    /**
     * Creates an abstract repository object.
     *
     * @param string $directory
     * @throws \CornyPhoenix\Tex\Exceptions\RepositoryException
     */
    public function __construct($directory)
    {
        if (!is_dir($directory)) {
            throw $this->createInvalidRepositoryDirectoryException();
        }
        $this->directory = $directory;
        $this->jobs = [];
    }

    /**
     * Returns the tree directory of the repository.
     *
     * @return string
     */
    public function getDirectory()
    {
        return $this->directory;
    }

    /**
     * Creates a TeX Job by a TeX source.
     *
     * @param string $source
     * @return Job
     */
    public function createJob($source)
    {
        $format = FileFormat::TEX;
        $jobFile = $this->generateJobFile($format);
        file_put_contents($jobFile, $source);

        return $this->addJob($this->extractName($jobFile), $format);
    }

    /**
     * Finds an existing TeX Job by its name.
     *
     * @param string $name
     * @return Job
     */
    public function findJob($name)
    {
        return $this->jobs[$name];
    }

    /**
     * Returns true, if a given Job is contained.
     *
     * @param \CornyPhoenix\Tex\Jobs\Job $job
     * @return bool
     */
    public function containsJob(Job $job)
    {
        return isset($this->jobs[$job->getName()]);
    }

    /**
     * Cleans the repository and leaves only job input files.
     *
     * @return \CornyPhoenix\Tex\Jobs\Job[]
     */
    public function getJobs()
    {
        return $this->jobs;
    }

    /**
     * Finds the provided formats to a given job.
     *
     * @param \CornyPhoenix\Tex\Jobs\Job $job
     * @return string[]
     */
    public function findFormatsByJob(Job $job)
    {
        return array_map(
            function ($path) {
                return FileFormat::fromPath($path);
            },
            glob($this->directory . '/' . $job->getName() . '.*')
        );
    }

    /**
     * Returns true, if a given file is contained.
     *
     * @param string $filename
     * @return bool
     */
    public function containsFile($filename)
    {
        return is_file($this->directory . '/' . $filename);
    }

    /**
     * Cleans the repository and leaves only job input files.
     *
     * @return void
     */
    public function clean()
    {
        foreach ($this->jobs as $job) {
            $job->clean();
        }
    }

    /**
     * Returns true, if no Jobs are available.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return empty($this->jobs);
    }

    /**
     * Returns a string containing a contents blob.
     *
     * @param $filename
     * @return mixed
     */
    public function getFileBlob($filename)
    {
        return file_get_contents($this->getFilePath($filename));
    }

    /**
     * Returns the full file path of a repository file.
     *
     * @param $filename
     * @return string
     */
    public function getFilePath($filename)
    {
        return $this->directory . '/' . $filename;
    }

    /**
     * Adds a job to the repository.
     *
     * @param string $name
     * @param string $format
     * @return Job
     */
    protected function addJob($name, $format)
    {
        $job = new Job($this, $name, $format);
        $this->jobs[$name] = $job;

        return $job;
    }

    /**
     * Finds the Job name by an absolute file path.
     *
     * @param string $path
     * @return string
     */
    protected function extractName($path)
    {
        $directory = dirname($path);
        $format = FileFormat::fromPath($path);
        $directoryLength = strlen($directory);
        $formatLength = strlen($format);

        return substr($path, $directoryLength + 1, strlen($path) - $formatLength - $directoryLength - 2);
    }

    /**
     * Generates a file for a new TeX Job.
     *
     * @param string $format
     * @return string
     */
    private function generateJobFile($format)
    {
        do {
            $temp = tempnam($this->directory, self::TEMP_FILE_PREFIX);
            $tempExt = $temp . '.' . $format;
            unlink($temp);
        } while (file_exists($tempExt));

        touch($tempExt);
        return $tempExt;
    }

    /**
     * Creates an InvalidRepositoryDirectoryException.
     *
     * @return RepositoryException
     */
    private function createInvalidRepositoryDirectoryException()
    {
        return new RepositoryException('The directory you specified for this repository is invalid.');
    }
}