# MyBiz HelpDesk by Gravita Tech: one image for demo.gravitatech.com/mybiz-helpdesk/
#
# FreeScout 1.8.248 (pinned: the committed tree in freescout/, tag 1.8.248, commit 56c4d01, with
# vendor/ as FreeScout ships it) plus the GravitaDemo module, on PHP 8.3 with Apache httpd,
# in the MyBiz POS pattern (apps/mybiz-pos/gravita/hosting/Dockerfile).
# The same image runs twice (compose.yaml):
#   app     Apache on port 8080, the pages
#   worker  FreeScout's scheduler every minute (it starts its own queue worker) and the idle reset
#
# Build context: apps/mybiz-helpdesk. From there:
#     docker build -f gravita/hosting/Dockerfile -t mybiz-helpdesk:1 .
# Dockerfile.dockerignore keeps .env, the laptop runtimes, data and logs out of the context.
#
# No secret is in this image. Every setting is read from the environment (compose.yaml, .env on
# the server): Laravel 5.5 runs without a .env file and reads APP_KEY, APP_URL, DB_* from the environment.
# FreeScout's self-update is off (APP_DISABLE_UPDATING=true below and in compose.yaml).

FROM php:8.3-apache AS mybiz-helpdesk

LABEL org.opencontainers.image.title="MyBiz HelpDesk by Gravita Tech" \
      org.opencontainers.image.description="FreeScout 1.8.248 served under /mybiz-helpdesk/" \
      org.opencontainers.image.licenses="AGPL-3.0"

ENV APP_ENV=production \
    APP_DEBUG=false \
    APP_DISABLE_UPDATING=true \
    APP_TIMEZONE=Asia/Jakarta \
    GRAVITA_APP_DIR=/var/www/app \
    PORT=8080

# FreeScout's required extensions (config/installer.php: OpenSSL PDO Mbstring Tokenizer JSON XML GD
# fileinfo ZIP iconv cURL DOM libxml) plus pdo_mysql and mysqli for MariaDB, intl (dates), exif and
# bcmath, and pcntl, which FreeScout uses to stop a stuck queue worker. IMAP is optional in
# FreeScout 1.8 and not needed: the demo never fetches mail.
# procps gives FreeScout the `ps` it uses to find its own queue worker.
RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        procps \
        libfreetype6-dev \
        libicu-dev \
        libjpeg62-turbo-dev \
        libonig-dev \
        libpng-dev \
        libzip-dev; \
    missing=""; \
    for ext in bcmath curl exif fileinfo gd iconv intl mbstring mysqli pcntl pdo_mysql zip; do \
        php -m | grep -qix "$ext" || missing="$missing $ext"; \
    done; \
    echo "PHP extensions missing from the base image:${missing:- none}"; \
    case " $missing " in *" gd "*) docker-php-ext-configure gd --with-freetype --with-jpeg ;; esac; \
    if [ -n "$missing" ]; then docker-php-ext-install -j"$(nproc)" $missing; fi; \
    apt-get clean; \
    rm -rf /var/lib/apt/lists/*

# The build stops if any extension is still missing ($missing above is unquoted on purpose).
RUN for ext in bcmath curl dom exif fileinfo gd iconv intl json libxml mbstring mysqli openssl pcntl pdo pdo_mysql tokenizer xml zip; do \
        php -m | grep -qix "$ext" || { echo "missing PHP extension: $ext" >&2; exit 1; }; \
    done

RUN a2enmod rewrite headers expires setenvif

# The Biznet server is shared by several apps. Apache's stock prefork setting allows 150 PHP
# processes; 8 is enough for the demo and fits the app's memory limit (compose.yaml, 512 MB):
# one FreeScout request peaked at 41 MB on the laptop (30 Oct 2026, six visitors at once).
RUN printf '%s\n' \
        '<IfModule mpm_prefork_module>' \
        '    StartServers             2' \
        '    MinSpareServers          2' \
        '    MaxSpareServers          4' \
        '    MaxRequestWorkers        8' \
        '    MaxConnectionsPerChild   500' \
        '</IfModule>' \
    > /etc/apache2/conf-available/mybiz-helpdesk-workers.conf \
    && a2enconf mybiz-helpdesk-workers

# apps/mybiz-helpdesk/runtime/php/php.ini, except error_log (containers write to stderr).
RUN printf '%s\n' \
        'memory_limit = 256M' \
        'upload_max_filesize = 20M' \
        'post_max_size = 20M' \
        'max_execution_time = 120' \
        'display_errors = Off' \
        'log_errors = On' \
        'error_log = /proc/self/fd/2' \
        'variables_order = "EGPCS"' \
        'expose_php = Off' \
        'date.timezone = "Asia/Jakarta"' \
    > /usr/local/etc/php/conf.d/zz-mybiz-helpdesk.ini

# The app: FreeScout (with the module) and the Gravita tools the reset uses.
# Layout: /var/www/app/freescout (served from its public/), /var/www/app/gravita, /var/www/app/logs.
WORKDIR /var/www/app
COPY --chown=www-data:www-data freescout/ /var/www/app/freescout/
COPY --chown=www-data:www-data gravita/seed/ /var/www/app/gravita/seed/
COPY --chown=www-data:www-data gravita/tools/reset-demo.sh /var/www/app/gravita/tools/reset-demo.sh
# The "Source code" link's zip (AGPL-3.0 section 13), made from the committed HEAD by
# gravita/tools/make-source-zip.php before packaging; the build stops if it is missing.
COPY dist/mybiz-helpdesk-source.zip /var/www/app/dist/mybiz-helpdesk-source.zip

# Files written on Windows may carry CR LF endings; shell scripts and PHP must not. Strip CR from every
# text file of the copied tree, then stop the build if any .sh, .php or .json file still has one.
# (RUN uses sh, which has no $'\r': the CR character comes from printf.)
RUN set -eux; \
    find /var/www/app -type f \( -name '*.sh' -o -name '*.php' -o -name '*.json' -o -name '*.js' -o -name '*.css' \
        -o -name '*.md' -o -name 'artisan' -o -name '.htaccess' \) -not -path '*/vendor/*' \
        -exec sed -i 's/\r$//' {} +; \
    CR="$(printf '\r')"; \
    if grep -rlI --include='*.sh' --include='*.php' --include='*.json' "$CR" /var/www/app/freescout/app \
        /var/www/app/freescout/Modules /var/www/app/freescout/config /var/www/app/freescout/resources/lang \
        /var/www/app/freescout/database /var/www/app/gravita; then \
        echo "CR line endings left in the files above" >&2; exit 1; \
    fi

# Links FreeScout makes at install time (storage:link, module install), made here so they exist in
# the image: public/storage -> storage/app/public, public/modules/gravitademo -> the module's Public/.
RUN set -eux; \
    cd /var/www/app/freescout; \
    rm -rf public/storage public/modules/gravitademo; \
    ln -s ../storage/app/public public/storage; \
    mkdir -p public/modules public/js/builds public/css/builds; \
    ln -s ../../Modules/GravitaDemo/Public public/modules/gravitademo; \
    rm -f .env storage/.installed bootstrap/cache/config.php; \
    mkdir -p /var/www/app/logs storage/app/gravita; \
    chown -R www-data:www-data /var/www/app/logs storage bootstrap/cache public/js/builds public/css/builds public/modules

COPY gravita/hosting/apache-mybiz-helpdesk.conf /etc/apache2/sites-available/mybiz-helpdesk.conf
COPY --chmod=0755 gravita/hosting/mybiz-helpdesk-entrypoint.sh /usr/local/bin/mybiz-helpdesk-entrypoint
COPY --chmod=0755 gravita/hosting/mybiz-helpdesk-worker.sh /usr/local/bin/mybiz-helpdesk-worker
RUN sed -i 's/\r$//' /etc/apache2/sites-available/mybiz-helpdesk.conf /usr/local/bin/mybiz-helpdesk-entrypoint /usr/local/bin/mybiz-helpdesk-worker \
    && a2dissite 000-default.conf \
    && a2ensite mybiz-helpdesk.conf

EXPOSE 8080

ENTRYPOINT ["/usr/local/bin/mybiz-helpdesk-entrypoint"]
CMD ["app"]
