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

// Protect from unauthorized access
defined('_JEXEC') or die();

if (function_exists('akeebaBackupOnAfterRenderToFixBrokenCloudFlareRocketLoader'))
{
	return;
}

/**
 * CloudFlare has a broken feature called Rocket Loader. It tries to load all Javascript asynchronously disregarding
 * the load order specified by the developers. As a result it causes JavaScript errors on the page which end
 * up preventing any JavaScript from running. Yes, including the JavaScript which powers every single Akeeba Backup
 * feature (as well as many Joomla, WordPress, Drupal etc features). For their description do read:
 * https://support.cloudflare.com/hc/en-us/articles/200168056-What-does-Rocket-Loader-do-
 *
 * For a developer's description of what this MASSIVELY BROKEN feature does read:
 * http://webmasters.stackexchange.com/a/60277
 * As the guy succinctly puts it "I'm actually quite shocked that it works (although perhaps it doesn't always)".
 *
 * In any case, their documentation (https://support.cloudflare.com/hc/en-us/articles/200169436--How-can-I-have-Rocket-Loader-ignore-my-script-s-in-Automatic-Mode-)
 * suggests adding the non-standard `data-cfasync="false"` attribute BEFORE the script's attribute. Here's the thing.
 * Joomla! does NOT let you do that. So the only thing we can do is parse Joomla!'s HTML output and forcibly add this
 * attribute using regular expressions search & replace. Normally this requires a system plugin to hook into Joomla's
 * onAfterRender event. But we can't do that. So we do the next best thing: abuse Joomla's event system to register the
 * even handler directly, without going through JPlugin. This is the kind of crap I was happy to had gotten rid of in
 * Akeeba Backup 5.0 because it's slow and cumbersome. Yet, the brokenness of CloudFlare forces me to re-implement a
 * slow, cumbersome approach which has a negative impact to the component's performance. Ironic, considering how
 * CloudFlare is supposed to speed up your site...
 *
 * RECOMMENDATION: AVOID USING CLOUDFLARE AT ALL COSTS.
 *
 * @return  void
 *
 * @since  5.1.3
 */
function akeebaBackupOnAfterRenderToFixBrokenCloudFlareRocketLoader()
{
	// The generated HTML
	$app    = JFactory::getApplication();
	$buffer = $app->getBody();

	// Find the <head.....</head> section
	$from = stripos($buffer, '<head');

	if ($from === false)
	{
		return;
	}

	$to = stripos($buffer, '</head', $from + 5);

	if ($to === false)
	{
		return;
	}

	// Extract <head> section
	$head = substr($buffer, $from, $to - $from);

	// Replace '<script...src' with '<script...data-cfasync="false" src'
	$regEx = '/<script([^>]*)src\s?=\s?(\'|")/im';
	$head = preg_replace($regEx, '<script$1 data-cfasync="false" src=$2', $head);

	// Reconstruct the page's HTML and set it back to the buffer
	$buffer = substr($buffer, 0, $from) . $head . substr($buffer, $to);
	$app->setBody($buffer);
}
