<?php
	require_once dirname(__FILE__)."/template.php";
	require_once dirname(__FILE__)."/control.php";
	require_once dirname(dirname(dirname(__FILE__)))."/registry.php";
	require_once dirname(dirname(dirname(__FILE__)))."/dal/book_categoryDAL.php";
	require_once dirname(dirname(dirname(__FILE__)))."/dal/bookDAL.php";
	require_once dirname(dirname(dirname(__FILE__)))."/dal/htaccessDAL.php";
	require_once dirname(dirname(dirname(__FILE__)))."/dal/scoreDAL.php";
	class page{
		//受保護屬性：頁面文檔內容
		protected $pageContent;

		//受保護屬性：頁面模版內容
		protected $template;

		//受保護屬性：頁面模版文件
		protected $templateFile;

		//私有屬性:模版類
		private $tmpManager;

		//私有屬性:頁面參數集
		private $parameters = array();

		//私有屬性:頁面控件集
		private $controls = array();

		//控件類名
		private $controlClassName = "control";
		
		//HTTPS OR HTTP
		private $protocol;

		//公有屬性
		/*
		 * registry 網站設定值
		 * htLink[1] htVisible[1] 文章(article)
		 * htLink[2] htVisible[2] 最新消息(news)
		 * htLink[3] htVisible[3] 問與答(faq)
		 * htLink[4] htVisible[4] 商品(product)
		 * htLink[5] htVisible[5] 相本(book)
		 * htLink[6] htVisible[6] 聯絡我們(contact)
		 * htLink[7] htVisible[7] 簡易訂單(order)
		 */
		public $registry, $htLink, $htVisible;

		//公開構造函數
		//參數$template為模版內容,也可以隨後再調用loadTemplate()方法加載模版內容
		public function __construct($template = "") {
			$this->tmpManager = new template();
		
			if (isset($template) && $template !== "") $this->template = $template;
			
			$this->protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
			
			// 取得網站設定值
			$this->registry = registry::createInstance();
		
			// 取得網址設定值
			$this->htLink = [];
			$this->htVisible = [];
			$dalH = new htaccessDAL();
			for ($i = 1; $i < 8; $i++) {
				$dalH->ID = $i;
				$dalH->loadRecord();
				$this->htLink[$i] = $dalH->HtmlName;
				$this->htVisible[$i] = $dalH->Visible;
			}
		}
		
		// 公開方法：呈現頁面
		public function render() {
			echo $this->pageContent;
		}
	
		// 公開方法：取得頁面文檔內容
		public function getContent() {
			return $this->pageContent;
		}
	
		// 公開方法：從模版內容加載模版	
		public function loadTemplate($template) {
			$this->template = $template;
		}
	
		// 公開方法：從模版文件加載模版
		public function loadTemplateFile($fileName) {
			$this->templateFile = $fileName;
			if (file_exists($fileName)) {
				$handler = fopen($fileName, "rb");
				$this->template = fread($handler, filesize($fileName));
				fclose($handler);
			}
		}
	
		// 公開方法：添加頁面參數
		public function addParameter($name, $value) {
			$arr = [
				"name" => $name,
				"value" => $value,
			];
	
			$this->parameters[] = $arr;
		}
		
		// 公開方法：獲取頁面參數
		public function getParameter($name) {
			foreach ($this->parameters as $parameter) {
				if ($parameter["name"] == $name) return $parameter["value"];
			}
		}
	
		// 公開方法：添加頁面控件
		// 參數$control為控件實例名
		public function addControl($control) {
			$this->controls[] = $control;
		}
	
		// 公開方法：加載頁面
		public function load() {
			if ($this->tmpManager !== null) {
				$this->tmpManager->template = $this->template;
				foreach ($this->parameters as $parameter) {
					$name = $parameter["name"];
					$value = $parameter["value"] ?? "";
					$this->tmpManager->addElement($name, $value);
				}
				for ($i = 0; $i < count($this->controls); $i++) {
					$control = $this->controls[$i];
					if (!class_exists($this->controlClassName) || !is_a($control, $this->controlClassName)) continue;
					$content = $this->tmpManager->addControl("control_" . $i, $control->tagPrefix, $control->tagName, $control->id);
					if ($control !== null) {
						if (property_exists($control, 'template')) {
							$control->template = $content;
							$control->load();
							$this->tmpManager->loadControl("control_" . $i, $control->getContent());
						}
					}
				}
				$this->pageContent = $this->tmpManager->getContent();
			}
		}
	
		// 公開方法：允許訪問
		public function allowAccess() {
			return true;
		}

		// 公開方法:權限檢查
		public function checkAccess($userId, $resourceId, $actionId) {
			return false;
		}
	
		// 頁面重定向
		public function redirect($url) {
			echo "<html><script language=\"javascript\">location.replace(\"" . $url . "\");</script></html>";
			exit;
		}
	
		// 頁面是否POST回放
		public function isPostBack() {
			return strtoupper($_SERVER['REQUEST_METHOD']) == "POST";
		}
	
		// 公開方法:悉放對象
		public function dispose() {
			// 這裡添加需要悉放的頁面對象,以悉放內存空間
		}
		
		//ip限制
		public function chkIP($ipLimit = 0, $ipBlackList = "", $ipWhiteList = "", $twipLimit = 0) {
			$flag = 0;
			// 蘋果IP
			$txtA = $this->load_contents($this->protocol . "://" . $_SERVER['HTTP_HOST'] . "/api/appleip.json");
			$aryA = json_decode($txtA);
			if (!$this->matchIP($aryA)) {
				if ($ipLimit == 1) {
					$aryBL = explode(PHP_EOL, $ipBlackList);
					if (!$this->matchIP($aryBL, 1)) $flag = 1;
				} else if ($ipLimit == 2) {
					$aryWL = explode(PHP_EOL, $ipWhiteList);
					if (!$this->matchIP($aryWL)) $flag = 1;
				}
				// 台灣IP限制
				if ($twipLimit !== "0") {
					$lines_string = $this->load_contents($this->protocol . "://" . $_SERVER['HTTP_HOST'] . "/api/twip.json");
					$flag2 = 0;
					$aryIP = json_decode($lines_string, true);
					if (is_array($aryIP) && count($aryIP) > 0) {
						foreach ($aryIP as $re) {
							if (preg_match($re, $this->getIP())) {
								$flag2 = 1;
								break;
							}
						}
					}
            
					if ($twipLimit == "1" && $flag2 == 1) {
						$flag = 1;
					} else if ($twipLimit == "2" && $flag2 == 0) {
						$flag = 1;
					}
				}
			}
			return ($flag === 0) ? true : false;
		}
		public function matchIP($aryIP = array(), $typ = 0) {	// typ=0，白名單；1，黑名單；
			$flag = 0;
			if (is_array($aryIP) || is_countable($aryIP)) {
				foreach ($aryIP as $v) {
					$v = preg_replace('/^\s+|\s+$/u', '', $v); // 移除字串前後的空白字符
					if (!empty($v)) {
						$aryIPParts = explode(".", $v);
		
						for ($i = count($aryIPParts); $i < 4; $i++) {
							$aryIPParts[] = "\d{1,3}";
						}
		
						$ipW = implode("\.", $aryIPParts);
						$ipW = "/" . $ipW . "/";
						if (preg_match($ipW, $this->getIP())) {
							$flag = ($typ === 1) ? 0 : 1;
							break; // 不需要繼續比對，已經有結果
						}
					}
				}
			}
			return ($flag === 0) ? false : true;
		}

		/*
		 * 資料庫操作增加參數陣列
		 * $name = 參數名稱
		 * $value = 參數值
		 * $type = 參數型態
		 * $number = 參數長度(字元數)，限定參數型態str才可使用
		 */
		public function addArray(string $name, string $value, string $type = "", string $number = "") {
			if (!preg_match("/^[1-9]\d*$/", $number)) $number = "";
		
			return [ "Name" => $name, "Value" => $value, "Type" => $type, "Number" => $number ];
		}
		
		public function getProtocol() {
			return $this->protocol;
		}

		public function getIP() {
			if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
				$myip = $_SERVER['HTTP_CLIENT_IP'];
			} else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
				$myip = $_SERVER['HTTP_X_FORWARDED_FOR'];
			} else {
				$myip = $_SERVER['REMOTE_ADDR'];
			}
			return $myip;
		}
		
		public function getPageParameter($name, $default) {
			$value = "";
			if (isset($_GET[$name]) && $_GET[$name] !== "") {
				$value = $_GET[$name];
			} else if (isset($_POST[$name]) && $_POST[$name] !== "") {
				$value = $_POST[$name];
			} else {
				$value = $default;
			}
			$value = htmlentities($value, ENT_QUOTES | ENT_HTML5);
			return $value;
		}
		
		public function alert($msg) {
			echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
			echo '<script language="javascript">window.alert("' . addslashes($msg) . '");history.back();</script>';
		}
		
		public function alert2($msg, $url) {
			echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
			echo '<script language="javascript">window.alert("' . addslashes($msg) . '");location.href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '";</script>';
		}

		public function getInput($name, $default = "", $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			$value = $this->getValueFromSuperGlobal($_GET, $name, $default);
			$typ = (int)$typ;
			$value = $this->processValue($value, $typ);
			return $value;
		}
		
		public function getPost($name, $default = "", $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			$value = $this->getValueFromSuperGlobal($_POST, $name, $default);
			$typ = (int)$typ;
			$value = $this->processValue($value, $typ);
			return $value;
		}
		
		public function getGet($name, $default = "", $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			$value = $this->getValueFromSuperGlobal($_GET, $name, $default);
			$typ = (int)$typ;
			$value = $this->processValue($value, $typ);
			return $value;
		}
		
		private function getValueFromSuperGlobal($superGlobal, $name, $default) {
			if (isset($superGlobal[$name]) && $superGlobal[$name] !== "") {
				return $superGlobal[$name];
			}
			return $default;
		}
		
		private function processValue($value, $typ, $level=0) { // typ=0，只取代tab符號，1，取代換行符號、tab符號
			$arr = ($level == 0) ? ["\t"] : ["\r", "\n", "\t"];
			$value = str_replace($arr, '', $value);
			$value = stripslashes($value);
			$value = $this->specialtocode($value, $typ);
			return $value;
		}

		public function getInputArray($name, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			return $this->processArrayValue($_GET, $name, $typ);
		}

		public function getPostArray($name, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			return $this->processArrayValue($_POST, $name, $typ);
		}

		public function getGetArray($name, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			return $this->processArrayValue($_GET, $name, $typ);
		}

		public function getInputArray2($name, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			return $this->processNestedArrayValue($_GET, $name, $typ);
		}

		public function getPostArray2($name, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			return $this->processNestedArrayValue($_POST, $name, $typ);
		}

		public function getGetArray2($name, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線
			return $this->processNestedArrayValue($_GET, $name, $typ);
		}

		private function processArrayValue($source, $name, $typ) {
			$aryV = isset($source[$name]) && is_array($source[$name]) ? $source[$name] : [];
			
			$typ = (int)$typ;
			foreach ($aryV as &$value) {
				$this->processSingleValue($value, $typ);
			}
			
			return $aryV;
		}

		private function processNestedArrayValue($source, $name, $typ) {
			$aryV = isset($source[$name]) && is_array($source[$name]) ? $source[$name] : [];
			
			$typ = (int)$typ;
			foreach ($aryV as &$rows) {
				if (is_array($rows)) {
					foreach ($rows as &$value) {
						$this->processSingleValue($value, $typ);
					}
				} else {
					$this->processSingleValue($rows, $typ);
				}
			}
			
			return $aryV;
		}

		private function processSingleValue(&$value, $typ, $level=0) { // typ=0，只取代tab符號，1，取代換行符號、tab符號
			$arr = ($level == 0) ? ["\t"] : ["\r", "\n", "\t"];
			$value = str_replace($arr, '', $value);
			$value = stripslashes($value);
			$value = $this->specialtocode($value, $typ);
		}
		
		public function specialtocode($value, $typ = 1) {	//typ=1，一般，所有特殊符號取代；2，編輯器，最低限度特殊符號取代；3，特殊，完全不取代只對單引號加斜線；4，先去a和script標籤，再取代所有特殊符號
			$typ = (int)$typ;
			if ($typ == 4) {
				$value = preg_replace("/<\s*a.*<\/\s*a\s*>/iU", "", $value);
				$value = preg_replace("/<\s*s\s*c\s*r\s*i\s*p\s*t.*<\/\s*s\s*c\s*r\s*i\s*p\s*t\s*>/iU", "", $value);
				$typ = 1;
			}
			if ($typ == 3) {
				$value = str_replace("'", "\'", $value);
			} else {
				$value = str_replace(["$", "'"], ["&#36;", "&#39;"], $value);
				if ($typ == 1) $value = str_replace(["\"", "(", ")", "{", "}", "<", ">"], ["&#34;", "&#40;", "&#41;", "&#123;", "&#125;", "&#60;", "&#62;"], $value);
			}
			
			return $value;
		}

		public function codetospecial($value) {
			$value = str_replace(["&#62;", "&#60;", "&#125;", "&#123;", "&#41;", "&#40;", "&#34;", "&#39;", "&#36;"], [">", "<", "}", "{", ")", "(", "\"", "'", "$"], $value);
			return $value;
		}
		
		public function nametopath($value) {
			$value = str_replace(["#", "$", "%", "&", "\\", "/", "?"], "_", $value);
			return $value;
		}
		
		public function xss_filter($content){
			$purifier = new HTMLPurifier();
			$cleanContent = $purifier->purify($content);
			return $cleanContent;
		}

		public function image_exists($url) {
			if (preg_match("/^\/\//", $url)) $url = $_SERVER['REQUEST_SCHEME'] . $url;
			if (!preg_match("/^http/", $url)) return (preg_match("/^\//", $url)) ? (file_exists("." . $url)) : (file_exists($url));
			
			$parts = parse_url($url);
			if (isset($parts['user'])) return false;
			
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0');
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
			curl_setopt($ch, CURLOPT_TIMEOUT, 20);
			curl_setopt($ch, CURLOPT_NOBODY, true);
			curl_setopt($ch, CURLOPT_HEADER, true);
			if ($parts['scheme'] == 'https') {
				curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
				curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			}
			$response = curl_exec($ch);
			curl_close($ch);
		
			$content_type = false;
			if (preg_match('/Content-Type: (.+\/.+?)/i', $response, $matches)) {
				if (preg_match('/image\/.*/', $matches[1])) $content_type = true;
			}
			if (!$content_type) return false;
			
			if (preg_match('/HTTP\/\d+\.?\d*\s+(\d+)/', $response, $matches)) {
				$code = intval($matches[1]);
			} else {
				return false;
			}
		
			return (($code >= 200) && ($code < 400));
		}

		public function video_exists($url) {
			$parts = parse_url($url);
			if (isset($parts['user'])) return false;
		
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0');
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
			curl_setopt($ch, CURLOPT_TIMEOUT, 20);
			curl_setopt($ch, CURLOPT_NOBODY, true);
			curl_setopt($ch, CURLOPT_HEADER, true);
			if ($parts['scheme'] == 'https') {
				curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
				curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			}
			$response = curl_exec($ch);
			curl_close($ch);
		
			$content_type = false;
			
			if (preg_match('/Content-Type: (.+\/.+?)/i', $response, $matches)) {
				if (preg_match('/audio\/.*/', $matches[1]) || preg_match('/video\/.*/', $matches[1])) {
					$content_type = true;
				} else {
					$referer = parse_url($url);
					if ($referer["host"] == "www.youtube.com" || $referer["host"] == "youtu.be") $content_type = true;
				}
			}
			
			if (!$content_type) return false;
		
			if (preg_match('/HTTP\/\d+\.?\d*\s+(\d+)/', $response, $matches)) {
				$code = intval($matches[1]);
			} else {
				return false;
			}
		
			return (($code >= 200) && ($code < 400));
		}
		
		//取得檔案
		public function load_contents($url) {
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_URL, $url);
			$contents = curl_exec($ch);
			curl_close($ch);
			return ($contents !== false) ? $contents : false;
		}
		
		//取得Logo
		public function getLogo($type = 0) {
			$dalP = new pictureDAL();
			$dalP->PictureType = ($type == 0) ? "10" : "15";
			$dalP->TypeOrderNO = "0";
			$dalP->loadRecord();
			$image = $dalP->Image;
			if (preg_match("/^\/\//", $image)) $image = $this->protocol . ":" . $image;
			if (!preg_match("/^https?:\/\//", $image)) $image = $this->protocol . "://" . $_SERVER["HTTP_HOST"] . $image;
			
			return $image;
		}
		
		public function localBusinessHtml($image = "", $name = "", $phone = "", $ratingValue = 0, $bestRating = 5): string {
			$jsonData = [
				"@context" => "https://schema.org",
				"@type" => "LocalBusiness",
				"@id" => "{$this->protocol}://{$_SERVER['HTTP_HOST']}",
				"image" => $image,
				"name" => $name,
				"telephone" => $phone,
				"address" => [
					"@type" => "PostalAddress",
					"postalCode" => "",
					"addressLocality" => $this->registry->webAddress,
					"streetAddress" => ""
				],
				"review" => [
					"@type" => "Review",
					"reviewRating" => [
						"@type" => "Rating",
						"ratingValue" => $ratingValue,
						"bestRating" => $bestRating
					],
					"author" => [
						"@type" => "Person",
						"name" => $this->registry->webName
					]
				]
			];

			$jsonString = json_encode($jsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
			$scriptTag = "<script type=\"application/ld+json\">\n{$jsonString}\n</script>";

			return $scriptTag;
		}

		public function reviewHtml($image = "", $name = "", $ratingValue = 5, $bestRating = 0): string {
			$jsonData = [
				"@context" => "https://schema.org",
				"@type" => "Review",
				"itemReviewed" => [
					"@type" => "LocalBusiness",
					"name" => $name,
					"image" => $image,
				],
				"reviewRating" => [
					"@type" => "Rating",
					"ratingValue" => $ratingValue,
					"bestRating" => $bestRating,
				],
				"author" => [
					"@type" => "Person",
					"name" => $this->registry->webName
				]
			];

			$jsonString = json_encode($jsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
			$scriptTag = "<script type=\"application/ld+json\">\n{$jsonString}\n</script>";

			return $scriptTag;
		}

		public function productHtml($id, $price, $image, $name, $description, $bestRating, $ratingCount, $ratingValue): string {
			$jsonData = [
				"@context" => "https://schema.org",
				"@type" => "Product",
				"name" => $name,
				"description" => $description,
				"image" => $image,
				"sku" => $id,
				"brand" => $price,
				"aggregateRating" => [
					"@type" => "AggregateRating",
					"bestRating" => $bestRating,
					"ratingCount" => $ratingCount,
					"ratingValue" => $ratingValue
				]
			];
			$jsonString = json_encode($jsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
			$scriptTag = "<script type=\"application/ld+json\">\n{$jsonString}\n</script>";

			return $scriptTag;
		}

		public function faqHtml(int $id): string {
			$aryF = [];
			$dal = new faqDAL();
			$intoAry = [ $this->addArray(":categoryID", $id, "int") ];
			$data = $dal->executeRecordset($intoAry, "a.`CategoryID`=:categoryID AND a.`Visible`=1 AND a.`Disable`=0 AND b.`Visible`=1 AND b.`Disable`=0");
			
			foreach ($data as $item) {
				$aryF[] = [
					"@type" => "Question",
					"name" => $item["Title"],
					"acceptedAnswer" => [
						"@type" => "Answer",
						"text" => $item["Description"]
					]
				];
			}

			$faqlist = json_encode($aryF, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
			$jsonString = json_encode([
				"@context" => "https://schema.org",
				"@type" => "FAQPage",
				"mainEntity" => $aryF
			], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
			$scriptTag = "<script type=\"application/ld+json\">\n{$jsonString}\n</script>";
		
			return $scriptTag;
		}

		public function isShowStars($ratingValue = 0, $reviewCount = 0) {
			$starsHtml = "";
			$num2 = floor($ratingValue); // 整數部分
			$num3 = $ratingValue - $num2; // 小數部分
			if ($num3 == 0) {
				$num4 = 5 - (int)$num2;
				$starlast = "";
			} else {
				$num4 = 4 - (int)$num2;
				$starlast = "<i class=\"fa fa-star-half-o\"></i>";
			}
			
			$starsHtml .= str_repeat("<i class=\"fa fa-star\"></i>", $num2);
			$starsHtml .= $starlast;
			$starsHtml .= str_repeat("<i class=\"fa fa-star-o\"></i>", $num4);

			$txt = "<div id=\"SeoStarRating\">".
				"<font>{$ratingValue}</font>".
				"<font>{$starsHtml}</font>".
				"<font>{$reviewCount} 則評論</font>".
				"</div>";

			return $txt;
		}

		// 取得是否為 ios safari
		public function generateIosDevice() {
			$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
			$isDevice = $this->determineDevice();
			$isIos = (strpos($userAgent, 'iPhone') || strpos($userAgent, 'iPad'));
			$isNotCriOS = !strpos($userAgent, "CriOS");
			$isVersion = strpos($userAgent, "Version");
			
			return ($isDevice && $isIos && $isNotCriOS && $isVersion) ? true : false;
		}

		// 取得當前瀏覽器是否為行動裝置
		public function determineDevice() {
			$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
			
			$iPod = stripos($userAgent, "iPod") !== false;
			$iPhone = stripos($userAgent, "iPhone") !== false;
			$iPad = stripos($userAgent, "iPad") !== false;
			$Android = stripos($userAgent, "Android") !== false;
			$AndroidTablet = false;
			
			if ($Android && stripos($userAgent, "mobile") === false) $AndroidTablet = true;
			$webOS = stripos($userAgent, "webOS") !== false;
			$BlackBerry = stripos($userAgent, "BlackBerry") !== false;
			$RimTablet = stripos($userAgent, "RIM Tablet") !== false;
			
			return $iPod || $iPhone || $iPad || $Android || $AndroidTablet || $webOS || $BlackBerry || $RimTablet;
		}
	}
?>