Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
@@ -12,7 +12,7 @@
|
||||
namespace IPS\cms\modules\admin\pages;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _templates extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* @brief Has been CSRF-protected
|
||||
*/
|
||||
public static $csrfProtected = TRUE;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
@@ -41,6 +46,8 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function importInDev()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
\IPS\cms\Theme::importInDev('database');
|
||||
\IPS\cms\Theme::importInDev('page');
|
||||
|
||||
@@ -67,7 +74,7 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
move_uploaded_file( $values['cms_templates_import'], $tempFile );
|
||||
|
||||
/* Initate a redirector */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=importProcess' )->setQueryString( array( 'file' => $tempFile, 'key' => md5_file( $tempFile ) ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=importProcess' )->csrf()->setQueryString( array( 'file' => $tempFile, 'key' => md5_file( $tempFile ) ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -85,100 +92,198 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function importProcess()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if ( !file_exists( \IPS\Request::i()->file ) or md5_file( \IPS\Request::i()->file ) !== \IPS\Request::i()->key )
|
||||
{
|
||||
\IPS\Output::i()->error( 'generic_error', '3T285/3', 403, '' );
|
||||
}
|
||||
|
||||
/* Open XML file */
|
||||
$xml = new \IPS\Xml\XMLReader;
|
||||
$xml->open( \IPS\Request::i()->file );
|
||||
$prefix = 'm' . date('m') . '_' . date('d') . '_' . date('y') . '_';
|
||||
$templates = \IPS\cms\Theme::i()->getRawTemplates( 'cms', NULL, NULL, \IPS\cms\Theme::RETURN_ALL );
|
||||
|
||||
if ( ! @$xml->read() )
|
||||
$result = NULL;
|
||||
try
|
||||
{
|
||||
$result = \IPS\cms\Templates::importUserTemplateXml( \IPS\Request::i()->file );
|
||||
}
|
||||
catch( \Throwable $e )
|
||||
{
|
||||
@unlink( \IPS\Request::i()->file );
|
||||
\IPS\Output::i()->error( 'xml_upload_invalid', '2C163/1', 403, '' );
|
||||
}
|
||||
$xml->read();
|
||||
while ( $xml->read() )
|
||||
|
||||
/* Done */
|
||||
if ( $result instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
if ( $xml->name === 'template' )
|
||||
\IPS\Output::i()->redirect( $result );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=manage' ), 'cms_templates_imported' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show and manage conflicts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function conflicts()
|
||||
{
|
||||
$key = \intval( \IPS\Request::i()->key );
|
||||
$form = new \IPS\Helpers\Form( 'form', 'theme_conflict_save' );
|
||||
$conflicts = array();
|
||||
|
||||
/* If this is part of plugin/app installation, set relevant form data */
|
||||
if( \IPS\Request::i()->app OR \IPS\Request::i()->plugin )
|
||||
{
|
||||
if( \IPS\Request::i()->app )
|
||||
{
|
||||
$node = new \SimpleXMLElement( $xml->readOuterXML() );
|
||||
$attrs = array();
|
||||
$form->hiddenValues['app'] = \IPS\Request::i()->app;
|
||||
}
|
||||
elseif( \IPS\Request::i()->plugin )
|
||||
{
|
||||
$form->hiddenValues['plugin'] = \IPS\Request::i()->plugin;
|
||||
}
|
||||
|
||||
foreach( $node->attributes() as $k => $v )
|
||||
{
|
||||
$attrs[ $k ] = (string) $v;
|
||||
}
|
||||
if( \IPS\Request::i()->marketplace )
|
||||
{
|
||||
$form->hiddenValues['marketplace'] = (int) \IPS\Request::i()->marketplace;
|
||||
}
|
||||
|
||||
/* Any kids of your own? */
|
||||
foreach( $node->children() as $k => $v )
|
||||
{
|
||||
$tryJson = json_decode( $v, TRUE );
|
||||
$attrs[ $k ] = ( $tryJson ) ? $tryJson : (string) $v;
|
||||
}
|
||||
if( \IPS\Request::i()->lang )
|
||||
{
|
||||
$form->hiddenValues['lang'] = \IPS\Request::i()->lang;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $attrs['template_title'] ) and isset( $attrs['template_location'] ) and isset( $attrs['template_group'] ) )
|
||||
/* Get conflict data */
|
||||
foreach( \IPS\Db::i()->select( '*', 'cms_template_conflicts', array( 'conflict_key=?', $key ) )->setKeyField( 'conflict_id' ) as $cid => $data )
|
||||
{
|
||||
$conflicts[ $cid ] = $data;
|
||||
}
|
||||
|
||||
require_once \IPS\ROOT_PATH . "/system/3rd_party/Diff/class.Diff.php";
|
||||
|
||||
foreach( $conflicts as $cid => $data )
|
||||
{
|
||||
try
|
||||
{
|
||||
$template = \IPS\cms\Templates::load( $data['conflict_item_id'], 'template_id' );
|
||||
|
||||
if ( !\IPS\Login::compareHashes( md5( $data['conflict_content'] ), md5( $template->content ) ) )
|
||||
{
|
||||
/* Got this template? */
|
||||
if ( $attrs['template_location'] === 'database' )
|
||||
if ( mb_strlen( $data['conflict_content'] ) <= 10000 )
|
||||
{
|
||||
/* Database templates are really governed by the group as they are a collection of templates */
|
||||
if ( isset( $templates['cms'][$attrs['template_location']][$attrs['template_group']] ) )
|
||||
{
|
||||
$attrs['template_group'] = $prefix . $attrs['template_group'];
|
||||
}
|
||||
$conflicts[ $cid ]['diff'] = \Diff::toTable( \Diff::compare( $template->content, $data['conflict_content'] ) );
|
||||
$conflicts[ $cid ]['large'] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* But post and block templates are not */
|
||||
if ( isset( $templates['cms'][$attrs['template_location']][$attrs['template_group']] ) )
|
||||
{
|
||||
$exists = FALSE;
|
||||
foreach ( $templates['cms'][$attrs['template_location']][$attrs['template_group']] as $key => $template )
|
||||
{
|
||||
if ( $template['template_title'] === $attrs['template_title'] )
|
||||
{
|
||||
$exists = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $exists )
|
||||
{
|
||||
$attrs['template_title'] = $prefix . $attrs['template_title'];
|
||||
}
|
||||
}
|
||||
$conflicts[ $cid ]['diff'] = \IPS\Theme::i()->getTemplate( 'customization' )->templateConflictLarge( $template->content, $data['conflict_content'], 'html' );
|
||||
$conflicts[ $cid ]['large'] = true;
|
||||
}
|
||||
|
||||
$obj = new \IPS\cms\Templates;
|
||||
$obj->location = $attrs['template_location'];
|
||||
$obj->group = $attrs['template_group'];
|
||||
$obj->title = $attrs['template_title'];
|
||||
$obj->params = $attrs['template_params'];
|
||||
$obj->content = $attrs['template_content'];
|
||||
$obj->original_group = $attrs['template_original_group'];
|
||||
$obj->type = 'template';
|
||||
$obj->user_created = 1;
|
||||
$obj->user_edited = 1;
|
||||
$obj->desc = '';
|
||||
$obj->save();
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'conflict_' . $data['conflict_id'], 'old', false, array('options' => array('old' => '', 'new' => '')) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
unset( $conflicts[ $cid ] );
|
||||
}
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
unset( $conflicts[ $cid ] );
|
||||
}
|
||||
}
|
||||
|
||||
$obj->key = $obj->location . \IPS\Http\Url\Friendly::seoTitle( $obj->group ) . '_' . \IPS\Http\Url\Friendly::seoTitle( $obj->title ) . '_' . $obj->id;
|
||||
$obj->save();
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$conflicts = array();
|
||||
$conflictIds = array();
|
||||
$templates = array();
|
||||
|
||||
foreach( $values as $k => $v )
|
||||
{
|
||||
if ( \substr( $k, 0, 9 ) == 'conflict_' )
|
||||
{
|
||||
if ( $v == 'new' )
|
||||
{
|
||||
$conflictIds[ (int) \substr( $k, 9 ) ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$xml->next();
|
||||
if ( \count( $conflictIds ) )
|
||||
{
|
||||
/* Get conflict data */
|
||||
foreach( \IPS\Db::i()->select( '*', 'cms_template_conflicts', \IPS\Db::i()->in( 'conflict_id', array_keys( $conflictIds ) ) )->setKeyField( 'conflict_id' ) as $cid => $data )
|
||||
{
|
||||
$conflicts[ $data['conflict_item_id'] ] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
if ( \count( $conflicts ) )
|
||||
{
|
||||
$templates = iterator_to_array( \IPS\Db::i()->select(
|
||||
'*',
|
||||
'cms_templates',
|
||||
array( \IPS\Db::i()->in( 'template_id', array_keys( $conflicts ) ) )
|
||||
)->setKeyField( 'template_id' ) );
|
||||
}
|
||||
|
||||
foreach( $templates as $templateid => $template )
|
||||
{
|
||||
if ( isset( $conflicts[ $template['template_id'] ] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$templateObj = \IPS\cms\Templates::load( $template['template_id'], 'template_id' );
|
||||
$templateObj->params = $conflicts[ $template['template_id'] ]['conflict_data'];
|
||||
$templateObj->content = $conflicts[ $template['template_id'] ]['conflict_content'];
|
||||
$templateObj->user_edited = (int) $templateObj->isDifferentFromMaster();
|
||||
$templateObj->save();
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear out conflicts for this theme set */
|
||||
\IPS\Db::i()->delete( 'cms_template_conflicts', array('conflict_key=?', \IPS\Request::i()->key ) );
|
||||
|
||||
$lang = NULL;
|
||||
if( !empty( $values['lang'] ) )
|
||||
{
|
||||
$lang = $values['lang'] == 'updated' ? 'app_now_updated' : 'app_now_installed';
|
||||
}
|
||||
|
||||
if( !empty( $values['marketplace'] ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=marketplace&controller=marketplace&do=viewFile&id=' . $values['marketplace'] ), $lang );
|
||||
}
|
||||
elseif( !empty( $values['app'] ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=applications&controller=applications' ), $lang );
|
||||
}
|
||||
elseif( !empty( $values['plugin'] ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins' ), 'plugin_now_installed' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=manage' ), 'completed' );
|
||||
}
|
||||
|
||||
@unlink( \IPS\Request::i()->file );
|
||||
if ( \count( $conflicts ) )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/diff.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/codemirror.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'codemirror/codemirror.css', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'customization/themes.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_templates.js', 'core', 'admin' ) );
|
||||
|
||||
/* Done */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=manage' ), 'cms_templates_imported' );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'templates', 'cms' ), 'templateConflict' ), $conflicts );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=manage' ), 'completed' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,149 +293,17 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form( 'form', 'next' );
|
||||
$templates = array();
|
||||
|
||||
$form->addMessage( 'cms_templates_export_description', 'ipsMessage ipsMessage_information' );
|
||||
foreach( \IPS\cms\Templates::getTemplates( \IPS\cms\Templates::RETURN_DATABASE_ONLY + \IPS\cms\Templates::RETURN_ALL ) as $template )
|
||||
{
|
||||
$title = \IPS\cms\Templates::readableGroupName( $template->group );
|
||||
|
||||
if ( $template->location === 'database' )
|
||||
{
|
||||
$templates['database'][ $template->group ] = $title;
|
||||
}
|
||||
else if ( $template->location === 'block' )
|
||||
{
|
||||
$templates['block'][ $template->key ] = $title . ' > ' . $template->title;
|
||||
}
|
||||
else if ( $template->location === 'page' )
|
||||
{
|
||||
$templates['page'][ $template->key ] = $title . ' > ' . $template->title;
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $templates as $location => $data )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'templates_' . $location, FALSE, FALSE, array( 'options' => $data ) ) );
|
||||
}
|
||||
$form->addButton( 'cms_templates_export_return', 'link', \IPS\Http\Url::internal( "app=cms&module=pages&controller=templates" ) );
|
||||
$form = \IPS\cms\Templates::exportForm();
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$exportTemplates = array();
|
||||
foreach( $templates as $location => $data )
|
||||
{
|
||||
if ( isset( $values[ 'templates_' . $location ] ) and count( $values[ 'templates_' . $location ] ) )
|
||||
{
|
||||
if ( $location === 'database' )
|
||||
{
|
||||
$tmp = \IPS\cms\Theme::i()->getRawTemplates( 'cms', array('database'), array_values( $values[ 'templates_' . $location ] ) );
|
||||
$xml = \IPS\cms\Templates::exportAsXml( $values );
|
||||
|
||||
foreach( $tmp['cms'] as $loc => $data )
|
||||
{
|
||||
if ( $loc === $location )
|
||||
{
|
||||
foreach ( $data as $key => $tdata )
|
||||
{
|
||||
foreach ( $tdata as $tkey => $tkdata )
|
||||
{
|
||||
$exportTemplates['cms'][ $location ][ $key ][ $tkey ] = $tkdata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmp = \IPS\cms\Theme::i()->getRawTemplates( 'cms', array( $location ), NULL, \IPS\cms\Theme::RETURN_DATABASE_ONLY + \IPS\cms\Theme::RETURN_ALL );
|
||||
|
||||
foreach( $tmp['cms'] as $loc => $data )
|
||||
{
|
||||
if ( $loc === $location )
|
||||
{
|
||||
foreach( $data as $key => $tdata )
|
||||
{
|
||||
foreach( $tdata as $tkey => $tkdata )
|
||||
{
|
||||
if ( in_array( $tkey, $values[ 'templates_' . $location ] ) )
|
||||
{
|
||||
$exportTemplates['cms'][ $location ][ $key ][ $tkey ] = $tkdata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $exportTemplates ) )
|
||||
{
|
||||
/* Init */
|
||||
$xml = new \XMLWriter;
|
||||
$xml->openMemory();
|
||||
$xml->setIndent( TRUE );
|
||||
$xml->startDocument( '1.0', 'UTF-8' );
|
||||
|
||||
/* Root tag */
|
||||
$xml->startElement('templates');
|
||||
|
||||
foreach ( $exportTemplates as $app => $location )
|
||||
{
|
||||
foreach ( $location as $key => $data )
|
||||
{
|
||||
foreach ( $data as $group => $template )
|
||||
{
|
||||
foreach( $template as $key => $templateData )
|
||||
{
|
||||
/* Initiate the <template> tag */
|
||||
$xml->startElement( 'template' );
|
||||
|
||||
foreach ( $templateData as $k => $v )
|
||||
{
|
||||
if ( ! in_array( \substr( $k, 9 ), array( 'content', 'params' ) ) )
|
||||
{
|
||||
$xml->startAttribute( $k );
|
||||
$xml->text( $v );
|
||||
$xml->endAttribute();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write (potential) HTML fields */
|
||||
foreach( array( 'template_params', 'template_content' ) as $field )
|
||||
{
|
||||
if ( isset( $templateData[ $field ] ) )
|
||||
{
|
||||
$xml->startElement( $field );
|
||||
if ( preg_match( '/<|>|&/', $templateData[ $field ] ) )
|
||||
{
|
||||
$xml->writeCData( str_replace( ']]>', ']]]]><![CDATA[>', $templateData[ $field ] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$xml->text( $templateData[ $field ] );
|
||||
}
|
||||
$xml->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the <template> tag */
|
||||
$xml->endElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish */
|
||||
$xml->endDocument();
|
||||
|
||||
\IPS\Output::i()->sendOutput( $xml->outputMemory(), 200, 'application/xml', array( 'Content-Disposition' => \IPS\Output::getContentDisposition( 'attachment', "pages_templates.xml" ) ) );
|
||||
}
|
||||
else
|
||||
if( $xml === NULL )
|
||||
{
|
||||
\IPS\Output::i()->error( 'cms_no_templates_selected', '1T285/1', 403, '' );
|
||||
}
|
||||
\IPS\Output::i()->sendOutput( $xml->outputMemory(), 200, 'application/xml', array( 'Content-Disposition' => \IPS\Output::getContentDisposition( 'attachment', "pages_templates.xml" ) ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=cms&module=pages&controller=templates" ), \IPS\Member::loggedIn()->language()->addToStack( 'menu__cms_pages_templates' ) );
|
||||
@@ -430,7 +403,7 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->sidebar['actions']['add'] = array(
|
||||
'icon' => 'cog',
|
||||
'title' => 'content_import_dev_templates',
|
||||
'link' => \IPS\Http\Url::internal( "app=cms&module=pages&controller=templates&do=importInDev" ),
|
||||
'link' => \IPS\Http\Url::internal( "app=cms&module=pages&controller=templates&do=importInDev" )->csrf(),
|
||||
'data' => array()
|
||||
);
|
||||
}
|
||||
@@ -523,10 +496,21 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
/* PHP Keywords cannot be used as template names - so make sure the full template name is not in the list */
|
||||
$keywords = array( 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor' );
|
||||
|
||||
if ( in_array( $val, $keywords ) )
|
||||
if ( \in_array( $val, $keywords ) )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( 'template_reserved_word', FALSE, array( 'htmlsprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $keywords ) ) ) ) );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'cms_templates', array( "LOWER(template_title)=?", mb_strtolower( str_replace( ' ', '_', $val ) ) ) )->first();
|
||||
|
||||
if ( $count )
|
||||
{
|
||||
throw new \DomainException( 'cms_template_title_exists' );
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $e ) {}
|
||||
} ) );
|
||||
|
||||
/* Very specific */
|
||||
@@ -558,7 +542,7 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
foreach ( \IPS\Db::i()->select( "*", 'core_widgets', array( 'embeddable=1') ) as $widget )
|
||||
{
|
||||
/* Skip disabled applications */
|
||||
if ( !in_array( $widget['app'], array_keys( \IPS\Application::enabledApplications() ) ) )
|
||||
if ( !\in_array( $widget['app'], array_keys( \IPS\Application::enabledApplications() ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -609,7 +593,7 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! count( $groups ) )
|
||||
if ( ! \count( $groups ) )
|
||||
{
|
||||
$groups[ $type ] = \IPS\cms\Templates::readableGroupName( $type );
|
||||
}
|
||||
@@ -621,7 +605,18 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
'new' => array( 'group_new' ) )
|
||||
) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'template_group_new', NULL, FALSE, array( 'regex' => '/^([a-z_][a-z0-9_]+?)?$/' ), NULL, NULL, NULL, 'group_new' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'template_group_new', NULL, FALSE, array( 'regex' => '/^([a-z_][a-z0-9_]+?)?$/' ), function( $val ) {
|
||||
try
|
||||
{
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'cms_templates', array( "LOWER(template_group)=?", mb_strtolower( str_replace( ' ', '_', $val ) ) ) )->first();
|
||||
|
||||
if ( $count )
|
||||
{
|
||||
throw new \DomainException( 'cms_template_group_exists' );
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $e ) {}
|
||||
}, NULL, NULL, 'group_new' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'template_group_existing', NULL, FALSE, array( 'options' => $groups ), NULL, NULL, NULL, 'group_existing' ) );
|
||||
}
|
||||
|
||||
@@ -779,7 +774,7 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates' )->setQueryString( ['id' => $newTemplate->id, 't_location' => $newTemplate->location, 't_type' => $type ] ), 'saved' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,6 +841,27 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a difference report for an individual template file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function diffTemplate()
|
||||
{
|
||||
$customVersion = \IPS\Db::i()->select( '*', 'cms_templates', array( 'template_id=?', (int) \IPS\Request::i()->t_item_id ) )->first();
|
||||
|
||||
try
|
||||
{
|
||||
$original = \IPS\Db::i()->select( 'template_content', 'cms_templates', array( 'template_location=? and template_group=? and template_title=? and template_master=1', $customVersion['template_location'], $customVersion['template_original_group'], $customVersion['template_title'] ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$original = FALSE;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $original );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a template
|
||||
*
|
||||
@@ -853,6 +869,8 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$key = \IPS\Request::i()->t_key;
|
||||
|
||||
$contentKey = 'editor_' . $key;
|
||||
@@ -864,12 +882,33 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
try
|
||||
{
|
||||
$obj = \IPS\cms\Templates::load( $key );
|
||||
|
||||
$obj->location = \IPS\Request::i()->t_location;
|
||||
$obj->group = empty( \IPS\Request::i()->t_group ) ? null : \IPS\Request::i()->t_group;
|
||||
$obj->title = \IPS\Request::i()->t_name;
|
||||
$obj->params = $variables;
|
||||
$obj->content = $content;
|
||||
|
||||
if ( $obj->master )
|
||||
{
|
||||
/* Do not edit a master bit directly, but overload it */
|
||||
$clone = new \IPS\cms\Templates;
|
||||
$clone->key = $obj->key;
|
||||
$clone->title = \IPS\Request::i()->t_name;
|
||||
$clone->content = $content;
|
||||
$clone->location = \IPS\Request::i()->t_location;
|
||||
$clone->group = empty( \IPS\Request::i()->t_group ) ? null : \IPS\Request::i()->t_group;
|
||||
$clone->params = $variables;
|
||||
$clone->container = $obj->container;
|
||||
$clone->position = $obj->position;
|
||||
$clone->user_edited = 1;
|
||||
$clone->master = 0;
|
||||
$clone->save();
|
||||
}
|
||||
else
|
||||
{
|
||||
$obj->location = \IPS\Request::i()->t_location;
|
||||
$obj->group = empty( \IPS\Request::i()->t_group ) ? null : \IPS\Request::i()->t_group;
|
||||
$obj->title = \IPS\Request::i()->t_name;
|
||||
$obj->params = $variables;
|
||||
$obj->content = $content;
|
||||
$obj->user_edited = 1;
|
||||
}
|
||||
|
||||
if( $description )
|
||||
{
|
||||
$obj->description = $description;
|
||||
@@ -935,7 +974,7 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
$databases[ $database['database_id'] ] = \IPS\cms\Databases::constructFromData( $database );
|
||||
}
|
||||
|
||||
if ( count( $databases ) )
|
||||
if ( \count( $databases ) )
|
||||
{
|
||||
$names = array();
|
||||
foreach( $databases as $db )
|
||||
@@ -946,8 +985,25 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack( 'cms_database_template_used_in', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $names ) ) ) ), 'ipsMessage ipsMessage_info' );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'cms_database_group_name', \IPS\cms\Templates::readableGroupName( \IPS\Request::i()->group ), NULL, array( 'regex' => '/^([A-Z_][A-Z0-9_\.\s]+?)$/i' ) ) );
|
||||
$form->addButton( "delete", "link", \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=deleteTemplateGroup&group=' . \IPS\Request::i()->group . '&t_location=' . \IPS\Request::i()->t_location ), 'ipsButton ipsButton_negative', array( 'data-confirm' => 'true' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'cms_database_group_name', \IPS\cms\Templates::readableGroupName( \IPS\Request::i()->group ), NULL, array( 'regex' => '/^([A-Z_][A-Z0-9_\.\s]+?)$/i' ), function( $val ) {
|
||||
/* PHP Keywords cannot be used as template names - so make sure the full template name is not in the list */
|
||||
$keywords = array( 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor' );
|
||||
|
||||
if ( \in_array( $val, $keywords ) )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( 'template_reserved_word', FALSE, array( 'htmlsprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $keywords ) ) ) ) );
|
||||
}
|
||||
|
||||
if ( mb_strtolower( str_replace( ' ', '_', $val ) ) != mb_strtolower( str_replace( ' ', '_', \IPS\Request::i()->group ) ) )
|
||||
{
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'cms_templates', array( "LOWER(template_group)=?", mb_strtolower( str_replace( ' ', '_', $val ) ) ) )->first();
|
||||
if ( $count )
|
||||
{
|
||||
throw new \DomainException( 'cms_template_group_exists' );
|
||||
}
|
||||
}
|
||||
} ) );
|
||||
$form->addButton( "delete", "link", \IPS\Http\Url::internal( 'app=cms&module=pages&controller=templates&do=deleteTemplateGroup&group=' . \IPS\Request::i()->group . '&t_location=' . \IPS\Request::i()->t_location )->csrf(), 'ipsButton ipsButton_negative', array( 'data-confirm' => 'true' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -983,6 +1039,8 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function findAndUpdateTemplates( $new, $old )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'cms_templates', array( 'template_content LIKE ?', '%' . $old . '%' ) ) as $template )
|
||||
{
|
||||
/* Make sure template tags call the correct group */
|
||||
@@ -1025,6 +1083,8 @@ class _templates extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function deleteTemplateGroup()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
foreach( \IPS\cms\Templates::$databaseDefaults as $field => $template )
|
||||
{
|
||||
\IPS\Db::i()->update( 'cms_databases', array( 'database_template_' . $field => $template ), array( 'database_template_' . $field . ' =?', \IPS\Request::i()->group ) );
|
||||
|
||||
Reference in new issue
Block a user