From Obese Mosquito, 4 Months ago, written in Plain Text.
- view diff
Embed
  1. <?php
  2.  
  3. namespace Collective\Remote;
  4.  
  5. use Closure;
  6. use Illuminate\Filesystem\Filesystem;
  7. use Symfony\Component\Console\Output\NullOutput;
  8. use Symfony\Component\Console\Output\OutputInterface;
  9.  
  10. class Connection implements ConnectionInterface
  11. {
  12.     /**
  13.      * The SSH gateway implementation.
  14.      *
  15.      * @var \Collective\Remote\GatewayInterface
  16.      */
  17.     protected $gateway;
  18.  
  19.     /**
  20.      * The name of the connection.
  21.      *
  22.      * @var string
  23.      */
  24.     protected $name;
  25.  
  26.     /**
  27.      * The host name of the server.
  28.      *
  29.      * @var string
  30.      */
  31.     protected $host;
  32.  
  33.     /**
  34.      * The username for the connection.
  35.      *
  36.      * @var string
  37.      */
  38.     protected $username;
  39.  
  40.     /**
  41.      * All of the defined tasks.
  42.      *
  43.      * @var array
  44.      */
  45.     protected $tasks = [];
  46.  
  47.     /**
  48.      * The output implementation for the connection.
  49.      *
  50.      * @var \Symfony\Component\Console\Output\OutputInterface
  51.      */
  52.     protected $output;
  53.  
  54.     /**
  55.      * Create a new SSH connection instance.
  56.      *
  57.      * @param string                              $name
  58.      * @param string                              $host
  59.      * @param string                              $username
  60.      * @param array                               $auth
  61.      * @param \Collective\Remote\GatewayInterface $gateway
  62.      * @param int                                 $timeout
  63.      */
  64.     public function __construct($name, $host, $username, array $auth, GatewayInterface $gateway = null, $timeout = 10)
  65.     {
  66.         $this->name = $name;
  67.         $this->host = $host;
  68.         $this->username = $username;
  69.         $this->gateway = $gateway ?: new SecLibGateway($host, $auth, new Filesystem(), $timeout);
  70.     }
  71.  
  72.     /**
  73.      * Define a set of commands as a task.
  74.      *
  75.      * @param string       $task
  76.      * @param string|array $commands
  77.      *
  78.      * @return void
  79.      */
  80.     public function define($task, $commands)
  81.     {
  82.         $this->tasks[$task] = $commands;
  83.  
  84.         return $this;
  85.     }
  86.  
  87.     /**
  88.      * Run a task against the connection.
  89.      *
  90.      * @param string   $task
  91.      * @param \Closure $callback
  92.      *
  93.      * @return void
  94.      */
  95.     public function task($task, Closure $callback = null)
  96.     {
  97.         if (isset($this->tasks[$task])) {
  98.             $this->run($this->tasks[$task], $callback);
  99.         }
  100.     }
  101.  
  102.     /**
  103.      * Run a set of commands against the connection.
  104.      *
  105.      * @param string|array $commands
  106.      * @param \Closure $callback
  107.      *
  108.      * @param int|null $timeout
  109.      * @return void
  110.      */
  111.     public function run($commands, Closure $callback = null, int $timeout = null)
  112.     {
  113.         // First, we will initialize the SSH gateway, and then format the commands so
  114.         // they can be run. Once we have the commands formatted and the server is
  115.         // ready to go we will just fire off these commands against the server.
  116.         $gateway = $this->getGateway();
  117.  
  118.         if ($timeout != null) {
  119.             $gateway->setTimeout($timeout);
  120.         }
  121.  
  122.         $callback = $this->getCallback($callback);
  123.  
  124.         $gateway->run($this->formatCommands($commands));
  125.  
  126.         // After running the commands against the server, we will continue to ask for
  127.         // the next line of output that is available, and write it them out using
  128.         // our callback. Once we hit the end of output, we'll bail out of here.
  129.         while (true) {
  130.             if (is_null($line = $gateway->nextLine())) {
  131.                 break;
  132.             }
  133.  
  134.             call_user_func($callback, $line, $this);
  135.         }
  136.     }
  137.  
  138.     /**
  139.      * Get the gateway implementation.
  140.      *
  141.      * @throws \RuntimeException
  142.      *
  143.      * @return \Collective\Remote\GatewayInterface
  144.      */
  145.     public function getGateway()
  146.     {
  147.         if (!$this->gateway->connected() && !$this->gateway->connect($this->username)) {
  148.             throw new \RuntimeException('Unable to connect to remote server.');
  149.         }
  150.  
  151.         return $this->gateway;
  152.     }
  153.  
  154.     /**
  155.      * Get the display callback for the connection.
  156.      *
  157.      * @param \Closure|null $callback
  158.      *
  159.      * @return \Closure
  160.      */
  161.     protected function getCallback($callback)
  162.     {
  163.         if (!is_null($callback)) {
  164.             return $callback;
  165.         }
  166.  
  167.         return function ($line) {
  168.             $this->display($line);
  169.         };
  170.     }
  171.  
  172.     /**
  173.      * Display the given line using the default output.
  174.      *
  175.      * @param string $line
  176.      *
  177.      * @return void
  178.      */
  179.     public function display($line)
  180.     {
  181.         $server = $this->username.'@'.$this->host;
  182.  
  183.         $lead = '<comment>['.$server.']</comment> <info>('.$this->name.')</info>';
  184.  
  185.         $this->getOutput()->writeln($lead.' '.$line);
  186.     }
  187.  
  188.     /**
  189.      * Get the output implementation for the connection.
  190.      *
  191.      * @return \Symfony\Component\Console\Output\OutputInterface
  192.      */
  193.     public function getOutput()
  194.     {
  195.         if (is_null($this->output)) {
  196.             $this->output = new NullOutput();
  197.         }
  198.  
  199.         return $this->output;
  200.     }
  201.  
  202.     /**
  203.      * Set the output implementation.
  204.      *
  205.      * @param \Symfony\Component\Console\Output\OutputInterface $output
  206.      *
  207.      * @return void
  208.      */
  209.     public function setOutput(OutputInterface $output)
  210.     {
  211.         $this->output = $output;
  212.     }
  213.  
  214.     /**
  215.      * Format the given command set.
  216.      *
  217.      * @param string|array $commands
  218.      *
  219.      * @return string
  220.      */
  221.     protected function formatCommands($commands)
  222.     {
  223.         return is_array($commands) ? implode(' && ', $commands) : $commands;
  224.     }
  225.  
  226.     /**
  227.      * Download the contents of a remote file.
  228.      *
  229.      * @param string $remote
  230.      * @param string $local
  231.      *
  232.      * @return void
  233.      */
  234.     public function get($remote, $local)
  235.     {
  236.         $this->getGateway()->get($remote, $local);
  237.     }
  238.  
  239.     /**
  240.      * Get the contents of a remote file.
  241.      *
  242.      * @param string $remote
  243.      *
  244.      * @return string
  245.      */
  246.     public function getString($remote)
  247.     {
  248.         return $this->getGateway()->getString($remote);
  249.     }
  250.  
  251.     /**
  252.      * Upload a local file to the server.
  253.      *
  254.      * @param string $local
  255.      * @param string $remote
  256.      *
  257.      * @return void
  258.      */
  259.     public function put($local, $remote)
  260.     {
  261.         $this->getGateway()->put($local, $remote);
  262.     }
  263.  
  264.     /**
  265.      * Upload a string to to the given file on the server.
  266.      *
  267.      * @param string $remote
  268.      * @param string $contents
  269.      *
  270.      * @return void
  271.      */
  272.     public function putString($remote, $contents)
  273.     {
  274.         $this->getGateway()->putString($remote, $contents);
  275.     }
  276.  
  277.     /**
  278.      * Check whether a given file exists on the server.
  279.      *
  280.      * @param string $remote
  281.      *
  282.      * @return bool
  283.      */
  284.     public function exists($remote)
  285.     {
  286.         return $this->getGateway()->exists($remote);
  287.     }
  288.  
  289.     /**
  290.      * Rename a remote file.
  291.      *
  292.      * @param string $remote
  293.      * @param string $newRemote
  294.      *
  295.      * @return bool
  296.      */
  297.     public function rename($remote, $newRemote)
  298.     {
  299.         return $this->getGateway()->rename($remote, $newRemote);
  300.     }
  301.  
  302.     /**
  303.      * Delete a remote file from the server.
  304.      *
  305.      * @param string $remote
  306.      *
  307.      * @return bool
  308.      */
  309.     public function delete($remote)
  310.     {
  311.         return $this->getGateway()->delete($remote);
  312.     }
  313.  
  314.     /**
  315.      * Get the exit status of the last command.
  316.      *
  317.      * @return int|bool
  318.      */
  319.     public function status()
  320.     {
  321.         return $this->gateway->status();
  322.     }
  323.  
  324.     public function setTimeout($timeout) {
  325.  
  326.         $this->getGateway()->setTimeout($timeout);
  327.  
  328.         return $this;
  329.     }
  330. }