1: <?php
2: /**
3: * This file contains the uri class.
4: *
5: * @package Core
6: * @subpackage Frontend_URI
7: * @version SVN Revision $Rev:$
8: *
9: * @author Murat Purc
10: * @copyright four for business AG <www.4fb.de>
11: * @license http://www.contenido.org/license/LIZENZ.txt
12: * @link http://www.4fb.de
13: * @link http://www.contenido.org
14: */
15:
16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
17:
18: /**
19: * Frontend URL creation. Works as a wrapper of an UriBuilder instance.
20: *
21: * @package Core
22: * @subpackage Frontend_URI
23: */
24: class cUri {
25:
26: /**
27: * Self instance.
28: * @var cUri
29: */
30: static private $_instance;
31:
32: /**
33: * UriBuilder instance.
34: * @var cUriBuilder
35: */
36: private $_oUriBuilder;
37:
38: /**
39: * UriBuilder name.
40: * @var string
41: */
42: private $_sUriBuilderName;
43:
44: /**
45: * Constructor of cUri. Is not callable from outside.
46: * Gets the UriBuilder configuration and creates an UriBuilder instance.
47: */
48: private function __construct() {
49: $this->_sUriBuilderName = cUriBuilderConfig::getUriBuilderName();
50: $this->_oUriBuilder = cUriBuilderFactory::getUriBuilder(
51: $this->_sUriBuilderName
52: );
53: }
54:
55: /**
56: * Returns self instance
57: * @return cUri
58: */
59: public static function getInstance() {
60: if (self::$_instance == null) {
61: self::$_instance = new self();
62: }
63: return self::$_instance;
64: }
65:
66: /**
67: * Creates a URL to frontend page.
68: *
69: * @param mixed $param Either url or assoziative array containing parameter:
70: * - url: front_content.php?idcat=12&lang=1
71: * - params: array('idcat' => 12, 'lang' => 1)
72: * Required values depend on used UriBuilder, but a must have is 'lang'.
73: * @param boolean $bUseAbsolutePath Flag to create absolute Urls
74: * @param array $aConfig If not set, cUriBuilderConfig::getConfig() will be used by the UriBuilder
75: * @throws cInvalidArgumentException if the given params do not contain the lang
76: * @return string The Url build by cUriBuilder
77: */
78: public function build($param, $bUseAbsolutePath = false, array $aConfig = array()) {
79: if (!is_array($param)) {
80: $arr = $this->parse($param);
81: $param = $arr['params'];
82: }
83:
84: // fallback for urls to homepage (/ or front_content.php)
85: if (count($param) == 0 || (!isset($param['idart']) && !isset($param['idartlang']) &&
86: !isset($param['idcat']) && !isset($param['idcatlang']) && !isset($param['idcatart']))) {
87: $param['idcat'] = getEffectiveSetting('navigation', 'idcat-home', 1);
88: }
89:
90: // execute preprocess hook
91: $aHookParams = array(
92: 'param' => $param, 'bUseAbsolutePath' => $bUseAbsolutePath, 'aConfig' => $aConfig
93: );
94: if ($aResult = cApiCecHook::executeAndReturn('Contenido.Frontend.PreprocessUrlBuilding', $aHookParams)) {
95: $param = (isset($aResult['param'])) ? $aResult['param'] : '';
96: if (isset($aResult['bUseAbsolutePath'])) {
97: $bUseAbsolutePath = (bool) $aResult['bUseAbsolutePath'];
98: }
99: if (isset($aResult['aConfig']) && is_array($aResult['aConfig'])) {
100: $aConfig = $aResult['aConfig'];
101: }
102: }
103:
104: if ($this->_sUriBuilderName == 'custom_path' && !isset($aParams['level'])) {
105: // downwards compatibility to cUriBuilderCustomPath
106: $aParams['level'] = '1';
107: }
108:
109: if (!isset($param['lang'])) {
110: // another downwards compatibility to cUriBuilderCustomPath
111: throw new cInvalidArgumentException('$param[lang] must be set!');
112: }
113:
114: if ($this->_sUriBuilderName == 'custom_path' && count($param) <= 3) {
115: // third downwards compatibility
116: $param['_c_p_'] = '1';
117: }
118:
119: $this->_oUriBuilder->buildUrl($param, $bUseAbsolutePath, $aConfig);
120:
121: $url = $this->_oUriBuilder->getUrl();
122:
123: // execute postprocess hook
124: if ($result = cApiCecHook::executeAndReturn('Contenido.Frontend.PostprocessUrlBuilding', $url)) {
125: $url = (string) $result;
126: }
127:
128: return $url;
129: }
130:
131: /**
132: * Creates a URL used to redirect to frontend page.
133: *
134: * @param mixed $param Either url or assoziative array containing parameter:
135: * - url: front_content.php?idcat=12&lang=1
136: * - params: array('idcat' => 12, 'lang' => 1)
137: * Required values depend on used UriBuilder, but a must have is 'lang'.
138: * @param array $aConfig If not set, cUriBuilderConfig::getConfig() will be used by the UriBuilder
139: * @return string The redirect Url build by cUriBuilder
140: */
141: public function buildRedirect($param, array $aConfig = array()) {
142: $url = $this->build($param, true, $aConfig);
143: return str_replace('&', '&', $url);
144: }
145:
146: /**
147: * Splits passed url into its components
148: *
149: * @param string $sUrl The Url to strip down
150: * @return array Assoziative array created by using parse_url() having the key 'params' which
151: * includes the parameter value pairs.
152: */
153: public function parse($sUrl) {
154: $aUrl = @parse_url($sUrl);
155: if (isset($aUrl['query'])) {
156: $aUrl['query'] = str_replace('&', '&', $aUrl['query']);
157: parse_str($aUrl['query'], $aUrl['params']);
158: }
159: if (!isset($aUrl['params']) || !is_array($aUrl['params'])) {
160: $aUrl['params'] = array();
161: }
162: return $aUrl;
163: }
164:
165: /**
166: * Composes a url using passed components array
167: *
168: * @param array Assoziative array created by parse_url()
169: * @return string $sUrl The composed Url
170: */
171: public function composeByComponents(array $aComponents) {
172: $sUrl = (isset($aComponents['scheme']) ? $aComponents['scheme'] . '://' : '') .
173: (isset($aComponents['user']) ? $aComponents['user'] . ':' : '') .
174: (isset($aComponents['pass']) ? $aComponents['pass'] . '@' : '') .
175: (isset($aComponents['host']) ? $aComponents['host'] : '') .
176: (isset($aComponents['port']) ? ':' . $aComponents['port'] : '') .
177: (isset($aComponents['path']) ? $aComponents['path'] : '') .
178: (isset($aComponents['query']) ? '?' . $aComponents['query'] : '') .
179: (isset($aComponents['fragment']) ? '#' . $aComponents['fragment'] : '');
180: return $sUrl;
181: }
182:
183: /**
184: * Checks, if passed url is an external url while performing hostname check
185: *
186: * @param string $sUrl Url to check
187: * @return bool True if url is a external url, otherwhise false
188: */
189: public function isExternalUrl($sUrl) {
190: $aComponents = $this->parse($sUrl);
191: if (!isset($aComponents['host'])) {
192: return false;
193: }
194: if (!$path = $this->_oUriBuilder->getHttpBasePath()) {
195: return false;
196: }
197:
198: $aComponents2 = $this->parse($path);
199: if (!isset($aComponents2['host'])) {
200: return false;
201: }
202:
203: return (strtolower($aComponents['host']) !== strtolower($aComponents2['host']));
204: }
205:
206: /**
207: * Checks, if passed url is an identifiable internal url.
208: *
209: * Following urls will be identified as a internal url:
210: * - "/", "/?idart=123", "/?idcat=123", ...
211: * - "front_content.php", "front_content.php?idart=123", "front_content.php?idcat=123", ...
212: * - "/front_content.php", "/front_content.php?idart=123", "/front_content.php?idcat=123", ...
213: * - The path component of an client HTML base path: e. g. "/cms/", "/cms/?idart=123", "/cms/?idcat=123"
214: * - Also possible: "/cms/front_content.php", "/cms/front_content.php?idart=123", "/cms/front_content.php?idcat=123"
215: * All of them prefixed with protocol and client host (e. g. http://host/) will also be identified
216: * as a internal Url.
217: *
218: * Other Urls, even internal Urls like /unknown/path/to/some/page.html will not be identified as
219: * internal url event if they are real working clean URLs.
220: *
221: * @param string $sUrl Url to check
222: * @return bool True if url is identifiable internal url, otherwhise false
223: */
224: public function isIdentifiableFrontContentUrl($sUrl) {
225: if ($this->isExternalUrl($sUrl)) {
226: // detect a external url, return false
227: return false;
228: }
229:
230: $aComponents = $this->parse($sUrl);
231: if (!isset($aComponents['path']) || $aComponents['path'] == '') {
232: return false;
233: }
234:
235: $clientPath = '';
236: if ($httpBasePath = $this->_oUriBuilder->getHttpBasePath()) {
237: $aComponents2 = $this->parse($httpBasePath);
238: if (isset($aComponents2['path'])) {
239: $clientPath = $aComponents2['path'];
240: }
241: }
242:
243: // Use pathinfo to get the path part (dirname) of the url
244: $pathinfo = pathinfo($aComponents['path']);
245: $baseName = $pathinfo['basename'];
246: $path = $pathinfo['dirname'];
247: $path = str_replace('\\', '/', $path);
248: if ($path == '.') {
249: $path = '';
250: }
251:
252: // Remove leading/ending slashes
253: $path = trim($path, '/');
254: $clientPath = trim($clientPath, '/');
255:
256: if (($path == '' && ($baseName == 'front_content.php' || $baseName == ''))) {
257: return true;
258: } elseif (($path == $clientPath && ($baseName == 'front_content.php' || $baseName == ''))) {
259: return true;
260: } elseif ($path == '' && $baseName !== 'front_content.php' && $baseName == $clientPath) {
261: // If url is e. g. "/cms/"
262: return true;
263: } else {
264: return false;
265: }
266: }
267:
268: /**
269: * Returns UriBuilder instance.
270: *
271: * @return cUriBuilder
272: */
273: public function getUriBuilder() {
274: return $this->_oUriBuilder;
275: }
276:
277: }
278: