#!/bin/bash
# Brought from gugod's perlbrew.
# Authors:
# - Yo-An Lin
# - Márcio Almada
# PHPBrew defaults:
# PHPBREW_HOME: contains the phpbrew config (for users)
# PHPBREW_ROOT: contains installed php(s) and php source files.
# PHPBREW_SKIP_INIT: if you need to skip loading config from the init file.
# PHPBREW_PHP: the current php version.
# PHPBREW_PATH: the bin path of the current php.
# PHPBREW_SYSTEM_PHP: the path to the system php binary.
[[ -z "$PHPBREW_ROOT" ]] && export PHPBREW_ROOT="$HOME/.phpbrew"
[[ -z "$PHPBREW_HOME" ]] && export PHPBREW_HOME="$HOME/.phpbrew"
# The minimal PHP version that PhpBrew supports as interpreter
MIN_PHP_VERSION="7.2.0"
MIN_PHP_VERSION_ID=70200
# Returns the absolute path corresponding to the command excluding the alias
function __phpbrew_which()
{
command which "$1"
}
# Executes the given command via the PHP implementation
function __phpbrew_php_exec()
{
local cmd
# Check if we are in a PHPBrew source directory (this is only for development)
if [[ -e bin/phpbrew ]] ; then
cmd=bin/phpbrew
else
cmd="$(__phpbrew_which phpbrew)"
fi
# Force the usage of the system PHP interpreter if it's set
if [[ -n "$PHPBREW_SYSTEM_PHP" ]] ; then
command "$PHPBREW_SYSTEM_PHP" "$cmd" "$@"
else
command "$cmd" "$@"
fi
}
# Normalizes a PHP build by adding the "php-" prefix if it's missing
function __phpbrew_normalize_build()
{
if [[ ! -d "$PHPBREW_ROOT/php/$1" && "$1" =~ ^([[:digit:]]+\.){2}[[:digit:]]+(-dev|((alpha|beta|RC)[[:digit:]]+))?$ ]] ; then
echo "php-$1"
else
echo "$1"
fi
}
# Returns the PHP binary path for a given version
function __phpbrew_get_version_bin()
{
if [[ ! "$1" == /* ]] ; then
echo "$PHPBREW_ROOT/php/$(__phpbrew_normalize_build $1)/bin/php"
else
echo "$1"
fi
}
# Validates the PHP binary that is to be used as interpreter
function __phpbrew_validate_interpreter()
{
if [[ -d "$1" ]] ; then
echo "$1 is a directory"
return 1
fi
if [[ ! -f "$1" ]] ; then
echo "$1 not found"
return 1
fi
if [[ ! -x "$1" ]] ; then
echo "$1 is not executable"
return 1
fi
local PHP_VERSION_ID=$(command "$1" -r "echo PHP_VERSION_ID;")
if [[ $? -ne 0 ]] ; then
return 1
fi
if [[ $PHP_VERSION_ID -lt $MIN_PHP_VERSION_ID ]] ; then
echo "Only PHP $MIN_PHP_VERSION or newer can be used as PHPBrew interpreter"
return 1
fi
}
# Checks whether the given PHP build can be currently used or switched to
function __phpbrew_can_use_build()
{
if [[ ! -z "$PHPBREW_SYSTEM_PHP" ]] ; then
# Can use any version since the system interpreter is set
return
fi
__phpbrew_validate_interpreter "$(__phpbrew_get_version_bin $1)"
if [[ $? -ne 0 ]] ; then
echo "The system interpreter is not currently set"
echo "Please execute 'phpbrew system' using PHP $MIN_PHP_VERSION or newer before using an older one"
return 1
fi
}
function __phpbrew_set_path()
{
local PATH_WITHOUT_PHPBREW
if [[ -n "$PHPBREW_ROOT" ]] ; then
PATH_WITHOUT_PHPBREW=$(p=$(echo $PATH | tr ":" "\n" | grep -v "^$PHPBREW_ROOT" | tr "\n" ":"); echo ${p%:})
else
PATH_WITHOUT_PHPBREW=$PATH
fi
if [[ -z "$PHPBREW_PATH" ]]
then
export PATH=$PATH_WITHOUT_PHPBREW
else
export PATH=$PHPBREW_PATH:$PATH_WITHOUT_PHPBREW
fi
}
function __phpbrew_load_user_config()
{
# load user-defined config
if [[ -f $PHPBREW_HOME/init ]]; then
. $PHPBREW_HOME/init
__phpbrew_set_path
fi
}
if [[ -z "$PHPBREW_SKIP_INIT" ]]; then
__phpbrew_load_user_config
fi
[[ -e "$PHPBREW_ROOT" ]] || mkdir "$PHPBREW_ROOT"
[[ -e "$PHPBREW_HOME" ]] || mkdir "$PHPBREW_HOME"
# When setting lookup prefix, the alias name will be translated into the real
# path.
#
# Homebrew uses it's own prefix system with cellars, it's more dynamic then
# others.
#
# Detect package system automatically
function __phpbrew_set_lookup_prefix ()
{
case $1 in
debian|ubuntu|linux)
# echo /usr/lib/x86_64-linux-gnu:/usr/lib/i386-linux-gnu
echo /usr
;;
macosx)
echo /usr
;;
macports)
echo /opt/local
;;
homebrew)
# TODO: make this more dynamic. with brew --prefix call.
echo /usr/local/opt:/usr/local
;;
*)
if [[ -e $1 ]] ; then
echo $1
else
for dir in /opt/local /usr/local/Cellar /usr/local /usr ; do
if [[ -e $dir ]] ; then
echo $dir
return
fi
done
fi
;;
esac
}
function phpbrew ()
{
local short_option
if [[ `echo $1 | awk 'BEGIN{FS=""}{print $1}'` = '-' ]]
then
short_option=$1
shift
else
short_option=""
fi
case $1 in
use)
if [[ -z "$2" ]] ; then
if [[ -z "$PHPBREW_PHP" ]]
then
echo "Currently using system php"
else
echo "Currently using $PHPBREW_PHP"
fi
return
fi
if ! output="$(__phpbrew_php_exec env $(__phpbrew_normalize_build $2))"; then
echo "$output"
return 1
fi
eval "$output"
__phpbrew_set_path
;;
cd-src)
local SOURCE_DIR=$PHPBREW_HOME/build/$PHPBREW_PHP
if [[ -d $SOURCE_DIR ]] ; then
builtin cd $SOURCE_DIR
fi
;;
switch)
if [[ -z "$2" ]]; then
echo "Please specify the php version."
return 1
fi
__phpbrew_reinit $(__phpbrew_normalize_build $2)
;;
lookup-prefix)
if [[ -z "$2" ]] ; then
if [[ -n $PHPBREW_LOOKUP_PREFIX ]] ; then
echo $PHPBREW_LOOKUP_PREFIX
fi
else
export PHPBREW_LOOKUP_PREFIX=$(__phpbrew_set_lookup_prefix $2)
echo $PHPBREW_LOOKUP_PREFIX
__phpbrew_update_config
fi
;;
cd)
case $2 in
var)
local chdir=$PHPBREW_ROOT/php/$PHPBREW_PHP/var
;;
etc)
local chdir=$PHPBREW_ROOT/php/$PHPBREW_PHP/etc
;;
dist)
local chdir=$PHPBREW_ROOT/php/$PHPBREW_PHP
;;
build)
local chdir=$PHPBREW_ROOT/build/$PHPBREW_PHP
;;
*)
echo "$2 not found"
return 0
;;
esac
echo "Switching to $chdir, run 'cd -' to go back."
builtin cd $chdir
return 0
;;
each)
shift
__phpbrew_each "$@"
;;
fpm)
if ! [[ -z $3 ]]; then
PHP_BUILD=$3
else
PHP_BUILD=${PHPBREW_PHP}
fi
mkdir -p ${PHPBREW_ROOT}/php/${PHP_BUILD}/var/run
PHPFPM_BIN=${PHPBREW_ROOT}/php/${PHP_BUILD}/sbin/php-fpm
PHPFPM_PIDFILE=${PHPBREW_ROOT}/php/${PHP_BUILD}/var/run/php-fpm.pid
function fpm_start()
{
echo "Starting php-fpm..."
local regex="^php-5\.2.*"
if [[ ${PHP_BUILD} =~ ${regex} ]]; then
${PHPFPM_BIN} start
else
${PHPFPM_BIN} --php-ini ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/fpm/php.ini \
--fpm-config ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf \
--pid ${PHPFPM_PIDFILE} \
"$@"
fi
if [[ $? != "0" ]] ; then
echo "php-fpm start failed."
fi
}
function fpm_stop()
{
local regex="^php-5\.2.*"
if [[ ${PHPBREW_PHP} =~ ${regex} ]]; then
${PHPFPM_BIN} stop
elif [[ -e ${PHPFPM_PIDFILE} ]] ; then
echo "Stopping php-fpm..."
kill $(cat ${PHPFPM_PIDFILE})
rm -f ${PHPFPM_PIDFILE}
fi
}
case $2 in
start)
fpm_start "${@:4}"
;;
stop)
fpm_stop
;;
setup)
__phpbrew_php_exec $short_option "$@"
;;
restart)
fpm_stop
fpm_start "${@:4}"
;;
current)
if [[ -f $PHPFPM_PIDFILE ]] ; then
ps ux -p "$(cat $PHPFPM_PIDFILE)"
fi
;;
module)
$PHPFPM_BIN --php-ini ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/fpm/php.ini \
--fpm-config ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf \
-m | less
;;
info)
$PHPFPM_BIN --php-ini ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/fpm/php.ini \
--fpm-config ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf \
-i
;;
config)
if [[ -n $EDITOR ]] ; then
$EDITOR ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf
else
echo "Please set EDITOR environment variable for your favor."
nano ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf
fi
;;
which)
echo $PHPFPM_BIN
;;
help)
$PHPFPM_BIN --php-ini ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/fpm/php.ini \
--fpm-config ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf --help
;;
test)
$PHPFPM_BIN --php-ini ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/fpm/php.ini \
--fpm-config ${PHPBREW_ROOT}/php/${PHP_BUILD}/etc/php-fpm.conf --test
;;
*)
echo "Usage: phpbrew fpm [start|stop|restart|module|test|config|setup|info|current|which|help]"
;;
esac
;;
info)
__phpbrew_php_exec info | php
;;
off)
unset PHPBREW_PHP
unset PHPBREW_PATH
eval $(__phpbrew_php_exec env)
__phpbrew_set_path
;;
switch-off)
unset PHPBREW_PHP
unset PHPBREW_PATH
eval $(__phpbrew_php_exec env)
__phpbrew_reinit
echo "phpbrew is switched off."
;;
system)
if [[ -z "$2" ]] ; then
__phpbrew_php_exec system
else
local bin="$(__phpbrew_get_version_bin $2)"
__phpbrew_validate_interpreter "$bin" || return 1
export PHPBREW_SYSTEM_PHP="$bin"
__phpbrew_update_config
fi
;;
system-off)
__phpbrew_validate_interpreter "$(__phpbrew_which php)"
if [[ $? -ne 0 ]] ; then
echo "The currently used PHP build $PHPBREW_PHP cannot be used as PhpBrew interpreter"
echo "Please execute `phpbrew switch` using PHP $MIN_PHP_VERSION or newer before switching the system interpreter off"
return 1
fi
unset PHPBREW_SYSTEM_PHP
__phpbrew_update_config
;;
rehash)
echo "Rehashing..."
. ~/.phpbrew/bashrc
;;
purge)
if [[ -z "$2" ]]
then
__phpbrew_php_exec help
else
shift
__phpbrew_purge "$@"
fi
;;
*)
__phpbrew_php_exec $short_option "$@"
;;
esac
local exit_status=$?
if [[ $exit_status -ne 0 ]]; then
return $exit_status
fi
hash -r
}
function __phpbrew_update_config ()
{
if ! output="$(__phpbrew_php_exec env $(__phpbrew_normalize_build $1))"; then
echo "$output"
return 1
fi
(
echo "# DO NOT EDIT THIS FILE"
echo "$output"
) > "$PHPBREW_HOME/init"
. "$PHPBREW_HOME/init"
}
function __phpbrew_reinit ()
{
__phpbrew_update_config "$@" && __phpbrew_set_path
}
function __phpbrew_each()
{
local result=0
current="$PHPBREW_PHP"
for build in ${PHPBREW_ROOT}/php/* ; do
if [ -x "$build/bin/php" ]; then
phpbrew use $(basename "$build")
eval "$@" || result=$?
fi
done;
if ! [[ -z "$current" ]]
then
phpbrew use $current
else
phpbrew off
fi
return $result
}
function __phpbrew_purge()
{
local result=0
for arg in "$@"
do
__phpbrew_purge_build "$arg" || result=$?
done
return $result
}
function __phpbrew_purge_build ()
{
local PHP_BUILD=$(__phpbrew_normalize_build $1)
if [[ "$PHP_BUILD" = "$PHPBREW_PHP" ]]
then
echo "php version: $PHP_BUILD is already in use."
return 1
fi
local bin="$(__phpbrew_get_version_bin $PHP_BUILD)"
if [[ "$bin" = "$PHPBREW_SYSTEM_PHP" ]] ; then
echo "PHP build $PHP_BUILD is used as the system interpreter"
return 1
fi
_PHP_BIN_PATH=$PHPBREW_ROOT/php/$PHP_BUILD
if [ ! -d $_PHP_BIN_PATH ]; then
echo "php version: $PHP_BUILD not installed."
return 1
fi
_PHP_SOURCE_FILE=$PHPBREW_ROOT/build/$PHP_BUILD.tar.bz2
_PHP_BUILD_PATH=$PHPBREW_ROOT/build/$PHP_BUILD
rm -fr $_PHP_SOURCE_FILE $_PHP_BUILD_PATH $_PHP_BIN_PATH
echo "php version: $PHP_BUILD is removed and purged."
return 0
}
function phpbrew_current_php_version() {
if type "php" > /dev/null; then
local version=$(php -v | grep -E "PHP [578]" | sed 's/.*PHP \([^-]*\).*/\1/' | cut -c 1-6)
if [[ -z "$PHPBREW_PHP" ]]; then
echo "php:$version-system"
else
echo "php:$version-phpbrew"
fi
else
echo "php:not-installed"
fi
}
if [[ -n "$PHPBREW_SET_PROMPT" && "$PHPBREW_SET_PROMPT" == "1" ]]; then
export PS1="\w > \u@\h [\$(phpbrew_current_php_version)]\n\\$ "
fi
# the _phpbrewrc_load will be called after *every simple command* executed in bash,
# this will make the start up process slower if you have many commands to be run in your .bashrc or .zshrc
# so this function simply compares the directory and return if nothing neccessary to do.
#
# here is the description of trap from bash manual page:
#
# If one of the signals is DEBUG, the list of COMMANDS is executed after
# every simple command.
#
function _phpbrewrc_load ()
{
# check if working dir has changed
if [[ "$PWD" == "$PHPBREW_LAST_DIR" ]]; then
return
fi
local curr_dir="$PWD"
local prev_dir=""
local curr_fs=0
local prev_fs=0
while [[ -n "$curr_dir" && -d "$curr_dir" ]] ; do
prev_fs=$curr_fs
curr_fs=$(stat -c %d "$curr_dir" 2>/dev/null) # GNU version
if [ $? -ne 0 ]; then
curr_fs=$(stat -f %d "$curr_dir" 2>/dev/null) # BSD version
fi
# check if top level directory or filesystem boundary is reached
if [[ "$curr_dir" == "/" ]] || [ -z "$PHPBREW_RC_DISCOVERY_ACROSS_FILESYSTEM" -a $prev_fs -ne 0 -a $curr_fs -ne $prev_fs ]; then
# check if there's a previously loaded .phpbrewrc
if [[ ! -z "$PHPBREW_LAST_RC_DIR" ]]; then
unset PHPBREW_LAST_RC_DIR
__phpbrew_load_user_config
fi
break
fi
# check if .phpbrewrc present
if [[ -r "$curr_dir/.phpbrewrc" ]]; then
# check if it's not the same .phpbrewrc which was previously loaded
if [[ "$curr_dir" != "$PHPBREW_LAST_RC_DIR" ]]; then
__phpbrew_load_user_config
PHPBREW_LAST_RC_DIR="$curr_dir"
source "$curr_dir/.phpbrewrc"
fi
break
fi
curr_dir=$(dirname "$curr_dir")
done
PHPBREW_LAST_DIR="$PWD"
}
if [[ -n "$PHPBREW_RC_ENABLE" ]]; then
if [[ -n "$BASH_VERSION" ]]; then
trap "_phpbrewrc_load" DEBUG
fi
# zsh has easy-to-extend cd hooks, so we migth as well use them instead
# of running _phpbrewrc_load after EVERY command.
if [[ -n "$ZSH_VERSION" ]]; then
if [[ -n "$chpwd_functions" ]]; then
if [[ ${chpwd_functions[(ie)_phpbrewrc_load]} -gt ${#chpwd_functions} ]]; then
chpwd_functions+=_phpbrewrc_load
fi
else
chpwd_functions=( _phpbrewrc_load )
fi
fi
fi