<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package clearFusionCMS
 * @copyright Copyright (c) 2017 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * cfFacebookInstantArticle Class
 *
 * Class to transform a chunk of HTML to be compatible with Facebook instant articles.
 *
 * @package clearFusionCMS
 */
abstract class cfFacebookInstantArticle {

	/**
	 * Transform the HTML for an article body to be instant article compatiable.
	 *
	 * @param string $html The article body to transform.
	 * @return string The transformed HTML.
	 */
	static function transform($html) {
		// Get the site base URL
		$baseURI = clearFusionCMS::getRequest()->getBasePath(true, clearFusionCMS::getSiteSSL());

		// Create the document from the HTML
		$doc = new DOMDocument();
		libxml_use_internal_errors(true); // Stop HTML5 blowing up
		$doc->loadHTML($html);
		libxml_use_internal_errors(false);

		$domx = new DOMXPath($doc);

		// Remove styles from tags
		$items = $domx->query('//*[@style]');
		foreach($items as $item) {
			$item->removeAttribute('style');
		}

		// Remove classes from tags
		$items = $domx->query('//*[@class]');
		foreach($items as $item) {
			$item->removeAttribute('class');
		}

		// Remove script and forms tags
		$items = $domx->query('//script|//form');
		foreach($items as $item) {
			$item->parentNode->removeChild($item);
		}

		// Find the lowest header number and convert to h1, everything higher becomes h2
		$level = 1;
		for(;$level<=6;$level++) {
			$items = $domx->query('//h' . $level);
			if($items->length)
				break;
		}

		if($level > 1) {
			foreach($items as $item) {
				$f = $item->ownerDocument->createElement('h1', $item->firstChild->nodeValue);
				$item->parentNode->replaceChild($f, $item);
			}
		}

		$items = $domx->query('//h2|//h3|//h4|//h5|//h6');
		foreach($items as $item) {
			$f = $item->ownerDocument->createElement('h2', $item->firstChild->nodeValue);
			$item->parentNode->replaceChild($f, $item);
		}

		// Look for empty p tags and remove
		$items = $domx->query('//p');
		foreach($items as $item) {
			if(empty($item->nodeValue)) {
				if(!$item->hasChildNodes() || ($item->childNodes->length == 1 && $item->firstChild->tagName == 'br')) {
					$item->parentNode->removeChild($item);
				}
			}
		}

		// Wrap images in figures
		$items = $domx->query('//img');
		foreach($items as $item) {
			if($item->parentNode->tagName != 'figure') {
				$f = $item->ownerDocument->createElement('figure');
				$item->parentNode->replaceChild($f, $item);
				$f->appendChild($item);
			}

			// Convert relative URLs to absolute
			$src = $item->getAttribute('src');
			if(!preg_match('#^https?://#', $src)) {
				if(preg_match('#^//#', $src))
					$item->setAttribute('src', 'https:' . $src);
				else
					$item->setAttribute('src', $baseURI . ltrim($src, '/'));
			}
		}

		// Convert relative links to absolute links
		$items = $domx->query('//a');
		foreach($items as $item) {
			$src = $item->getAttribute('href');
			if(!preg_match('#^https?://#', $src)) {
				if(preg_match('#^//#', $src))
					$item->setAttribute('href', 'https:' . $src);
				else
					$item->setAttribute('href', $baseURI . ltrim($src, '/'));
			}
		}

		// Wrap iframes
		$items = $domx->query('//iframe');
		foreach($items as $item) {
			$f = $item->ownerDocument->createElement('figure');
			$f->setAttribute('class', 'op-interactive');
			$item->parentNode->replaceChild($f, $item);
			$f->appendChild($item);

			// If width in %
			$w = $item->getAttribute('width');
			if(empty($w) || substr($w, -1) == '%')
				$item->setAttribute('width', '600');

			// If height in %
			$h = $item->getAttribute('height');
			if(empty($h) || substr($h, -1) == '%')
				$item->setAttribute('height', '400');

			// Convert relative to abs
			$src = $item->getAttribute('src');
			if(!preg_match('#^https?://#', $src)) {
				if(preg_match('#^//#', $src))
					$item->setAttribute('src', 'https:' . $src);
				else
					$item->setAttribute('src', $baseURI . ltrim($src, '/'));
			}
		}

		// Wrap tables
		$items = $domx->query('//table');
		foreach($items as $item) {
			$f = $item->ownerDocument->createElement('figure');
			$f->setAttribute('class', 'op-interactive');
			$f->appendChild($frame = $item->ownerDocument->createElement('iframe'));
			$item->parentNode->replaceChild($f, $item);
			$frame->appendChild($item);
		}

		// Convert the transformed HTML back to a string
		$output = $doc->saveHTML();

		// Strip off the body wrapper saveHTML just added
		$output = preg_replace('#<!DOCTYPE.*<body>#s', '', $output);
		$output = preg_replace('#</body.*$#s', '', $output);

		return $output;
	}
}
