diff --git a/bin/ctrlhelper.sh b/bin/ctrlhelper.sh
new file mode 100644
index 000000000..d0169fae2
--- /dev/null
+++ b/bin/ctrlhelper.sh
@@ -0,0 +1,294 @@
+#!/bin/bash
+#
+# This script is designed to facilitate the tasks of
+# installing dependencies and updating CtrlPanel via CLI
+
+# shellcheck disable=SC2034
+readonly SCRIPT_VER="1.0.0"
+readonly DEFAULT_DIR="/var/www/ctrlpanel"
+
+#######################################
+# Colors
+#######################################
+readonly T_BL="\033[30m" # Blue text
+readonly T_RE="\033[31m" # Red text
+readonly T_CY="\033[36m" # Cyan text
+readonly T_WH="\033[37m" # White text
+
+readonly BT_RE="\033[91m" # Bright red text
+readonly BT_GR="\033[92m" # Bright green text
+readonly BT_YE="\033[93m" # Bright yellow text
+readonly BT_BLU="\033[94m" # Bright blue text
+readonly BT_CY="\033[96m" # Bright cyan text
+readonly BT_WH="\033[97m" # Bright white text
+
+readonly B_RE="\033[41m" # Red background
+
+readonly BB_GR="\033[102m" # Green bright background
+readonly BB_YE="\033[103m" # Yellow bright background
+readonly BB_BLU="\033[104m" # Blue bright background
+readonly BB_CY="\033[106m" # Cyan bright background
+
+readonly NC="\033[0m" # Reset
+readonly TB="\033[1m" # Bold
+readonly TU="\033[4m" # Underline
+
+#######################################
+# Visual blocks
+#######################################
+readonly CHECK="${BT_YE}${TB}(${BT_GR}✓${BT_YE})${NC}"
+readonly WARN="${BT_YE}${TB}(${BT_RE}!!${BT_YE})${NC}"
+readonly INFO="${BB_BLU}${BT_WH} INFO ${NC}"
+readonly ERROR="${B_RE}${BT_WH} ERROR ${NC}"
+
+#######################################
+# Return an error message in STDERR
+# Arguments:
+# Error message
+#######################################
+error_out() {
+ echo -e " ${ERROR} ${T_RE}$*${NC}" >&2
+}
+
+#######################################
+# Set the directory where CtrlPanel is installed
+# Globals:
+# DEFAULT_DIR
+# cpgg_dir
+#######################################
+set_cpgg_dir() {
+ local is_exists=""
+ local is_cpgg_root=""
+ local is_null=""
+
+ if [[ -z "${cli_mode}" ]]; then
+ if [[ ! -d "${DEFAULT_DIR}" ]] && [[ -z "${cpgg_dir}" ]]; then
+ while true; do
+ # Message that the user will see by default, if he specifies a
+ # non-existent directory or not root CtrlPanel directory
+ echo ""
+ if [[ -z "${is_exists}" ]] && [[ -z "${is_cpgg_root}" ]] || [[ "${is_null}" == "true" ]]; then
+ echo -e " ${T_CY}Default directory wasn't found. Specify directory \
+where your CtrlPanel is installed (e.g. /var/www/ctrlpanel)${NC}"
+ elif [[ ${is_exists} == false ]]; then
+ echo -e " ${T_CY}Directory ${BT_YE}${cpgg_dir}${T_CY} doesn't exist. \
+Specify directory where your CtrlPanel is installed \
+(e.g. /var/www/ctrlpanel)${NC}"
+ elif [[ ${is_cpgg_root} == false ]]; then
+ echo -e " ${BT_YE}${cpgg_dir}${T_CY} is not a root CtrlPanel \
+directory. Specify directory where your CtrlPanel is installed \
+(e.g. /var/www/ctrlpanel)${NC}"
+ fi
+
+ read -rep " > " cpgg_dir
+
+ # Deleting / at the end of the specified directory
+ cpgg_dir="${cpgg_dir%/}"
+
+ # Resetting validation values before validation
+ is_null=""
+ is_exists=""
+ is_cpgg_root=""
+
+ # Validation of directory specified by user
+ if [[ "${cpgg_dir}" == "" ]]; then
+ is_null="true"
+ elif [[ ! -d "${cpgg_dir}" ]]; then
+ is_exists="false"
+ elif [[ ! -f "${cpgg_dir}/config/app.php" ]]; then
+ is_cpgg_root="false"
+ else
+ break
+ fi
+
+ done
+ fi
+ else
+ # Error if default directory is not found and CtrlPanel root directory is
+ # not specified when using the CLI mode
+ if [[ ! -d "${DEFAULT_DIR}" ]] && [[ -z "${cpgg_dir}" ]]; then
+ error_out "Default directory wasn't found. Specify directory where your \
+CtrlPanel is installed using ${BT_YE}--cpgg-dir${T_RE} argument"
+ exit 1
+ fi
+ fi
+}
+
+#######################################
+# Handling startup arguments
+#######################################
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --cli)
+ cli_mode="true"
+ shift
+ ;;
+ --cpgg-dir=*)
+ cpgg_dir="${1#*=}"
+ cpgg_dir="${cpgg_dir%/}"
+ shift
+
+ if [[ "${cpgg_dir}" == "" ]]; then
+ error_out "Argument ${BT_YE}--cpgg-dir${T_RE} can't be empty!"
+ exit 1
+ elif [[ ! -d "${cpgg_dir}" ]]; then
+ error_out "Directory ${BT_YE}${cpgg_dir}${T_RE} doesn't exist."
+ exit 1
+ elif [[ ! -f "${cpgg_dir}/config/app.php" ]]; then
+ error_out "${BT_YE}${cpgg_dir}${T_RE} is not a root CtrlPanel directory."
+ exit 1
+ else
+ continue
+ fi
+ ;;
+ --force)
+ force="true"
+ shift
+ ;;
+ --install=*)
+ if [[ -n "${update}" ]]; then
+ error_out "You can't use ${BT_YE}--install${T_RE} with \
+${BT_YE}--update${T_RE} argument"
+ exit 1
+ fi
+
+ install="${1#*=}"
+ shift
+
+ if [[ "${install}" == "" ]]; then
+ error_out "Argument ${BT_YE}--install${T_RE} can't be empty!"
+ exit 1
+ elif [[ "${install}" != "full" && "${install}" != "min" ]]; then
+ error_out "Invalid option ${BT_YE}${install}${T_RE} for \
+${BT_YE}--install${T_RE} argument. Valid values are only \
+${BT_YE}${TU}full${NC}${T_RE} or ${BT_YE}${TU}min"
+ exit 1
+ fi
+ ;;
+ --update)
+ if [[ -n "${install}" ]]; then
+ error_out "You can't use ${BT_YE}--update${T_RE} with \
+${BT_YE}--install${T_RE} argument"
+ exit 1
+ fi
+
+ update="true"
+ shift
+ ;;
+ --help)
+ echo -e " ${BT_WH}Usage: ${T_CY}$0 ${BT_CY}[options]${NC}"
+ echo -e " ${BT_WH}Options:${NC}"
+ echo -e " ${BT_CY}--cli \
+${BT_WH}Use CLI mode. It does not have CLI-GUI interface, and all actions are \
+specified using action arguments${NC}"
+ echo -e " ${BT_CY}--cpgg-dir=
\
+${BT_WH}Allows you to specify the root directory of the CtrlPanel${NC}"
+ echo -e " ${BT_CY}--force \
+${BT_WH}Performs an action without confirmation (applicable for --install and \
+--update arguments in CLI mode)${NC}"
+ echo -e " ${BT_CY}--install= \
+${BT_WH}Perform installation. Valid values are full or min${NC}"
+ echo -e " ${BT_CY}--update \
+${BT_WH}Perform an update${NC}"
+ echo -e " ${BT_CY}--help \
+${BT_WH}Display this help message${NC}"
+ exit 0
+ ;;
+ *)
+ error_out "Argument ${BT_YE}$1${T_RE} not exists. Use \
+${BT_YE}--help${T_RE} to display all available arguments"
+ exit 1
+ ;;
+ esac
+done
+
+set_cpgg_dir
+
+# shellcheck source=/dev/null
+source "${cpgg_dir:-$DEFAULT_DIR}/bin/ctrlhelper_sub_scripts/menus.sh" \
+ || {
+ error_out "Source files could not be added! Are you sure you are using \
+script for version 0.10 or above of CtrlPanel? Please try to run the script \
+again, if the error persists, create support forum post on CtrlPanel's \
+Discord server!"
+ exit 1
+}
+# shellcheck source=/dev/null
+source "${cpgg_dir:-$DEFAULT_DIR}/bin/ctrlhelper_sub_scripts/functions.sh" \
+ || {
+ error_out "Source files could not be added! Are you sure you are using \
+script for version 0.10 or above of CtrlPanel? Please try to run the script \
+again, if the error persists, create support forum post on CtrlPanel's \
+Discord server!"
+ exit 1
+}
+
+cd "${cpgg_dir:-$DEFAULT_DIR}" \
+ || {
+ error_out "An error occurred while trying to switch to the working \
+directory. Please try to run the script again, if the error persists, create \
+support forum post on CtrlPanel's Discord server!"
+ exit 1
+}
+
+if [[ -z "${cli_mode}" ]]; then
+ save_terminal
+
+ get_version
+ update_needed_checker
+
+ main_menu
+
+ restore_terminal
+else
+ if [[ "${install}" == "full" ]]; then
+ if [[ "${force}" == "true" ]]; then
+ install_deps
+ else
+ confirm_dialog \
+ "${BT_YE}This action will install all the necessary dependencies such as \
+PHP, Redis, MariaDB and others, as well as install composer files.
+ You will still have to create MySQL user and configure nginx yourself.
+
+ ${BT_GR}Below is a list of all packages that will be installed${NE}" \
+ "${T_WH}software-properties-common curl apt-transport-https \
+ca-certificates gnupg lsb-release php8.3 \
+php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip,intl,redis} \
+mariadb-server nginx redis-server tar unzip git${NC}" \
+ "install_deps" \
+ "exit 0"
+ fi
+ elif [[ "${install}" == "min" ]]; then
+ if [[ "${force}" == "true" ]]; then
+ install_deps "true"
+ else
+ confirm_dialog \
+ "${BT_YE}This action will install all the necessary dependencies such as \
+PHP, Redis, Composer and others, as well as install composer files.
+
+ ${BT_GR}Below is a list of all packages that will be installed${NE}" \
+ "${T_WH}software-properties-common curl apt-transport-https \
+ca-certificates gnupg lsb-release php8.3 \
+php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip,intl,redis} \
+redis-server tar unzip git${NC}" \
+ "install_deps \"true\"" \
+ "exit 0"
+ fi
+ elif [[ "${update}" == "true" ]]; then
+ if [[ "${force}" == "true" ]]; then
+ update
+ else
+ confirm_dialog \
+ "${B_RE}${BT_WH} This action cannot be undone, create backup of the \
+database before updating! ${NC}" \
+ "${B_RE}${BT_WH} It will also remove all installed themes and addons. ${NC}" \
+ "update" \
+ "exit 0"
+ fi
+ else
+ error_out \
+ "You have not specified the action you want to do! Use \
+${BT_YE}--help${T_RE} to display all available arguments"
+ exit 1
+ fi
+fi
diff --git a/bin/ctrlhelper_sub_scripts/functions.sh b/bin/ctrlhelper_sub_scripts/functions.sh
new file mode 100644
index 000000000..b90a0ac2a
--- /dev/null
+++ b/bin/ctrlhelper_sub_scripts/functions.sh
@@ -0,0 +1,272 @@
+#!/bin/bash
+#
+# The auxiliary file for CtrlHelper script.
+# Contains important functions for the main script to work
+
+#######################################
+# Terminal save function, for recovery after exiting
+#######################################
+save_terminal() {
+ trap restore_terminal SIGINT
+ tput smcup
+}
+
+#######################################
+# Terminal recovery function, after execution
+#######################################
+restore_terminal() {
+ tput rmcup
+ exit
+}
+
+#######################################
+# Return an info message in STDOUT
+# Arguments:
+# Info message
+#######################################
+info_out() {
+ echo -e " ${INFO} ${BT_WH}$*${NC}"
+}
+
+#######################################
+# Getting current and latest version of CtrlPanel
+# Globals:
+# PANEL_VER
+# PANEL_LATEST_VER
+# DEFAULT_DIR
+# cpgg_dir
+#######################################
+get_version() {
+ PANEL_VER=$(
+ grep -oP "'version' => '\K[^']+" "${cpgg_dir:-$DEFAULT_DIR}/config/app.php"
+ )
+ readonly PANEL_VER
+ PANEL_LATEST_VER=$(
+ curl -s https://api.github.com/repos/ctrlpanel-gg/panel/tags \
+ | sed -n 's/.*"name": "\([^"]*\)".*/\1/p' \
+ | head -n 1
+ )
+ readonly PANEL_LATEST_VER
+}
+
+#######################################
+# Comparing current and latest version of CtrlPanel
+# Arguments:
+# Current version
+# Latest version
+# Outputs:
+# 0 if versions match
+# 1 if latest version is newer than the current one
+# 2 if current version is newer than the latest one
+#######################################
+version_compare() {
+ local current_version="$1"
+ readonly current_version
+ local latest_version="$2"
+ readonly latest_version
+
+ # Break down versions into components
+ IFS='.' read -r -a current_parts <<<"${current_version}"
+ IFS='.' read -r -a latest_parts <<<"${latest_version}"
+
+ # Add zeros to the shorter version (e.g. 0.10 => 0.10.0)
+ while ((${#current_parts[@]} < ${#latest_parts[@]})); do
+ current_parts+=("0")
+ done
+
+ # Compare components one by one
+ for ((i = 0; i < ${#current_parts[@]}; i++)); do
+ if ((current_parts[i] < latest_parts[i])); then
+ echo "1"
+ return 0
+ elif ((current_parts[i] > latest_parts[i])); then
+ echo "2"
+ return 0
+ fi
+ done
+
+ echo "0"
+ return 0
+}
+
+#######################################
+# Checking if the CtrlPanel needs to be updated
+# Globals:
+# PANEL_VER
+# PANEL_LATEST_VER
+# Outputs:
+# 0 if versions match
+# 1 if latest version is newer than the current one
+# 2 if current version is newer than the latest one
+#######################################
+update_needed_checker() {
+ is_update_needed=$(version_compare "${PANEL_VER}" "${PANEL_LATEST_VER}")
+ # shellcheck disable=SC2034
+ readonly is_update_needed
+}
+
+#######################################
+#
+#######################################
+check_distro() {
+ local choice
+ local unknown_choice="$1"
+ local previous_choice="$2"
+ distro=$(lsb_release -is)
+ distro="${distro,,}"
+
+ if [[ "${distro}" != "debian" && "${distro}" != "ubuntu" ]]; then
+ logo
+
+ error_out "Your OS is not supported! You can continue the installation in compatibility mode, but in this case it is not guaranteed that all packages will be installed successfully"
+ echo -e ""
+ echo -e " So that we can add support for your OS, please let us know the information below"
+ echo -e " Detected OS: ${distro}"
+ echo -e " Detected OS (full): $(lsb_release -sd)"
+ echo ""
+ echo -e " ${BB_CY} ${T_BL}Select an option: ${NC}"
+ echo -e " ${BT_WH}1. Continue in Debian compatibility mode${NC}"
+ echo -e " ${BT_WH}2. Continue in Ubuntu compatibility mode${NC}"
+ echo -e " ${BT_WH}q. Quit${NC}"
+ echo ""
+ if [[ "${unknown_choice}" == "true" ]]; then
+ echo -e " ${T_RE}Unknown choice ${BT_YE}${TU}${previous_choice}${NC}"
+ fi
+ read -rp " > " choice
+
+ case ${choice} in
+ 1) distro="debian" ;;
+ 2) distro="ubuntu" ;;
+ q) restore_terminal ;;
+ *) check_distro "true" "${choice}" ;;
+ esac
+ fi
+}
+
+#######################################
+# Installing dependencies
+# Globals:
+# cli_mode
+# Arguments:
+# NULL for full installation, true for minimal install
+#######################################
+install_deps() {
+ local minimal="$1"
+ # Removing double quotes at the beginning and end
+ minimal=${minimal#\"}
+ minimal=${minimal%\"}
+ readonly minimal
+
+ logo
+
+ info_out "Adding \"add-apt-repository\" command and additional dependencies"
+ sudo apt -y -qq install software-properties-common curl apt-transport-https ca-certificates gnupg lsb-release
+
+ check_distro
+
+ if [[ "$distro" == "debian" ]]; then
+ if [[ ! -f "/usr/share/keyrings/deb.sury.org-php.gpg" ]]; then
+ info_out "Adding PHP repository keyring"
+ sudo curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
+ fi
+
+ if [[ ! -f "/etc/apt/sources.list.d/deb.sury.org-php.list" ]]; then
+ info_out "Adding PHP repository"
+ sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/deb.sury.org-php.list'
+ fi
+ elif [[ "$distro" == "ubuntu" ]]; then
+ info_out "Adding PHP repository"
+ LC_ALL=C.UTF-8 sudo add-apt-repository -y ppa:ondrej/php
+ fi
+
+ if [[ ! -f "/usr/share/keyrings/redis-archive-keyring.gpg" ]]; then
+ info_out "Adding Redis repository"
+ curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
+ echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" \
+ | sudo tee /etc/apt/sources.list.d/redis.list
+ fi
+
+ if [[ "$distro" == "ubuntu" && "$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"')" != "24.04" ]]; then
+ if [[ -z "${minimal}" ]]; then
+ info_out "Adding MariaDB repository"
+ curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
+ elif [[ -n "${minimal}" && "${minimal}" != "true" ]]; then
+ error_out "Invalid argument ${minimal} for install_deps function. Please, report to developers!"
+ exit 1
+ fi
+ fi
+
+ info_out "Running \"apt update\""
+ sudo apt update
+
+ info_out "Installing dependencies"
+ if [[ "${minimal}" ]]; then
+ sudo apt -y -qq install php8.3 php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip,intl,redis} redis-server tar unzip git
+ elif [[ -z "${minimal}" ]]; then
+ sudo apt -y -qq install php8.3 php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip,intl,redis} mariadb-server nginx redis-server tar unzip git
+ else
+ error_out "Invalid argument ${minimal} for install_deps function. Please, report to developers!"
+ exit 1
+ fi
+
+ info_out "Installing Composer"
+ curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
+
+ info_out "Installing Composer dependencies to the CtrlPanel"
+ sudo COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --optimize-autoloader --no-interaction
+
+ if [[ -z "${cli_mode}" ]]; then
+ echo ""
+ echo -e " ${BB_GR}${T_BL} Done! ${NC} ${BT_GR}Installation finished. Press any key to exit${NC}"
+ read -rsn 1 -p " "
+ fi
+}
+
+#######################################
+# Update CtrlPanel
+# Globals:
+# DEFAULT_DIR
+# cpgg_dir
+# cli_mode
+#######################################
+update() {
+ logo
+
+ info_out "Enabling maintenance mode"
+ sudo php "${cpgg_dir:-$DEFAULT_DIR}"/artisan down
+
+ if ! sudo git config --global --get-all safe.directory | grep -q -w "${cpgg_dir:-$DEFAULT_DIR}"; then
+ info_out "Adding CtrlPanel directory to the git save.directory list"
+ sudo git config --global --add safe.directory "${cpgg_dir:-$DEFAULT_DIR}"
+ fi
+
+ info_out "Downloading file updates"
+ sudo git stash
+ sudo git pull
+
+ info_out "Installing Composer dependencies"
+ sudo COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --optimize-autoloader --no-interaction
+
+ info_out "Migrating database updates"
+ sudo php "${cpgg_dir:-$DEFAULT_DIR}"/artisan migrate --seed --force
+
+ info_out "Clearing the cache"
+ sudo php "${cpgg_dir:-$DEFAULT_DIR}"/artisan view:clear
+ sudo php "${cpgg_dir:-$DEFAULT_DIR}"/artisan config:clear
+
+ info_out "Setting permissions"
+ sudo chown -R www-data:www-data "${cpgg_dir:-$DEFAULT_DIR}"
+ sudo chmod -R 755 "${cpgg_dir:-$DEFAULT_DIR}"
+
+ info_out "Restarting Queue Workers"
+ sudo php "${cpgg_dir:-$DEFAULT_DIR}"/artisan queue:restart
+
+ info_out "Disabling maintenance mode"
+ sudo php "${cpgg_dir:-$DEFAULT_DIR}"/artisan up
+
+ if [[ -z "${cli_mode}" ]]; then
+ echo ""
+ echo -e " ${BB_GR}${T_BL} Done! ${NC} ${BT_GR}Update finished. Press any key to exit${NC}"
+ read -rsn 1 -p " "
+ fi
+}
\ No newline at end of file
diff --git a/bin/ctrlhelper_sub_scripts/menus.sh b/bin/ctrlhelper_sub_scripts/menus.sh
new file mode 100644
index 000000000..7000778e3
--- /dev/null
+++ b/bin/ctrlhelper_sub_scripts/menus.sh
@@ -0,0 +1,232 @@
+#!/bin/bash
+#
+# The auxiliary file for CtrlHelper script.
+# Contains the CLI-GUI parts of the interface
+
+#######################################
+# Logo to display in the CLI-GUI
+#######################################
+logo() {
+ if [[ -z "${cli_mode}" ]]; then
+ clear
+ fi
+ echo -e "${BT_CY} ________ ______ __ ${NC}"
+ echo -e "${BT_CY} / ____/ /______/ / __ \____ _____ ___ / /____ _____ _${NC}"
+ echo -e "${BT_CY} / / / __/ ___/ / /_/ / __ \`/ __ \/ _ \/ // __ \`/ __ \`/${NC}"
+ echo -e "${T_CY} / /___/ /_/ / / / ____/ /_/ / / / / __/ // /_/ / /_/ / ${NC}"
+ echo -e "${T_CY} \____/\__/_/ /_/_/ \__,_/_/ /_/\___/_(_)__, /\__, / ${NC}"
+ echo -e "${T_CY} /____//____/ ${NC}"
+ echo ""
+}
+
+#######################################
+# Displaying the current version of the script and CtrlPanel under the logo
+# Globals:
+# SCRIPT_VER
+# PANEL_VER
+#######################################
+logo_version() {
+ echo -e " ${BT_YE}Script version:${NC}${BT_WH} ${SCRIPT_VER}${NC}"
+ echo -e " ${BT_YE}CtrlPanel version:${NC}${BT_WH} ${PANEL_VER}${NC}"
+ echo ""
+}
+
+#######################################
+# Message to the user about whether they need to update, or if they are
+# already using latest version
+# Globals:
+# is_update_needed
+#######################################
+logo_message() {
+ # shellcheck disable=SC2154
+ if [[ ${is_update_needed} == 0 ]]; then
+ echo -e " ${CHECK} ${BT_GR}You are using the latest version! \
+No update required.${NC}"
+ echo ""
+ elif [[ ${is_update_needed} == 1 ]]; then
+ echo -e " ${WARN} ${BT_RE}New version available! You can update right now \
+by selecting ${BT_YE}${TU}Update${NC} ${BT_RE}option.${NC}"
+ echo ""
+ elif [[ ${is_update_needed} == 2 ]]; then
+ echo -e " ${CHECK} ${BT_GR}You are using a newer version! Most likely you \
+have a development version installed.${NC}"
+ echo ""
+ fi
+}
+
+#######################################
+# Action confirmation dialog
+# Arguments:
+# First line of the message
+# Second line of the message
+# Action that will be performed upon confirmation
+# Exit action
+# Unknown choice validation response
+# Previous choice if $unknown_choice is true
+#######################################
+confirm_dialog() {
+ local choice
+ local message_line1="$1"
+ local message_line2="$2"
+ local action="$3"
+ local exit_action="$4"
+ local unknown_choice="$5"
+ local previous_choice="$6"
+
+ logo
+ echo -e " ${message_line1}"
+ if [[ -n "${message_line2}" ]]; then
+ echo -e " ${message_line2}"
+ fi
+ echo ""
+ echo -e " ${BT_WH}Continue? (Y/n)${NC}"
+ if [[ "${unknown_choice}" == "true" ]]; then
+ echo -e " ${T_RE}Unknown choice ${BT_YE}${TU}${previous_choice}${NC}"
+ fi
+ read -rp " > " choice
+
+ case "${choice}" in
+ y | Y) ${action} ;;
+ n | N) ${exit_action} ;;
+ *)
+ confirm_dialog \
+ "${message_line1}" \
+ "${message_line2}" \
+ "${action}" \
+ "${exit_action}" \
+ "true" \
+ "${choice}"
+ ;;
+ esac
+}
+
+#######################################
+# Main menu in CLI-GUI mode
+#######################################
+main_menu() {
+ local choice=""
+
+ logo
+ logo_version
+ logo_message
+ echo -e " ${BB_CY} ${T_BL}Select an option: ${NC}"
+ echo -e " ${BT_WH}1. Install dependencies${NC}"
+ echo -e " ${BT_WH}2. Update${NC}"
+ echo -e " ${BT_WH}3. Info & Help${NC}"
+ echo -e " ${BT_WH}q. Quit${NC}"
+ echo ""
+ read -rp " > " choice
+
+ case ${choice} in
+ 1) install_menu ;;
+ 2)
+ confirm_dialog "${B_RE}${BT_WH} This action cannot be undone, create \
+backup of the database before updating! ${NC}" \
+ "${B_RE}${BT_WH} It will also remove all installed themes and addons. ${NC}" \
+ "update" \
+ "main_menu"
+ ;;
+ 3) info_help_menu ;;
+ q) restore_terminal ;;
+ *) main_menu ;;
+ esac
+}
+
+#######################################
+# Install dependencies menu in CLI-GUI mode
+#######################################
+install_menu() {
+ local choice=""
+
+ logo
+ echo -e " ${BT_YE}This action will install all the necessary dependencies \
+such as PHP, Redis, MariaDB and others, as well as install composer files.${NC}"
+ echo -e " ${BT_YE}You will still need to create MySQL user/database and \
+configure nginx yourself.${NC}"
+ echo ""
+ echo -e " ${BB_CY} ${T_BL}Select an option: ${NC}"
+ echo -e " ${BT_WH}1. Full install${NC}"
+ echo -e " ${BT_WH}2. Minimal install (Not include MariaDB and nginx)${NC}"
+ echo -e " ${BT_WH}b. Back to main menu${NC}"
+ echo ""
+ read -rp " > " choice
+
+ case "${choice}" in
+ 1)
+ confirm_dialog \
+ "${BT_YE}You are going to install full set of dependencies, below is a \
+list of all packages that will be installed" \
+ "${T_WH}software-properties-common curl apt-transport-https \
+ca-certificates gnupg lsb-release php8.3 \
+php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip,intl,redis} \
+mariadb-server nginx redis-server tar unzip git${NC}" \
+ "install_deps" \
+ "install_menu"
+ ;;
+ 2)
+ confirm_dialog \
+ "${BT_YE}You are going to install minimal set of dependencies, below is a \
+list of all packages that will be installed${NC}" \
+ "${T_WH}software-properties-common curl apt-transport-https \
+ca-certificates gnupg lsb-release php8.3 \
+php8.3-{cli,gd,mysql,pdo,mbstring,tokenizer,bcmath,xml,fpm,curl,zip,intl,redis} \
+redis-server tar unzip git${NC}" \
+ "install_deps \"true\"" \
+ "install_menu"
+ ;;
+ b) main_menu ;;
+ *) install_menu ;;
+ esac
+}
+
+#######################################
+# Info & Help menu in CLI-GUI mode
+#######################################
+info_help_menu() {
+ local choice=""
+ local easter_egg="$1"
+
+ logo
+ logo_version
+ if [[ "${easter_egg}" == "unlocked" ]]; then
+ echo -e " ${B_RE}${BT_WH} Easter egg unlocked!!! ${NC}"
+ echo -e " ${BT_WH}${TB}Congratulations, you found Easter egg. Here's a \
+well-deserved cake${NC}"
+ echo -e " ${BT_BLU}${TU}https://bit.ly/ctrlhelper_easter_egg_cake${NC}"
+ echo ""
+ fi
+ echo -e " ${BB_BLU}${BT_WH} Info ${NC}"
+ echo -e " ${BT_WH}This script is designed to simplify the installation of \
+dependencies and updating the CtrlPanel.${NC}"
+ echo -e " ${BT_WH}It can be executed both in CLI-GUI interface mode and in \
+CLI mode with an action argument specified${NC}"
+ echo ""
+ echo -e " ${BB_CY}${T_BL} Help ${NC}"
+ echo -e " ${BT_WH}Usage: ${T_CY}$0 ${BT_CY}[options]${NC}"
+ echo -e " ${BT_WH}Options:${NC}"
+ echo -e " ${BT_CY}--cli \
+${BT_WH}Use CLI mode. It does not have CLI-GUI interface, and all actions are \
+specified using action arguments${NC}"
+ echo -e " ${BT_CY}--cpgg-dir= \
+${BT_WH}Allows you to specify the root directory of the CtrlPanel${NC}"
+ echo -e " ${BT_CY}--force \
+${BT_WH}Performs an action without confirmation (applicable for --install and \
+--update arguments in CLI mode)${NC}"
+ echo -e " ${BT_CY}--install= \
+${BT_WH}Perform installation. Valid values are full or min${NC}"
+ echo -e " ${BT_CY}--update \
+${BT_WH}Perform an update${NC}"
+ echo -e " ${BT_CY}--help \
+${BT_WH}Display help message${NC}"
+ echo -e " ${BB_YE}${T_BL} Credits ${NC}"
+ echo -e " ${BT_WH}${TB}Made by MrWeez with \
+${NC}${BT_RE}♥${NC}"
+ echo ""
+ echo " Press any key to return to the main menu"
+
+ read -rsn 1 -p " " choice
+ case "${choice}" in
+ ^) info_help_menu "unlocked" ;;
+ *) main_menu ;;
+ esac
+}