#!/usr/local/cpanel/3rdparty/bin/perl

#                                      Copyright 2026 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

package scripts::ensure_imagick_for_php;

use cPstrict;

use Getopt::Long ();

exit( run(@ARGV) // 0 ) unless caller();

=head1 NAME

ensure_imagick_for_php - Ensure the imagick PECL extension is installed
and compiled against the current system ImageMagick library for all
installed PHP versions.

=head1 SYNOPSIS

    ensure_imagick_for_php [--help]

=head1 DESCRIPTION

Discovers all installed C<ea-phpXX> packages and, for each one:

=over 4

=item *

Installs the C<imagick> PECL extension if it is not already present.

=item *

Detects whether the loaded ImageMagick library version differs from the
version against which C<imagick> was compiled (the warning
C<"Imagick was compiled against ImageMagick version X but version Y is loaded">).

=item *

Automatically reinstalls C<imagick> when such a mismatch is detected,
ensuring the extension is compiled against the currently-installed library.

=back

This script can be run manually, scheduled via cron, or called as part of
the WP2 installation and upgrade flow.

=cut

sub run (@args) {

    my $help;

    Getopt::Long::GetOptionsFromArray( \@args, 'help' => \$help )
      or return usage(1);

    return usage() if $help;

    ensure_imagick_for_all_php();

    return 0;
}

sub ensure_imagick_for_all_php() {

    require Cpanel::ProgLang;
    require Cpanel::ProgLang::Supported::php::pecl;

    my $lang         = Cpanel::ProgLang->new( 'type' => 'php' );
    my @php_packages = $lang->get_installed_packages()->@*;

    if ( !@php_packages ) {
        say 'No ea-php packages found; nothing to do.';
        return;
    }

    for my $php_version (@php_packages) {
        eval { _ensure_imagick_for_php_version( $lang, $php_version ); 1 }
          or warn "Failed to ensure imagick for $php_version: $@\n";
    }

    return;
}

sub _ensure_imagick_for_php_version ( $lang, $php_version ) {

    my $pecl           = Cpanel::ProgLang::Supported::php::pecl->new( { lang => $lang, package => $php_version } );
    my $installed_list = $pecl->get_installed_list();
    my $is_installed   = grep { lc $_->{module} eq 'imagick' } @{$installed_list};

    if ($is_installed) {
        if ( _has_version_mismatch($php_version) ) {
            say "Re-installing imagick for $php_version (ImageMagick version mismatch detected).";
            say $pecl->reinstall( { module => 'imagick' } );
        }
        else {
            say "imagick for $php_version is installed with no version mismatch; skipping.";
        }
    }
    else {
        say "Installing imagick for $php_version.";
        say $pecl->install( { module => 'imagick' } );
    }

    return;
}

sub _has_version_mismatch ($php_version) {

    my $php_bin = _php_binary_path($php_version);

    return 0 unless _file_exists($php_bin);

    require Cpanel::SafeRun::Object;

    my $run = Cpanel::SafeRun::Object->new(
        program => $php_bin,
        args    => [ '-r', 'new Imagick();' ],
    );

    my $stderr = $run->stderr() // '';

    return $stderr =~ /Imagick was compiled against ImageMagick version \d+ but version \d+ is loaded/ ? 1 : 0;
}

sub _php_binary_path ($php_version) {
    return "/opt/cpanel/$php_version/root/usr/bin/php";
}

sub _file_exists ($path) {
    return -x $path ? 1 : 0;
}

sub usage ( $status = 0 ) {

    my $msg = <<'EOM';

ensure_imagick_for_php: Ensure imagick PECL extension is installed and compiled against the current ImageMagick library

Usage:
    ensure_imagick_for_php [--help]

  Options:
    --help:   Output usage and exit

Description:
    Discovers all installed ea-phpXX packages and ensures the imagick PECL
    extension is installed for each one. When a version mismatch between the
    imagick extension and the system ImageMagick library is detected, imagick
    is automatically reinstalled so that it is compiled against the current
    library version.

EOM

    if ($status) {
        print STDERR $msg;
    }
    else {
        print $msg;
    }

    return $status;
}

1;
