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