99 * file that was distributed with this source code.
1010 */
1111
12+ use CodeIgniter \HTTP \IncomingRequest ;
1213use CodeIgniter \HTTP \URI ;
1314use CodeIgniter \Router \Exceptions \RouterException ;
1415use Config \App ;
1819 * CodeIgniter URL Helpers
1920 */
2021
21- if (! function_exists ('site_url ' ))
22+ if (! function_exists ('_get_uri ' ))
2223{
2324 /**
24- * Return a site URL to use in views
25+ * Used by the other URL functions to build a
26+ * framework-specific URI based on the App config.
2527 *
26- * @param mixed $uri URI string or array of URI segments
27- * @param string|null $protocol
28- * @param App|null $altConfig Alternate configuration to use
28+ * @internal Outside of the framework this should not be used directly.
2929 *
30- * @return string
30+ * @param string $relativePath May include queries or fragments
31+ * @param App|null $config
32+ *
33+ * @return URI
34+ *
35+ * @throws InvalidArgumentException For invalid paths or config
3136 */
32- function site_url ( $ uri = '' , string $ protocol = null , App $ altConfig = null ): string
37+ function _get_uri ( string $ relativePath = '' , App $ config = null ): URI
3338 {
34- // convert segment array to string
35- if (is_array ($ uri ))
39+ $ config = $ config ?? config ('App ' );
40+
41+ if ($ config ->baseURL === '' )
3642 {
37- $ uri = implode ( ' / ' , $ uri );
43+ throw new InvalidArgumentException ( ' _get_uri() requires a valid baseURL. ' );
3844 }
3945
40- // use alternate config if provided, else default one
41- $ config = $ altConfig ?? config (App::class);
42-
43- $ fullPath = rtrim (base_url (), '/ ' ) . '/ ' ;
44-
45- // Add index page, if so configured
46- if (! empty ($ config ->indexPage ))
46+ // If a full URI was passed then convert it
47+ if (is_int (strpos ($ relativePath , ':// ' )))
4748 {
48- $ fullPath .= rtrim ($ config ->indexPage , '/ ' );
49+ $ full = new URI ($ relativePath );
50+ $ relativePath = URI ::createURIString (null , null , $ full ->getPath (), $ full ->getQuery (), $ full ->getFragment ());
4951 }
50- if ($ uri !== '' )
52+
53+ $ relativePath = URI ::removeDotSegments ($ relativePath );
54+
55+ // Build the full URL based on $config and $relativePath
56+ $ url = rtrim ($ config ->baseURL , '/ ' ) . '/ ' ;
57+
58+ // Check for an index page
59+ if ($ config ->indexPage !== '' )
5160 {
52- $ fullPath .= '/ ' . $ uri ;
61+ $ url .= $ config ->indexPage ;
62+
63+ // Check if we need a separator
64+ if ($ relativePath !== '' && $ relativePath [0 ] !== '/ ' && $ relativePath [0 ] !== '? ' )
65+ {
66+ $ url .= '/ ' ;
67+ }
5368 }
5469
55- $ url = new URI ($ fullPath );
70+ $ url .= $ relativePath ;
71+
72+ $ uri = new URI ($ url );
5673
57- // allow the scheme to be over-ridden; else, use default
58- if (! empty ( $ protocol ) )
74+ // Check if the baseURL scheme needs to be coerced into its secure version
75+ if ($ config -> forceGlobalSecureRequests && $ uri -> getScheme () === ' http ' )
5976 {
60- $ url ->setScheme ($ protocol );
77+ $ uri ->setScheme (' https ' );
6178 }
6279
63- return ( string ) $ url ;
80+ return $ uri ;
6481 }
6582}
6683
6784//--------------------------------------------------------------------
6885
69- if (! function_exists ('base_url ' ))
86+ if (! function_exists ('site_url ' ))
7087{
7188 /**
72- * Return the base URL to use in views
89+ * Returns a site URL as defined by the App config.
90+ *
91+ * @param mixed $relativePath URI string or array of URI segments
92+ * @param string|null $scheme
93+ * @param App|null $config Alternate configuration to use
7394 *
74- * @param mixed $uri URI string or array of URI segments
75- * @param string $protocol
7695 * @return string
7796 */
78- function base_url ( $ uri = '' , string $ protocol = null ): string
97+ function site_url ( $ relativePath = '' , string $ scheme = null , App $ config = null ): string
7998 {
80- // convert segment array to string
81- if (is_array ($ uri ))
99+ // Convert array of segments to a string
100+ if (is_array ($ relativePath ))
82101 {
83- $ uri = implode ('/ ' , $ uri );
102+ $ relativePath = implode ('/ ' , $ relativePath );
84103 }
85- $ uri = trim ($ uri , '/ ' );
86-
87- // We should be using the configured baseURL that the user set;
88- // otherwise get rid of the path, because we have
89- // no way of knowing the intent...
90- $ config = Services::request ()->config ;
91104
92- // If baseUrl does not have a trailing slash it won't resolve
93- // correctly for users hosting in a subfolder.
94- $ baseUrl = ! empty ($ config ->baseURL ) && $ config ->baseURL !== '/ '
95- ? rtrim ($ config ->baseURL , '/ ' ) . '/ '
96- : $ config ->baseURL ;
105+ $ uri = _get_uri ($ relativePath , $ config );
97106
98- $ url = new URI ($ baseUrl );
99- unset($ config );
100-
101- // Merge in the path set by the user, if any
102- if ($ uri !== '' )
103- {
104- $ url = $ url ->resolveRelativeURI ($ uri );
105- }
107+ return URI ::createURIString ($ scheme ?? $ uri ->getScheme (), $ uri ->getAuthority (), $ uri ->getPath (), $ uri ->getQuery (), $ uri ->getFragment ());
108+ }
109+ }
106110
107- // If the scheme wasn't provided, check to
108- // see if it was a secure request
109- if (empty ($ protocol ) && Services::request ()->isSecure ())
110- {
111- $ protocol = 'https ' ;
112- }
111+ //--------------------------------------------------------------------
113112
114- if (! empty ($ protocol ))
115- {
116- $ url ->setScheme ($ protocol );
117- }
113+ if (! function_exists ('base_url ' ))
114+ {
115+ /**
116+ * Returns the base URL as defined by the App config.
117+ * Base URLs are trimmed site URLs without the index page.
118+ *
119+ * @param mixed $relativePath URI string or array of URI segments
120+ * @param string $scheme
121+ * @return string
122+ */
123+ function base_url ($ relativePath = '' , string $ scheme = null ): string
124+ {
125+ $ config = clone config ('App ' );
126+ $ config ->indexPage = '' ;
118127
119- return rtrim (( string ) $ url , ' / ' );
128+ return rtrim (site_url ( $ relativePath , $ scheme , $ config ), ' / ' );
120129 }
121130}
122131
@@ -125,22 +134,32 @@ function base_url($uri = '', string $protocol = null): string
125134if (! function_exists ('current_url ' ))
126135{
127136 /**
128- * Current URL
129- *
130- * Returns the full URL (including segments) of the page where this
131- * function is placed
137+ * Returns the current full URL based on the IncomingRequest.
138+ * String returns ignore query and fragment parts.
132139 *
133- * @param boolean $returnObject True to return an object instead of a strong
140+ * @param boolean $returnObject True to return an object instead of a string
141+ * @param IncomingRequest|null $request A request to use when retrieving the path
134142 *
135143 * @return string|URI
136144 */
137- function current_url (bool $ returnObject = false )
145+ function current_url (bool $ returnObject = false , IncomingRequest $ request = null )
138146 {
139- $ uri = clone Services::request ()->uri ;
147+ $ request = $ request ?? Services::request ();
148+ $ path = $ request ->getPath ();
149+
150+ // Append queries and fragments
151+ if ($ query = $ request ->getUri ()->getQuery ())
152+ {
153+ $ path .= '? ' . $ query ;
154+ }
155+ if ($ fragment = $ request ->getUri ()->getFragment ())
156+ {
157+ $ path .= '# ' . $ fragment ;
158+ }
159+
160+ $ uri = _get_uri ($ path );
140161
141- // Since we're basing off of the IncomingRequest URI,
142- // we are guaranteed to have a host based on our own configs.
143- return $ returnObject ? $ uri : (string ) $ uri ->setQuery ('' );
162+ return $ returnObject ? $ uri : URI ::createURIString ($ uri ->getScheme (), $ uri ->getAuthority (), $ uri ->getPath ());
144163 }
145164}
146165
@@ -285,7 +304,7 @@ function anchor_popup($uri = '', string $title = '', $attributes = false, App $a
285304 // use alternate config if provided, else default one
286305 $ config = $ altConfig ?? config (App::class);
287306
288- $ siteUrl = preg_match ('#^(\w+:)?//#i ' , $ uri ) ? $ uri : site_url ($ uri , '' , $ config );
307+ $ siteUrl = preg_match ('#^(\w+:)?//#i ' , $ uri ) ? $ uri : site_url ($ uri , null , $ config );
289308 $ siteUrl = rtrim ($ siteUrl , '/ ' );
290309
291310 if ($ title === '' )
0 commit comments