      1: <?php
      2:
      3: /**
      4:  * A utility class controlling the build-in HTTP server in PHP
      5:  *
      6:  * @package alpha::util
      7:  * @since 1.2.2
      8:  * @author John Collins <dev@alphaframework.org>
      9:  * @version $Id: AlphaPHPServerUtils.inc 1671 2013-09-22 21:10:24Z alphadevx $
     10:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
     11:  * @copyright Copyright (c) 2013, John Collins (founder of Alpha Framework).
     12:  * All rights reserved.
     13:  *
     14:  * <pre>
     15:  * Redistribution and use in source and binary forms, with or
     16:  * without modification, are permitted provided that the
     17:  * following conditions are met:
     18:  *
     19:  * * Redistributions of source code must retain the above
     20:  *   copyright notice, this list of conditions and the
     21:  *   following disclaimer.
     22:  * * Redistributions in binary form must reproduce the above
     23:  *   copyright notice, this list of conditions and the
     24:  *   following disclaimer in the documentation and/or other
     25:  *   materials provided with the distribution.
     26:  * * Neither the name of the Alpha Framework nor the names
     27:  *   of its contributors may be used to endorse or promote
     28:  *   products derived from this software without specific
     29:  *   prior written permission.
     30:  *
     31:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     32:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     33:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     34:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     35:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     36:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     37:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     38:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     39:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     41:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     42:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     43:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     44:  * </pre>
     45:  *
     46:  */
     47: class AlphaPHPServerUtils {
     48:
     49:     /**
     50:      * Starts a new HTTP server at the hostname and port provided, and returns the process ID (PID) of
     51:      * the service if it was started successfully.
     52:      *
     53:      * @param string $host The hostname or IP address
     54:      * @param int $port The port number to use
     55:      * @param string $docRoot The file path to directory containing the documents we want to serve
     56:      * @return int The PID of the new server
     57:      * @throws AlphaException
     58:      */
     59:     public static function start($host, $port, $docRoot) {
     60:         // we are on Windows
     61:         if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
     62:             // Command that starts the built-in web server
     63:             $command = sprintf(
     64:                 'php -S %s:%d -t %s',
     65:                 $host,
     66:                 $port,
     67:                 $docRoot
     68:             );
     69:
     70:             $descriptorspec = array (
     71:                 0 => array("pipe", "r"),
     72:                 1 => array("pipe", "w"),
     73:             );
     74:
     75:             // Execute the command and store the process ID of the parent
     76:             $prog = proc_open($command, $descriptorspec, $pipes, '.', NULL);
     77:             $ppid = proc_get_status($prog)['pid'];
     78:
     79:             // this gets us the process ID of the child (i.e. the server we just started)
     80:             $output = array_filter(explode(" ", shell_exec("wmic process get parentprocessid,processid | find \"$ppid\"")));
     81:             array_pop($output);
     82:             $pid = end($output);
     83:         }else{ // we are on Linux
     84:             // Command that starts the built-in web server
     85:             $command = sprintf(
     86:                 'php -S %s:%d -t %s >/dev/null 2>&1 & echo $!',
     87:                 $host,
     88:                 $port,
     89:                 $docRoot
     90:             );
     91:
     92:             // Execute the command and store the process ID
     93:             $output = array();
     94:             exec($command, $output);
     95:             $pid = (int) $output[0];
     96:         }
     97:
     98:         if(!isset($pid))
     99:             throw new AlphaException("Could not start the build-in PHP server [$host:$port] using the doc root [$docRoot]");
    100:         else
    101:             return $pid;
    102:
    103:     }
    104:
    105:     /**
    106:      * Stops the server running locally under the process ID (PID) provided.
    107:      *
    108:      * @param int $PID The PID of the running server we want to stop
    109:      */
    110:     public static function stop($PID) {
    111:         // we are on Windows
    112:         if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    113:             exec("taskkill /F /pid $PID");
    114:         }else{ // we are on Linux
    115:             exec("kill -9 $PID");
    116:         }
    117:     }
    118:
    119:     /**
    120:      * CHecks to see if there is a server running locally under the process ID (PID) provided.
    121:      *
    122:      * @param int $PID The PID of the running server we want to check
    123:      * @return bool True if there is a server process running under the PID, false otherwise
    124:      */
    125:     public static function status($PID) {
    126:         $output = array();
    127:         // we are on Windows
    128:         if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    129:             exec("tasklist /fi \"PID eq $PID\"", $output);
    130:
    131:             if(isset($output[0]) && $output[0] == 'INFO: No tasks are running which match the specified criteria.')
    132:                 return false;
    133:             else
    134:                 return true;
    135:         }else{ // we are on Linux
    136:             exec("ps -ef | grep $PID | grep -v grep", $output);
    137:
    138:             if(count($output) == 0)
    139:                 return false;
    140:             else
    141:                 return true;
    142:         }
    143:     }
    144:
    145: }
    146:
    147: ?>