<?php
/*
 * Copyright (c) 2012, webvariants GbR, http://www.webvariants.de
 *
 * This file is released under the terms of the MIT license. You can find the
 * complete text in the attached LICENSE file or online at:
 *
 * http://www.opensource.org/licenses/mit-license.php
 */

/**
 * @since  v4.0
 * @author Christoph
 */
class WV24_Util {
	/**
	 * Überführt einen String in ein URL-freundliches Format
	 *
	 * Diese Method entfernt alle Sonderzeichen, übersetzt Umlaute und führt
	 * weitere Veränderungen an $str durch, um ein sauberes URL-Fragment zu
	 * erzeugen.
	 *
	 * @param  string $str  der zu verarbeitende String
	 * @return string       die URL-freundliche Variante von $str
	 */
	public static function makeURLFriendly($str, $cleanup, $lowercase) {
		if ($cleanup) {
			$str = str_replace(array('ä', 'ö', 'ü', 'ß'), array('ae', 'oe', 'ue', 'ss'), $str);
			$str = str_replace(array('Ä', 'Ö', 'Ü', '@'), array('Ae', 'Oe', 'Ue', 'at'), $str);
			$str = preg_replace('#[^a-z0-9-]#i', '-', $str);
		}
		else {
			$str = str_replace(array('/', '#', '!', '?', '&', '(', ')'), '-', $str);
		}

		if ($lowercase) {
			$str = mb_strtolower($str);
		}

		$str = trim($str, '.-+ ');
		$str = preg_replace('#([+.-])+#', '$1', $str);

		if (!$cleanup) {
			$str = urlencode($str);
			$str = preg_replace('#([+-])+#', '+', $str);
		}

		return $str;
	}

	/**
	 * Checks if a fragment is absolute
	 *
	 * @param string $fragment
	 */
	public static function isAbsoluteFragment($fragment) {
		return mb_substr($fragment, 0, 1) === '/';
	}

	/**
	 * @param string $fragment
	 */
	public static function isDomainFragment($fragment) {
		return mb_substr($fragment, 0, 2) === '//';
	}

	public static function getFragment(sly_Model_Base_Article $article) {
		return $article->getExtendedValue('wv24_fragment', '');
	}

	public static function isSkipped(sly_Model_Base_Article $article) {
		return (boolean) $article->getExtendedValue('wv24_skip', false);
	}

	public static function getTree($id) {
		$id     = $id === null ? null : (int) $id;
		$db     = sly_DB_Persistence::getInstance();
		$clangs = sly_Util_Language::findAll(true);
		$clang  = reset($clangs);

		$db->select('article', 'id, path', ($id === null ? '' : '(id = '.$id.' OR path LIKE "%|'.$id.'|%") AND ').'clang = '.$clang, null, '!startpage, path, catpos, pos');

		$articles = $db->all();
		$result   = array();

		foreach ($articles as $row) {
			$result[(int) $row['id']] = $row['path'];
		}

		return $result;
	}

	/**
	 * Entfernt die Domain aus einer URL
	 *
	 * Sollte die URL auf den aktuellen Server zeigen, wird diese Methode den
	 * Hostnamen aus der URL entfernen. Der aktuelle Server wird aus
	 * <code>$_SERVER['SERVER_NAME']</code> ausgelesen.
	 *
	 * Zusätzlich wird ein eventuell vorhandenes Pfad-Präfix (wenn die Website
	 * zum Beispiel nicht direkt im Root der Domain verfügbar ist) entfernt, da
	 * diese Pfadangabe bereits mit in das <base>-Tag eingefügt wird.
	 *
	 * @param  string  $url          die URL, aus die Domain wenn möglich entfernt werden soll
	 * @param  boolean $forceDomain  wenn true, wird immer eine Domain-Angabe ("http://.../") erzeugt (andernfalls nur, wenn nötig)
	 * @return string                die ggf. geänderte URL
	 */
	public static function shortenUrl($url, $forceDomain = false) {
		$baseUrl = sly_Util_HTTP::getBaseUrl(true, 'http');

		// do nothing if the URL points somewhere outside the project
		if (mb_strpos($url, $baseUrl) === false) {
			// but keep the protocol
			if (sly_Util_HTTP::isSecure() && substr($url, 0, 5) !== 'https') {
				$url = 'https'.substr($url, 4);
			}

			return $url;
		}

		// remove domain if possible
		if (!$forceDomain) {
			$thisDomain = sly_Util_HTTP::getHost();
			$urlDomain  = parse_url($url, PHP_URL_HOST);

			if ($urlDomain === $thisDomain) {
				$url = mb_substr($url, 7 + mb_strlen($thisDomain));

				if (mb_strlen($url) === 0) {
					$url = '/';
				}
			}
		}

		// Remove path prefix ("/website/" or "/"), since the prefix (the part
		// of the URL that is already contained in the default fragment) will be
		// put in the <base> tag. It may only be removed on URLs without a domain
		// part.
		if (mb_substr($url, 0, 4) !== 'http') {
			$baseUrl  = sly_Util_HTTP::getBaseUrl(true).'/';
			$basePath = parse_url($baseUrl, PHP_URL_PATH);

			if (mb_substr($url, 0, mb_strlen($basePath)) === $basePath) {
				$url = mb_substr($url, mb_strlen($basePath));

				if (mb_strlen($url) === 0) {
					$url = './';
				}
			}
		}

		return $url;
	}

	/**
	 * Wrapper um http_build_query()
	 *
	 * Diese Methode wrapped die PHP-eigene http_build_query()-Funktion. Der
	 * Query-String kann auch bereits als String angegeben werden. Wenn dies der
	 * Fall ist, wird der $divider am Anfang abgeschnitten (falls er dort
	 * fälschlicherweise steht).
	 *
	 * @param  mixed  $params   die Parameter als assoziatives Array über ein bereits fertiger String
	 * @param  string $divider  das Trennzeichen zwischen einzelnen Werten
	 * @return string           der fertige Query-String im Format mit einem Fragzeichen am Anfang (?foo=bar)
	 */
	public static function buildQuery($params, $divider = '&amp;') {
		$params = is_array($params) ? http_build_query($params, '', $divider) : $params;

		if (mb_strlen($params) > 0) {
			if (mb_substr($params, 0, mb_strlen($divider)) === $divider) {
				$params = mb_substr($params, mb_strlen($divider));
			}

			if (mb_strlen($params) > 0 && $params[0] !== '?') {
				$params = '?'.$params;
			}
		}

		return $params;
	}

	/**
	 * Removes query string and forces HTTP as the protocol
	 *
	 * @param  string
	 * @return string
	 */
	public static function cleanUrl($url) {
		// remove query string, if present
		$pos = mb_strpos($url, '?');

		if ($pos !== false) {
			$url = mb_substr($url, 0, $pos);
		}

		// apply the same for broken URLs ('example.com/foo.php&bar=1')
		$pos = mb_strpos($url, '&');

		if ($pos !== false) {
			$url = mb_substr($url, 0, $pos);
		}

		// force protocol
		$protocol = parse_url($url, PHP_URL_SCHEME);

		if ($protocol !== 'http') {
			$url = 'http'.mb_substr($url, strlen($protocol));
		}

		return $url;
	}

	public static function getDefaultFragments() {
		return WV8_Settings::getValue('realurl2', 'default_fragment', null, WV_Sally::CLANG_ALL, true);
	}

	public static function getDefaultDomains($addWwwAlternatives = false) {
		$fragments = self::getDefaultFragments();
		$result    = array();

		foreach ($fragments as $clang => $fragment) {
			$domain = self::getDomainFromFragment($fragment);

			$result[$clang] = $addWwwAlternatives ? array($domain, self::getWwwAlternative($domain)) : $domain;
		}

		return $result;
	}

	public static function getDomainFromFragment($fragment) {
		$dummyUrl = 'http:'.rtrim($fragment, '/').'/';
		return parse_url($dummyUrl, PHP_URL_HOST);
	}

	public static function redirect($url) {
		if ($url instanceof _WV24_URL) $url = $url->getRawURL();

		if (sly_Util_HTTP::isSecure()) {
			$url = preg_replace('#^http://#i', 'https://', $url);
		}

		$data = $_GET;
		unset($data['article_id'], $data['clang']);
		$query = http_build_query($data, '', '&');

		if (!empty($query)) {
			if (strpos($url, '?') === false) {
				$url .= '?'.$query;
			}
			else {
				$url .= '&'.$query;
			}
		}

		sly_Util_HTTP::redirect($url); // stirbt weg
	}

	public static function decodePath($path) {
		$path = is_array($path) ? $path : explode('|', $path);
		return array_values(array_filter(array_map('intval', $path)));
	}

	public static function getStorage() {
		return new _WV24_Storage(sly_DB_Persistence::getInstance(), sly_Core::cache());
	}

	public static function hasSiteStartArticle() {
		return sly_Util_Article::exists(sly_Core::getSiteStartArticleId());
	}

	public static function getWwwAlternative($host) {
		if (strpos($host, 'www.') === 0) {
			return substr($host, 4);
		}
		else {
			return 'www.'.$host;
		}
	}
}
