Last active
February 11, 2023 22:36
-
-
Save robfrawley/5e4851c27c62026955bb54fa66b4755e to your computer and use it in GitHub Desktop.
Download PHP Versions (Ubuntu)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
## | |
## GLOBAL VARIABLE DEFINITIONS | |
## | |
declare -a PHP_VER_LIST_DISABLED=( | |
'5.6' | |
) | |
declare -a PHP_VER_LIST_DEFAULTS=("${(@f)$( | |
apt-cache search php 2> /dev/null \ | |
| grep -E -o '\bphp[0-9\.]{3}' 2> /dev/null \ | |
| sort \ | |
| uniq \ | |
| grep -oE '[0-9\.]{3}' 2> /dev/null | |
)}") | |
declare -a SUDO_OPT_LIST=( | |
'-p' 'Enter the %u user password to continue with the requested installation or removal operations...' | |
) | |
declare -A APT_OPT_LIST=( | |
[install]='-qqq -y' | |
[remove]='-qqq -y --purge' | |
[autoremove]='-qqq -y --purge' | |
) | |
declare -A CMD_ACT_ALTS=( | |
[i]='install' | |
[r]='remove' | |
[u]='remove' | |
[uninstall]='remove' | |
[l]='list' | |
[a]='list' | |
[available]='list' | |
[t]='list' | |
[targets]='list' | |
) | |
declare -A CMD_ACT_DESC=( | |
[install]='Installation' | |
[remove]='Removal' | |
[list]='List' | |
) | |
declare -a SYS_PKG_LIST=( | |
imagemagick-6.q16hdri | |
memcached | |
sqlite3 | |
mariadb-server | |
mariadb-client | |
) | |
declare -a PHP_PKG_LIST=( | |
apcu | |
apcu-bc | |
ast | |
bcmath | |
bz2 | |
cli | |
curl | |
decimal | |
dev | |
gd | |
geoip | |
gmp | |
gnupg | |
grpc | |
igbinary | |
imagick | |
inotify | |
intl | |
json | |
lz4 | |
mbstring | |
mcrypt | |
memcached | |
msgpack | |
mysql | |
opcache | |
pgsql | |
phpdbg | |
protobuf | |
ps | |
pspell | |
readline | |
rrd | |
sqlite3 | |
ssh2 | |
xdebug | |
xml | |
xmlrpc | |
xsl | |
yaml | |
zip | |
zstd | |
) | |
declare -A PHP_PKG_VERS=( | |
[5.6]='' | |
[7.0]='' | |
[7.1]='' | |
[7.2]='' | |
[7.3]='' | |
[7.4]='' | |
[8.0]='' | |
[8.1]='' | |
[8.2]='' | |
) | |
## | |
## INTERNAL VARIABLE DEFINITIONS | |
## | |
declare _SDO_CALL_EXE="$(command -v sudo)" | |
declare _APT_CALL_EXE="$(command -v apt)" | |
declare -a _APT_OPTS_EXE=() | |
declare _APT_CALL_STR='' | |
declare _APT_CALL_LEN=0 | |
## | |
## GLOBAL FUNCTION DEFINITIONS | |
## | |
function print_wrap() | |
{ | |
printf -- "${@}" | |
} | |
function str_repeat() | |
{ | |
local str="${1}" | |
local len="${2:-1}" | |
for i in $(seq 1 ${len}); do | |
print_wrap "${str}" | |
done | |
} | |
function str_pluralize() | |
{ | |
local size="${1}" | |
local base="${2}" | |
local plur="${3:-${base}}s" | |
if [[ ${size} -eq 1 ]]; then | |
print_wrap '%s' "${base}" | |
else | |
print_wrap '%s' "${plur}" | |
fi | |
} | |
function str_explode_on_regex() | |
{ | |
local value="${1}" | |
local regex_s="${2}" | |
local regex_r="${3:-\n}" | |
sed -E 's/'"${regex_s}"'/'"${regex_r}"'/g' \ | |
<<< "${value}" 2> /dev/null | |
} | |
function str_explode_on_spaces() | |
{ | |
str_explode_on_regex "${1}" "\b[ ]+\b" "\n" | |
} | |
function arr_join() | |
{ | |
local separator="${1}" | |
local str_quote="${2:-1}" | |
sed -E 's/'"${separator}"'$//g' <<< $( | |
sed -E 's/[ ]+/'"${separator}"'/g' <<< "$( | |
[[ ${str_quote} -eq 1 ]] \ | |
&& print_wrap '"%s" ' "${@:3}" \ | |
|| print_wrap '%s ' "${@:3}" | |
)" | |
) | |
} | |
function arr_join_on_spaced_comma() | |
{ | |
arr_join ', ' 0 "${@}" | |
} | |
function arr_join_quoted_on_spaced_comma() | |
{ | |
arr_join ', ' 1 "${@}" | |
} | |
function write_text() | |
{ | |
print_wrap "${@}" | |
} | |
function write_newl() | |
{ | |
local num="${1:-1}" | |
for i in {1.."${num}"}; do | |
write_text "\n" | |
done | |
} | |
function write_line() | |
{ | |
write_text "${1:-}\n" "${@:2}" | |
} | |
function write_capt() | |
{ | |
local package_list="${@}" | |
write_line '>> %s %s' "${_APT_CALL_STR}" "$( | |
write_text '%s' "${package_list[*]}" \ | |
| fold -s -w $(($(tput cols)-$((4+_APT_CALL_LEN)))) \ | |
| head -n1 | |
)" | |
write_text '%s' "${package_list[*]}" \ | |
| fold -s -w $(($(tput cols)-$((4+_APT_CALL_LEN)))) \ | |
| sed -E '1d; s/^/>> '"$(str_repeat ' ' ${_APT_CALL_LEN})"' /g' | |
} | |
function write_list() | |
{ | |
write_line '-- %s' "${@}" | |
} | |
function write_line_type_fail() | |
{ | |
1>&2 write_newl | |
1>&2 write_text '!! ' | |
1>&2 write_line "${@:2}" | |
1>&2 write_newl | |
exit "${1}" | |
} | |
function write_line_type_warn() | |
{ | |
1>&2 write_newl | |
1>&2 write_text '!! ' | |
1>&2 write_line "${@}" | |
} | |
function write_line_type_head() | |
{ | |
write_newl | |
write_text '## ' | |
write_line "${@}" | |
} | |
function exists_in_list() | |
{ | |
local find="${1}" | |
local -a list=("${@:2}") | |
write_line '%s' "${(@v)list}" \ | |
| grep -oE '^'"${find}"'$' &> /dev/null | |
} | |
function exists_in_list_and_non_empty() | |
{ | |
exists_in_list "${@}" && [[ ${#} -gt 1 ]] | |
} | |
function resolve_real_pkg_name() | |
{ | |
local package="${1}" | |
local version="${2}" | |
write_text 'php%s-%s' "${version}" "${package}" | |
} | |
function is_pkg_available() | |
{ | |
local p="${1}" | |
apt info "${p}" 2> /dev/null \ | |
| grep -oE '^Version:' &> /dev/null | |
} | |
function is_php_ver_installed() | |
{ | |
local v="${1}" | |
dpkg -l 2> /dev/null \ | |
| grep -Eo '^ii[ ]+php'"${v}"'[^ ]+' &> /dev/null | |
} | |
function build_and_filter_pkg_list() | |
{ | |
local v="${1}" | |
for p in "${@:2}"; do | |
local r="$(resolve_real_pkg_name "${p}" "${v}")" | |
if is_pkg_available "${r}"; then | |
write_line "${r}" | |
fi | |
done | |
} | |
function resolve_php_act_name() | |
{ | |
local name="${1}" | |
for a r in "${(@vk)CMD_ACT_ALTS}"; do | |
if [[ "${name}" == "${a}" ]]; then | |
name="$(resolve_php_act_name "${r}")" | |
fi | |
done | |
write_text '%s' "${name}" | |
} | |
function resolve_php_pkg_list__adls() | |
{ | |
local v="${1}" | |
if exists_in_list_and_non_empty "${v}" "${(@k)PHP_PKG_VERS}"; then | |
build_and_filter_pkg_list "${v}" "${(@f)$( | |
str_explode_on_spaces "${PHP_PKG_VERS[${v}]}" | |
)}" | |
fi | |
} | |
function resolve_php_pkg_list__base() | |
{ | |
local v="${1}" | |
build_and_filter_pkg_list "${v}" "${(@v)PHP_PKG_LIST}" | |
} | |
function resolve_php_pkg_list() | |
{ | |
local version="${1}" | |
local -a pkglist=("${(@f)$( | |
sort <<< "$( | |
resolve_php_pkg_list__base "${version}" | |
resolve_php_pkg_list__adls "${version}" | |
)" | uniq | |
)}") | |
write_line '%s' "${(@v)pkglist}" | |
} | |
function resolve_sys_pkg_list__autoinstalled() | |
{ | |
"${_SDO_CALL_EXE}" "${(@v)SUDO_OPT_LIST}" "${_APT_CALL_EXE}" autoremove --dry-run 2> /dev/null \ | |
| grep -Po '^Remv \K[^ ]+' 2> /dev/null | |
} | |
function update_sys_pkgs__rmtcache() | |
{ | |
write_line_type_head 'Updating Package Cache...' | |
if ! "${_SDO_CALL_EXE}" "${(@v)SUDO_OPT_LIST}" "${_APT_CALL_EXE}" update -qqq; then | |
write_line_type_fail 3 'Failed to update package cache!' | |
fi | |
} | |
function remove_sys_pkgs__autoinst() | |
{ | |
local -a del_packages=($(resolve_sys_pkg_list__autoinstalled)) | |
if [[ ${#del_packages[@]} -le 0 ]]; then | |
return | |
fi | |
write_line_type_head \ | |
'System Auto-Installation %s (%d %s)' \ | |
"$(str_pluralize "${#del_packages[@]}" "Removal")" \ | |
"${#del_packages[@]}" \ | |
"$(str_pluralize "${#del_packages[@]}" "package")" | |
write_list "${(@v)del_packages}" | |
write_line '>> %s %s autoremove %s' \ | |
"${_SDO_CALL_EXE}" \ | |
"${_APT_CALL_EXE}" \ | |
"${APT_OPT_LIST[autoremove]}" | |
if ! "${_SDO_CALL_EXE}" "${(@v)SUDO_OPT_LIST}" "${_APT_CALL_EXE}" autoremove $( | |
str_explode_on_spaces "${APT_OPT_LIST[autoremove]}" | |
); then | |
write_line_type_fail 2 'Failed to successfully complete requested operations!' | |
fi | |
} | |
function remove_sys_pkgs__depslist() | |
{ | |
local name="${1}" | |
local -a list=("${@:2}") | |
if [[ ${#list[@]} -ne ${#PHP_VER_LIST_DEFAULTS[@]} ]] && [[ ${name} != 'install' ]]; then | |
return | |
fi | |
write_line_type_head \ | |
'System Package %s Command (%d %s)' \ | |
"${CMD_ACT_DESC[${name}]}" \ | |
"${#SYS_PKG_LIST[@]}" \ | |
"$(str_pluralize "${#SYS_PKG_LIST[@]}" "package")" | |
write_list "${(@v)SYS_PKG_LIST}" | |
write_capt "${(@v)SYS_PKG_LIST}" | |
if ! "${_SDO_CALL_EXE}" "${(@v)SUDO_OPT_LIST}" "${_APT_CALL_EXE}" "${(@v)_APT_OPTS_EXE}" "${(@v)SYS_PKG_LIST}"; then | |
write_line_type_fail 2 'Failed to successfully complete requested operations!' | |
fi | |
} | |
function output_php_vers__listings() | |
{ | |
write_line_type_head \ | |
'Listing available PHP targets (%d %s)' \ | |
"${#PHP_VER_LIST_DEFAULTS[@]}" \ | |
"$(str_pluralize "${#PHP_VER_LIST_DEFAULTS[@]}" "version")" | |
write_list "${(@v)PHP_VER_LIST_DEFAULTS}" | |
write_newl | |
exit 0 | |
} | |
function output_php_vers__subjects() | |
{ | |
local name="${1}" | |
local -a list=("${@:2}") | |
write_line_type_head \ | |
'Performing PHP %s (%d %s)' \ | |
"$(str_pluralize "${#list[@]}" "${CMD_ACT_DESC[${name}]}")" \ | |
"${#list[@]}" \ | |
"$(str_pluralize "${#list[@]}" "version")" | |
write_list "${(@v)list}" | |
} | |
function resolve_apt_opt_list() | |
{ | |
local name="${1}" | |
sed -E 's/\b[ ]+\B/\n/g' <<< "${APT_OPT_LIST[${name}]}" 2> /dev/null | |
} | |
function main() | |
{ | |
if command -v ssh-askpass &> /dev/null; then | |
export SUDO_ASKPASS="$(command -v ssh-askpass)" | |
SUDO_OPT_LIST+=("--askpass") | |
fi | |
local php_act_name="$(resolve_php_act_name "${1:-install}")" | |
local -a php_ver_list=() | |
local php_ver_temp='' | |
local php_ver_posn=0 | |
local php_ver_opts=0 | |
if [[ "${php_act_name}" == 'list' ]]; then | |
output_php_vers__listings | |
fi | |
for v in "${@:2}"; do | |
for s in "${(@v)php_ver_list}"; do | |
if [[ "${v}" == "${s}" ]]; then | |
continue 2 | |
fi | |
done | |
php_ver_opts=$((php_ver_opts + 1)) | |
for s in "${(@v)PHP_VER_LIST_DEFAULTS}"; do | |
if [[ ${v} == ${s} ]]; then | |
php_ver_list+="${v}" | |
continue 2 | |
fi | |
done | |
write_line_type_warn 'Ignoring invalid specified PHP version "%s"...' "${v}" | |
done | |
if [[ ${php_ver_opts} -eq 0 ]]; then | |
for v in "${(@v)PHP_VER_LIST_DEFAULTS}"; do | |
for b in "${(@v)PHP_VER_LIST_DISABLED}"; do | |
if [[ "${v}" == "${b}" ]] && [[ "${php_act_name}" != 'remove' ]]; then | |
continue 2 | |
fi | |
done | |
php_ver_list+=("${v}") | |
done | |
fi | |
php_ver_temp="${(@v)php_ver_list}" | |
php_ver_list=($( | |
str_explode_on_spaces "${php_ver_temp}" \ | |
| sort --general-numeric-sort \ | |
| uniq | |
)) | |
if [[ ${#php_ver_list[@]} -eq 0 ]]; then | |
write_line_type_fail 3 \ | |
'No valid PHP versions specified (use one of %s)...' \ | |
"$(arr_join_quoted_on_spaced_comma "${(@v)PHP_VER_LIST_DEFAULTS}")" | |
fi | |
if ! exists_in_list_and_non_empty "${php_act_name:-x}" "${(@k)APT_OPT_LIST}"; then | |
write_line_type_fail 3 \ | |
'Invalid action type of "%s" (use one of %s)' \ | |
"${php_act_name}" \ | |
"$(arr_join_quoted_on_spaced_comma "${(@k)APT_OPT_LIST}")" | |
fi | |
_APT_OPTS_EXE=("${php_act_name}" $(resolve_apt_opt_list "${php_act_name}")) | |
_APT_CALL_STR="$(write_line '%s' "${_SDO_CALL_EXE} ${_APT_CALL_EXE} ${_APT_OPTS_EXE[*]}")" | |
_APT_CALL_LEN="${#_APT_CALL_STR}" | |
update_sys_pkgs__rmtcache | |
remove_sys_pkgs__autoinst | |
output_php_vers__subjects "${php_act_name}" "${(@v)php_ver_list}" | |
for v in "${(@v)php_ver_list}"; do | |
php_ver_posn=$((php_ver_posn + 1)) | |
write_newl | |
write_text '## PHP %s %d/%d [%s] ' \ | |
"${CMD_ACT_DESC[${php_act_name}]}" \ | |
"${php_ver_posn}" \ | |
"${#php_ver_list[@]}" \ | |
"${v}" | |
if [[ ${php_act_name} == 'remove' ]] && ! is_php_ver_installed "${v}"; then | |
write_newl | |
write_line '-- Skipping (no matching installed packages found for version "%s")...' "${v}" | |
continue | |
fi | |
local -a package_list=("${(@f)$(resolve_php_pkg_list "${v}")}") | |
write_line '(%d %s)' "${#package_list[@]}" "$(str_pluralize "${#package_list[@]}" "package")" | |
write_list "${(@v)package_list}" | |
write_capt "${(@v)package_list}" | |
write_newl | |
if ! "${_SDO_CALL_EXE}" "${(@v)SUDO_OPT_LIST}" "${_APT_CALL_EXE}" "${(@v)_APT_OPTS_EXE}" "${(@v)package_list}"; then | |
write_line_type_fail 2 'Failed to successfully complete requested operations!' | |
fi | |
done | |
remove_sys_pkgs__depslist "${php_act_name}" "${(@v)php_ver_list}" | |
remove_sys_pkgs__autoinst | |
write_line_type_head 'Completed all operations...' | |
write_newl | |
} | |
## | |
## CALL MAIN FUNCTION | |
## | |
main "${@}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment