Version 4.1.2

This commit is contained in:
Neo committed 2025-12-19 05:32:19 -08:00
1 parent 3ba79295ee
commit 28bd025b35
1131 files changed
+63658 -20579

No files matched your search

+118 -68
View File
@@ -246,10 +246,17 @@ class _Theme extends \IPS\Node\Model
$setId = NULL;
\IPS\Session\Front::i()->setTheme(0);
}
else if ( static::load( $setId )->canAccess() !== true )
else
{
$setId = NULL;
try
{
if ( static::load( $setId )->canAccess() !== true )
{
$setId = NULL;
}
} catch ( \OutOfRangeException $ex ){}
}
}
}
if ( ! $setId and \IPS\Member::loggedIn()->$column and array_key_exists( \IPS\Member::loggedIn()->$column, static::themes() ) )
@@ -418,10 +425,12 @@ class _Theme extends \IPS\Node\Model
* Switches the currently initialized theme during execution
*
* @param int $themeId Id of the theme to switch to
* @param boolean $persistent Allow to persist through ajax calls
* @return boolean
* @note This will not check to ensure the member has permission to view the theme
*/
public static function switchTheme( $themeId )
public static function switchTheme( $themeId, $persistent=TRUE )
{
static::themes();
@@ -430,7 +439,10 @@ class _Theme extends \IPS\Node\Model
static::$memberTheme = static::load( $themeId );
/* Store the ID in sessions so ajax loads correct theme */
\IPS\Session\Front::i()->setTheme( $themeId );
if ( $persistent )
{
\IPS\Session\Front::i()->setTheme( $themeId );
}
/* Flush loaded CSS */
\IPS\Output::i()->cssFiles = array();
@@ -708,9 +720,9 @@ class _Theme extends \IPS\Node\Model
$class = "\\IPS\\Theme\\{$class}";
/* Init */
static::$calledTemplates[ $key ] = new $class();
static::$calledTemplates[ $key ] = new \IPS\Theme\SandboxedTemplate( new $class( $app, $location, $group ) );
}
return static::$calledTemplates[ $key ];
}
@@ -1112,8 +1124,6 @@ class _Theme extends \IPS\Node\Model
*/
public function delete()
{
if ( \IPS\IN_DEV AND $this->_id == 1 )
{
\IPS\Output::i()->error( 'theme_error_not_available_in_dev', '2S140/1', 403, '' );
@@ -1191,14 +1201,14 @@ class _Theme extends \IPS\Node\Model
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('core_theme_editing_set', FALSE, array( 'sprintf' => array( $this->_title ) ) );
$form->addtab( 'theme_set_tab__general' );
$form->addTab( 'theme_set_tab__general' );
}
else
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('theme_set_add_button');
$form->hiddenValues['theme_type'] = \IPS\Request::i()->type;
$form->addtab( ( \IPS\Request::i()->type === 'vse' ) ? 'theme_set_tab__new_vse_set' : 'theme_set_tab__new_custom_set' );
$form->addTab( ( \IPS\Request::i()->type === 'vse' ) ? 'theme_set_tab__new_vse_set' : 'theme_set_tab__new_custom_set' );
}
$form->add( new \IPS\Helpers\Form\Translatable( 'core_theme_set_title', NULL, TRUE, array( 'app' => 'core', 'key' => ( $this->id ? "core_theme_set_title_{$this->id}" : NULL ) ) ) );
@@ -1251,35 +1261,35 @@ class _Theme extends \IPS\Node\Model
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_export_author_url' , $this->author_url, false ) );
$form->add( new \IPS\Helpers\Form\Text( 'theme_update_check' , $this->update_check, false ) );
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_export_version' , $this->version , false, array( 'placeholder' => '1.0.0' ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'theme_template_export_long_version' , $this->long_version, false ) );
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_export_version' , $this->version ? $this->version : '1.0' , true, array( 'placeholder' => '1.0.0' ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'theme_template_export_long_version' , $this->long_version ? $this->long_version : 10000, true ) );
}
/* Logo */
$form->addtab( 'theme_set_tab__logo' );
$form->addTab( 'theme_set_tab__logo' );
/* SITE LOGO */
$form->addHeader( 'core_theme_set_logo_manage' );
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_set_logo', ( isset( $this->logo['front']['url'] ) ? \IPS\File::get( 'core_Theme', $this->logo['front']['url'] ) : NULL ), FALSE, array( 'image' => true, 'storageExtension' => 'core_Theme', 'storageContainer' => 'set_resources_' . $this->id ), NULL, NULL, NULL, 'core_theme_set_logo' ) );
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_set_logo', ( isset( $this->logo['front']['url'] ) ? \IPS\File::get( 'core_Theme', $this->logo['front']['url'] ) : NULL ), FALSE, array( 'image' => true, 'storageExtension' => 'core_Theme' ), NULL, NULL, NULL, 'core_theme_set_logo' ) );
/* SHARER LOGO */
$form->addHeader( 'core_theme_set_sharer_logo_manage' );
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_set_sharer_logo', ( isset( $this->logo['sharer']['url'] ) ? \IPS\File::get( 'core_Theme', $this->logo['sharer']['url'] ) : NULL ), FALSE, array( 'image' => true, 'storageExtension' => 'core_Theme', 'storageContainer' => 'set_resources_' . $this->id ), NULL, NULL, NULL, 'core_theme_set_sharer_logo' ) );
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_set_sharer_logo', ( isset( $this->logo['sharer']['url'] ) ? \IPS\File::get( 'core_Theme', $this->logo['sharer']['url'] ) : NULL ), FALSE, array( 'image' => true, 'storageExtension' => 'core_Theme' ), NULL, NULL, NULL, 'core_theme_set_sharer_logo' ) );
/* FAVICO LOGO */
$form->addHeader( 'core_theme_set_favico_logo_manage' );
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_set_favico_logo', ( isset( $this->logo['favicon']['url'] ) ? \IPS\File::get( 'core_Theme', $this->logo['favicon']['url'] ) : NULL ), FALSE, array( 'allowedFileTypes' => array('ico'), 'storageExtension' => 'core_Theme', 'storageContainer' => 'set_resources_' . $this->id ), NULL, NULL, NULL, 'core_theme_set_favico_logo' ) );
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_set_favico_logo', ( isset( $this->logo['favicon']['url'] ) ? \IPS\File::get( 'core_Theme', $this->logo['favicon']['url'] ) : NULL ), FALSE, array( 'allowedFileTypes' => array('ico'), 'storageExtension' => 'core_Theme' ), NULL, NULL, NULL, 'core_theme_set_favico_logo' ) );
/* EDITOR */
$form->addTab('core_theme_set_editor_header');
if ( \IPS\IN_DEV )
{
//$form->addMessage( \IPS\Member::loggedIn()->language()->get('core_theme_set_editor_dev'), 'ipsMessage ipsMessage_warning' );
$form->addMessage( \IPS\Member::loggedIn()->language()->get('core_theme_set_editor_dev'), 'ipsMessage ipsMessage_warning' );
}
$form->addMessage('core_theme_set_editor_blurb');
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack( 'core_theme_set_editor_blurb', FALSE, array( 'sprintf' => array( \IPS\Helpers\Form\Editor::ckeditorVersion() ) ) ) );
if ( !\IPS\NO_WRITES and class_exists( 'ZipArchive', FALSE ) )
{
$form->add( new \IPS\Helpers\Form\Radio( 'core_theme_set_editor', 'existing', FALSE, array(
@@ -1353,7 +1363,7 @@ class _Theme extends \IPS\Node\Model
foreach( $customTabs as $tabKey => $data )
{
$form->addtab( 'theme_custom_tab_' . $tabKey );
$form->addTab( 'theme_custom_tab_' . $tabKey );
if ( \IPS\IN_DEV AND $this->_id === 1 )
{
@@ -1423,7 +1433,6 @@ class _Theme extends \IPS\Node\Model
break;
case 'Upload':
$options['storageExtension'] = 'core_Theme';
$options['storageContainer'] = 'set_resources_' . $this->id;
if ( $value )
{
@@ -1609,6 +1618,7 @@ class _Theme extends \IPS\Node\Model
$this->child_array = '[]';
$this->parent_id = ( $values['core_theme_parent_id'] instanceof \IPS\Theme ) ? $values['core_theme_parent_id']->id : 0;
$this->by_skin_gen = ( \IPS\Request::i()->theme_type === 'vse' ) ? 1 : 0;
$this->long_version = \IPS\Application::load( 'core' )->long_version;
$this->save();
/* Copy across resources */
@@ -1812,7 +1822,7 @@ class _Theme extends \IPS\Node\Model
\IPS\File::getClass('core_Theme')->deleteContainer( 'css_built_' . $this->id );
$this->css_map = array();
foreach( $themeSetToBuild->children() as $child )
foreach( $themeSetToBuild->allChildren() as $id => $child )
{
\IPS\File::getClass('core_Theme')->deleteContainer( 'css_built_' . $child->id );
$child->css_map = array();
@@ -2071,6 +2081,24 @@ class _Theme extends \IPS\Node\Model
$this->save();
}
/**
* Return all children
*
* @param $theme \IPS\Theme item
* @return array
*/
public function allChildren( &$return=array() )
{
foreach( $this->children() as $child )
{
$return[ $child->id ] = $child;
$child->allChildren( $return );
}
return $return;
}
/**
* Compile CSS ready for non IN_DEV use. This replaces any HTML logic such as {resource="foo.png"} with full URLs
*
@@ -2222,10 +2250,15 @@ class _Theme extends \IPS\Node\Model
{
if ( !class_exists( "IPS\\Theme\\{$data['class']}_tmp", FALSE ) )
{
if ( eval( "namespace IPS\\Theme;\n\n" . str_replace( array( ' extends _HOOK_CLASS_', 'parent::hookData()' ), array( '_tmp', 'array()' ), file_get_contents( \IPS\ROOT_PATH . '/' . $data['file'] ) ) ) !== FALSE )
/* Like code hooks, we should only attempt to load the files contents if it actually exists */
/* @see https://community.invisionpower.com/4bugtrack/archived-reports/ipsipsmonkeypatch-r6333/ */
if ( file_exists( \IPS\ROOT_PATH . '/' . $data['file'] ) )
{
$class = "IPS\\Theme\\{$data['class']}_tmp";
$templateHooks = array_merge_recursive( $templateHooks, $class::hookData() );
if ( eval( "namespace IPS\\Theme;\n\n" . str_replace( array( ' extends _HOOK_CLASS_', 'parent::hookData()' ), array( '_tmp', 'array()' ), file_get_contents( \IPS\ROOT_PATH . '/' . $data['file'] ) ) ) !== FALSE )
{
$class = "IPS\\Theme\\{$data['class']}_tmp";
$templateHooks = array_merge_recursive( $templateHooks, $class::hookData() );
}
}
}
}
@@ -2246,7 +2279,7 @@ class _Theme extends \IPS\Node\Model
/* Put them in a class */
$template = <<<EOF
namespace IPS\Theme;
class class_{$app}_{$location}_{$group}
class class_{$app}_{$location}_{$group} extends \IPS\Theme\Template
{
EOF;
@@ -2346,7 +2379,7 @@ EOF;
{
$children = array( $this->_id );
foreach( $this->children() as $child )
foreach( $this->allChildren() as $id => $child )
{
$children[] = $child->_id;
}
@@ -2406,7 +2439,7 @@ EOF;
$css = array();
$children = array( $this->_id );
foreach( $this->children() as $child )
foreach( $this->allChildren() as $child )
{
$children[] = $child->_id;
}
@@ -2459,6 +2492,7 @@ EOF;
{
\IPS\Db::i()->update( 'core_theme_css', array( 'css_attributes' => ( ! empty( $data['attributes'] ) ) ? $data['attributes'] : '',
'css_content' => $data['content'],
'css_user_edited' => \IPS\Application::load( $data['app'] )->long_version,
'css_updated' => time() ), array('css_id=?', (int)$data['item_id'] ) );
$newCssId = $data['item_id'];
@@ -2499,7 +2533,7 @@ EOF;
{
$children = array( $this->_id );
foreach( $this->children() as $child )
foreach( $this->allChildren() as $child )
{
$children[] = $child->_id;
}
@@ -2583,7 +2617,7 @@ EOF;
$template = array();
$children = array( $this->_id );
foreach( $this->children() as $child )
foreach( $this->allChildren() as $child )
{
$children[] = $child->_id;
}
@@ -2744,9 +2778,18 @@ EOF;
try
{
$allParents = array();
foreach( $this->parents() as $parent )
{
$parents[] = $parent->_id;
$allParents[] = $parent->_id;
}
if ( count( $allParents ) )
{
foreach( array_reverse( $allParents ) as $id )
{
$parents[] = $id;
}
}
}
catch( \OutOfRangeException $e ) { }
@@ -2772,7 +2815,7 @@ EOF;
}
$select = ( $returnType & static::RETURN_BIT_NAMES ) ? 'css_app, css_location, css_path, css_set_id, css_id, css_name, css_modules, css_attributes, css_removed, css_added_to, css_hidden' : '*';
foreach(
\IPS\Db::i()->select(
$select . ', INSTR(\',' . implode( ',' , $parents ) . ',\', CONCAT(\',\',css_set_id,\',\') ) as theorder',
@@ -2808,7 +2851,7 @@ EOF;
{
continue;
}
if ( $row['css_set_id'] === 0 )
{
$row['InheritedValue'] = 'original';
@@ -2903,9 +2946,18 @@ EOF;
try
{
$allParents = array();
foreach( $this->parents() as $parent )
{
$parents[] = $parent->_id;
$allParents[] = $parent->_id;
}
if ( count( $allParents ) )
{
foreach( array_reverse( $allParents ) as $id )
{
$parents[] = $id;
}
}
}
catch( \OutOfRangeException $e ) { }
@@ -2964,7 +3016,7 @@ EOF;
{
$row['InheritedValue'] = 'inherit';
}
else if ( $row['template_user_added'] and $row['template_set_id'] != $this->_id )
else if ( $row['template_user_added'] and $row['template_added_to'] != $this->_id )
{
$row['InheritedValue'] = 'original';
}
@@ -3127,7 +3179,7 @@ EOF;
{
$save = array();
$fields = array( 'name', 'key', 'parent_id', 'permissions', 'is_default', 'author_name', 'author_url', 'resource_dir', 'emo_dir', 'hide_from_list', 'order', 'version', 'long_version', 'update_check' );
foreach( $fields as $k )
{
if ( isset( $data[ 'set_' . $k ] ) )
@@ -3135,8 +3187,15 @@ EOF;
$save[ 'set_' . $k ] = $data[ 'set_' . $k ];
}
}
$save['set_long_version'] = ( isset( $save['set_long_version'] ) ) ? (int) $save['set_long_version'] : 0;
if ( ! $this->_id )
{
$save['set_long_version'] = ( ! empty( $save['set_long_version'] ) ) ? (int) $save['set_long_version'] : \IPS\Application::load( 'core' )->long_version;
}
else if ( isset( $save['set_long_version'] ) )
{
$save['set_long_version'] = intval( $save['set_long_version'] );
}
foreach( array( 'front', 'sharer', 'favicon' ) as $icon )
{
@@ -3414,15 +3473,10 @@ EOF;
if ( ! empty( $themeId ) )
{
$themeSet = static::load( $themeId );
$themeSets[] = $themeId;
$themeSet = static::load( $themeId );
$themeSets = array( $themeId => $themeSet ) + $themeSet->allChildren();
foreach( $themeSet->children() as $child )
{
$themeSets[] = $child->_id;
}
$where[] = array( \IPS\Db::i()->in( 'template_set_id', $themeSets ) );
$where[] = array( \IPS\Db::i()->in( 'template_set_id', array_keys( $themeSets ) ) );
}
foreach(
@@ -3437,7 +3491,7 @@ EOF;
/* ... remove from each theme */
foreach( static::themes() as $id => $set )
{
if ( $themeId === null OR in_array( $id, $themeSets ) )
if ( $themeId === null OR in_array( $id, array_keys( $themeSets ) ) )
{
$key = \strtolower( 'template_' . $set->id . '_' .static::makeBuiltTemplateLookupHash( $data['template_app'], $data['template_location'], $data['template_group'] ) . '_' . static::cleanGroupName( $data['template_group'] ) );
@@ -3465,15 +3519,10 @@ EOF;
if ( $themeId !== null )
{
$themeSet = static::load( $themeId );
$themeSets[] = $themeId;
foreach( $themeSet->children() as $child )
{
$themeSets[] = $child->_id;
}
$where[] = array( \IPS\Db::i()->in( 'css_set_id', $themeSets ) );
$themeSet = static::load( $themeId );
$themeSets = array( $themeId => $themeSet ) + $themeSet->allChildren();
$where[] = array( \IPS\Db::i()->in( 'css_set_id', array_keys( $themeSets ) ) );
}
if ( $app === null )
@@ -3481,7 +3530,7 @@ EOF;
/* Each theme... */
foreach( static::themes() as $id => $set )
{
if ( $themeId === null OR in_array( $id, $themeSets ) )
if ( $themeId === null OR in_array( $id, array_keys( $themeSets ) ) )
{
\IPS\File::getClass( 'core_Theme')->deleteContainer('css_built_' . $set->_id );
@@ -3530,7 +3579,7 @@ EOF;
/* Each theme... */
foreach( static::themes() as $id => $set )
{
if ( $themeId === null OR in_array( $id, $themeSets ) )
if ( $themeId === null OR in_array( $id, array_keys( $themeSets ) ) )
{
$built = array();
$map = $set->css_map;
@@ -3607,12 +3656,7 @@ EOF;
if ( ! empty( $themeId ) )
{
$themeSet = static::load( $themeId );
$themeSets[] = $themeId;
foreach( $themeSet->children() as $child )
{
$themeSets[] = $child->_id;
}
$themeSets = array( $themeId => $themeSet ) + $themeSet->allChildren();
}
if ( $app === null )
@@ -3620,7 +3664,7 @@ EOF;
/* Each theme... */
foreach( static::themes() as $id => $set )
{
if ( $themeId === null OR in_array( $id, $themeSets ) )
if ( $themeId === null OR in_array( $id, array_keys( $themeSets ) ) )
{
\IPS\File::getClass( 'core_Theme' )->deleteContainer('set_resources_' . $set->_id );
@@ -3647,7 +3691,7 @@ EOF;
if ( $themeId !== null )
{
$query[] = \IPS\Db::i()->in( 'resource_set_id', $themeSets );
$query[] = \IPS\Db::i()->in( 'resource_set_id', array_keys( $themeSets ) );
}
if ( $app !== NULL )
@@ -4056,7 +4100,13 @@ PHP;
}
}
}
/* Still doesn't exist? */
if( ! class_exists( $pluginClass ) )
{
return $matches[0];
}
/* can be used in CSS? */
if ( $isCSS AND $pluginClass::$canBeUsedInCss !== TRUE )
{
@@ -4122,11 +4172,11 @@ PHP;
{
if ( \stristr( $var[1], '|doubleencode' ) )
{
$replace = "\nCONTENT;\n\$return .= htmlentities( \$" . str_ireplace( '|doubleencode', '', $var[1] ) . ", ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', TRUE );\n\$return .= <<<CONTENT\n";
$replace = "\nCONTENT;\n\$return .= htmlspecialchars( \$" . str_ireplace( '|doubleencode', '', $var[1] ) . ", ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', TRUE );\n\$return .= <<<CONTENT\n";
}
else
{
$replace = "\nCONTENT;\n\$return .= htmlentities( \$" . $var[1] . ", ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );\n\$return .= <<<CONTENT\n";
$replace = "\nCONTENT;\n\$return .= htmlspecialchars( \$" . $var[1] . ", ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );\n\$return .= <<<CONTENT\n";
}
$all = str_replace( $var[0], $replace, $all );