atelierspierrot/library

View on GitHub
src/Library/Command.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php
/**
 * This file is part of the Library package.
 *
 * Copyleft (ↄ) 2013-2016 Pierre Cassat <me@e-piwi.fr> and contributors
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * The source code of this package is available online at 
 * <http://github.com/atelierspierrot/library>.
 */

namespace Library;

use \Library\CommandNotFoundException;

/**
 * Largely inspired from <http://github.com/kbjr/Git.php>
 *
 * @author  piwi <me@e-piwi.fr>
 */
class Command
{

// ---------------------
// Cache Management
// ---------------------

    protected $cache = array();
    
    public function addCache($command, $result, $error, $status = 0, $cwd = null, $env = null, $options = null)
    {
        $this->cache[] = array(
            'command'   =>$command,
            'cwd'       =>$cwd,
            'env'       =>$env,
            'options'   =>$options,
            'result'    =>$result,
            'error'     =>$error,
            'status'    =>$status,
        );
    }

    public function isCached($command, $cwd = null)
    {
        foreach ($this->cache as $i=>$cache) {
            if ($cache['command']===$command) {
                if (is_null($cwd)) {
                    return $i;
                } elseif ($cache['cwd']===$cwd) {
                    return $i;
                }
            }
        }
        return false;
    }

    public function getCached($command, $cwd = null)
    {
        $i = $this->isCached($command, $cwd);
        return (false!==$i ? $this->cache[$i] : null);
    }

    public function getCache()
    {
        return $this->cache;
    }

// ---------------------
// Process
// ---------------------

    /**
     * Run a command on a Linux/UNIX system reading it from cache if so
     *
     * @param string $command The command to run
     * @param string $path The path to go to
     * @param bool $force Force the command to really run (avoid caching)
     * @return array An array like ( stdout , status , stderr )
     */
    public function run($command, $path = null, $force = false)
    {
        if (true!==$force && $this->isCached($command, $path)) {
            $cached = $this->getCached($command, $path);
            return array($cached['result'], $cached['status'], $cached['error']);
        }
        return $this->runCommand($command, $path);
    }
    
    /**
     * Run a command on a Linux/UNIX system
     *
     * Accepts a shell command to run
     *
     * @param string $command The command to run
     * @param string $path The path to go to
     * @return array An array like ( stdout , status , stderr )
     */
    public function runCommand($command, $path = null)
    {
        $descriptorspec = array(
            1 => array('pipe', 'w'),
            2 => array('pipe', 'a'),
        );
        $pipes = array();
        $resource = proc_open($command, $descriptorspec, $pipes, $path);

        $stdout = stream_get_contents($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        foreach ($pipes as $pipe) {
            fclose($pipe);
        }

        $status = trim(proc_close($resource));
        $stdout = rtrim($stdout, PHP_EOL);
        $this->addCache($command, $stdout, $stderr, $status, $path);
        return array( $stdout, $status, $stderr );
    }

    /**
     * Get the system path of a command
     *
     * @param string $cmd The command name to retrieve
     * @return string The realpath of the command in the system
     * @throws \Library\CommandNotFoundException if the command doesn't exist
     */
    public static function getCommandPath($cmd)
    {
        $os_cmd = exec('which '.$cmd);
        if (empty($os_cmd)) {
            throw new CommandNotFoundException($cmd);
        }
        return $os_cmd;
    }
    
}