<?php namespace ProcessWire;

/**
 * URL Inputfield Module
 * 
 * An Inputfield for handling input of URLs in ProcessWire forms.
 * 
 * ProcessWire 3.x, Copyright 2022 by Ryan Cramer
 * https://processwire.com
 * 
 * @property int|bool $noRelative Whether relative URLs are disabled
 * @property int|bool $addRoot Whether to prepend root path
 * @property int|bool $allowIDN Whether to allow IDNs
 * @property int|bool $allowQuotes Whether to allow quote characters in URLs
 *
 */
class InputfieldURL extends InputfieldText {

	public static function getModuleInfo() {
		return array(
			'title' => __('URL', __FILE__), // Module Title
			'summary' => __('URL in valid format', __FILE__), // Module Summary
			'version' => 103,
		);
	}

	/**
	 * Construct
	 * 
	 */
	public function __construct() {
		parent::__construct();
		$this->setAttribute('type', 'text'); 
		$this->setAttribute('maxlength', 1024); 
		$this->setAttribute('size', 0); 
		$this->setAttribute('name', 'href'); 
		$this->label = 'URL';
		$this->set('noRelative', 0); // whether relative URLs are disabled
		$this->set('addRoot', 0); // whether to prepend root path
		$this->set('allowIDN', 0); // whether to allow IDNs
		$this->set('allowQuotes', 0); // whether to allow quote characters in URLs
	}

	/**
	 * Render Inputfield
	 * 
	 * @return string
	 * 
	 */
	public function ___render() {
		$rootUrl = $this->wire()->config->urls->root;
		if($this->addRoot && !$this->noRelative && !$this->notes && strlen($rootUrl) > 1) {
			$this->notes = sprintf(
				$this->_("Start local URLs with “/” and leave off the “%s” part."), // Instruction for local URLs displayed when site is running from a subdirectory
				$rootUrl
			); 
		}
		return parent::___render();
	}

	/**
	 * Set value attribute
	 * 
	 * @param string $value
	 * @return string
	 * 
	 */
	protected function setAttributeValue($value) {

		$value = trim((string) $value);
		$dirty = $value; 
		$label = $this->label ? $this->label : $this->name;
		
		if(!strlen($dirty)) return '';
		
		$value = $this->wire()->sanitizer->url($dirty, array(
			'allowRelative' => $this->noRelative ? false : true,
			'allowIDN' => $this->allowIDN ? true : false,
			'stripQuotes' => $this->allowQuotes ? false : true,
		));
		
		if(empty($value) || ($dirty !== $value && "http://$dirty" !== $value && "https://$dirty" !== $value)) {
			$error = true;
			if(strpos($dirty, '%') !== false) {
				$test = rawurldecode($dirty);
				if($value === $test || $value === "http://$test" || $value === "https://$test") $error = false;
			}
			if($error) {
				$value = $this->val();
				$this->error("$label - " . $this->_("Error found - please check that it is a valid URL")); // Error message when invalid URL found
			}

		} else if($value !== $dirty) { 
			$scheme = '';
			foreach(array('http', 'https') as $s) {
				if($value !== "$s://$dirty") continue;
				$scheme = "$s://";
				break;
			}
			if($scheme) {
				$this->message("$label - " . sprintf($this->_("Note that %s was added"), $scheme)); // Message displayed when scheme was automatically added to the URL
			}
		}

		return $value; 
	}

	/**
	 * Configure Inputfield
	 * 
	 * @return InputfieldWrapper
	 * 
	 */
	public function ___getConfigInputfields() {
		$inputfields = parent::___getConfigInputfields();
		$f = $inputfields->get('stripTags');
		if($f) $inputfields->remove($f);
		return $inputfields;
	}
}
