├── .gitignore ├── LICENSE.md ├── README.md ├── lib ├── php-server-server.coffee ├── php-server-view.coffee └── php-server.coffee ├── menus └── php-server.cson ├── package.json ├── styles └── php-server.less └── tree-context.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Stephen Hawkes - @leijou 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP Server 2 | 3 | An Atom package to run PHP's built-in development server and display the log in a bottom pane. Can be started from any folder in the tree, the currently opened file, or the project root. 4 | 5 | > :exclamation::exclamation::exclamation: 6 | > This package is no longer maintained. Please fork or seek alternatives 7 | > :exclamation::exclamation::exclamation: 8 | 9 | ![Screenshot](http://i.imgur.com/FhVtl9v.png) 10 | 11 | ## Requirements 12 | 13 | PHP must be installed on your machine, version 5.4 or greater. 14 | 15 | If `php` is not in your system PATH you will need to put in the full path to your PHP executable in the settings of this package. 16 | 17 | ## Commands 18 | 19 | * `php-server:start` — Start / Restart PHP server from project path 20 | * `php-server:start-tree` — Start / Restart PHP server from folder/file selected in tree 21 | * `php-server:start-document` — Start / Restart PHP server from currently open file 22 | * `php-server:stop` — Stop running PHP server 23 | * `php-server:clear` — Clear message panel 24 | -------------------------------------------------------------------------------- /lib/php-server-server.coffee: -------------------------------------------------------------------------------- 1 | {Emitter} = require 'atom' 2 | {spawn} = require 'child_process' 3 | portfinder = require 'portfinder' 4 | 5 | module.exports = 6 | class PhpServerServer 7 | # Settings 8 | path: 'php' 9 | host: 'localhost' 10 | basePort: 8000 11 | ini: '' 12 | overrideErrorlog: true 13 | 14 | # Properties 15 | documentRoot: null 16 | routerFile: null 17 | href: null 18 | 19 | # Protected 20 | server: null 21 | 22 | 23 | constructor: (@documentRoot, @routerFile) -> 24 | @emitter = new Emitter 25 | 26 | 27 | destroy: -> 28 | @stop() 29 | 30 | 31 | on: (eventName, handler) -> 32 | @emitter.on eventName, handler 33 | 34 | 35 | preempt: (eventName, handler) -> 36 | @emitter.preempt eventName, handler 37 | 38 | 39 | start: (callback) -> 40 | @stop() 41 | 42 | # Find free port 43 | portfinder.basePort = @basePort 44 | portfinder.getPort (err, port) => 45 | try 46 | # Build CLI options 47 | options = [] 48 | 49 | if @overrideErrorlog 50 | # ini settings for errors to be logged to stderr 51 | options.push "-d", "error_log=", "-d", "log_errors=1", "-d", "display_errors=" 52 | 53 | if @ini 54 | # Set specified php.ini file 55 | options.push "-c", @ini 56 | 57 | options.push "-S", "#{@host}:#{port}" 58 | 59 | if @routerFile 60 | # Use given file as request router 61 | options.push @routerFile 62 | 63 | 64 | # Spawn PHP server process 65 | @server = spawn @path, options, env: process.env, cwd: @documentRoot 66 | 67 | # Catch process failures 68 | @server.once 'exit', (code) => 69 | @emitter.emit 'error', code if code != 0 70 | 71 | @server.on 'error', (err) => 72 | @emitter.emit 'error', err 73 | 74 | # Relay PHP output 75 | @server.stdout.on 'data', (data) => 76 | @emitter.emit 'message', data.asciiSlice() 77 | 78 | @server.stderr.on 'data', (data) => 79 | @emitter.emit 'message', data.asciiSlice() 80 | 81 | # Record server state 82 | @href = "http://#{@host}:#{port}" 83 | 84 | # Once process has spawned execute callback 85 | callback?() 86 | 87 | catch err 88 | # Failure 89 | @server = null 90 | @emitter.emit 'error', code: null, message: err 91 | 92 | 93 | stop: (callback) -> 94 | if @server 95 | # Replace exit listener 96 | @server.removeAllListeners 'exit' 97 | @server.once 'exit', (code) => 98 | @server.removeAllListeners 99 | 100 | @href = null 101 | 102 | @server = null 103 | callback?() 104 | 105 | # Send Ctrl+C 106 | @server.kill 'SIGINT' 107 | -------------------------------------------------------------------------------- /lib/php-server-view.coffee: -------------------------------------------------------------------------------- 1 | {$, View} = require 'atom-space-pen-views' 2 | {MessagePanelView, PlainMessageView, LineMessageView} = require 'atom-message-panel' 3 | 4 | module.exports = 5 | class PhpServerView extends MessagePanelView 6 | addMessage: (lines, logLevel) -> 7 | for text in lines.split "\n" 8 | linematch = /in ([a-z\\\/\.\-_]+) on line ([0-9]+)$/i 9 | match = text.match linematch 10 | if match 11 | @add(new LineMessageView( 12 | line: match[2] 13 | file: match[1] 14 | message: text.substr(0, text.length - match[0].length) 15 | )) 16 | else 17 | @add(new PlainMessageView( 18 | message: text 19 | )) 20 | @toggle() if !@body.isVisible() && logLevel == 'all' 21 | @body.scrollToBottom() 22 | 23 | addError: (lines) -> 24 | @add(new PlainMessageView( 25 | message: lines 26 | className: 'text-error' 27 | )) 28 | 29 | hide: -> 30 | @toggle() if @body.isVisible() 31 | -------------------------------------------------------------------------------- /lib/php-server.coffee: -------------------------------------------------------------------------------- 1 | PhpServerView = require './php-server-view' 2 | PhpServerServer = require './php-server-server' 3 | open = require 'open' 4 | fs = require 'fs' 5 | 6 | module.exports = 7 | config: 8 | phpPath: 9 | title: 'Path to PHP Executable' 10 | description: 'On Windows this might need to be the full path to php.exe' 11 | type: 'string' 12 | default: 'php' 13 | localhost: 14 | title: 'Hostname to use' 15 | type: 'string' 16 | default: 'localhost' 17 | startPort: 18 | title: 'Default port to bind to' 19 | description: 'Will search for an empty port starting from here' 20 | type: 'integer' 21 | default: 8000 22 | phpIni: 23 | title: 'Custom php.ini file' 24 | description: 'Will replace your standard CLI php.ini settings' 25 | type: 'string' 26 | default: '' 27 | overrideErrorlog: 28 | title: 'Override error log' 29 | description: 'Redirect error log to panel in Atom. Overrides ini settings. May not work on Windows' 30 | type: 'boolean' 31 | default: false 32 | expandOnLog: 33 | title: 'Expand on log message' 34 | description: 'Expands the server console window when selected requests are received by the server' 35 | type: 'string' 36 | enum: ['all', 'none'] 37 | default: 'all' 38 | openInBrowser: 39 | title: 'Open in browser' 40 | description: 'Open browser at local URL on server start' 41 | type: 'boolean' 42 | default: true 43 | 44 | 45 | server: null 46 | view: null 47 | 48 | 49 | activate: -> 50 | atom.commands.add 'atom-workspace', "php-server:start", => @start() 51 | atom.commands.add 'atom-workspace', "php-server:start-tree", => @startTree() 52 | atom.commands.add 'atom-workspace', "php-server:start-tree-route", => @startTreeRoute() 53 | atom.commands.add 'atom-workspace', "php-server:start-document", => @startDocument() 54 | atom.commands.add 'atom-workspace', "php-server:clear", => @clear() 55 | atom.commands.add 'atom-workspace', "php-server:stop", => @stop() 56 | 57 | 58 | deactivate: -> 59 | @stop() 60 | 61 | 62 | startTree: -> 63 | @start atom.packages.getLoadedPackage('tree-view').mainModule.treeView.selectedPath 64 | 65 | 66 | startTreeRoute: -> 67 | [path, basename] = @splitPath atom.packages.getLoadedPackage('tree-view').mainModule.treeView.selectedPath 68 | @start path, basename 69 | 70 | 71 | startDocument: -> 72 | @start(atom.workspace.getActiveTextEditor()?.getPath()) 73 | 74 | 75 | splitPath: (path) -> 76 | basename = false 77 | if !fs.lstatSync(path).isDirectory() 78 | basename = path.split(/[\\/]/).pop() 79 | path = path.substring(0, Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"))) 80 | 81 | return [path, basename] 82 | 83 | 84 | start: (documentroot, router) -> 85 | # Stop server if currently running 86 | if @server 87 | @server.stop() 88 | @server = null 89 | 90 | # Set up panel 91 | if !@view 92 | @view = new PhpServerView( 93 | title: "PHP Server: Launching..." 94 | ) 95 | 96 | @view.attach() 97 | 98 | # Collapse view if expandOnLog is set to none 99 | if atom.config.get('php-server.expandOnLog') == 'none' 100 | @view?.hide() 101 | 102 | # Launch server in given working directory 103 | if !documentroot 104 | documentroot = atom.project.getPaths()[0] 105 | 106 | if !documentroot 107 | @view.addError "PHP Server could not launch" 108 | @view.addError "Atom project directory not found" 109 | return 110 | 111 | [documentroot, basename] = @splitPath documentroot 112 | 113 | @server = new PhpServerServer documentroot, router 114 | 115 | # Pass package settings 116 | @server.path = atom.config.get('php-server.phpPath') 117 | @server.host = atom.config.get('php-server.localhost') 118 | @server.basePort = atom.config.get('php-server.startPort') 119 | @server.ini = atom.config.get('php-server.phpIni') 120 | @server.overrideErrorlog = atom.config.get('php-server.overrideErrorlog') 121 | 122 | # Listen 123 | @server.on 'message', (message) => 124 | @view?.addMessage message, atom.config.get('php-server.expandOnLog') 125 | 126 | @server.on 'error', (err) => 127 | console.error err 128 | 129 | if @view 130 | if err.code == 'ENOENT' 131 | @view.addError "PHP Server could not launch" 132 | @view.addError "Have you defined the right path to PHP in your settings? Using #{@server.path}" 133 | else if err.code == 'ENOTDIR' 134 | @view.addError "PHP Server could not launch" 135 | @view.addError "Not a directory? Using #{@server.documentRoot}" 136 | else 137 | @view.addError err.message 138 | 139 | # Start server 140 | @server.start => 141 | @view.setTitle "PHP Server: #{@server.href}", true 142 | 143 | @view.addMessage "Listening on #{@server.href}", atom.config.get('php-server.expandOnLog') 144 | @view.addMessage "Document root is #{@server.documentRoot}", atom.config.get('php-server.expandOnLog') 145 | 146 | href = @server.href 147 | if basename 148 | href += '/' + basename 149 | 150 | # Launch browser 151 | if atom.config.get('php-server.openInBrowser') 152 | open href 153 | 154 | 155 | stop: -> 156 | @server?.stop() 157 | 158 | @view?.clear() 159 | @view?.close() 160 | 161 | @server = null 162 | @view = null 163 | 164 | 165 | clear: -> 166 | @view?.clear() 167 | -------------------------------------------------------------------------------- /menus/php-server.cson: -------------------------------------------------------------------------------- 1 | 'context-menu': 2 | '.tree-view': [ 3 | {type: 'separator'} 4 | {label: 'PHP Server here', command: 'php-server:start-tree'} 5 | {label: 'PHP Server route file', command: 'php-server:start-tree-route'} 6 | {type: 'separator'} 7 | ] 8 | 'atom-text-editor': [ 9 | {type: 'separator'} 10 | {label: 'PHP Server here', command: 'php-server:start-document'} 11 | {type: 'separator'} 12 | ] 13 | 14 | 'menu': [{ 15 | label: 'Packages' 16 | submenu: [ 17 | label: 'PHP Server', 18 | submenu: [ 19 | { label: 'Start in project root', command: 'php-server:start' } 20 | { label: 'Start in folder selected in tree', command: 'php-server:start-tree' } 21 | { label: 'Start in folder of current file', command: 'php-server:start-document' } 22 | ] 23 | ] 24 | }] 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-server", 3 | "main": "./lib/php-server", 4 | "version": "0.8.0", 5 | "description": "Run a local PHP server from within Atom, displaying the log in a bottom panel", 6 | "activationCommands": { 7 | "atom-workspace": "php-server:start", 8 | ".tree-view": [ 9 | "php-server:start-tree", 10 | "php-server:start-tree-route" 11 | ], 12 | "atom-text-editor": "php-server:start-document" 13 | }, 14 | "repository": "https://github.com/leijou/php-server", 15 | "license": "MIT", 16 | "engines": { 17 | "atom": ">0.50.0" 18 | }, 19 | "dependencies": { 20 | "portfinder": "latest", 21 | "open": "latest", 22 | "atom-message-panel": "latest", 23 | "atom-space-pen-views": "^2.0.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /styles/php-server.less: -------------------------------------------------------------------------------- 1 | // The ui-variables file is provided by base themes provided by Atom. 2 | // 3 | // See https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less 4 | // for a full listing of what's available. 5 | @import "ui-variables"; 6 | 7 | .php-server { 8 | } 9 | -------------------------------------------------------------------------------- /tree-context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leijou/php-server/7fcbc4b75a524311dafada28a1ef19618bff0a8a/tree-context.png --------------------------------------------------------------------------------