From 2743621223d852cca4dad85aa6b026870f96d17f Mon Sep 17 00:00:00 2001
From: ftimme <ft@falkotimme.com>
Date: Wed, 18 Apr 2012 11:48:12 -0400
Subject: [PATCH] - Added PHP-FPM support for Apache.

---
 interface/web/sites/templates/web_domain_advanced.htm    |   17 ++
 server/conf/vhost.conf.master                            |   17 ++
 interface/web/admin/templates/server_config_web_edit.htm |   10 
 server/plugins-available/apache2_plugin.inc.php          |  248 +++++++++++++++++++++++++++++++++++++++++
 interface/web/sites/ajax_get_json.php                    |    9 +
 interface/web/sites/form/web_domain.tform.php            |    2 
 6 files changed, 292 insertions(+), 11 deletions(-)

diff --git a/interface/web/admin/templates/server_config_web_edit.htm b/interface/web/admin/templates/server_config_web_edit.htm
index ed522f6..7f150f2 100644
--- a/interface/web/admin/templates/server_config_web_edit.htm
+++ b/interface/web/admin/templates/server_config_web_edit.htm
@@ -121,23 +121,23 @@
       	<label for="php_ini_path_cgi">{tmpl_var name='php_ini_path_cgi_txt'}</label>
         <input name="php_ini_path_cgi" id="php_ini_path_cgi" value="{tmpl_var name='php_ini_path_cgi'}" size="40" maxlength="255" type="text" class="textInput" />
 	  </div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder">
       	<label for="php_fpm_init_script">{tmpl_var name='php_fpm_init_script_txt'}</label>
         <input name="php_fpm_init_script" id="php_fpm_init_script" value="{tmpl_var name='php_fpm_init_script'}" size="40" maxlength="255" type="text" class="textInput" />
 	  </div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder">
       	<label for="php_fpm_ini_path">{tmpl_var name='php_fpm_ini_path_txt'}</label>
         <input name="php_fpm_ini_path" id="php_fpm_ini_path" value="{tmpl_var name='php_fpm_ini_path'}" size="40" maxlength="255" type="text" class="textInput" />
 	  </div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder">
       	<label for="php_fpm_pool_dir">{tmpl_var name='php_fpm_pool_dir_txt'}</label>
         <input name="php_fpm_pool_dir" id="php_fpm_pool_dir" value="{tmpl_var name='php_fpm_pool_dir'}" size="40" maxlength="255" type="text" class="textInput" />
 	  </div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder">
       	<label for="php_fpm_start_port">{tmpl_var name='php_fpm_start_port_txt'}</label>
         <input name="php_fpm_start_port" id="php_fpm_start_port" value="{tmpl_var name='php_fpm_start_port'}" size="40" maxlength="255" type="text" class="textInput" />
 	  </div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder">
       	<label for="php_fpm_socket_dir">{tmpl_var name='php_fpm_socket_dir_txt'}</label>
         <input name="php_fpm_socket_dir" id="php_fpm_socket_dir" value="{tmpl_var name='php_fpm_socket_dir'}" size="40" maxlength="255" type="text" class="textInput" />
 	  </div>
diff --git a/interface/web/sites/ajax_get_json.php b/interface/web/sites/ajax_get_json.php
index 26e8211..2672965 100644
--- a/interface/web/sites/ajax_get_json.php
+++ b/interface/web/sites/ajax_get_json.php
@@ -88,6 +88,15 @@
 		if(substr($json,-1) == ',') $json = substr($json,0,-1);
 		$json .= '}';
 	}
+	
+	if($type == 'getphptype'){
+		$json = '{"phptype":"';
+		$sql = "SELECT php FROM web_domain WHERE domain_id = $web_id";
+		$php = $app->db->queryOneRecord($sql);
+		$json .= $php['php'];
+		unset($php);
+		$json .= '"}';
+	}
 
 //}
 
diff --git a/interface/web/sites/form/web_domain.tform.php b/interface/web/sites/form/web_domain.tform.php
index 5e79c19..3b27287 100644
--- a/interface/web/sites/form/web_domain.tform.php
+++ b/interface/web/sites/form/web_domain.tform.php
@@ -208,7 +208,7 @@
 			'formtype'	=> 'SELECT',
 			'default'	=> 'fast-cgi',
 			'valuelimit' => 'client:web_php_options',
-			'value'		=> array('no' => 'disabled_txt', 'fast-cgi' => 'Fast-CGI', 'cgi' => 'CGI', 'mod' => 'Mod-PHP', 'suphp' => 'SuPHP')
+			'value'		=> array('no' => 'disabled_txt', 'fast-cgi' => 'Fast-CGI', 'cgi' => 'CGI', 'mod' => 'Mod-PHP', 'suphp' => 'SuPHP', 'php-fpm' => 'PHP-FPM')
 		),
 		'fastcgi_php_version' => array (
 			'datatype'	=> 'VARCHAR',
diff --git a/interface/web/sites/templates/web_domain_advanced.htm b/interface/web/sites/templates/web_domain_advanced.htm
index 2000ff6..9665f42 100644
--- a/interface/web/sites/templates/web_domain_advanced.htm
+++ b/interface/web/sites/templates/web_domain_advanced.htm
@@ -20,25 +20,25 @@
       	<label for="allow_override">{tmpl_var name='allow_override_txt'}</label>
         <input name="allow_override" id="allow_override" value="{tmpl_var name='allow_override'}" size="30" maxlength="255" type="text" class="textInput" />
 	  </div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder phpfpm">
 				<p class="label">{tmpl_var name='php_fpm_use_socket_txt'}</p>
 					<div class="multiField">
 						{tmpl_var name='php_fpm_use_socket'}
 					</div>
 			</div>
-	  <div class="ctrlHolder nginx">
+	  <div class="ctrlHolder phpfpm">
       	<label for="pm_max_children">{tmpl_var name='pm_max_children_txt'}</label>
         <input name="pm_max_children" id="pm_max_children" value="{tmpl_var name='pm_max_children'}" size="3" maxlength="3" type="text" class="textInput formLengthLimit" />
 			</div>
-	<div class="ctrlHolder nginx">
+	<div class="ctrlHolder phpfpm">
       	<label for="pm_start_servers">{tmpl_var name='pm_start_servers_txt'}</label>
         <input name="pm_start_servers" id="pm_start_servers" value="{tmpl_var name='pm_start_servers'}" size="3" maxlength="3" type="text" class="textInput formLengthLimit" />
 			</div>
-	<div class="ctrlHolder nginx">
+	<div class="ctrlHolder phpfpm">
       	<label for="pm_min_spare_servers">{tmpl_var name='pm_min_spare_servers_txt'}</label>
         <input name="pm_min_spare_servers" id="pm_min_spare_servers" value="{tmpl_var name='pm_min_spare_servers'}" size="3" maxlength="3" type="text" class="textInput formLengthLimit" />
 			</div>
-	<div class="ctrlHolder nginx">
+	<div class="ctrlHolder phpfpm">
       	<label for="pm_max_spare_servers">{tmpl_var name='pm_max_spare_servers_txt'}</label>
         <input name="pm_max_spare_servers" id="pm_max_spare_servers" value="{tmpl_var name='pm_max_spare_servers'}" size="3" maxlength="3" type="text" class="textInput formLengthLimit" />
 			</div>
@@ -91,6 +91,13 @@
 					jQuery('.apache').show();
 				}
 			});
+			jQuery.getJSON('sites/ajax_get_json.php'+ '?' + Math.round(new Date().getTime()), {web_id : webId, type : "getphptype"}, function(data) {
+				if(data.phptype == "php-fpm"){
+					jQuery('.phpfpm').show();
+				} else {
+					jQuery('.phpfpm').hide();
+				}
+			});
 		}
 			
 </script>
\ No newline at end of file
diff --git a/server/conf/vhost.conf.master b/server/conf/vhost.conf.master
index 47c5eb2..b3d5ca7 100644
--- a/server/conf/vhost.conf.master
+++ b/server/conf/vhost.conf.master
@@ -214,6 +214,23 @@
         Allow from all
     </Directory>
 </tmpl_if>
+<tmpl_if name='php' op='==' value='php-fpm'>
+    <IfModule mod_fastcgi.c>
+        <Directory /usr/lib/cgi-bin>
+            Order allow,deny
+            Allow from all
+        </Directory>
+        AddHandler php5-fcgi .php
+        Action php5-fcgi /php5-fcgi
+        Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
+<tmpl_if name='use_tcp'>
+        FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:<tmpl_var name='fpm_port'> -pass-header Authorization
+</tmpl_if>
+<tmpl_if name='use_socket'>
+        FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket <tmpl_var name='fpm_socket'> -pass-header Authorization
+</tmpl_if>
+    </IfModule>
+</tmpl_if>
 
 <tmpl_if name="rewrite_enabled">
     RewriteEngine on
diff --git a/server/plugins-available/apache2_plugin.inc.php b/server/plugins-available/apache2_plugin.inc.php
index f620b57..e048b5f 100644
--- a/server/plugins-available/apache2_plugin.inc.php
+++ b/server/plugins-available/apache2_plugin.inc.php
@@ -961,6 +961,41 @@
 			$tpl->setVar('fastcgi_config_syntax',$fastcgi_config['fastcgi_config_syntax']);
 
 		}
+		
+		/**
+		* PHP-FPM
+		*/
+		// Support for multiple PHP versions
+		if(trim($data['new']['fastcgi_php_version']) != ''){
+			$default_php_fpm = false;
+			list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
+			if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+		} else {
+			$default_php_fpm = true;
+		}
+		
+		if($default_php_fpm){
+			$pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		} else {
+			$pool_dir = $custom_php_fpm_pool_dir;
+		}
+		if(substr($pool_dir,-1) != '/') $pool_dir .= '/';
+		$pool_name = 'web'.$data['new']['domain_id'];
+		$socket_dir = escapeshellcmd($web_config['php_fpm_socket_dir']);
+		if(substr($socket_dir,-1) != '/') $socket_dir .= '/';
+		
+		if($data['new']['php_fpm_use_socket'] == 'y'){
+			$use_tcp = 0;
+			$use_socket = 1;
+		} else {
+			$use_tcp = 1;
+			$use_socket = 0;
+		}
+		$tpl->setVar('use_tcp', $use_tcp);
+		$tpl->setVar('use_socket', $use_socket);
+		$fpm_socket = $socket_dir.$pool_name.'.sock';
+		$tpl->setVar('fpm_socket', $fpm_socket);
+		$tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
 
 		/**
 		 * install cgi starter script and add script alias to config.
@@ -1153,6 +1188,8 @@
 			$this->awstats_update($data,$web_config);
 		}
 		
+		$this->php_fpm_pool_update($data,$web_config,$pool_dir,$pool_name,$socket_dir);
+		
 		if($web_config['check_apache_config'] == 'y') {
 			//* Test if apache starts with the new configuration file
 			$apache_online_status_before_restart = $this->_checkTcp('localhost',80);
@@ -1255,6 +1292,11 @@
 				if (is_dir($fastcgi_starter_path)) {
 					exec('rm -rf '.$fastcgi_starter_path);
 				}
+			}
+			
+			// remove PHP-FPM pool
+			if ($data['old']['php'] == 'php-fpm') {
+				$this->php_fpm_pool_delete($data,$web_config);
 			}
 
 			//remove the php cgi starter script if available
@@ -1879,6 +1921,212 @@
 		}
 	}
 	
+	//* Update the PHP-FPM pool configuration file
+	private function php_fpm_pool_update ($data,$web_config,$pool_dir,$pool_name,$socket_dir) {
+		global $app, $conf;
+		//$reload = false;
+		
+		if(trim($data['new']['fastcgi_php_version']) != ''){
+			$default_php_fpm = false;
+			list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
+			if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+		} else {
+			$default_php_fpm = true;
+		}
+		
+		$app->uses("getconf");
+		$web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
+		
+		if($data['new']['php'] != 'php-fpm'){
+			if(@is_file($pool_dir.$pool_name.'.conf')){
+				unlink($pool_dir.$pool_name.'.conf');
+				//$reload = true;
+			}
+			if($data['old']['php'] == 'php-fpm'){
+				if(!$default_php_fpm){
+					$app->services->restartService('php-fpm','reload:'.$custom_php_fpm_init_script);
+				} else {
+					$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+				}
+			}
+			//if($reload == true) $app->services->restartService('php-fpm','reload');
+			return;
+		}
+				
+		$app->load('tpl');
+		$tpl = new tpl();
+		$tpl->newTemplate('php_fpm_pool.conf.master');
+
+		if($data['new']['php_fpm_use_socket'] == 'y'){
+			$use_tcp = 0;
+			$use_socket = 1;
+			if(!is_dir($socket_dir)) exec('mkdir -p '.$socket_dir);
+		} else {
+			$use_tcp = 1;
+			$use_socket = 0;
+		}
+		$tpl->setVar('use_tcp', $use_tcp);
+		$tpl->setVar('use_socket', $use_socket);
+			
+		$fpm_socket = $socket_dir.$pool_name.'.sock';
+		$tpl->setVar('fpm_socket', $fpm_socket);
+			
+		$tpl->setVar('fpm_pool', $pool_name);
+		$tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
+		$tpl->setVar('fpm_user', $data['new']['system_user']);
+		$tpl->setVar('fpm_group', $data['new']['system_group']);
+		$tpl->setVar('pm_max_children', $data['new']['pm_max_children']);
+		$tpl->setVar('pm_start_servers', $data['new']['pm_start_servers']);
+		$tpl->setVar('pm_min_spare_servers', $data['new']['pm_min_spare_servers']);
+		$tpl->setVar('pm_max_spare_servers', $data['new']['pm_max_spare_servers']);
+		$tpl->setVar('document_root', $data['new']['document_root']);
+		$tpl->setVar('security_level',$web_config['security_level']);
+		$php_open_basedir = ($data['new']['php_open_basedir'] == '')?escapeshellcmd($data['new']['document_root']):escapeshellcmd($data['new']['php_open_basedir']);
+		$tpl->setVar('php_open_basedir', $php_open_basedir);
+		if($php_open_basedir != ''){
+			$tpl->setVar('enable_php_open_basedir', '');
+		} else {
+			$tpl->setVar('enable_php_open_basedir', ';');
+		}
+			
+		// Custom php.ini settings
+		$final_php_ini_settings = array();
+		$custom_php_ini_settings = trim($data['new']['custom_php_ini']);
+		if($custom_php_ini_settings != ''){
+			// Make sure we only have Unix linebreaks
+			$custom_php_ini_settings = str_replace("\r\n", "\n", $custom_php_ini_settings);
+			$custom_php_ini_settings = str_replace("\r", "\n", $custom_php_ini_settings);
+			$ini_settings = explode("\n", $custom_php_ini_settings);
+			if(is_array($ini_settings) && !empty($ini_settings)){
+				foreach($ini_settings as $ini_setting){
+						list($key, $value) = explode('=', $ini_setting);
+						if($value){
+							$value = escapeshellcmd(trim($value));
+							$key = escapeshellcmd(trim($key));
+							switch (strtolower($value)) {
+								case 'on':
+								case 'off':
+								case '1':
+								case '0':
+									// PHP-FPM might complain about invalid boolean value if you use 0
+									$value = 'off';
+								case 'true':
+								case 'false':
+								case 'yes':
+								case 'no':
+									$final_php_ini_settings[] = array('ini_setting' => 'php_admin_flag['.$key.'] = '.$value);
+									break;
+								default:
+									$final_php_ini_settings[] = array('ini_setting' => 'php_admin_value['.$key.'] = '.$value);
+							}
+						}
+				}
+			}
+		}
+			
+		$tpl->setLoop('custom_php_ini_settings', $final_php_ini_settings);
+			
+		file_put_contents($pool_dir.$pool_name.'.conf',$tpl->grab());
+		$app->log('Writing the PHP-FPM config file: '.$pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
+		unset($tpl);
+		
+		// delete pool in all other PHP versions
+		$default_pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		if(substr($default_pool_dir,-1) != '/') $default_pool_dir .= '/';
+		if($default_pool_dir != $pool_dir){
+			if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
+					unlink($default_pool_dir.$pool_name.'.conf');
+					$app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
+					$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+			}
+		}
+		$php_versions = $app->db->queryAllRecords("SELECT * FROM server_php WHERE php_fpm_init_script != '' AND php_fpm_ini_dir != '' AND php_fpm_pool_dir != '' AND server_id = ".$conf["server_id"]);
+		if(is_array($php_versions) && !empty($php_versions)){
+			foreach($php_versions as $php_version){
+				if(substr($php_version['php_fpm_pool_dir'],-1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
+				if($php_version['php_fpm_pool_dir'] != $pool_dir){
+					if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
+						unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
+						$app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf',LOGLEVEL_DEBUG);
+						$app->services->restartService('php-fpm','reload:'.$php_version['php_fpm_init_script']);
+					}
+				}
+			}
+		}
+		// Reload current PHP-FPM after all others
+		sleep(1);
+		if(!$default_php_fpm){
+			$app->services->restartService('php-fpm','reload:'.$custom_php_fpm_init_script);
+		} else {
+			$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+		}
+		
+		//$reload = true;
+
+		//if($reload == true) $app->services->restartService('php-fpm','reload');
+	}
+	
+	//* Delete the PHP-FPM pool configuration file
+	private function php_fpm_pool_delete ($data,$web_config) {
+		global $app, $conf;
+		
+		if(trim($data['old']['fastcgi_php_version']) != ''){
+			$default_php_fpm = false;
+			list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
+			if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+		} else {
+			$default_php_fpm = true;
+		}
+		
+		if($default_php_fpm){
+			$pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		} else {
+			$pool_dir = $custom_php_fpm_pool_dir;
+		}
+		
+		if(substr($pool_dir,-1) != '/') $pool_dir .= '/';
+		$pool_name = 'web'.$data['old']['domain_id'];
+		
+		if ( @is_file($pool_dir.$pool_name.'.conf') ) {
+			unlink($pool_dir.$pool_name.'.conf');
+			$app->log('Removed PHP-FPM config file: '.$pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
+			
+			//$app->services->restartService('php-fpm','reload');
+		}
+		
+		// delete pool in all other PHP versions
+		$default_pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		if(substr($default_pool_dir,-1) != '/') $default_pool_dir .= '/';
+		if($default_pool_dir != $pool_dir){
+			if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
+					unlink($default_pool_dir.$pool_name.'.conf');
+					$app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
+					$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+			}
+		}	
+		$php_versions = $app->db->queryAllRecords("SELECT * FROM server_php WHERE php_fpm_init_script != '' AND php_fpm_ini_dir != '' AND php_fpm_pool_dir != '' AND server_id = ".$data['old']['server_id']);
+		if(is_array($php_versions) && !empty($php_versions)){
+			foreach($php_versions as $php_version){
+				if(substr($php_version['php_fpm_pool_dir'],-1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
+				if($php_version['php_fpm_pool_dir'] != $pool_dir){
+					if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
+						unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
+						$app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf',LOGLEVEL_DEBUG);
+						$app->services->restartService('php-fpm','reload:'.$php_version['php_fpm_init_script']);
+					}
+				}
+			}
+		}
+		
+		// Reload current PHP-FPM after all others
+		sleep(1);
+		if(!$default_php_fpm){
+			$app->services->restartService('php-fpm','reload:'.$custom_php_fpm_init_script);
+		} else {
+			$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+		}
+	}
+	
 	function client_delete($event_name,$data) {
 		global $app, $conf;
 		

--
Gitblit v1.9.1