#!/bin/sh
#
# phpmod - a PHP module manager
#
# Copyright 2025 Marc Henderkes <pkg@henderkes.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

set -ue

SCRIPT_NAME=${0##*/}
QUIET=no
CONFDIR="/etc/php-zts"
PHP_BINARY="/usr/bin/php-zts"

warning() {
    if [ "$QUIET" = "no" ]; then
        echo "$@" >&2
    fi
}

usage() {
    [ -n "$@" ] && warning $@
    case "$SCRIPT_NAME" in
        *enmod*)
            echo "usage: ${SCRIPT_NAME} [-q] module_name [ module_name_2 ]"
            ;;
        *dismod*)
            echo "usage: ${SCRIPT_NAME} [-q] module_name [ module_name_2 ]"
            ;;
        *)
            echo "usage: ${SCRIPT_NAME} [-q] module_name [ module_name_2 ]"
            ;;
    esac
    exit 1
}

# Find the ini file for a module (could be modname.ini, NN-modname.ini, or .disabled variants)
find_ini_file() {
    local modname=$1
    local include_disabled=${2:-no}

    # Check for numbered file first (dynamic extension)
    for file in "${CONFDIR}/conf.d/"*"-${modname}.ini"; do
        if [ -f "$file" ]; then
            echo "$file"
            return 0
        fi
    done

    # Check for disabled numbered file if requested
    if [ "$include_disabled" = "yes" ]; then
        for file in "${CONFDIR}/conf.d/"*"-${modname}.ini.disabled"; do
            if [ -f "$file" ]; then
                echo "$file"
                return 0
            fi
        done
    fi

    # Check for non-numbered file (static extension)
    if [ -f "${CONFDIR}/conf.d/${modname}.ini" ]; then
        echo "${CONFDIR}/conf.d/${modname}.ini"
        return 0
    fi

    # Check for disabled non-numbered file if requested
    if [ "$include_disabled" = "yes" ]; then
        if [ -f "${CONFDIR}/conf.d/${modname}.ini.disabled" ]; then
            echo "${CONFDIR}/conf.d/${modname}.ini.disabled"
            return 0
        fi
    fi

    return 1
}

# Check if extension is statically compiled (no number prefix)
is_static_extension() {
    local inifile=$1
    local basename=$(basename "$inifile")

    # Static extensions have format "modname.ini" (no number prefix)
    # Dynamic extensions have format "NN-modname.ini" (with number prefix)
    case "$basename" in
        [0-9]*-*.ini)
            return 1  # Dynamic extension
            ;;
        *.ini)
            return 0  # Static extension
            ;;
    esac
    return 1
}

enmod() {
    local modname=$1
    local inifile

    # First check if already enabled
    if inifile=$(find_ini_file "$modname"); then
        # Check if it's a static extension
        if is_static_extension "$inifile"; then
            echo "Module ${modname} is statically compiled into PHP and always enabled"
            return 0
        fi

        if [ "$QUIET" = "no" ]; then
            echo "Module ${modname} already enabled"
        fi
        return 0
    fi

    # Not found as enabled, check for disabled version
    if ! inifile=$(find_ini_file "$modname" "yes"); then
        warning "Module ${modname} ini file not found in ${CONFDIR}/conf.d"
        return 1
    fi

    # If we found a .disabled file, it must be disabled, so enable it
    case "$inifile" in
        *.ini.disabled)
            local enabled_file="${inifile%.disabled}"
            mv "$inifile" "$enabled_file"
            echo "Enabled module: ${modname}"
            return 0
            ;;
        *)
            # Should not reach here, but handle gracefully
            if [ "$QUIET" = "no" ]; then
                echo "Module ${modname} already enabled"
            fi
            return 0
            ;;
    esac
}

dismod() {
    local modname=$1
    local inifile

    if ! inifile=$(find_ini_file "$modname"); then
        # Not found as enabled, check if already disabled
        if inifile=$(find_ini_file "$modname" "yes"); then
            # Found a .disabled file
            if [ "$QUIET" = "no" ]; then
                echo "Module ${modname} already disabled"
            fi
            return 0
        fi
        warning "Module ${modname} ini file not found in ${CONFDIR}/conf.d"
        return 1
    fi

    # Check if it's a static extension
    if is_static_extension "$inifile"; then
        if [ "$QUIET" = "no" ]; then
            echo "Module ${modname} is statically compiled into PHP and cannot be disabled"
        fi
        return 0
    fi

    # Rename .ini to .ini.disabled
    mv "$inifile" "${inifile}.disabled"
    echo "Disabled module: ${modname}"
    return 0
}

# Parse options
mods=""
while [ $# -gt 0 ]; do
    case "$1" in
        -q)
            QUIET=yes
            shift
            ;;
        -*)
            warning "Unknown option: $1"
            usage
            ;;
        *)
            mods="${mods}${mods:+ }${1%%/*}"
            shift
            ;;
    esac
done

[ -z "$mods" ] && usage

# Determine action based on script name
case "$SCRIPT_NAME" in
    *enmod*)
        for mod in $mods; do
            enmod "$mod" || true
        done
        ;;
    *dismod*)
        for mod in $mods; do
            dismod "$mod" || true
        done
        ;;
    *)
        warning "Unknown script name: ${SCRIPT_NAME}"
        exit 1
        ;;
esac

exit 0
