Version 4.2.0

This commit is contained in:
Neo committed 2025-12-19 05:44:59 -08:00
1 parent 0dc2aee5ed
commit 96997ddd8e
2074 files changed
+125454 -55780

No files matched your search

+86 -34
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Page Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Content
* @since 15 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\cms\Pages;
@@ -73,6 +72,11 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
* @brief [Node] Parent ID Database Column
*/
public static $databaseColumnOrder = 'seo_name';
/**
* @brief [Node] Automatically set position for new nodes
*/
public static $automaticPositionDetermination = FALSE;
/**
* @brief [Node] Show forms modally?
@@ -143,9 +147,6 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public static $defaultPage = array();
/**
*
*/
/**
* @brief Pre save flag
*/
@@ -187,8 +188,8 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public static function loadFromUrl( \IPS\Http\Url $url )
{
$qs = array_merge( $url->queryString, $url->hiddenQueryString );
$qs = array_merge( $url->hiddenQueryString, $url->queryString );
if ( isset( $qs['id'] ) )
{
if ( method_exists( get_called_class(), 'loadAndCheckPerms' ) )
@@ -202,7 +203,15 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
else if ( isset( $qs['path'] ) )
{
$return = static::load( $qs['path'], 'page_full_path' );
try
{
$return = static::load( $qs['path'], 'page_full_path' );
}
catch( \OutOfRangeException $ex )
{
$return = static::loadFromPath( $qs['path'] );
}
if ( method_exists( $return, 'can' ) )
{
if ( !$return->can( 'view' ) )
@@ -270,7 +279,6 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
return $children;
}
/**
* Returns a page object (or NULL) based on the path
*
@@ -538,8 +546,9 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
try
{
$page = static::load( \IPS\Settings::i()->cms_error_page );
$page->content = str_replace( '{error_message}', $message, $page->content );
$page->content = str_replace( '{error_code}', $code, $page->content );
$content = $page->getHtmlContent();
$content = str_replace( '{error_message}', $message, $content );
$content = str_replace( '{error_code}', $code, $content );
/* Pages are compiled and cached, which we do not want for the error page as the {error_*} tags are saved with their text content */
$functionName = 'content_pages_' . $page->id;
@@ -548,7 +557,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
unset( \IPS\Data\Store::i()->$functionName );
}
$page->output( $title, $httpStatusCode, $httpHeaders );
$page->output( $title, $httpStatusCode, $httpHeaders, $content );
}
catch( \Exception $ex )
{
@@ -567,7 +576,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
$return = array();
$pageType = isset( \IPS\Request::i()->page_type ) ? \IPS\Request::i()->page_type : ( $item ? $item->type : 'html' );
$return['tab_details'] = array( 'content_page_form_tab__details' );
$return['tab_details'] = array( 'content_page_form_tab__details', NULL, NULL, 'ipsForm_horizontal' );
$return['page_name'] = new \IPS\Helpers\Form\Translatable( 'page_name', NULL, TRUE, array( 'app' => 'cms', 'key' => ( $item and $item->id ) ? "cms_page_" . $item->id : NULL, 'maxLength' => 64 ), function( $val )
{
@@ -689,7 +698,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
if ( count( $js ) OR count( $css ) )
{
$return['tab_js_css'] = array( 'content_page_form_tab__includes' );
$return['tab_js_css'] = array( 'content_page_form_tab__includes', NULL, NULL, 'ipsForm_horizontal' );
$return['msg_js_css'] = array( 'cms_page_includes_message', 'ipsMessage ipsMessage_info ipsCmsIncludesMessage' );
if ( count( $js ) )
@@ -788,7 +797,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}, NULL, NULL, 'page_content' );
}
$return['tab_meta'] = array( 'content_page_form_tab__meta' );
$return['tab_meta'] = array( 'content_page_form_tab__meta', NULL, NULL, 'ipsForm_horizontal' );
$return['page_title'] = new \IPS\Helpers\Form\Text( 'page_title', $item ? $item->title : '', FALSE, array( 'maxLength' => 64 ), NULL, NULL, NULL, 'page_title' );
$return['page_meta_keywords'] = new \IPS\Helpers\Form\TextArea( 'page_meta_keywords', $item ? $item->meta_keywords : '', FALSE, array(), NULL, NULL, NULL, 'page_meta_keywords' );
$return['page_meta_description'] = new \IPS\Helpers\Form\TextArea( 'page_meta_description', $item ? $item->meta_description : '', FALSE, array(), NULL, NULL, NULL, 'page_meta_description' );
@@ -1022,7 +1031,35 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
public function getIncludes()
{
$return = array( 'css' => NULL, 'js' => NULL );
if ( \IPS\Theme::designersModeEnabled() )
{
foreach( array( 'js', 'css' ) as $thing )
{
$includeKey = $thing . '_includes';
if ( count( $this->$includeKey ) )
{
/* Build a file object for each thing */
foreach( $this->$includeKey as $key )
{
try
{
$template = \IPS\cms\Templates::load( $key );
$return[ $thing ][ $key ] = \IPS\Http\Url::createFromString( \IPS\Http\Url::baseUrl() . "/applications/cms/interface/developer/developer.php" )
->setQueryString( 'file', '/themes/cms/' . $template->location . '/' . $template->group . '/' . $template->title );
}
catch( \OutOfRangeException $e )
{
continue;
}
}
}
}
return $return;
}
/* Empty? Lets take a look and see if we need to compile anything */
if ( empty( $this->_data['js_css_objects'] ) )
{
@@ -1063,10 +1100,13 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
}
}
/* Save this to prevent it looking for includes on every page refresh */
$this->js_css_objects = json_encode( $return );
$this->save();
if ( ! \IPS\Theme::designersModeEnabled() )
{
/* Save this to prevent it looking for includes on every page refresh */
$this->js_css_objects = json_encode( $return );
$this->save();
}
}
else
{
@@ -1350,6 +1390,9 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
$pageType = $this->type;
}
/* We shut off the main class and add it per-tab to allow the content field to look good */
$form->class = '';
foreach( static::formElements( $this ) as $name => $field )
{
if ( $pageType !== 'html' and in_array( $name, array( 'page_ipb_wrapper', 'page_show_sidebar', 'page_wrapper_template' ) ) )
@@ -2083,12 +2126,13 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
* Displays a page
*
* @param string|NULL $title The Page title
* @param int $httpStatusCode HTTP Status Code
* @param array $httpHeaders Additional HTTP Headers
* @param int|NULL $httpStatusCode HTTP Status Code
* @param array|NULL $httpHeaders Additional HTTP Headers
* @param string|NULL $content Optional content to use. Useful if dynamic replacements need to be made at runtime
* @throws \ErrorException
* @return void
*/
public function output( $title=NULL, $httpStatusCode=NULL, $httpHeaders=NULL )
public function output( $title=NULL, $httpStatusCode=NULL, $httpHeaders=NULL, $content=NULL )
{
$includes = $this->getIncludes();
@@ -2121,11 +2165,9 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
/* Populate \IPS\Output::i()->sidebar['widgets'] sidebar/header/footer widgets */
$this->getWidgets();
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'pages', 'cms' )->globalWrap( $nav, $this->getHtmlContent(), $this );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'pages', 'cms' )->globalWrap( $nav, $content ?: $this->getHtmlContent(), $this );
}
\IPS\Output::i()->sidebar['enabled'] = true;
/* Set the meta tags, but do not reset them if they are already set - articles can define custom meta tags and this code
overwrites the ones set by articles if we don't verify they aren't set first */
if ( $this->meta_keywords AND ( !isset( \IPS\Output::i()->metaTags['keywords'] ) OR !\IPS\Output::i()->metaTags['keywords'] ) )
@@ -2138,8 +2180,9 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Output::i()->metaTags['description'] = $this->meta_description;
}
/* If this is a default page, we may be accessing this from the folder only */
if ( $this->default )
/* If this is a default page, we may be accessing this from the folder only. The isset() check is to ensure canonical
tags for more specific things (like databases) are not overridden. */
if ( $this->default AND !isset( \IPS\Output::i()->linkTags['canonical'] ) )
{
\IPS\Output::i()->linkTags['canonical'] = (string) $this->url();
}
@@ -2166,7 +2209,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
/* Set the title */
\IPS\Output::i()->title = ( $title ) ? $title : $this->getHtmlTitle();
\IPS\Output::i()->output = $this->getHtmlContent();
\IPS\Output::i()->output = $content ?: $this->getHtmlContent();
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( \IPS\Output::i()->title );
/* Send straight to the output engine */
@@ -2182,6 +2225,8 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
else
{
$this->setTheme();
if ( isset( $includes['css'] ) and is_array( $includes['css'] ) )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, array_values( $includes['css'] ) );
@@ -2200,12 +2245,17 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
/* Meta tags */
\IPS\Output::i()->buildMetaTags();
/* Ensure MFA pop up shows */
$mfa = \IPS\Dispatcher\Front::i()->checkMfa( TRUE );
$mfa = $mfa ?: '';
if ( $this->wrapper_template and $this->wrapper_template !== '_none_' and ! \IPS\Request::i()->isAjax() )
{
try
{
list( $group, $name, $key ) = explode( '__', $this->wrapper_template );
\IPS\Output::i()->sendOutput( \IPS\cms\Theme::i()->getTemplate($group, 'cms', 'page')->$name( $this->getHtmlContent(), $this->getHtmlTitle() ), 200, $this->getContentType(), \IPS\Output::i()->httpHeaders );
$content = $content ?: $this->getHtmlContent();
$content .= $mfa;
\IPS\Output::i()->sendOutput( \IPS\cms\Theme::i()->getTemplate($group, 'cms', 'page')->$name( $content, $this->getHtmlTitle() ), 200, $this->getContentType(), \IPS\Output::i()->httpHeaders );
}
catch( \OutOfRangeException $e )
{
@@ -2218,7 +2268,9 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( \IPS\Output::i()->title );
/* Send straight to the output engine */
\IPS\Output::i()->sendOutput( $this->getHtmlContent(), ( $httpStatusCode ? $httpStatusCode : 200 ), $this->getContentType(), ( $httpHeaders ? $httpHeaders : \IPS\Output::i()->httpHeaders ) );
$content = $content ?: $this->getHtmlContent();
$content .= $mfa;
\IPS\Output::i()->sendOutput( $content, ( $httpStatusCode ? $httpStatusCode : 200 ), $this->getContentType(), ( $httpHeaders ? $httpHeaders : \IPS\Output::i()->httpHeaders ) );
}
}