[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\n    \"es2017\",\n    \"es2016\",\n    \"es2015\"\n  ]\n}"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nend_of_line = lf\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\n.idea\n*.tgz\n"
  },
  {
    "path": ".npmignore",
    "content": "node_modules/\n.idea\n.gitignore\n*.sh\n*.xml\n.babelrc\n.editorconfig\n*.tgz\n*.txz"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Micah Blu\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# gulp-connect-php\n\n***REQUIRES NODE 4 OR GREATER***\n\n> Start a [PHP-server](http://php.net/manual/en/features.commandline.webserver.php)\n\nThis is pretty much a gulp version of [@sindresorhus's](https://github.com/sindresorhus) [grunt-php](https://github.com/sindresorhus/grunt-php) and acts as a _basic version_ drop-in replacement for [gulp-connect](https://www.npmjs.com/package/gulp-connect), though please note not all features from gulp-connect are supported with gulp-connect-php. I am open to supporting other features and pull requests that implement them.\n\nUses the built-in server in PHP 5.4.0+.\n\n## Install\n\n```sh\n$ npm install --save-dev gulp-connect-php\n```\n\n## Usage\n\n### As a Singleton\n```js\nvar gulp = require('gulp'),\n    connect = require('gulp-connect-php');\n\ngulp.task('connect', function() {\n\tconnect.server();\n});\n\ngulp.task('default', ['connect']);\n```\n\n### As an Instance\n```js\nvar gulp = require('gulp'),\n    connect = require('gulp-connect-php');\n\nlet server = new connect();\n\ngulp.task('connect', function() {\n\tserver.server();\n});\ngulp.task('disconnect', function() {\n\tserver.closeServer();\n});\n\ngulp.task('default', ['connect', 'disconnect']);\n```\n\n## Examples\n\n### Use it with Browser Sync\n\n```js\nvar gulp = require('gulp'),\n    connect = require('gulp-connect-php'),\n    browserSync = require('browser-sync');\n\ngulp.task('connect-sync', function() {\n  connect.server({}, function (){\n    browserSync({\n      proxy: '127.0.0.1:8000'\n    });\n  });\n\n  gulp.watch('**/*.php').on('change', function () {\n    browserSync.reload();\n  });\n});\n```\n\n### Advanced Option Manipulation\n\n```js\ngulp.task('connect', function() {\n  connect.server({\n    configCallback: function _configCallback(type, collection) {\n      // If you wish to leave one of the argument types alone, simply return the passed in collection.\n      if (type === connect.OPTIONS_SPAWN_OBJ) { // As the constant suggests, collection is an Object.\n\n        // Lets add a custom env var. Good for injecting AWS_RDS config variables.\n        collection.env = Object.assign({\n          MY_CUSTOM_ENV_VAR: \"env_var_value\"\n        }, process.env);\n\n        return collection;\n      } else if (type === connect.OPTIONS_PHP_CLI_ARR) { // As the constant suggests, collection is an Array.\n        let newArgs = [\n          '-e',                     // Generate extended information for debugger/profiler.\n          '-d', 'memory_limit=2G'   // Define INI entry, Up memory limit to 2G.\n        ];\n\n        // Ensure our argument switches appear before the rest.\n        return newArgs.concat(collection);\n      }\n    }\n  }, function _connected_callback() {\n    console.log(\"PHP Development Server Connected.\");\n  });\n});\n\ngulp.task('disconnect', function() {\n\tconnect.closeServer();\n});\n\ngulp.task('default', ['connect', 'disconnect']);\n```\n\n### Windows (via Batch file)\n\nWindows Batch file execution via a `%PATH%` specified batchfile is possible, but some considerations are required.\n\n1. The batch file must be on your `%PATH%` and executable with permissions of the invoker.\n2. You must pass the parameter set off to the PHP process.\n3. We have no -real- way of detecting an error state at this point.\n4. You must use the 'Advanced Option Maniulation' scheme and set the `shell` option on `spawn(...)`.\n\n#### Scenario\n\n- PHP is located at `C:\\Users\\mainuser\\Applications\\PHP\\7.0.17-NTS-VC14\\php.exe`.\n- The batch file is located at `C:\\Users\\mainuser\\MyProject\\strap\\php.bat`.\n- I have set `%PATH%` manually to `C:\\Users\\mainuser\\MyProject\\strap\\;%PATH%`.\n\n#### Contents of php.bat\n\n```batch\n@echo off\n\nREM We specify the whole path to PHP since the working directory is that of gulp...\nREM unless we also changed that in our gulp callback.\n\nC:\\Users\\mainuser\\Applications\\PHP\\7.0.17-NTS-VC14\\php.exe %*\n```\n\n#### Contents of our gulp task\n```js\ngulp.task('connect', function _gulp_connect_task() {\n  connect.server({\n    configCallback: function _configCallback(type, collection) {\n      if (type === connect.OPTIONS_SPAWN_OBJ) {\n        // Windows Batch files are NOT executable on their own. This will start a shell\n        // session then execute.\n        collection.shell = true;\n        return collection;\n      }\n    }\n  }, function _connected_callback() {\n    console.log(\"PHP Development Server Connected.\");\n  });\n});\n\ngulp.task('default', ['connect']);\n````\n\n## Options\n\n### port\n\nType: `number`  \nDefault: `8000`\n\nThe port on which you want to access the webserver. Task will fail if the port is already in use.\n\n### hostname\n\nType: `string`  \nDefault: `'127.0.0.1'` *(usually same as `localhost`)*\n\nThe hostname the webserver will use.\n\nUse `0.0.0.0` if you want it to be accessible from the outside.\n\n### base\n\nType: `string`  \nDefault: `'.'`\n\nFrom which folder the webserver will be served. Defaults to the directory of the gulpfile.\n\n### open\n\nType: `boolean`  \nDefault: `false`\n\nOpen the server in the browser when the task is triggered.\n\n### router\n\nType: `string`  \n\nOptionally specify the path to a [router script](http://php.net/manual/en/features.commandline.webserver.php#example-380) that is run at the start of each HTTP request. If this script returns `false`, then the requested resource is returned as-is. Otherwise the script's output is returned to the browser.\n\nExample router script:\n\n```php\n<?php\n// router.php\nif (preg_match('/\\.(?:png|jpg|jpeg|gif)$/', $_SERVER[\"REQUEST_URI\"])) {\n\treturn false;    // serve the requested resource as-is\n} else {\n\techo \"<p>Thanks for using gulp-connect-php :)</p>\";\n}\n?>\n```\n\n### bin\n\nType: `string`  \nDefault: `'php'`\n\nPath to the PHP binary. Useful if you have multiple versions of PHP installed.\n\n### ini\n\nType: `string`  \nDefault: Built-in `php.ini`\n\nPath to a custom [`php.ini`](http://php.net/manual/en/ini.php) config file.\n\n### stdio\n\nType: `string`  \nDefault: `'inherit'`\n\nNode's [stdio parameter](https://nodejs.org/api/child_process.html#child_process_options_stdio), set it to `'ignore'` to suppress all the logging into console of the php server process.\n\n### configCallback\n\nType: `function (type, collection) : collection`  \n\nPrototype:\n\n  - `type` - String, either `OPTIONS_SPAWN_OBJ` or `OPTIONS_PHP_CLI_ARR`.\n  - `collection` - Array or Object, the initial version of the collection specified by `type`.\n\n     Return: Optionally modified version of `collection`.\n\nDefault: `'null'` (Which is replaced with a no-op call that returns an unmodified version of the `collection` parameter)\n\nAllows the caller to modify the `spawn` [options](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) object and or the [PHP command line arguments](http://php.net/manual/en/features.commandline.options.php) (array) before the [PHP development server](http://php.net/manual/en/features.commandline.webserver.php) is invoked.\n\n### debug\n\nType: `boolean`\nDefault: `'false'`\n\nEnables debugging of the spawn call and its parameters.\n\n## Building\n\nThis package comes with a NPM run-script command called `prepack`. This is intended to be run before the packaging and pushing to NPM, however it is also what builds the Node 4.X compatibility script `index-compat.js`. Without it the default `package.json` will not execute properly.\n\n## License\n\nMIT © [Micah Blu](http://micahblu.net)\n"
  },
  {
    "path": "convert.sh",
    "content": "#!/usr/bin/env bash\n\n# set -x # verbose debugging\n\nIN_FILE='index.js'\nOUT_FILE='index-compat.js'\nBABEL_PATH='./node_modules/babel-cli/bin/babel.js'\n\n# Get script location, resolve if a link.\nexport SCRIPT_ROOT_ENV_SOURCE=\"${BASH_SOURCE[0]}\"\nwhile [ -h \"$SCRIPT_ROOT_ENV_SOURCE\" ]; do\n  export SCRIPT_ROOT_DIR=\"$( cd -P \"$( dirname \"$SCRIPT_ROOT_ENV_SOURCE\" )\" && pwd )\"\n  export SCRIPT_ROOT_ENV_SOURCE=\"$(readlink \"$SCRIPT_ROOT_ENV_SOURCE\")\"\n  [[ ${SCRIPT_ROOT_ENV_SOURCE} != /* ]] && SCRIPT_ROOT_ENV_SOURCE=\"$SCRIPT_ROOT_DIR/$SCRIPT_ROOT_ENV_SOURCE\"\ndone\nexport SCRIPT_ROOT_DIR=\"$( cd -P \"$( dirname \"$SCRIPT_ROOT_ENV_SOURCE\" )\" && pwd )\"\n\npushd \"$SCRIPT_ROOT_DIR\" || { echo 'Could not enter primary directory.' ; exit 1; }\n\nif [ ! -f \"$BABEL_PATH\" ]; then\n    npm i || { echo 'NPM Installation Failed.' ; exit 1; }\nfi\n\necho \"/* The following JavaScript file was preprocessed from $IN_FILE via Babel for support on older Node installations. */\" > \"$OUT_FILE.tmp\"\n\"$BABEL_PATH\" \"$IN_FILE\" --presets es2017,es2016,es2015 | sed '1d' >> \"$OUT_FILE.tmp\"  || { echo 'Babel Processing Failed.' ;  rm \"$OUT_FILE.tmp\"; exit 1; }\nmv \"$OUT_FILE.tmp\" \"$OUT_FILE\"\n\npopd || { echo 'Could not return from primary directory.' ; exit 1; }\n"
  },
  {
    "path": "examples/browser-sync/gulpfile.js",
    "content": "/* jshint esversion: 6, node: true */\n'use strict';\n\nconst gulp = require('gulp'),\n  connect = require('../../index.js'),\n  browserSync = require('browser-sync');\n\ngulp.task('connect-sync', function () {\n  connect.server({}, function () {\n    browserSync({\n      proxy: 'localhost:8000'\n    });\n  });\n\n  gulp.watch('**/*.php').on('change', function () {\n    browserSync.reload();\n  });\n});\n"
  },
  {
    "path": "examples/browser-sync/index.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>Browser Sync Example</title>\n</head>\n<body>\n\t<?php echo \"hello PHP world! :)\"; ?>\n</body>\n</html>"
  },
  {
    "path": "examples/browser-sync/package.json",
    "content": "{\n  \"name\": \"browser-sync-test\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"gulpfile.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"browser-sync\": \"^1.9.1\",\n    \"gulp\": \"^3.8.10\"\n  }\n}\n"
  },
  {
    "path": "examples/browser-sync-02/gulpfile.js",
    "content": "/* jshint esversion: 6, node: true */\n'use strict';\n\nconst gulp = require('gulp'),\n  connect = require('../../index.js'),\n  browserSync = require('browser-sync');\n\n\n//task that fires up php server at port 8001\ngulp.task('connect', function (callback) {\n  connect.server({\n    port: 8001\n  }, callback);\n});\n\n\n//task that fires up browserSync proxy after connect server has started\ngulp.task('browser-sync', ['connect'], function () {\n  browserSync({\n    proxy: '127.0.0.1:8001',\n    port: 8910\n  });\n});\n\n\n//default task that runs task browser-sync ones and then watches php files to change. If they change browserSync is reloaded\ngulp.task('default', ['browser-sync'], function () {\n  gulp.watch(['**/*.php'], browserSync.reload);\n});"
  },
  {
    "path": "examples/browser-sync-02/index.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>Browser Sync Example 02</title>\n</head>\n<body>\n\t<p><?php echo \"hello PHP world :)\"; ?></p>\n\n\t<a href=\"link.php\">Link to next page</a>\n\t\n</body>\n</html>"
  },
  {
    "path": "examples/browser-sync-02/link.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>Browser Sync Example 02</title>\n</head>\n<body>\n\t<p><?php echo \"Hopefuly we are still at browserSync proxy port 8910:))\"; ?></p>\n\n\t<a href=\"index.php\">Link to previous page</a>\n\t\n</body>\n</html>"
  },
  {
    "path": "examples/browser-sync-02/package.json",
    "content": "{\n  \"name\": \"browser-sync-test\",\n  \"version\": \"1.0.1\",\n  \"description\": \"\",\n  \"main\": \"gulpfile.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"browser-sync\": \"^2.0.0-rc9\",\n    \"gulp\": \"^3.8.10\"\n  }\n}\n"
  },
  {
    "path": "examples/simple/gulpfile.js",
    "content": "/* jshint esversion: 6, node: true */\n'use strict';\n\nconst gulp = require('gulp'),\n  connect = require('../../index.js');\n\ngulp.task('connect', function () {\n  connect.server({}, function () {\n    // connected\n  });\n});\n\ngulp.task('default', ['connect']);\n"
  },
  {
    "path": "examples/simple/index.php",
    "content": "<?php echo \"hello world :)\"; ?>"
  },
  {
    "path": "examples/simple-with-argument-manipulation/gulpfile.js",
    "content": "/* jshint esversion: 6, node: true */\n'use strict';\n\nconst gulp = require('gulp'),\n  connect = require('../../index.js');\n\ngulp.task('connect', function _gulp_connect_task() {\n  connect.server({\n    configCallback: function _configCallback(type, collection) {\n      // If you wish to leave one of the argument types alone, simply return the passed in collection.\n      if (type === connect.OPTIONS_SPAWN_OBJ) { // As the constant suggests, collection is an Object.\n\n        // Lets add a custom env var. Good for injecting AWS_RDS config variables.\n        collection.env = Object.assign({\n          MY_CUSTOM_ENV_VAR: \"env_var_value\"\n        }, process.env);\n\n        return collection;\n      } else if (type === connect.OPTIONS_PHP_CLI_ARR) { // As the constant suggests, collection is an Array.\n        let newArgs = [\n          '-e',                     // Generate extended information for debugger/profiler.\n          '-d', 'memory_limit=2G'   // Define INI entry, Up memory limit to 2G.\n        ];\n\n        // Ensure our argument switches appear before the rest.\n        return newArgs.concat(collection);\n      }\n    }\n  }, function _connected_callback() {\n    console.log(\"PHP Development Server Connected.\");\n  });\n});\n\ngulp.task('default', ['connect']);\n"
  },
  {
    "path": "examples/simple-with-argument-manipulation/index.php",
    "content": "<?php\nphpinfo();\n?>\n"
  },
  {
    "path": "formatting.idea.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!-- This is an IDEA/JetBrains Code Scheme File for use with PhpStorm, WebStorm and IntelliJ -->\n<code_scheme name=\"gulp-connect-php\">\n  <option name=\"OTHER_INDENT_OPTIONS\">\n    <value>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"8\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n      <option name=\"USE_TAB_CHARACTER\" value=\"false\" />\n      <option name=\"SMART_TABS\" value=\"false\" />\n      <option name=\"LABEL_INDENT_SIZE\" value=\"0\" />\n      <option name=\"LABEL_INDENT_ABSOLUTE\" value=\"false\" />\n      <option name=\"USE_RELATIVE_INDENTS\" value=\"false\" />\n    </value>\n  </option>\n  <option name=\"FORMATTER_TAGS_ENABLED\" value=\"true\" />\n  <MarkdownNavigatorCodeStyleSettings>\n    <option name=\"RIGHT_MARGIN\" value=\"72\" />\n  </MarkdownNavigatorCodeStyleSettings>\n  <PHPCodeStyleSettings>\n    <option name=\"ALIGN_PHPDOC_PARAM_NAMES\" value=\"true\" />\n    <option name=\"CONCAT_SPACES\" value=\"false\" />\n    <option name=\"LOWER_CASE_BOOLEAN_CONST\" value=\"true\" />\n    <option name=\"LOWER_CASE_NULL_CONST\" value=\"true\" />\n    <option name=\"VARIABLE_NAMING_STYLE\" value=\"CAMEL_CASE\" />\n  </PHPCodeStyleSettings>\n  <codeStyleSettings language=\"Blade\">\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"CSS\">\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"Gherkin\">\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"HTML\">\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"Haml\">\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"JSON\">\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"2\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"JavaScript\">\n    <option name=\"KEEP_SIMPLE_BLOCKS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_METHODS_IN_ONE_LINE\" value=\"true\" />\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"2\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"LESS\">\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"PHP\">\n    <option name=\"CLASS_BRACE_STYLE\" value=\"1\" />\n    <option name=\"METHOD_BRACE_STYLE\" value=\"1\" />\n  </codeStyleSettings>\n  <codeStyleSettings language=\"SASS\">\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"SCSS\">\n    <indentOptions>\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"Twig\">\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"TypeScript\">\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n  <codeStyleSettings language=\"XML\">\n    <indentOptions>\n      <option name=\"INDENT_SIZE\" value=\"2\" />\n      <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      <option name=\"TAB_SIZE\" value=\"2\" />\n    </indentOptions>\n  </codeStyleSettings>\n</code_scheme>\n"
  },
  {
    "path": "index-compat.js",
    "content": "/* The following JavaScript file was preprocessed from index.js via Babel for support on older Node installations. */\n'use strict';\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n(function _gulp_connect_php_module_scoping(OPTIONS_SPAWN_OBJ, OPTIONS_PHP_CLI_ARR) {\n  var childProcess = require('child_process');\n  var spawn = childProcess.spawn;\n  var exec = childProcess.exec;\n  var http = require('http');\n  var open = require('opn');\n  var binVersionCheck = require('bin-version-check');\n  var fs = require('fs');\n\n  //let counter = 0;\n\n  function EnumSet() {\n    var _this = this;\n\n    [].concat(Array.prototype.slice.call(arguments)).forEach(function (x) {\n      _this[x] = Symbol(x);\n    });\n  }\n\n  var PhpDevelopmentServerConnection = function _PhpDevelopmentServerConnection_private_scope() {\n    var Status = new EnumSet('NEW', 'STARTING', 'STARTED', 'FINISHED');\n\n    /**\n     * Private: Check wherther the server is running.\n     * @param hostname\n     * @param port\n     * @param cb\n     */\n    function checkServer(hostname, port, cb) {\n      var self = this;\n      //console.log(`[${this.counter}] checkServer`);\n\n      if (self.status !== Status.STARTING) return;\n\n      setTimeout(function _checkServer_fire() {\n        http.request({\n          method: 'HEAD',\n          hostname: hostname,\n          port: port\n        }, function _checkServer_httpCallback(res) {\n          var statusCodeType = Number(res.statusCode.toString()[0]);\n\n          if ([2, 3, 4].indexOf(statusCodeType) !== -1) {\n            return cb(true);\n          } else if (statusCodeType === 5) {\n            console.log('Server docroot returned 500-level response. Please check ' + 'your configuration for possible errors.');\n            return cb(true);\n          }\n\n          checkServer.call(self, hostname, port, cb);\n        }).on('error', function _checkServer_httpError(err) {\n          // back off after 1s\n          if (++self.checkServerTries > 20) {\n            console.log('PHP server not started. Retrying...');\n            return cb(false);\n          }\n          checkServer.call(self, hostname, port, cb);\n        }).end();\n      }, 15);\n    }\n\n    /**\n     * PHP Development Server Connection Instance\n     *\n     * {@link http://php.net/manual/en/features.commandline.webserver.php}\n     */\n\n    var PhpDevelopmentServerConnection = function () {\n      /**\n       * Create a new Instance\n       * @param opts Default Options. Will be merged with our own internal set of default options. Can be overwridden in the connect ('server') call.\n       * @returns {PhpDevelopmentServerConnection}\n       */\n      function PhpDevelopmentServerConnection(opts) {\n        _classCallCheck(this, PhpDevelopmentServerConnection);\n\n        //this.counter = ++counter;\n        //console.log(`[${this.counter}] constructor`);\n\n        this.status = Status.NEW;\n\n        this.checkServerTries = 0;\n\n        this.workingPort = 8000;\n\n        this.defaults = Object.assign({\n          port: 8000,\n          hostname: '127.0.0.1',\n          base: '.',\n          open: false,\n          bin: 'php',\n          root: '/',\n          stdio: 'inherit',\n          configCallback: null,\n          debug: false\n        }, opts || {});\n\n        return this; // `new` bug\n      }\n\n      /**\n       * 'Close'/Shutdown the PHP Development Server\n       * @param cb Optional single parameter Callback. Parameter is the return (if any) of the node `ChildProcess.kill(...)` call or nothing if not started.\n       */\n\n\n      _createClass(PhpDevelopmentServerConnection, [{\n        key: 'closeServer',\n        value: function closeServer(cb) {\n          cb = cb || function _closeServerCb_noop() {};\n          //console.log(`[${this.counter}] closeServer`);\n          var self = this;\n          if (this.loading) {\n            setTimeout(function () {\n              return self.closeServer(cb);\n            }, 5);\n            return;\n          }\n\n          if (this.childProcess) {\n            cb(this.childProcess.kill('SIGKILL'));\n            this.status = Status.FINISHED;\n            return;\n          }\n\n          cb();\n        }\n\n        /**\n         * Get the port the server is running on.\n         * @returns {number|*} Port number.\n         */\n\n      }, {\n        key: 'server',\n\n\n        /**\n         * Start the Server\n         * @param options Optional Server Options to overwrite the defaults in the CTor.\n         * @param cb Optional Callback for Completion. May pass in an error when there is a fault.\n         */\n        value: function server(options, cb) {\n          //console.log(`[${this.counter}] server`);\n          cb = cb || function _serverCB_noop() {};\n\n          var self = this;\n\n          if (this.status !== Status.NEW && this.status !== Status.FINISHED) {\n            return cb(new Error('You may not start a server that is starting or started.'));\n          }\n\n          options = Object.assign({}, this.defaults, options);\n\n          this.workingPort = options.port;\n          var host = options.hostname + ':' + options.port;\n          var args = ['-S', host, '-t', options.base];\n\n          if (options.ini) {\n            args.push('-c', options.ini);\n          }\n\n          if (options.router) {\n            args.push(require('path').resolve(options.router));\n          }\n\n          if (options.debug) {\n            spawn = function _debugSpawn(outerSpawn) {\n              return function debugSpawnWrapper(file, args, options) {\n                console.log('Invoking Spawn with:');\n                console.log(file);\n                console.log(args);\n                console.log(options);\n\n                return outerSpawn(file, args, options);\n              };\n            }(spawn);\n          }\n\n          if (options.configCallback === null || options.configCallback === undefined) {\n            options.configCallback = function noOpConfigCallback(type, collection) {\n              return collection;\n            };\n          }\n\n          spawn = function _configCallbackSpawn(outerSpawn) {\n            return function configCallbackSpawnWrapper(file, spawnArgs, spawnOptions) {\n              return outerSpawn(file, options.configCallback(OPTIONS_PHP_CLI_ARR, spawnArgs) || spawnArgs, options.configCallback(OPTIONS_SPAWN_OBJ, spawnOptions) || spawnOptions);\n            };\n          }(spawn);\n\n          binVersionCheck('\"' + options.bin + '\"', '>=5.4', function _binVerCheck(err) {\n            if (err) {\n              cb(err);\n              return;\n            }\n            var checkPath = function _checkPath() {\n              var exists = fs.existsSync(options.base);\n              if (exists === true) {\n                self.status = Status.STARTING;\n                self.childProcess = spawn(options.bin, args, {\n                  cwd: '.',\n                  stdio: options.stdio\n                });\n              } else {\n                setTimeout(checkPath, 100);\n              }\n            };\n            checkPath();\n            // check when the server is ready. tried doing it by listening\n            // to the child process `data` event, but it's not triggered...\n            checkServer.call(self, options.hostname, options.port, function _server_checkServer() {\n              self.status = Status.STARTED;\n              if (options.open) {\n                open('http://' + host + options.root);\n              }\n              cb();\n            }.bind(this));\n          }.bind(this));\n        }\n      }, {\n        key: 'port',\n        get: function get() {\n          return this.workingPort;\n        }\n      }]);\n\n      return PhpDevelopmentServerConnection;\n    }();\n\n    return PhpDevelopmentServerConnection;\n  }();\n\n  module.exports = function _export_scoping() {\n\n    var returnStructure = PhpDevelopmentServerConnection;\n\n    var adopterBinder = function adopterBinder(adopter, inst, method) {\n      return adopter[method] = inst[method].bind(inst);\n    };\n\n    returnStructure.compat = function _naught_version_compatibility() {\n      // This is segregated beacuse in the future around v1.5 we will make it emit a warning.\n      // In v2.0 we will gut it completely.\n      var inst = new PhpDevelopmentServerConnection();\n      inst.OPTIONS_SPAWN_OBJ = OPTIONS_SPAWN_OBJ;\n      inst.OPTIONS_PHP_CLI_ARR = OPTIONS_PHP_CLI_ARR;\n      return inst;\n    }();\n\n    // You cannot actually bind a function to a method directly... so... lets manually bind to get a function that calls the right instance.\n    adopterBinder(returnStructure, returnStructure.compat, 'server');\n    adopterBinder(returnStructure, returnStructure.compat, 'closeServer');\n\n    returnStructure.OPTIONS_SPAWN_OBJ = OPTIONS_SPAWN_OBJ;\n    returnStructure.OPTIONS_PHP_CLI_ARR = OPTIONS_PHP_CLI_ARR;\n\n    return returnStructure;\n  }();\n})('spawn', 'php_args');\n\n"
  },
  {
    "path": "index.js",
    "content": "/* jshint esversion: 6, node: true */\n'use strict';\n\n(function _gulp_connect_php_module_scoping(OPTIONS_SPAWN_OBJ, OPTIONS_PHP_CLI_ARR) {\n  const childProcess = require('child_process');\n  let spawn = childProcess.spawn;\n  const exec = childProcess.exec;\n  const http = require('http');\n  const open = require('opn');\n  const binVersionCheck = require('bin-version-check');\n  const fs = require('fs');\n\n  //let counter = 0;\n\n  function EnumSet() {\n    [...arguments].forEach((x) => { this[x] = Symbol(x) });\n  }\n\n  const PhpDevelopmentServerConnection = ((function _PhpDevelopmentServerConnection_private_scope() {\n    const Status = new EnumSet('NEW', 'STARTING', 'STARTED', 'FINISHED');\n\n    /**\n     * Private: Check wherther the server is running.\n     * @param hostname\n     * @param port\n     * @param cb\n     */\n    function checkServer(hostname, port, cb) {\n      const self = this;\n      //console.log(`[${this.counter}] checkServer`);\n\n      if (self.status !== Status.STARTING) return;\n\n      setTimeout(function _checkServer_fire() {\n        http.request({\n          method: 'HEAD',\n          hostname: hostname,\n          port: port\n        }, function _checkServer_httpCallback(res) {\n          const statusCodeType = Number(res.statusCode.toString()[0]);\n\n          if ([2, 3, 4].indexOf(statusCodeType) !== -1) {\n            return cb(true);\n          } else if (statusCodeType === 5) {\n            console.log(\n              'Server docroot returned 500-level response. Please check ' +\n              'your configuration for possible errors.'\n            );\n            return cb(true);\n          }\n\n          checkServer.call(self, hostname, port, cb);\n        }).on('error', function _checkServer_httpError(err) {\n          // back off after 1s\n          if (++self.checkServerTries > 20) {\n            console.log('PHP server not started. Retrying...');\n            return cb(false);\n          }\n          checkServer.call(self, hostname, port, cb);\n        }).end();\n      }, 15);\n    }\n\n    /**\n     * PHP Development Server Connection Instance\n     *\n     * {@link http://php.net/manual/en/features.commandline.webserver.php}\n     */\n    class PhpDevelopmentServerConnection {\n      /**\n       * Create a new Instance\n       * @param opts Default Options. Will be merged with our own internal set of default options. Can be overwridden in the connect ('server') call.\n       * @returns {PhpDevelopmentServerConnection}\n       */\n      constructor(opts) {\n        //this.counter = ++counter;\n        //console.log(`[${this.counter}] constructor`);\n\n        this.status = Status.NEW;\n\n        this.checkServerTries = 0;\n\n        this.workingPort = 8000;\n\n        this.defaults = Object.assign({\n          port: 8000,\n          hostname: '127.0.0.1',\n          base: '.',\n          open: false,\n          bin: 'php',\n          root: '/',\n          stdio: 'inherit',\n          configCallback: null,\n          debug: false\n        }, opts || {});\n\n        return this; // `new` bug\n      }\n\n      /**\n       * 'Close'/Shutdown the PHP Development Server\n       * @param cb Optional single parameter Callback. Parameter is the return (if any) of the node `ChildProcess.kill(...)` call or nothing if not started.\n       */\n      closeServer(cb) {\n        cb = cb || function _closeServerCb_noop() { };\n        //console.log(`[${this.counter}] closeServer`);\n        const self = this;\n        if (this.loading) {\n          setTimeout(() => self.closeServer(cb), 5);\n          return;\n        }\n\n        if (this.childProcess) {\n          cb(this.childProcess.kill('SIGKILL'));\n          this.status = Status.FINISHED;\n          return;\n        }\n\n        cb();\n      }\n\n      /**\n       * Get the port the server is running on.\n       * @returns {number|*} Port number.\n       */\n      get port() { return this.workingPort; }\n\n      /**\n       * Start the Server\n       * @param options Optional Server Options to overwrite the defaults in the CTor.\n       * @param cb Optional Callback for Completion. May pass in an error when there is a fault.\n       */\n      server(options, cb) {\n        //console.log(`[${this.counter}] server`);\n        cb = cb || function _serverCB_noop() { };\n\n        const self = this;\n\n        if (this.status !== Status.NEW && this.status !== Status.FINISHED) {\n          return cb(new Error('You may not start a server that is starting or started.'));\n        }\n\n        options = Object.assign({}, this.defaults, options);\n\n        this.workingPort = options.port;\n        const host = options.hostname + ':' + options.port;\n        const args = ['-S', host, '-t', options.base];\n\n        if (options.ini) {\n          args.push('-c', options.ini);\n        }\n\n        if (options.router) {\n          args.push(require('path').resolve(options.router));\n        }\n\n        if (options.debug) {\n          spawn = function _debugSpawn(outerSpawn) {\n            return function debugSpawnWrapper(file, args, options) {\n              console.log('Invoking Spawn with:');\n              console.log(file);\n              console.log(args);\n              console.log(options);\n\n              return outerSpawn(file, args, options);\n            }\n          }(spawn);\n        }\n\n        if (options.configCallback === null || options.configCallback === undefined) {\n          options.configCallback = function noOpConfigCallback(type, collection) {\n            return collection;\n          }\n        }\n\n        spawn = function _configCallbackSpawn(outerSpawn) {\n          return function configCallbackSpawnWrapper(file, spawnArgs, spawnOptions) {\n            return outerSpawn(file, options.configCallback(OPTIONS_PHP_CLI_ARR, spawnArgs) || spawnArgs, options.configCallback(OPTIONS_SPAWN_OBJ, spawnOptions) || spawnOptions);\n          }\n        }(spawn);\n\n        binVersionCheck(`\"${options.bin}\"`, '>=5.4', function _binVerCheck(err) {\n          if (err) {\n            cb(err);\n            return;\n          }\n          const checkPath = function _checkPath() {\n            const exists = fs.existsSync(options.base);\n            if (exists === true) {\n              self.status = Status.STARTING;\n              self.childProcess = spawn(options.bin, args, {\n                cwd: '.',\n                stdio: options.stdio\n              });\n            }\n            else {\n              setTimeout(checkPath, 100);\n            }\n          };\n          checkPath();\n          // check when the server is ready. tried doing it by listening\n          // to the child process `data` event, but it's not triggered...\n          checkServer.call(self, options.hostname, options.port, function _server_checkServer() {\n            self.status = Status.STARTED;\n            if (options.open) {\n              open('http://' + host + options.root);\n            }\n            cb();\n          }.bind(this));\n        }.bind(this));\n      };\n    }\n\n    return PhpDevelopmentServerConnection;\n  }))();\n\n  module.exports = (function _export_scoping() {\n\n    let returnStructure = PhpDevelopmentServerConnection;\n\n    const adopterBinder = (adopter, inst, method) => adopter[method] = inst[method].bind(inst);\n\n    returnStructure.compat = (function _naught_version_compatibility() {\n      // This is segregated beacuse in the future around v1.5 we will make it emit a warning.\n      // In v2.0 we will gut it completely.\n      const inst = new PhpDevelopmentServerConnection;\n      inst.OPTIONS_SPAWN_OBJ = OPTIONS_SPAWN_OBJ;\n      inst.OPTIONS_PHP_CLI_ARR = OPTIONS_PHP_CLI_ARR;\n      return inst;\n    })();\n\n    // You cannot actually bind a function to a method directly... so... lets manually bind to get a function that calls the right instance.\n    adopterBinder(returnStructure, returnStructure.compat, 'server');\n    adopterBinder(returnStructure, returnStructure.compat, 'closeServer');\n\n    returnStructure.OPTIONS_SPAWN_OBJ = OPTIONS_SPAWN_OBJ;\n    returnStructure.OPTIONS_PHP_CLI_ARR = OPTIONS_PHP_CLI_ARR;\n\n    return returnStructure;\n  })();\n})('spawn', 'php_args');\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"gulp-connect-php\",\n  \"version\": \"1.0.3\",\n  \"description\": \"Starts a php server\",\n  \"main\": \"index-compat.js\",\n  \"scripts\": {\n    \"__anchor\": \"cd .\",\n    \"test-compat\": \"npm run __anchor; mocha ./test\",\n    \"test-normative\": \"npm run __anchor; GCP_ES6=1 mocha ./test\",\n    \"test\": \"npm run test-normative; npm run test-compat\",\n    \"prepack\": \"npm run __anchor; ./convert.sh\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/micahblu/gulp-connect-php\"\n  },\n  \"keywords\": [\n    \"gulp\",\n    \"php\",\n    \"server\",\n    \"connect\"\n  ],\n  \"author\": \"micahblu\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/micahblu/gulp-php/issues\"\n  },\n  \"dependencies\": {\n    \"bin-version-check\": \"^2.1.0\",\n    \"opn\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"babel-cli\": \"^6.24.1\",\n    \"babel-preset-es2015\": \"^6.24.1\",\n    \"babel-preset-es2016\": \"^6.24.1\",\n    \"babel-preset-es2017\": \"^6.24.1\",\n    \"mocha\": \"^3.2.0\",\n    \"supertest\": \"^3.0.0\"\n  }\n}\n"
  },
  {
    "path": "test/fixtures/config-cb-checker.php",
    "content": "ENVVAR=<?php echo getenv('TEST_ENV_VAR'); ?>,MEM_LIMIT=<?php echo ini_get('memory_limit'); ?>;"
  },
  {
    "path": "test/fixtures/hello.php",
    "content": "<?php echo \"hello world\"; ?>\n"
  },
  {
    "path": "test/fixtures/index.php",
    "content": "<?php echo \"I am the root\"; ?>"
  },
  {
    "path": "test/test.js",
    "content": "/* jshint esversion: 6, node: true */\n'use strict';\n\nrequire(\"mocha\");\n\nconst testJSMain = process.env['GCP_ES6'] ? \"../index.js\" : \"../index-compat.js\";\n\nconsole.log(\"Testing against primary => \", testJSMain);\n\nconst request = require(\"supertest\"),\n  connect = require(testJSMain);\n\n/*\n - Anonymous Functions in the Test Suite should have internal names. This makes failure traces easier to read.\n - For Simplicities sake, please avoid 'Arrow'-Functions (Lambda-like Constructs) and Opt for Anonymous Functions...\n Like the first point, this makes failure traces simpler to read.\n - Suites should be grouped by IIFE.\n */\n\nconst noop = function _noop() { };\nconst noopReturn = function _noopReturn(x) { return x; };\n\ndescribe('gulp-connect-php', function _base_suite1() {\n\n  it('Should start a basic php server', function _test_basic(done) {\n    connect.server({port: 8001}, function _basic_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8001')\n        .get('/test/fixtures/hello.php')\n        .expect(/hello world/)\n        .expect(200)\n        .end(function _basic_endEvent(err, res) {\n          if (err) return done(err);\n          connect.closeServer(function _basic_closeServer() {\n            done();\n          });\n        });\n    });\n  });\n\n  it('Should start a set of basic php servers', function _test_multiples(done) {\n    let doneCounter = 0;\n\n    const tickDone = function _tickDone(x) {\n      ++doneCounter === 2 ? done(x) : noopReturn(x)\n    };\n\n    const conn1 = new connect();\n    const conn2 = new connect();\n\n    conn1.server({port: 8002}, function _multiples1_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8002')\n        .get('/test/fixtures/hello.php')\n        .expect(/hello world/)\n        .expect(200)\n        .end(function _multiples1_endEvent(err, res) {\n          if (err) return done(err);\n          conn1.closeServer(function _multiples1_closeServer() {\n            tickDone();\n          });\n        });\n    });\n\n    conn2.server({port: 8003}, function _multiples2_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8003')\n        .get('/test/fixtures/hello.php')\n        .expect(/hello world/)\n        .expect(200)\n        .end(function _multiples2_endEvent(err, res) {\n          if (err) return done(err);\n          conn2.closeServer(function _multiples2_closeServer() {\n            tickDone();\n          });\n        });\n    });\n  });\n\n  it('Should start a basic php server, with a set environment variable and updated memory limits set via the configCallback option', function _test_configCallback(done) {\n    connect.server({\n      port: 8004,\n      configCallback: function _configCallback(type, collection) {\n        if (type === connect.OPTIONS_SPAWN_OBJ) {\n          collection.env = Object.assign({\n            TEST_ENV_VAR: \"SET_OK\"\n          }, process.env);\n\n          return collection;\n        } else if (type === connect.OPTIONS_PHP_CLI_ARR) {\n          let newArgs = [\n            '-d', 'memory_limit=2.1G'\n          ];\n          return newArgs.concat(collection);\n        }\n      }\n    }, function _configCallback_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8004')\n        .get('/test/fixtures/config-cb-checker.php')\n        .expect(/ENVVAR=SET_OK,MEM_LIMIT=2\\.1G;/)\n        .expect(200)\n        .end(function _configCallback_endEvent(err, res) {\n          if (err) return done(err);\n          connect.closeServer(function _configCallback_closeServer() {\n            done();\n          });\n        });\n    });\n  });\n\n  it('Should start a basic php server without a close callback', function _test_basicNoCloseCB(done) {\n    connect.server({port: 8005}, function _basicNoCloseCB_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8005')\n        .get('/test/fixtures/hello.php')\n        .expect(/hello world/)\n        .expect(200)\n        .end(function _basicNoCloseCB_endEvent(err, res) {\n          if (err) return done(err);\n          connect.closeServer();\n          setTimeout(done, 150);\n        });\n    });\n  });\n\n  it('Should start a basic php server, with a set environment variable and updated memory limits set via the configCallback option with null', function _test_configCallback(done) {\n    connect.server({\n      port: 8006,\n      configCallback: function _configCallback(type, collection) {\n        if (type === connect.OPTIONS_SPAWN_OBJ) {\n          collection.env = Object.assign({\n            TEST_ENV_VAR: \"SET_OK\"\n          }, process.env);\n\n          return collection;\n        } else if (type === connect.OPTIONS_PHP_CLI_ARR) {\n          return null;\n        }\n      }\n    }, function _configCallback_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8006')\n        .get('/test/fixtures/config-cb-checker.php')\n        .expect(/ENVVAR=SET_OK,MEM_LIMIT=2\\.1G;/)\n        .expect(200)\n        .end(function _configCallback_endEvent(err, res) {\n          if (err) return done(err);\n          connect.closeServer(function _configCallback_closeServer() {\n            done();\n          });\n        });\n    });\n  });\n\n  it('Should start a basic php server, with a set environment variable and updated memory limits set via the configCallback option with no return', function _test_configCallback(done) {\n    connect.server({\n      port: 8007,\n      configCallback: function _configCallback(type, collection) {\n        if (type === connect.OPTIONS_SPAWN_OBJ) {\n          collection.env = Object.assign({\n            TEST_ENV_VAR: \"SET_OK\"\n          }, process.env);\n\n          return collection;\n        }\n      }\n    }, function _configCallback_serverCallback(error) {\n      if (error) throw error;\n      request('http://127.0.0.1:8007')\n        .get('/test/fixtures/config-cb-checker.php')\n        .expect(/ENVVAR=SET_OK,MEM_LIMIT=2\\.1G;/)\n        .expect(200)\n        .end(function _configCallback_endEvent(err, res) {\n          if (err) return done(err);\n          connect.closeServer(function _configCallback_closeServer() {\n            done();\n          });\n        });\n    });\n  });\n});\n"
  }
]