
# script_ghost_desc()
sub script_ghost_desc
{
return "Ghost";
}

sub script_ghost_uses
{
return ( "node", "proxy" );
}

sub script_ghost_longdesc
{
return "Ghost is a powerful open source app for new-media creators to publish, share, and grow a business around their content";
}

# script_ghost_versions()
sub script_ghost_versions
{
return ( "5.26.3", "4.48.9" );
}

sub script_ghost_release
{
return 7;	# PATH order fix
}

sub script_ghost_category
{
return "Blog";
}

# script_ghost_depends(&domain, version)
# Make sure we are on Linux
sub script_ghost_depends
{
local ($d, $ver) = @_;
local @rv;
if ($gconfig{'os_type'} !~ /-linux$/) {
	push(@rv, "Node.js binaries are only available on Linux");
	}
return @rv;
}

# script_ghost_params(&domain, version, &upgrade-info)
# Returns HTML for table rows for options for installing PHP-NUKE
sub script_ghost_params
{
local ($d, $ver, $upgrade) = @_;
local $rv;
local $hdir = &public_html_dir($d, 1);
if ($upgrade) {
	# Options are fixed when upgrading
	local $dir = $upgrade->{'opts'}->{'dir'};
	$dir =~ s/^$d->{'home'}\///;
	$rv .= &ui_table_row("Install directory", $dir);
	}
else {
	# Show editable install options
	$rv .= &ui_table_row("Install sub-directory under <tt>$hdir</tt>",
			     &ui_opt_textbox("dir", &substitute_scriptname_template("ghostblog", $d), 30, "At top level"));
	}
return $rv;
}

# script_ghost_parse(&domain, version, &in, &upgrade-info)
# Returns either a hash ref of parsed options, or an error string
sub script_ghost_parse
{
local ($d, $ver, $in, $upgrade) = @_;
if ($upgrade) {
	# Options are always the same
	return $upgrade->{'opts'};
	}
else {
	local $hdir = &public_html_dir($d, 0);
	$in->{'dir_def'} || $in->{'dir'} =~ /\S/ && $in->{'dir'} !~ /\.\./ ||
		return "Missing or invalid installation directory";
	$in->{'dir_def'} || $in->{'dir'} ne "ghost" ||
		return "Installation directory cannot be named 'ghost'";
	local $dir = $in->{'dir_def'} ? $hdir : "$hdir/$in->{'dir'}";
	return { 'dir' => $dir,
		 'path' => $in->{'dir_def'} ? "/" : "/$in->{'dir'}", };
	}
}

# script_ghost_check(&domain, version, &opts, &upgrade-info)
# Returns an error message if a required option is missing or invalid
sub script_ghost_check
{
local ($d, $ver, $opts, $upgrade) = @_;
if (-r "$opts->{'dir'}/bin/node") {
	return "Ghost appears to be already installed in the selected directory";
	}
$opts->{'mongrels'} ||= 1;
return undef;
}

# script_ghost_files(&domain, version, &opts, &upgrade-info)
# Returns a list of files needed by Rails, each of which is a hash ref
# containing a name, filename and URL
sub script_ghost_files
{
local ($d, $ver, $opts, $upgrade) = @_;
my @files;
my $nodever = '16.19.0';
local $u = &backquote_command("uname -m");
local $arch = $u =~ /x86_64/ ? "x64" : ($u =~ /arm/i ? 'arm64' : "x86");
@files = ( $upgrade ? { } : {
	   'name' => "node",
	   'file' => "node-v$nodever-linux-$arch.tar.gz",
	   'url' => "http://nodejs.org/dist/v$nodever/node-v$nodever-linux-$arch.tar.gz"
	   },
	   {
	   'name' => "source",
	   'file' => "ghost-$ver.zip",
	   'url' => "https://github.com/TryGhost/Ghost/archive/refs/tags/v$ver.zip"
	   } 
	   );
return @files;
}

# script_ghost_install(&domain, version, &opts, &files, &upgrade-info)
# Actually installs PhpWiki, and returns either 1 and an informational
# message, or 0 and an error
sub script_ghost_install
{
my ($d, $version, $opts, $files, $upgrade) = @_;
my $port;
my $url = &script_path_url($d, $opts);
my $urlnns = $url;
$urlnns =~ s/\/$//;
$urlnns =~ s/https:/http:/;

# Set env path
$ENV{'PATH'} = "$opts->{'dir'}/bin:$opts->{'dir'}/node_modules/.bin:$ENV{'PATH'}";

# Prepare exports
my $export_path = $ENV{'PATH'};
my $export_node_options = "--max-old-space-size=1024";

# Stop running server if upgrading
if ($upgrade) {
	&script_ghost_stop_server($d, $opts);
	$port = $opts->{'port'};

	my $out = &run_as_domain_user($d, "export NODE_OPTIONS=\"$export_node_options\" && export PATH=\"$export_path\" && cd $opts->{'dir'}/installations && $opts->{'dir'}/node_modules/.bin/ghost update $version --no-setup-linux-user --no-restart 2>&1");
	if ($?) {
		return (-1, "Ghost upgrade failed: <pre>$out</pre>");
		} 
	else {
		&script_ghost_start_server($d, $opts);
		}
	}
else {
	# Extract tar file to temp dir and copy to target
	local $temp = &transname();
	local $err = &extract_script_archive($files->{'node'}, $temp, $d,
	                                     $opts->{'dir'}, "node-*");
	$err && return (0, "Failed to extract binaries : $err");
	local $temp2 = &transname();
	local $err = &extract_script_archive($files->{'source'}, $temp2, $d,
	                                     "$opts->{'dir'}/.ghost-tmp");
	$err && return (0, "Failed to extract source : $err");

	&copy_source_dest("$opts->{'dir'}/.ghost-tmp/package.json", $opts->{'dir'});
	&unlink_file("$opts->{'dir'}/.ghost-tmp");
	
	# Pick a free port
	$port = &allocate_mongrel_port(undef, 1);
	$opts->{'port'} = $port;

	# Run install
	my $out = &run_as_domain_user($d, "export NODE_OPTIONS=\"$export_node_options\" && export PATH=\"$export_path\" && cd $opts->{'dir'} && $opts->{'dir'}/bin/npm install ghost-cli\@latest && mkdir $opts->{'dir'}/installations && cd $opts->{'dir'}/installations && $opts->{'dir'}/node_modules/.bin/ghost install $version --port $port --url $urlnns local && $opts->{'dir'}/node_modules/.bin/ghost stop 2>&1");
	if ($?) {
		return (-1, "Ghost installation failed: <pre>$out</pre>");
		}

	# Create systemd script
	my $userd = $d->{'parent'} ? &get_domain($d->{'parent'}) : $d;
	if (&foreign_installed("init") && $userd && $userd->{'unix'} && !$upgrade) {
		&foreign_require("init");
		&init::enable_at_boot(
			"ghost-$userd->{'dom'}-$port",
			"Start Ghost server for $userd->{'dom'} (Virtualmin)",
			"$opts->{'dir'}/node_modules/.bin/ghost start --no-setup-linux-user",
			"$opts->{'dir'}/node_modules/.bin/ghost stop",
			undef,
			{ 'opts' => {
			  'type'    => 'forking',
			  'reload'  => "$opts->{'dir'}/node_modules/.bin/ghost restart",
			  'user'    => $userd->{'uid'},
			  'group'   => $userd->{'gid'},
			  'env'     => "PATH=$export_path",
			  'workdir' => "$opts->{'dir'}/installations",
			  'logstd'  => "$opts->{'dir'}/ghost.log",
			  'logerr'  => "$opts->{'dir'}/ghost.err"
			}},
			);
		&script_ghost_start_server($userd, $opts);
		}
	
	# Configure Apache to proxy to it
	&setup_mongrel_proxy($d, $opts->{'path'}, $port,
			     $opts->{'path'} eq "/" ? "" : $opts->{'path'});
	
	# Unlink tmp file
	&unlink_file("$opts->{'dir'}/package.json");
	}

local $rp = $opts->{'dir'};
$rp =~ s/^$d->{'home'}\///;
local $adminurl = $url.'ghost';
my $updtext = $upgrade ?
                "Ghost upgrade complete. Go to <a target=_blank href='$adminurl'>$adminurl</a> to manage your blog." :
                "Ghost installation complete. Go to <a target=_blank href='$adminurl'>$adminurl</a> to create the admin account.";
return (1, $updtext, "Under $rp", $url);
}

# script_ghost_`(&domain, version, &opts)
# Un-installs a Rails installation, by deleting the directory and database.
# Returns 1 on success and a message, or 0 on failure and an error
sub script_ghost_uninstall
{
local ($d, $version, $opts) = @_;

# Shut down and remove ghost server
&script_ghost_delete($d, $opts);

# Remove the contents of the target directory
local $derr = &delete_script_install_directory($d, $opts);
return (0, $derr) if ($derr);

# Remove proxy Apache config entry for /ghost
&delete_mongrel_proxy($d, $opts->{'path'});

return (1, "Ghost directory deleted.");
}

# script_ghost_delete(&domain, &opts)
sub script_ghost_delete
{
my ($d, $opts) = @_;
&script_ghost_stop_server($d, $opts);
&foreign_require("init");
&init::delete_at_boot("ghost-$d->{'dom'}-$opts->{'port'}");
}

# script_ghost_stop_server(&domain, &opts)
sub script_ghost_stop_server
{
my ($d, $opts) = @_;
&foreign_require("init");
my $name = "ghost-$d->{'dom'}-$opts->{'port'}";
&init::stop_action($name) if (&init::action_status($name));
&init::disable_at_boot($name);
}

sub script_ghost_start_server
{
my ($d, $opts) = @_;
&foreign_require("init");
my $name = "ghost-$d->{'dom'}-$opts->{'port'}";
if (&init::action_status($name)) {
	&init::start_action($name);
	&init::enable_at_boot($name);
	}
}

sub script_ghost_status_server
{
my ($d, $opts) = @_;
&foreign_require("init");
my $name = "ghost-$d->{'dom'}-$opts->{'port'}";
if (&init::action_status($name)) {
	my $status = &init::status_action($name);
	return $status ? ( $status ) : ( );
	}
}

sub script_ghost_latest
{
my ($ver) = @_;
if ($ver =~ /^0\.7\./) {
	return ( );
	}
else {
	return ( "https://github.com/TryGhost/Ghost/releases",
		 "v([0-9]+\\.[0-9\\.]+)" );
	}
}

sub script_ghost_site
{
return 'http://ghost.org/';
}

1;
