<?php
/**
 * @package   admintools
 * @copyright Copyright (c)2010-2026 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Plugin\System\AdminTools\Feature;

defined('_JEXEC') || die;

use Joomla\CMS\Uri\Uri;

class LinkMigration extends Base
{
	/** @var null|array The domains to migrate from */
	protected $oldDomains = null;

	/** @var null|string The domain of this site */
	protected $myDomain = null;

	/**
	 * Is this feature enabled?
	 *
	 * @return bool
	 */
	public function isEnabled()
	{
		// We only use this feature in the front-end
		if ($this->app->isClient('administrator'))
		{
			return false;
		}

		// The feature must be enabled
		if ($this->wafParams->getValue('linkmigration', 0) != 1)
		{
			return false;
		}

		// Populate the old domains array
		$this->populateOldDomains();

		// If there are no old domains to migrate from, what exactly am I doing here?
		if (empty($this->oldDomains))
		{
			return false;
		}

		return true;
	}

	/**
	 * Provides link migration services. All absolute links pointing to any of the old domain names
	 * are being rewritten to point to the current domain name. This runs a full page replacement
	 * using Regular Expressions, so even menus with absolute URLs will be migrated!
	 */
	public function onAfterRenderLatebound(): void
	{
		$this->populateOldDomains();

		if (empty($this->oldDomains))
		{
			// If there are no old domains to migrate from, what exactly am I doing here?
			return;
		}

		$this->populateMyDomain();

		$buffer = $this->app->getBody();

		$pattern           = '/(href|src)=\"([^"]*)\"/i';
		$number_of_matches = preg_match_all($pattern, $buffer, $matches, PREG_OFFSET_CAPTURE);

		if ($number_of_matches > 0)
		{
			$substitutions = $matches[2];
			$last_position = 0;
			$temp          = '';

			// Loop all URLs
			foreach ($substitutions as &$entry)
			{
				// Copy unchanged part, if it exists
				if ($entry[1] > 0)
				{
					$temp .= substr($buffer, $last_position, $entry[1] - $last_position);
				}

				// Add the new URL
				$temp .= $this->replaceDomain($entry[0]);

				// Calculate next starting offset
				$last_position = $entry[1] + strlen($entry[0]);
			}

			// Do we have any remaining part of the string we have to copy?
			if ($last_position < strlen($buffer))
			{
				$temp .= substr($buffer, $last_position);
			}

			// Replace content with the processed one
			unset($buffer);

			$this->app->setBody($temp);

			unset($temp);
		}
	}

	/**
	 * Replaces a URL's domain name (if it is in the substitution list) with the
	 * current site's domain name
	 *
	 * @param $url string The URL to process
	 *
	 * @return string The processed URL
	 */
	protected function replaceDomain($url)
	{
		foreach ($this->oldDomains as $domain)
		{
			if (substr($url, 0, strlen($domain)) == $domain)
			{
				return $this->myDomain . substr($url, strlen($domain));
			}
			elseif (substr($url, 0, strlen($domain) + 7) == 'http://' . $domain)
			{
				return 'http://' . $this->myDomain . substr($url, strlen($domain) + 7);
			}
			elseif (substr($url, 0, strlen($domain) + 8) == 'https://' . $domain)
			{
				return 'https://' . $this->myDomain . substr($url, strlen($domain) + 8);
			}
		}

		return $url;
	}

	/**
	 * Populates the oldDomains array
	 *
	 * @return  void
	 */
	protected function populateOldDomains()
	{
		$this->oldDomains = [];

		$list = $this->wafParams->getValue('migratelist', '');

		// Do not run if we don't have anything
		if (!$list)
		{
			return;
		}

		// Sanitize input
		$list = str_replace("\r", "", $list);

		$temp = explode("\n", $list);

		if (!empty($temp))
		{
			foreach ($temp as $entry)
			{
				// Skip empty lines
				if (!$entry)
				{
					continue;
				}

				if (substr($entry, -1) == '/')
				{
					$entry = substr($entry, 0, -1);
				}

				if (substr($entry, 0, 7) == 'http://')
				{
					$entry = substr($entry, 7);
				}

				if (substr($entry, 0, 8) == 'https://')
				{
					$entry = substr($entry, 8);
				}

				$this->oldDomains[] = $entry;
			}
		}
	}

	/**
	 * Populates the myDomain variable
	 *
	 * @return  void
	 */
	protected function populateMyDomain()
	{
		$this->myDomain = Uri::base(false);

		if (substr($this->myDomain, -1) == '/')
		{
			$this->myDomain = substr($this->myDomain, 0, -1);
		}

		if (substr($this->myDomain, 0, 7) == 'http://')
		{
			$this->myDomain = substr($this->myDomain, 7);
		}

		if (substr($this->myDomain, 0, 8) == 'https://')
		{
			$this->myDomain = substr($this->myDomain, 8);
		}
	}
}
