Version 5.0.0 beta 1

This commit is contained in:
Neo committed 2025-12-19 16:27:35 -08:00
1 parent 25ddeb65d6
commit 15c7beabc5
6736 files changed
+627902 -497943

No files matched your search

+98 -49
View File
@@ -11,30 +11,46 @@
namespace IPS\Http\Url;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use Exception;
use IPS\Content;
use IPS\Http\Url;
use IPS\Member\Club;
use IPS\Node\Model;
use IPS\cms\Pages\Router;
use IPS\Session;
use IPS\Application;
use OutOfRangeException;
use function count;
use function defined;
use function intval;
use function is_numeric;
use function is_string;
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Internal URL
*/
class _Internal extends \IPS\Http\Url
class Internal extends Url
{
/**
* Create internal URL from components - all arguments should be UNENCODED
*
* @param string $base Key for the URL base
* @param int|string|null $protocol Protocol (one of the PROTOCOL_* constants) or an actual scheme
* @param string $path Path, relative to site's base URL
* @param string|array|NULL $query Query
* @param string|NULL $fragment Fragment
* @return \IPS\Http\Url
* @param string $base Key for the URL base
* @param int|string|null $protocol Protocol (one of the PROTOCOL_* constants) or an actual scheme
* @param string $path Path, relative to site's base URL
* @param array|string|null $query Query
* @param string|null $fragment Fragment
* @return Url
*/
protected static function createInternalFromComponents( $base, $protocol, $path, $query = NULL, $fragment = NULL )
protected static function createInternalFromComponents( string $base, int|string|null $protocol, string $path, array|string $query = NULL, string $fragment = NULL ): Url
{
$baseUrlData = parse_url( static::baseUrl( \is_numeric( $protocol ) ? $protocol : NULL ) );
$baseUrlData = parse_url( static::baseUrl( is_numeric( $protocol ) ? $protocol : NULL ) );
$pathToUse = '';
if ( isset( $baseUrlData['path'] ) and $baseUrlData['path'] )
@@ -52,12 +68,12 @@ class _Internal extends \IPS\Http\Url
$return = static::createFromComponents(
$baseUrlData['host'],
( \is_string( $protocol ) and !\is_numeric( $protocol ) ) ? $protocol : ( ( isset( $baseUrlData['scheme'] ) AND $protocol !== NULL ) ? $baseUrlData['scheme'] : NULL ),
( is_string( $protocol ) and !is_numeric( $protocol ) ) ? $protocol : ( ( isset( $baseUrlData['scheme'] ) AND $protocol !== NULL ) ? $baseUrlData['scheme'] : NULL ),
$pathToUse ? "/{$pathToUse}" : '',
$query,
isset( $baseUrlData['port'] ) ? $baseUrlData['port'] : NULL,
isset( $baseUrlData['user'] ) ? $baseUrlData['user'] : NULL,
isset( $baseUrlData['pass'] ) ? $baseUrlData['pass'] : NULL,
$baseUrlData['port'] ?? NULL,
$baseUrlData['user'] ?? NULL,
$baseUrlData['pass'] ?? NULL,
$fragment
);
@@ -68,21 +84,23 @@ class _Internal extends \IPS\Http\Url
/**
* @brief Does this URL have the SEO pagination (page/n/)?
*/
public $seoPagination = NULL;
public ?bool $seoPagination = NULL;
/**
* @brief Base
*/
public $base;
public ?string $base = NULL;
/**
* Get the friendly URL for this URL if there is one
*
* @return mixed The friendly URL if there is one, TRUE if there isn't, or NULL if not sure
*/
public function correctFriendlyUrl()
public function correctFriendlyUrl(): mixed
{
foreach ( \IPS\Http\Url\Friendly::furlDefinition() as $seoTemplate => $furlDefinition )
$return = FALSE;
foreach (Friendly::furlDefinition() as $seoTemplate => $furlDefinition )
{
if( mb_stripos( $this->data[ static::COMPONENT_QUERY ], $furlDefinition['real'] ) !== FALSE )
{
@@ -95,9 +113,6 @@ class _Internal extends \IPS\Http\Url
switch ( mb_substr( $tag, 0, 1 ) )
{
case '#':
$params[] = mb_substr( $tag, 1 );
break;
case '@':
$params[] = mb_substr( $tag, 1 );
break;
@@ -105,7 +120,7 @@ class _Internal extends \IPS\Http\Url
}
/* If this definition requires a parameter, see if we have it. If not, skip to next definition to check. */
if( \count( array_diff( $params, array_keys( $this->queryString ) ) ) )
if( count( array_diff( $params, array_keys( $this->queryString ) ) ) )
{
continue;
}
@@ -119,16 +134,15 @@ class _Internal extends \IPS\Http\Url
/* Load it */
try
{
if ( $return = $this->correctUrlFromVerifyClass( $furlDefinition['verify'] ) )
if ( ! $return = $this->correctUrlFromVerifyClass( $furlDefinition['verify'] ) )
{
return $return;
$return = NULL;
}
return NULL;
}
/* It doesn't exist */
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
return NULL;
$return = NULL;
}
}
/* If not, we have to build it ourself */
@@ -147,27 +161,62 @@ class _Internal extends \IPS\Http\Url
$seoTitles[] = $class::load( $this->queryString[ $queryParam ] )->$property;
}
catch ( \OutOfRangeException $e ) {}
catch ( OutOfRangeException $e ) {}
}
}
return \IPS\Http\Url::internal( $this->data['query'], 'front', $seoTemplate, $seoTitles );
$return = Url::internal( $this->data['query'], 'front', $seoTemplate, $seoTitles );
}
}
catch ( \Exception $e ) {}
catch ( Exception $e ) {}
}
}
return TRUE;
/* If it it thinks it belongs to "pages", we might be able to be more accurate */
if ( Application::appIsEnabled( 'cms' ) and ( $return instanceof Friendly and $return->seoTemplate === 'content_page_path' and isset( $this->queryString['path'] ) ) )
{
/* Try to find a page */
try
{
/* Create it */
$correctUrl = Router::loadFromUrl( $this )->url();
/* Set extra stuff in our query string */
$paramsToSet = array();
foreach ( $this->queryString as $k => $v )
{
if ( !array_key_exists( $k, $correctUrl->queryString ) and !array_key_exists( $k, $correctUrl->hiddenQueryString ) )
{
$paramsToSet[ $k ] = $v;
}
}
if ( count( $paramsToSet ) )
{
$correctUrl = $correctUrl->setQueryString( $paramsToSet );
}
/* Return */
$return = $correctUrl;
}
/* Couldn't find one? Don't accept responsibility */
catch (OutOfRangeException $e ){}
}
else if( $return !== NULL )
{
$return = TRUE;
}
return $return;
}
/**
* Get the correct URL using a "verify" property from the FURL definition
*
* @param object $verify Class containing `preCorrectUrlFromVerifyClass()` method to check URL against
* @return NULL|\IPS\Http\Url
* @throws \OutOfRangeException
* @param mixed $verify Class containing `preCorrectUrlFromVerifyClass()` method to check URL against
* @return NULL|Url
* @throws OutOfRangeException
*/
protected function correctUrlFromVerifyClass( $verify )
protected function correctUrlFromVerifyClass( mixed $verify ): ?Url
{
/* Load it */
if ( method_exists( $verify, 'preCorrectUrlFromVerifyClass' ) )
@@ -179,11 +228,11 @@ class _Internal extends \IPS\Http\Url
/* Check the currently logged in user can view it, as we don't want to reveal the correct
URL to something the user has no permission to view */
$canView = TRUE;
if ( $contentObject instanceof \IPS\Content or $contentObject instanceof \IPS\Member\Club )
if ( $contentObject instanceof Content or $contentObject instanceof Club )
{
$canView = $contentObject->canView();
}
elseif ( $contentObject instanceof \IPS\Node\Model )
elseif ( $contentObject instanceof Model )
{
$canView = $contentObject->can('view');
}
@@ -204,7 +253,7 @@ class _Internal extends \IPS\Http\Url
$paramsToSet[ $k ] = $v;
}
}
if ( \count( $paramsToSet ) )
if ( count( $paramsToSet ) )
{
$correctUrl = $correctUrl->setQueryString( $paramsToSet );
}
@@ -216,26 +265,26 @@ class _Internal extends \IPS\Http\Url
/**
* Add CSRF check to query string
*
* @return \IPS\Http\Url
* @return Url
*/
public function csrf()
public function csrf(): Url
{
return $this->setQueryString( 'csrfKey', \IPS\Session::i()->csrfKey );
return $this->setQueryString( 'csrfKey', Session::i()->csrfKey );
}
/**
* Adds the page parameter to the URL
*
* @param string $param The page key, default is 'page'
* @param int|NULL $number The page number to use
* @return \IPS\Http\Url
* @param string $param The page key, default is 'page'
* @param int|null $number The page number to use
* @return Url
*/
public function setPage( $param='page', $number=1 )
public function setPage( string $param='page', ?int $number=1 ): Url
{
/* Remove any existing page param */
$url = $this->stripQueryString( $param );
if ( \intval( $number ) > 1 )
if ( intval( $number ) > 1 )
{
$url = $this->setQueryString( $param, $number );
}
@@ -248,7 +297,7 @@ class _Internal extends \IPS\Http\Url
*
* @return string
*/
public function acpQueryString()
public function acpQueryString(): string
{
$queryString = $this->queryString;
unset( $queryString['csrf'] );
@@ -261,7 +310,7 @@ class _Internal extends \IPS\Http\Url
*
* @return bool
*/
public function openRedirect()
public function openRedirect(): bool
{
return isset( $this->queryString['app'] ) and $this->queryString['app'] === 'core' and isset( $this->queryString['module'] ) and $this->queryString['module'] === 'system' and isset( $this->queryString['controller'] ) and $this->queryString['controller'] === 'redirect';
}