Version 4.3.0
This commit is contained in:
1 parent
96997ddd8e
commit
fe1acf984a
1349 files changed
+116159
-67711
No files matched your search
+236
-126
@@ -255,7 +255,7 @@ class _Theme extends \IPS\Node\Model
|
||||
static::themes();
|
||||
|
||||
/* Add in the default theme properties (_data array, etc) */
|
||||
$default = ( isset( static::$multitons[1] ) ) ? static::$multitons[1] : reset( static::$multitons );
|
||||
$default = ( isset( static::$multitons[ \IPS\DEFAULT_THEME_ID ] ) ) ? static::$multitons[ \IPS\DEFAULT_THEME_ID ] : reset( static::$multitons );
|
||||
|
||||
foreach( $default as $k => $v )
|
||||
{
|
||||
@@ -629,7 +629,7 @@ class _Theme extends \IPS\Node\Model
|
||||
|
||||
if ( $location === 'interface' )
|
||||
{
|
||||
return rtrim( \IPS\Http\Url::baseUrl( \IPS\Http\Url::PROTOCOL_RELATIVE ), '/' ) . "/applications/{$app}/interface{$path}{$name}";
|
||||
return \IPS\Http\Url::internal( "applications/{$app}/interface{$path}{$name}", 'interface', NULL, array(), \IPS\Http\Url::PROTOCOL_RELATIVE );
|
||||
}
|
||||
|
||||
if ( in_array( $key, array_keys( $this->resource_map ) ) )
|
||||
@@ -662,7 +662,7 @@ class _Theme extends \IPS\Node\Model
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$flagKey = 'resource_compiling_' . $this->_id . '_' . md5( $app . '_' . $location . '_' . $path );
|
||||
$flagKey = 'resource_compiling_' . $this->_id . '_' . md5( $key );
|
||||
if ( static::checkLock( $flagKey ) )
|
||||
{
|
||||
return NULL;
|
||||
@@ -744,8 +744,23 @@ class _Theme extends \IPS\Node\Model
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll compile it now, but let datastore serve the template this time round */
|
||||
$this->compileTemplates( $app, $location, $group );
|
||||
/* If it exists in datastore, use that to write the value */
|
||||
if ( isset( \IPS\Data\Store::i()->$key ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$cache->set( str_replace( 'namespace IPS\Theme;', 'namespace IPS\Theme\Cache;', \IPS\Data\Store::i()->$key ) );
|
||||
}
|
||||
catch( \RuntimeException $e )
|
||||
{
|
||||
/* Should we log, ignore or collect failures to notify admin? */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll compile it now, but let datastore serve the template this time round */
|
||||
$this->compileTemplates( $app, $location, $group );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,7 +823,7 @@ class _Theme extends \IPS\Node\Model
|
||||
{
|
||||
if ( @eval( $compiledGroup ) === FALSE )
|
||||
{
|
||||
throw new \UnexpectedValueException;
|
||||
throw new \IPS\Theme\TemplateException( 'Invalid Template', 1000, NULL, array( 'group' => $group, 'app' => $app, 'location' => $location ), $this );
|
||||
}
|
||||
}
|
||||
catch ( \ParseError $e )
|
||||
@@ -843,7 +858,7 @@ class _Theme extends \IPS\Node\Model
|
||||
{
|
||||
if ( file_exists( \IPS\ROOT_PATH . '/' . $data['file'] ) )
|
||||
{
|
||||
if ( class_exists( "{$namespace}\\{$data['class']}", FALSE ) )
|
||||
if ( class_exists( "{$namespace}\\" . $data['class'], FALSE ) )
|
||||
{
|
||||
$class = $data['class'];
|
||||
continue;
|
||||
@@ -970,6 +985,9 @@ class _Theme extends \IPS\Node\Model
|
||||
$this->editor_skin = 'ips';
|
||||
}
|
||||
|
||||
/* Re-calculate customised flag */
|
||||
$this->customized = $this->isCustomized();
|
||||
|
||||
parent::save();
|
||||
unset( \IPS\Data\Store::i()->themes );
|
||||
|
||||
@@ -1072,12 +1090,7 @@ class _Theme extends \IPS\Node\Model
|
||||
*/
|
||||
protected function get__description()
|
||||
{
|
||||
if( $this->author_name or $this->version )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'customization', 'core' )->themeDescription( $this->author_name, $this->author_url, $this->version );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return \IPS\Theme::i()->getTemplate( 'customization', 'core' )->themeDescription( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1224,9 +1237,6 @@ class _Theme extends \IPS\Node\Model
|
||||
case 'template_set_id':
|
||||
$name = $setId;
|
||||
break;
|
||||
case 'template_unique_key':
|
||||
$name = "MD5( CONCAT( {$setId}, ';', template_app, ';', template_location, ';', template_group, ';', LOWER(template_name) ) )";
|
||||
break;
|
||||
}
|
||||
}, $this->id );
|
||||
|
||||
@@ -1240,9 +1250,6 @@ class _Theme extends \IPS\Node\Model
|
||||
case 'css_set_id':
|
||||
$name = $setId;
|
||||
break;
|
||||
case 'css_unique_key':
|
||||
$name = "MD5( CONCAT( {$setId}, ';', css_app, ';', css_location, ';', css_path, ';', css_name ) )";
|
||||
break;
|
||||
}
|
||||
}, $this->id );
|
||||
|
||||
@@ -1295,6 +1302,34 @@ class _Theme extends \IPS\Node\Model
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__themeset_created', array( sprintf( \IPS\Member::loggedIn()->language()->get( 'theme_clone_copy_of' ), \IPS\Member::loggedIn()->language()->get( 'core_theme_set_title_' . $originalId ) ) => FALSE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Does the currently logged in user have permission to delete this node?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDelete()
|
||||
{
|
||||
if ( \IPS\IN_DEV AND $this->_id == \IPS\DEFAULT_THEME_ID )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( $this->is_default OR $this->is_acp_default )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
foreach( $this->children( NULL ) as $childTheme )
|
||||
{
|
||||
if( $childTheme->is_default OR $childTheme->is_acp_default )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::canDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Delete the theme set
|
||||
@@ -1303,7 +1338,7 @@ class _Theme extends \IPS\Node\Model
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if ( \IPS\IN_DEV AND $this->_id == 1 )
|
||||
if ( \IPS\IN_DEV AND $this->_id == \IPS\DEFAULT_THEME_ID )
|
||||
{
|
||||
\IPS\Output::i()->error( 'theme_error_not_available_in_dev', '2S140/1', 403, '' );
|
||||
}
|
||||
@@ -1357,8 +1392,6 @@ class _Theme extends \IPS\Node\Model
|
||||
\IPS\Db::i()->update( 'core_members', array( 'skin' => 0 ), array('skin=?', $this->_id ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_theme_settings_fields', array( 'sc_set_id=?', $this->_id ) );
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__themeset_delete', array( "core_theme_set_title_{$this->_id}" => true ) );
|
||||
|
||||
parent::delete();
|
||||
unset( \IPS\Data\Store::i()->themes );
|
||||
@@ -1575,7 +1608,7 @@ class _Theme extends \IPS\Node\Model
|
||||
{
|
||||
$form->addTab( 'theme_custom_tab_' . $tabKey );
|
||||
|
||||
if ( \IPS\IN_DEV AND $this->_id === 1 )
|
||||
if ( \IPS\IN_DEV AND $this->_id === \IPS\DEFAULT_THEME_ID )
|
||||
{
|
||||
$form->addHeader( 'core_theme_default_dev_reminder' );
|
||||
}
|
||||
@@ -1762,7 +1795,7 @@ class _Theme extends \IPS\Node\Model
|
||||
'icon' => 'upload',
|
||||
'title' => 'theme_set_import',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=customization&controller=themes&do=importForm&id={$this->_id}" ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('theme_set_import_title', FALSE, array( 'sprintf' => array( $this->name ) ) ) )
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('theme_set_import_title', FALSE, array( 'sprintf' => array( $this->_title ) ) ) )
|
||||
);
|
||||
|
||||
$buttons['download'] = array(
|
||||
@@ -1792,7 +1825,7 @@ class _Theme extends \IPS\Node\Model
|
||||
);
|
||||
}
|
||||
|
||||
if ( $this->id !== static::defaultTheme() )
|
||||
if ( $this->canDelete() )
|
||||
{
|
||||
$buttons['delete'] = $parentButtons['delete'];
|
||||
}
|
||||
@@ -2054,15 +2087,15 @@ class _Theme extends \IPS\Node\Model
|
||||
\IPS\Db::i()->delete( 'core_theme_settings_values', array( 'sv_id=?', $id ) );
|
||||
\IPS\Db::i()->insert( 'core_theme_settings_values', array( 'sv_id' => $id, 'sv_value' => (string) $value ) );
|
||||
|
||||
if ( \IPS\IN_DEV AND $this->id === 1 )
|
||||
if ( \IPS\IN_DEV AND $this->id === \IPS\DEFAULT_THEME_ID )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_theme_settings_fields', array( 'sc_default' => (string) $value ), array( 'sc_set_id=? and sc_id=?', 1, $id ) );
|
||||
\IPS\Db::i()->update( 'core_theme_settings_fields', array( 'sc_default' => (string) $value ), array( 'sc_set_id=? and sc_id=?', \IPS\DEFAULT_THEME_ID, $id ) );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_themes', array( 'set_template_settings' => json_encode( $json ) ), array( 'set_id=?', $this->id ) );
|
||||
|
||||
if ( \IPS\IN_DEV AND $this->id === 1 )
|
||||
if ( \IPS\IN_DEV AND $this->id === \IPS\DEFAULT_THEME_ID )
|
||||
{
|
||||
\IPS\Theme\Dev\Theme::writeThemeSettingsToDisk();
|
||||
}
|
||||
@@ -2107,16 +2140,6 @@ class _Theme extends \IPS\Node\Model
|
||||
$this->copyLogosFromSet( $this->parent_id );
|
||||
}
|
||||
}
|
||||
|
||||
/* Log */
|
||||
if ( $creating === FALSE )
|
||||
{
|
||||
\IPS\Session::i()->log( 'acplogs__themeset_updated', array( "core_theme_set_title_{$this->id}" => true ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Session::i()->log( 'acplogs__themeset_created', array( "core_theme_set_title_{$this->id}" => true ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2180,24 +2203,28 @@ class _Theme extends \IPS\Node\Model
|
||||
$key = static::makeBuiltTemplateLookupHash($data['resource_app'], $data['resource_location'], $data['resource_path']) . '_' . $data['resource_name'];
|
||||
|
||||
if ( $data['resource_data'] )
|
||||
{
|
||||
$fileName = (string) \IPS\File::create( 'core_Theme', $key, $data['resource_data'], 'set_resources_' . $this->_id, FALSE, NULL, FALSE );
|
||||
{
|
||||
try
|
||||
{
|
||||
$fileName = (string) \IPS\File::create( 'core_Theme', $key, $data['resource_data'], 'set_resources_' . $this->_id, FALSE, NULL, FALSE );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_theme_resources', array(
|
||||
'resource_set_id' => $this->_id,
|
||||
'resource_app' => $data['resource_app'],
|
||||
'resource_location' => $data['resource_location'],
|
||||
'resource_path' => $data['resource_path'],
|
||||
'resource_name' => $data['resource_name'],
|
||||
'resource_added' => time(),
|
||||
'resource_filename' => $fileName,
|
||||
'resource_data' => $data['resource_data'],
|
||||
'resource_plugin' => isset( $data['resource_plugin'] ) ? $data['resource_plugin'] : NULL,
|
||||
'resource_user_edited' => $data['resource_user_edited']
|
||||
) );
|
||||
\IPS\Db::i()->insert( 'core_theme_resources', array(
|
||||
'resource_set_id' => $this->_id,
|
||||
'resource_app' => $data['resource_app'],
|
||||
'resource_location' => $data['resource_location'],
|
||||
'resource_path' => $data['resource_path'],
|
||||
'resource_name' => $data['resource_name'],
|
||||
'resource_added' => time(),
|
||||
'resource_filename' => $fileName,
|
||||
'resource_data' => $data['resource_data'],
|
||||
'resource_plugin' => isset( $data['resource_plugin'] ) ? $data['resource_plugin'] : NULL,
|
||||
'resource_user_edited' => $data['resource_user_edited']
|
||||
) );
|
||||
|
||||
$resourceMap[ $key ] = $fileName;
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
}
|
||||
|
||||
$resourceMap[ $key ] = $fileName;
|
||||
}
|
||||
|
||||
/* Update theme map */
|
||||
@@ -2502,7 +2529,7 @@ class _Theme extends \IPS\Node\Model
|
||||
{
|
||||
foreach ( \IPS\IPS::$hooks[ "\\IPS\\Theme\\class_{$app}_{$location}_{$group}" ] as $k => $data )
|
||||
{
|
||||
if ( !class_exists( "IPS\\Theme\\{$data['class']}_tmp", FALSE ) )
|
||||
if ( !class_exists( "IPS\\Theme\\" . $data['class'] . "_tmp", FALSE ) )
|
||||
{
|
||||
/* Like code hooks, we should only attempt to load the files contents if it actually exists */
|
||||
if ( file_exists( \IPS\ROOT_PATH . '/' . $data['file'] ) )
|
||||
@@ -2511,7 +2538,7 @@ class _Theme extends \IPS\Node\Model
|
||||
{
|
||||
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";
|
||||
$class = "IPS\\Theme\\" . $data['class'] . "_tmp";
|
||||
$templateHooks = array_merge_recursive( $templateHooks, $class::hookData() );
|
||||
}
|
||||
}
|
||||
@@ -2657,14 +2684,7 @@ EOF;
|
||||
$children[] = $child->_id;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$css = \IPS\Db::i()->select( '*', 'core_theme_css', array( 'css_id=?', (int) $itemId ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
throw new \UnderflowException;
|
||||
}
|
||||
$css = \IPS\Db::i()->select( '*', 'core_theme_css', array( 'css_id=?', (int) $itemId ) )->first();
|
||||
|
||||
static::deleteCompiledCss( $css['css_app'], $css['css_location'], $css['css_path'], $css['css_name'], $css['css_set_id'] );
|
||||
|
||||
@@ -2685,7 +2705,12 @@ EOF;
|
||||
"css_app=? AND css_location=? AND css_path=? AND css_name=? AND css_set_id IN(" . implode( ',', $children ) . ")",
|
||||
$css['css_app'], $css['css_location'], $css['css_path'], $css['css_name'] ) );
|
||||
}
|
||||
|
||||
|
||||
if ( ! empty( $css['css_set_id'] ) )
|
||||
{
|
||||
static::setThemeCustomized( $css['css_set_id'] );
|
||||
}
|
||||
|
||||
$csses = $this->getRawCss( array( $css['css_app'] ), array( $css['css_location'] ), array( $css['css_path'] ) );
|
||||
|
||||
if ( isset( $csses[ $css['css_app'] ][ $css['css_location'] ][ $css['css_path'] ][ $css['css_name'] ] ) )
|
||||
@@ -2720,14 +2745,7 @@ EOF;
|
||||
/* Save */
|
||||
if ( ! empty( $data['item_id'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$css = \IPS\Db::i()->select( '*', 'core_theme_css', array( 'css_id=?', (int) $data['item_id'] ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
throw new \UnderflowException;
|
||||
}
|
||||
$css = \IPS\Db::i()->select( '*', 'core_theme_css', array( 'css_id=?', (int) $data['item_id'] ) )->first();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2758,14 +2776,11 @@ EOF;
|
||||
'css_added_to' => $data['set_id'],
|
||||
'css_plugin' => isset( $master['css_plugin'] ) ? $master['css_plugin'] : NULL );
|
||||
}
|
||||
|
||||
/* Unique key */
|
||||
$css['css_unique_key'] = md5( $data['set_id'] . ';' . $css['css_added_to'] . ';' . $css['css_app'] . ';' . $css['css_location'] . ';' . $css['css_path'] . ';' . $css['css_name'] );
|
||||
|
||||
/* Test to make sure CSS isn't broken */
|
||||
try
|
||||
{
|
||||
static::makeProcessFunction( static::fixResourceTags( $data['content'], $css['css_location'] ), 'css_' . md5( uniqid() . time() ), '', FALSE, TRUE );
|
||||
static::makeProcessFunction( static::fixResourceTags( $data['content'], $css['css_location'] ), 'css_' . md5( mt_rand() . time() ), '', FALSE, TRUE );
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
{
|
||||
@@ -2784,7 +2799,7 @@ EOF;
|
||||
else
|
||||
{
|
||||
/* First modification in this css set */
|
||||
$newCssId = \IPS\Db::i()->insert( 'core_theme_css', array( 'css_set_id' => $data['set_id'],
|
||||
$newCssId = \IPS\Db::i()->replace( 'core_theme_css', array( 'css_set_id' => $data['set_id'],
|
||||
'css_path' => $css['css_path'],
|
||||
'css_location' => $css['css_location'],
|
||||
'css_app' => $css['css_app'],
|
||||
@@ -2795,13 +2810,14 @@ EOF;
|
||||
'css_position' => intval( $css['css_position'] ),
|
||||
'css_version' => \IPS\Theme::load( $data['set_id'] )->long_version,
|
||||
'css_user_edited' => \IPS\Application::load( $css['css_app'] )->long_version,
|
||||
'css_unique_key' => $css['css_unique_key'],
|
||||
'css_updated' => time(),
|
||||
'css_plugin' => isset( $css['css_plugin'] ) ? $css['css_plugin'] : NULL ) );
|
||||
}
|
||||
|
||||
static::deleteCompiledCss( $css['css_app'], $css['css_location'], $css['css_path'], $css['css_name'], $data['set_id'] );
|
||||
|
||||
|
||||
static::setThemeCustomized( $data['set_id'] );
|
||||
|
||||
return $newCssId;
|
||||
}
|
||||
|
||||
@@ -2860,7 +2876,12 @@ EOF;
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_theme_templates', array( 'template_id=?', (int) $itemId ) );
|
||||
}
|
||||
|
||||
|
||||
if ( ! empty( $template['template_set_id'] ) )
|
||||
{
|
||||
static::setThemeCustomized( $template['template_set_id'] );
|
||||
}
|
||||
|
||||
$templates = $this->getRawTemplates( array( $template['template_app'] ), array( $template['template_location'] ), array( $template['template_group'] ) );
|
||||
|
||||
if ( isset( $templates[ $template['template_app'] ][ $template['template_location'] ][ $template['template_group'] ][ $template['template_name'] ] ) )
|
||||
@@ -2904,14 +2925,7 @@ EOF;
|
||||
/* Save */
|
||||
if ( $data['item_id'] )
|
||||
{
|
||||
try
|
||||
{
|
||||
$template = \IPS\Db::i()->select( '*', 'core_theme_templates', array( 'template_id=?', (int) $data['item_id'] ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
throw new \UnderflowException;
|
||||
}
|
||||
$template = \IPS\Db::i()->select( '*', 'core_theme_templates', array( 'template_id=?', (int) $data['item_id'] ) )->first();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2924,13 +2938,10 @@ EOF;
|
||||
'template_user_added' => 1 );
|
||||
}
|
||||
|
||||
/* Unique key */
|
||||
$template['template_unique_key'] = md5( $data['set_id'] . ';' . $template['template_added_to'] . ';' . $template['template_app'] . ';' . $template['template_location'] . ';' . $template['template_group'] . ';' . mb_strtolower( $template['template_name'] ) );
|
||||
|
||||
/* Test to make sure CSS isn't broken */
|
||||
try
|
||||
{
|
||||
static::makeProcessFunction( $data['content'], 'template_' . md5( uniqid() . time() ), $data['variables'], TRUE, FALSE );
|
||||
static::makeProcessFunction( $data['content'], 'template_' . md5( mt_rand() . time() ), $data['variables'], TRUE, FALSE );
|
||||
}
|
||||
/* PHP 5 */
|
||||
catch( \InvalidArgumentException $e )
|
||||
@@ -2965,9 +2976,6 @@ EOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First modification in this template set or new bit being added */
|
||||
\IPS\Db::i()->delete( 'core_theme_templates', array( 'template_set_id=? and template_unique_key=?', $data['set_id'], $template['template_unique_key'] ) );
|
||||
|
||||
$newTemplateId = \IPS\Db::i()->insert( 'core_theme_templates', array( 'template_set_id' => $data['set_id'],
|
||||
'template_group' => $template['template_group'],
|
||||
'template_location' => $template['template_location'],
|
||||
@@ -2980,7 +2988,6 @@ EOF;
|
||||
'template_user_edited' => \IPS\Application::load( $template['template_app'] )->long_version,
|
||||
'template_removable' => 1,
|
||||
'template_version' => $theme->long_version,
|
||||
'template_unique_key' => $template['template_unique_key'],
|
||||
'template_updated' => time() ) );
|
||||
}
|
||||
|
||||
@@ -3001,7 +3008,8 @@ EOF;
|
||||
}
|
||||
|
||||
static::deleteCompiledTemplate( $template['template_app'], $template['template_location'], $template['template_group'], $data['set_id'] );
|
||||
|
||||
static::setThemeCustomized( $data['set_id'] );
|
||||
|
||||
return $newTemplateId;
|
||||
}
|
||||
|
||||
@@ -3310,7 +3318,7 @@ EOF;
|
||||
}
|
||||
else if ( $row['template_user_added'] and in_array( $row['template_added_to'], array_values( $allParents ) ) )
|
||||
{
|
||||
$row['InheritedValue'] = 'inherit';
|
||||
$row['InheritedValue'] = ( $row['template_removable'] and $this->_id == $row['template_set_id'] ) ? 'changed' : 'inherit';
|
||||
}
|
||||
else if ( $row['template_user_added'] and ( $row['template_added_to'] != $this->_id and $row['template_set_id'] != $this->_id ) )
|
||||
{
|
||||
@@ -4101,6 +4109,13 @@ EOF;
|
||||
return $matches[1] . '="json--' . $jsonAttrI . '--"';
|
||||
}, $rawContent );
|
||||
|
||||
/* Remove raw JS as this can cause a timeout if there is a lot of it */
|
||||
$content = preg_replace_callback( '#<script\b[^>]*>([\s\S]*?)<\/script>#', function( $matches ) use ( &$phpQueryI, &$phpQueryStore )
|
||||
{
|
||||
$phpQueryStore[ ++$phpQueryI ] = $matches[0];
|
||||
return 'he-' . $phpQueryI . '--';
|
||||
}, $content );
|
||||
|
||||
$content = preg_replace_callback( array( '/{{?(?>[^{}]|(?R))*}?}/', '/\{([a-z]+?=([\'"]).+?\\2 ?+)}/' ), function( $matches ) use ( &$phpQueryI, &$phpQueryStore )
|
||||
{
|
||||
$phpQueryStore[ ++$phpQueryI ] = $matches[0];
|
||||
@@ -4230,7 +4245,17 @@ EOF;
|
||||
public static function checkTemplateSyntax( $content, $params='' )
|
||||
{
|
||||
ob_start();
|
||||
static::makeProcessFunction( $content, 'unique_function_so_it_doesnt_look_in_function_exists_' . uniqid(), $params );
|
||||
|
||||
try
|
||||
{
|
||||
static::makeProcessFunction( $content, 'unique_function_so_it_doesnt_look_in_function_exists_' . mt_rand(), $params );
|
||||
}
|
||||
catch( \ParseError $e )
|
||||
{
|
||||
ob_end_clean();
|
||||
throw new \LogicException( $e->getMessage() );
|
||||
}
|
||||
|
||||
$return = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
@@ -4318,7 +4343,7 @@ EOF;
|
||||
/* Parse shortcuts */
|
||||
foreach ( array( 'request' => 'i', 'member' => 'loggedIn', 'settings' => 'i', 'output' => 'i' ) as $class => $function )
|
||||
{
|
||||
$content = preg_replace( '/(^|[^\$\\\])' . $class . "\.(\S+?)/", '$1\IPS\\' . ucfirst( $class ) . '::' . $function . '()->$2', $content );
|
||||
$content = preg_replace( '/(^|[^\$\\\])' . $class . "\.(\S+?)/", '$1\IPS\\' . mb_ucfirst( $class ) . '::' . $function . '()->$2', $content );
|
||||
}
|
||||
|
||||
foreach( array( 'theme' => '\IPS\\Theme::i()->settings', 'cookie' => '\IPS\\Request::i()->cookie' ) as $shortcut => $array )
|
||||
@@ -4348,7 +4373,7 @@ EOF;
|
||||
{
|
||||
$content = $content . "\n<p id='elCopyright'>
|
||||
<span id='elCopyright_userLine'>{lang=\"copyright_line_value\"}</span>
|
||||
<a rel='nofollow' title='Invision Community' href='https://www.invisioncommunity.com/'>Powered by Invision Community</a><br><a href='http://ipbmafia.ru' style='display:none'>Поддержка Invision Community в России</a>
|
||||
<a rel='nofollow' title='Invision Community' href='https://www.invisioncommunity.com/'>Powered by Invision Community</a><br><a href='//ipbmafia.ru' style='display:none'>Поддержка Invision Community в России</a>
|
||||
</p>";
|
||||
}
|
||||
|
||||
@@ -4432,7 +4457,7 @@ PHP;
|
||||
preg_match_all( '/(.+?)='.$matches[2].'([^' . $matches[2] . ']*)'.$matches[2].'\s?/', $matches[1], $submatches );
|
||||
|
||||
$plugin = array_shift( $submatches[1] );
|
||||
$pluginClass = 'IPS\\Output\\Plugin\\' . ucfirst( $plugin );
|
||||
$pluginClass = 'IPS\\Output\\Plugin\\' . mb_ucfirst( $plugin );
|
||||
|
||||
$value = array_shift( $submatches[2] );
|
||||
$options = array();
|
||||
@@ -4447,9 +4472,9 @@ PHP;
|
||||
{
|
||||
foreach ( \IPS\Application::applications() as $app )
|
||||
{
|
||||
if ( file_exists( \IPS\ROOT_PATH . "/applications/{$app->directory}/extensions/core/OutputPlugins/" . ucfirst( $plugin ) . ".php" ) )
|
||||
if ( file_exists( \IPS\ROOT_PATH . "/applications/{$app->directory}/extensions/core/OutputPlugins/" . mb_ucfirst( $plugin ) . ".php" ) )
|
||||
{
|
||||
$pluginClass = 'IPS\\' . $app->directory . '\\extensions\\core\\OutputPlugins\\' . ucfirst( $plugin );
|
||||
$pluginClass = 'IPS\\' . $app->directory . '\\extensions\\core\\OutputPlugins\\' . mb_ucfirst( $plugin );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4525,11 +4550,11 @@ PHP;
|
||||
{
|
||||
if ( \stristr( $var[1], '|doubleencode' ) )
|
||||
{
|
||||
$replace = "\nCONTENT;\n\$return .= htmlspecialchars( \$" . 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 | ENT_DISALLOWED, 'UTF-8', TRUE );\n\$return .= <<<CONTENT\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$replace = "\nCONTENT;\n\$return .= htmlspecialchars( \$" . $var[1] . ", ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );\n\$return .= <<<CONTENT\n";
|
||||
$replace = "\nCONTENT;\n\$return .= htmlspecialchars( \$" . $var[1] . ", ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE );\n\$return .= <<<CONTENT\n";
|
||||
}
|
||||
|
||||
$all = str_replace( $var[0], $replace, $all );
|
||||
@@ -4742,7 +4767,7 @@ PHP;
|
||||
|
||||
/* Insert */
|
||||
$saveSetId = isset( $data['set_id'] ) ? $data['set_id'] : 0;
|
||||
$insertId = \IPS\Db::i()->insert( 'core_theme_css', array(
|
||||
$insertId = \IPS\Db::i()->replace( 'core_theme_css', array(
|
||||
'css_set_id' => $saveSetId,
|
||||
'css_app' => mb_strtolower( $data['app'] ),
|
||||
'css_location' => mb_strtolower( $data['location'] ),
|
||||
@@ -4752,10 +4777,14 @@ PHP;
|
||||
'css_added_to' => ( isset( $data['added_to'] ) ) ? intval( $data['added_to'] ) : 0,
|
||||
'css_updated' => time(),
|
||||
'css_version' => \IPS\Application::load('core')->long_version,
|
||||
'css_plugin' => isset( $data['plugin'] ) ? $data['plugin'] : NULL,
|
||||
'css_unique_key' => md5( $saveSetId . ';' . mb_strtolower( $data['app'] ) . ';' . mb_strtolower( $data['location'] ) . ';' . mb_strtolower( $data['path'] ) . ';' . mb_strtolower( $data['name'] ) )
|
||||
'css_plugin' => isset( $data['plugin'] ) ? $data['plugin'] : NULL
|
||||
) );
|
||||
|
||||
if ( ! empty( $data['set_id'] ) )
|
||||
{
|
||||
static::setThemeCustomized( $data['set_id'] );
|
||||
}
|
||||
|
||||
return $insertId;
|
||||
}
|
||||
|
||||
@@ -4776,23 +4805,50 @@ PHP;
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
/* Check for existing */
|
||||
$check = \IPS\Db::i()->select( 'template_id', 'core_theme_templates', array(
|
||||
'template_app=? AND template_location=? AND template_group=? AND LOWER(template_name)=? AND template_set_id=?',
|
||||
mb_strtolower( $data['app'] ),
|
||||
mb_strtolower( $data['location'] ),
|
||||
mb_strtolower( $data['group'] ),
|
||||
mb_strtolower( $data['name'] ),
|
||||
0
|
||||
) );
|
||||
if ( count( $check ) > 0 )
|
||||
/* Check for existing and there is not existing template, then it will throw an an UnderflowException */
|
||||
try
|
||||
{
|
||||
throw new \OverflowException;
|
||||
$check = \IPS\Db::i()->select( 'template_id, template_added_to, template_set_id', 'core_theme_templates', array(
|
||||
'template_app=? AND template_location=? AND template_group=? AND LOWER(template_name)=? AND template_set_id=?',
|
||||
mb_strtolower( $data['app'] ),
|
||||
mb_strtolower( $data['location'] ),
|
||||
mb_strtolower( $data['group'] ),
|
||||
mb_strtolower( $data['name'] ),
|
||||
( isset( $data['set_id'] ) ) ? $data['set_id'] : 0
|
||||
) )->first();
|
||||
|
||||
/* Template bit exists, are we trying to add a new master template with the same name as a third party template? */
|
||||
if ( isset( $data['_default_template'] ) and $check['template_added_to'] > 0 )
|
||||
{
|
||||
/* Update it to make it belong to the theme that added it so it is revertable before adding the new one to fix an issue with early 4.0 releases */
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_theme_templates', array(
|
||||
'template_set_id' => $check['template_added_to']
|
||||
), array( 'template_id=?', $check['template_id'] ) );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
/* This template bit exists in a custom template and also in the master space as a custom theme added this bit
|
||||
as of 4.3 we will not be polluting the master space with additional templates so this can be removed then.
|
||||
For now, we will remove the master template bit to allow the insert to work below */
|
||||
\IPS\Db::i()->delete( 'core_theme_templates', array( 'template_id=?', $check['template_id'] ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Master bit exists, skip */
|
||||
throw new \OverflowException;
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
/* Template doesn't exist, so it's all good bro */
|
||||
}
|
||||
|
||||
/* Insert */
|
||||
$insertId = \IPS\Db::i()->insert( 'core_theme_templates', array(
|
||||
'template_set_id' => 0,
|
||||
$insertId = \IPS\Db::i()->replace( 'core_theme_templates', array(
|
||||
'template_set_id' => ( isset( $data['set_id'] ) ) ? $data['set_id'] : 0,
|
||||
'template_app' => mb_strtolower( $data['app'] ),
|
||||
'template_location' => mb_strtolower( $data['location'] ),
|
||||
'template_group' => mb_strtolower( $data['group'] ),
|
||||
@@ -4803,10 +4859,14 @@ PHP;
|
||||
'template_updated' => time(),
|
||||
'template_user_added' => ( isset($data['_default_template']) ) ? 0 : 1,
|
||||
'template_version' => \IPS\Application::load('core')->long_version,
|
||||
'template_plugin' => isset( $data['plugin'] ) ? $data['plugin'] : NULL,
|
||||
'template_unique_key' => md5( '0;' . mb_strtolower( $data['app'] ) . ';' . mb_strtolower( $data['location'] ) . ';' . mb_strtolower( $data['group'] ) . ';' . mb_strtolower( $data['name'] ) )
|
||||
'template_plugin' => isset( $data['plugin'] ) ? $data['plugin'] : NULL
|
||||
), TRUE );
|
||||
|
||||
|
||||
if ( ! empty( $data['set_id'] ) )
|
||||
{
|
||||
static::setThemeCustomized( $data['set_id'] );
|
||||
}
|
||||
|
||||
return $insertId;
|
||||
}
|
||||
|
||||
@@ -5076,6 +5136,56 @@ PHP;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Any custom images/css/templates?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isCustomized()
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->select( 'template_id', 'core_theme_templates', array( 'template_set_id=?', $this->id ) )->first();
|
||||
return TRUE;
|
||||
}
|
||||
catch( \UnderflowException $e ) { }
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->select( 'css_id', 'core_theme_css', array( 'css_set_id=?', $this->id ) )->first();
|
||||
return TRUE;
|
||||
}
|
||||
catch( \UnderflowException $e ) { }
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->select( 'resource_id', 'core_theme_resources', array( 'resource_set_id=? and resource_user_edited=1', $this->id ) )->first();
|
||||
return TRUE;
|
||||
}
|
||||
catch( \UnderflowException $e ) { }
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static wrapper for customized
|
||||
*
|
||||
* return @void
|
||||
*/
|
||||
public static function setThemeCustomized( $themeId )
|
||||
{
|
||||
try
|
||||
{
|
||||
$theme = static::load( $themeId );
|
||||
$theme->customized = $theme->isCustomized();
|
||||
$theme->save();
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all cache keys
|
||||
* This will make all existing template caches stale for all themes
|
||||
|
||||
Reference in new issue
Block a user