Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

+460 -69
View File
@@ -2,9 +2,10 @@
/**
* @brief Page Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @subpackage Content
* @since 15 Jan 2014
* @version SVN_VERSION_NUMBER
*/
@@ -48,6 +49,11 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
protected static $databaseIdFields = array('page_seo_name', 'page_full_path');
/**
* @brief [ActiveRecord] Multiton Map
*/
protected static $multitonMap = array();
/**
* @brief [Node] Parent ID Database Column
*/
@@ -181,7 +187,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public static function loadFromUrl( \IPS\Http\Url $url )
{
$qs = array_merge( $url->queryString, $url->getFriendlyUrlData() );
$qs = array_merge( $url->queryString, $url->hiddenQueryString );
if ( isset( $qs['id'] ) )
{
@@ -196,14 +202,15 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
else if ( isset( $qs['path'] ) )
{
if ( method_exists( get_called_class(), 'loadAndCheckPerms' ) )
$return = static::load( $qs['path'], 'page_full_path' );
if ( method_exists( $return, 'can' ) )
{
return static::loadAndCheckPerms( $qs['path'], 'page_full_path' );
}
else
{
return static::load( $qs['path'], 'page_full_path' );
if ( !$return->can( 'view' ) )
{
throw new \OutOfRangeException;
}
}
return $return;
}
throw new \InvalidArgumentException;
@@ -288,10 +295,17 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
/* Nope - try a folder */
try
{
$class = static::$parentNodeClass;
$folder = $class::load( $path, 'folder_path' );
static::$loadedPagesFromPath[ $path ] = static::getDefaultPage( $folder->id );
if ( $path )
{
$class = static::$parentNodeClass;
$folder = $class::load( $path, 'folder_path' );
static::$loadedPagesFromPath[ $path ] = static::getDefaultPage( $folder->id );
}
else
{
static::$loadedPagesFromPath[ $path ] = static::getDefaultPage( 0 );
}
}
catch ( \OutOfRangeException $e )
{
@@ -323,12 +337,25 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
break;
}
}
/* Still here? It's possible this is a legacy URL that starts with "page" - last ditch effort */
if ( static::$loadedPagesFromPath[ $path ] === NULL AND mb_substr( $path, 0, 5 ) === 'page/' )
{
$pathWithoutPage = str_replace( 'page/', '', $path );
try
{
/* Pass back recursively so we don't have to duplicate all of the checks again */
static::$loadedPagesFromPath[ $path ] = static::loadFromPath( $pathWithoutPage );
}
catch( \OutOfRangeException $e ) {}
}
}
}
}
}
}
if ( static::$loadedPagesFromPath[ $path ] === NULL )
{
throw new \OutOfRangeException;
@@ -360,14 +387,12 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
foreach( \IPS\Db::i()->select( '*', 'cms_url_store', array( 'store_type=? and ? LIKE CONCAT( store_path, \'%\') OR store_path=?', 'page', $slug, $slug ) ) as $item )
{
$url = static::load( $item['store_current_id'] )->url();
$url->data['path'] = '/' . trim( str_replace( $item['store_path'], trim( $url->data['path'], '/' ), $slug ), '/' );
$url = $url->setPath( '/' . trim( str_replace( $item['store_path'], trim( $url->data['path'], '/' ), $slug ), '/' ) );
if ( $queryString !== NULL )
{
$url->data['query'] = $queryString;
$url = $url->setQueryString( $queryString );
}
return \IPS\Http\Url::createFromArray( $url->data );
return $url;
}
/* Still here? Ok, now we may have changed the folder name at some point, so lets look for that */
@@ -515,13 +540,20 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
$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 );
/* 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;
if ( isset( \IPS\Data\Store::i()->$functionName ) )
{
unset( \IPS\Data\Store::i()->$functionName );
}
$page->output( $title, $httpStatusCode, $httpHeaders );
}
catch( \Exception $ex )
{
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( $title, \IPS\Theme::i()->getTemplate( 'global', 'core' )->error( $title, $message, $code, NULL ), array( 'app' => \IPS\Dispatcher::i()->application ? \IPS\Dispatcher::i()->application->directory : NULL, 'module' => \IPS\Dispatcher::i()->module ? \IPS\Dispatcher::i()->module->key : NULL, 'controller' => \IPS\Dispatcher::i()->controller ) ), $httpStatusCode, 'text/html', $httpHeaders, FALSE, FALSE );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( $title, \IPS\Theme::i()->getTemplate( 'global', 'core' )->error( $title, $message, $code, NULL, \IPS\Member::loggedIn() ), array( 'app' => \IPS\Dispatcher::i()->application ? \IPS\Dispatcher::i()->application->directory : NULL, 'module' => \IPS\Dispatcher::i()->module ? \IPS\Dispatcher::i()->module->key : NULL, 'controller' => \IPS\Dispatcher::i()->controller ) ), $httpStatusCode, 'text/html', $httpHeaders, FALSE, FALSE );
}
}
@@ -549,9 +581,32 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
if ( empty( $val ) )
{
$val = \IPS\Http\Url::seoTitle( $val );
$val = \IPS\Http\Url\Friendly::seoTitle( $val );
}
/* We cannot have a page name the same as a folder name in this folder */
try
{
$testFolder = \IPS\cms\Pages\Folder::load( $val, 'folder_name' );
/* Ok, we have a folder, but is it on the same tree as us ?*/
if ( intval( \IPS\Request::i()->page_folder_id ) == $testFolder->parent_id )
{
/* Yep, this will break designers' mode and may confuse the FURL engine so we cannot allow this */
throw new \InvalidArgumentException('content_folder_name_furl_collision_pages');
}
}
catch ( \OutOfRangeException $e )
{
/* Nothing with the same name, so that's proper good that is */
}
/* If we hit here, we don't have an existing name so that's good */
if ( ! \IPS\Request::i()->page_folder_id and \IPS\cms\Pages\Page::isFurlCollision( $val ) )
{
throw new \InvalidArgumentException('content_folder_name_furl_collision_pages_app');
}
try
{
$test = \IPS\cms\Pages\Page::load( $val, 'page_seo_name' );
@@ -572,18 +627,14 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
}
catch ( \OutOfRangeException $e )
catch ( \OutOfRangeException $e )
{
/* If we hit here, we don't have an existing name so that's good */
if ( ! \IPS\Request::i()->page_folder_id and \IPS\cms\Pages\Page::isFurlCollision( $val ) )
{
throw new \InvalidArgumentException('content_folder_name_furl_collision');
}
/* An exception means we don't have a match, so that is good */
}
}, NULL, NULL, 'page_seo_name' );
$return['page_folder_id'] = new \IPS\Helpers\Form\Node( 'page_folder_id', ( $item ? intval( $item->folder_id ) : ( ( isset( \IPS\Request::i()->parent ) and \IPS\Request::i()->parent ) ? \IPS\Request::i()->parent : 0 ) ), FALSE, array(
'class' => '\IPS\cms\Pages\Folder',
'class' => 'IPS\cms\Pages\Folder',
'zeroVal' => 'node_no_parent',
'subnodes' => false
), NULL, NULL, NULL, 'page_folder_id' );
@@ -705,6 +756,35 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
throw new \LogicException('cms_page_error_bad_syntax');
}
/* New page? quick check to see if we added a DB tag, and if so, make sure it's not being used on another page. */
if ( ! isset( \IPS\Request::i()->id ) )
{
preg_match( '#{database="([^"]+?)"#', $val, $matches );
if ( isset( $matches[1] ) )
{
try
{
if ( is_numeric( $matches[1] ) )
{
$database = \IPS\cms\Databases::load( intval( $matches[1] ) );
}
else
{
$database = \IPS\cms\Databases::load( $matches[1], 'database_key' );
}
if ( $database->page_id )
{
throw new \LogicException('cms_err_db_in_use_other_page');
}
}
catch( \OutOfRangeException $ex )
{
throw new \LogicException('cms_err_db_does_not_exist');
}
}
}
}, NULL, NULL, 'page_content' );
}
@@ -752,7 +832,13 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
$path = trim( $path , '/');
$bits = explode( '/', $path );
$folder = $bits[0];
/* Ensure we cannot have a structure that starts with core/interface as we have this partial URL blacklisted in \IPS\Text\Parser::safeIframeRegexp() */
if ( mb_substr( $path, 0, 15 ) == 'core/interface/' )
{
return TRUE;
}
$defaultApplication = \IPS\Db::i()->select( 'app_directory', 'core_applications', 'app_default=1' )->first();
foreach( \IPS\Application::applications() as $key => $app )
@@ -792,6 +878,21 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
}
}
/* Still here? Some apps use very loose matching, like calendar looks for {id}-{?} which may conflict with a page with a filename of 123-foo */
try
{
$url = \IPS\Http\Url::createFromString( \IPS\Http\Url::baseUrl() . $path );
if ( $url and $url instanceof \IPS\Http\Url\Friendly and $url->seoTemplate !== 'content_page_path' )
{
return TRUE;
}
}
catch( \Exception $ex )
{
/* If we get an error, then it cannot be a legitimate link */
}
return FALSE;
}
@@ -814,6 +915,18 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public static function buildPageUrlStore()
{
/* This fails because hooks are not installed when this is attempted to build via admin/install */
if ( \IPS\Dispatcher::hasInstance() and \IPS\Dispatcher::i()->controllerLocation === 'setup' )
{
return;
}
/* This also fails if we're installing via ACP */
if ( \IPS\Dispatcher::hasInstance() and \IPS\Dispatcher::i()->controllerLocation === 'admin' and isset( \IPS\Request::i()->do ) and \IPS\Request::i()->do == 'install' )
{
return;
}
$store = array();
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'cms_pages' ), 'IPS\cms\Pages\Page' ) as $page )
{
@@ -839,7 +952,6 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
return \IPS\Data\Store::i()->pages_page_urls;
}
/**
* Set JS/CSS include keys
*
@@ -1031,16 +1143,30 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
$functionName = 'content_pages_' . $this->id;
if ( ! isset( \IPS\Data\Store::i()->$functionName ) )
{
\IPS\Data\Store::i()->$functionName = \IPS\Theme::compileTemplate( $this->content, $functionName, null, true );
if ( \IPS\Theme::i()->designersModeEnabled() and file_exists( \IPS\ROOT_PATH . '/themes/cms/pages/' . $this->full_path ) )
{
$contents = @file_get_contents( \IPS\ROOT_PATH . '/themes/cms/pages/' . $this->full_path );
$contents = preg_replace( '#^<ips:pages.+?/>(\r\n?|\n)#', '', $contents );
\IPS\Theme::runProcessFunction( \IPS\Theme::compileTemplate( $contents, $functionName, null, true ), $functionName );
}
else
{
if ( ! isset( \IPS\Data\Store::i()->$functionName ) )
{
\IPS\Data\Store::i()->$functionName = \IPS\Theme::compileTemplate( $this->content, $functionName, null, true );
}
\IPS\Theme::runProcessFunction( \IPS\Data\Store::i()->$functionName, $functionName );
}
\IPS\Theme::runProcessFunction( \IPS\Data\Store::i()->$functionName, $functionName );
return call_user_func( 'IPS\\Theme\\'. $functionName );
}
/**
* @brief Cached widgets
*/
protected $cachedWidgets = NULL;
/**
* Return the blocks for this page
*
@@ -1048,10 +1174,16 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public function getWidgets()
{
$widgets = array();
$return = array();
$dbWidgets = array();
$areas = array();
if( $this->cachedWidgets !== NULL )
{
return $this->cachedWidgets;
}
$this->cachedWidgets = array();
$widgets = array();
$dbWidgets = array();
$areas = array();
foreach( \IPS\Db::i()->select( '*', 'cms_page_widget_areas', array( 'area_page_id=?', $this->id ) ) as $k => $widgetMain )
{
@@ -1104,17 +1236,17 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Output::i()->sidebar['widgets'][ $areaKey ][] = $_widget;
}
$return[ $areaKey ][] = $_widget;
$this->cachedWidgets[ $areaKey ][] = $_widget;
}
catch ( \Exception $e )
{
\IPS\Log::i( LOG_ERR )->write( $e->getMessage() );
\IPS\Log::debug( $e, 'pages_widgets' );
}
}
}
}
return $return;
return $this->cachedWidgets;
}
/**
@@ -1212,7 +1344,6 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
if ( ! $this->id )
{
$form->hiddenValues['page_type'] = $pageType = \IPS\Request::i()->page_type;
}
else
{
@@ -1301,7 +1432,10 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
}
$form->addButton( 'save_and_reload', 'submit', null, 'ipsButton ipsButton_primary', array( 'name' => 'save_and_reload', 'value' => 1 ) );
if( $this->id )
{
$form->canSaveAndReload = true;
}
\IPS\Output::i()->title = $this->id ? \IPS\Member::loggedIn()->language()->addToStack('content_editing_page', NULL, array( 'sprintf' => array( $this->_title ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('content_add_page');
}
@@ -1335,7 +1469,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
$bits = explode( '.', $values['page_seo_name'] );
foreach( $bits as $i => $v )
{
$bits[ $i ] = \IPS\Http\Url::seoTitle( $v );
$bits[ $i ] = \IPS\Http\Url\Friendly::seoTitle( $v );
}
$values['page_seo_name'] = implode( '.', $bits );
@@ -1390,23 +1524,19 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
if( $values['page_add_to_menu'] )
{
$values = \IPS\cms\extensions\core\FrontNavigation\Pages::parseConfiguration( $values, $this->id );
$config = array( 'menu_content_page' => $this->id );
$permission = $values['menu_manager_access'] == '*' ? '*' : implode( ',', $values['menu_manager_access'] );
foreach( array( 'menu_title_page_type', 'menu_title_page' ) as $field )
if ( $values['menu_manager_access_type'] === 0 )
{
if ( isset( $values[ $field ] ) )
{
$config[ $field ] = $values[ $field ];
}
$permission = '';
}
$save = array(
'app' => 'cms',
'extension' => 'Pages',
'config' => json_encode( $config ),
'config' => '',
'parent' => $values['menu_parent'],
'permissions' => $values['menu_manager_access'] == '*' ? '*' : implode( ',', $values['menu_manager_access'] )
'permissions' => $permission
);
try
@@ -1418,7 +1548,21 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
$save['position'] = 1;
}
\IPS\Db::i()->insert( 'core_menu', $save );
$id = \IPS\Db::i()->insert( 'core_menu', $save );
$values = \IPS\cms\extensions\core\FrontNavigation\Pages::parseConfiguration( $values, $id );
$config = array( 'menu_content_page' => $this->id );
foreach( array( 'menu_title_page_type', 'menu_title_page' ) as $field )
{
if ( isset( $values[ $field ] ) )
{
$config[ $field ] = $values[ $field ];
}
}
\IPS\Db::i()->update( 'core_menu', array( 'config' => json_encode( $config ) ), array( 'id=?', $id ) );
unset( \IPS\Data\Store::i()->frontNavigation );
}
@@ -1530,9 +1674,19 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
{
if( $this->_url === NULL )
{
if ( \IPS\Application::load('cms')->default AND $this->default AND ! $this->folder_id )
if ( ( \IPS\Application::load('cms')->default OR \IPS\Settings::i()->cms_use_different_gateway ) AND $this->default AND ! $this->folder_id )
{
$this->_url = \IPS\Http\Url::internal( '', 'front' );
/* Are we using the gateway file? */
if ( \IPS\Settings::i()->cms_use_different_gateway )
{
/* Yes, work out the proper URL. */
$this->_url = \IPS\Http\Url::createFromString( \IPS\Settings::i()->cms_root_page_url, TRUE );
}
else
{
/* No - that's easy */
$this->_url = \IPS\Http\Url::internal( '', 'front' );
}
}
else
{
@@ -1611,7 +1765,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
if ( isset( $seen['database'] ) )
{
/* Yep, is it the same ID? */
if ( $seen['database']['value'] != $database->id )
if ( $seen['database']['value'] != $database->id AND $seen['database']['value'] != $database->key )
{
/* There's been a change.. */
try
@@ -1805,8 +1959,13 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
unset( \IPS\Data\Store::i()->frontNavigation );
return parent::delete();
parent::delete();
if ( $this->full_path and \IPS\Theme::designersModeEnabled() )
{
static::cleanUpDesignersModeFiles();
}
}
/**
@@ -1878,6 +2037,11 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
parent::save();
static::buildPageUrlStore();
if ( $this->full_path and \IPS\Theme::designersModeEnabled() )
{
static::exportDesignersMode( $this->id );
}
}
/**
@@ -1897,8 +2061,8 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public function setAsDefault()
{
\IPS\DB::i()->update( 'cms_pages', array( 'page_default' => 0 ), array( 'page_folder_id=?', $this->folder_id ) );
\IPS\DB::i()->update( 'cms_pages', array( 'page_default' => 1 ), array( 'page_id=?', $this->id ) );
\IPS\Db::i()->update( 'cms_pages', array( 'page_default' => 0 ), array( 'page_folder_id=?', $this->folder_id ) );
\IPS\Db::i()->update( 'cms_pages', array( 'page_default' => 1 ), array( 'page_id=?', $this->id ) );
static::buildPageUrlStore();
}
@@ -1918,8 +2082,9 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
/**
* Displays a page
*
* @param int $httpStatusCode HTTP Status Code
* @param array $httpHeaders Additional HTTP Headers
* @param string|NULL $title The Page title
* @param int $httpStatusCode HTTP Status Code
* @param array $httpHeaders Additional HTTP Headers
* @throws \ErrorException
* @return void
*/
@@ -1956,7 +2121,7 @@ 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')->globalWrap( $nav, $this->getHtmlContent(), $this );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'pages', 'cms' )->globalWrap( $nav, $this->getHtmlContent(), $this );
}
\IPS\Output::i()->sidebar['enabled'] = true;
@@ -1972,6 +2137,12 @@ 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 )
{
\IPS\Output::i()->linkTags['canonical'] = (string) $this->url();
}
/* Can only disable sidebar if HTML page */
if ( ! $this->show_sidebar and $this->type === 'html' )
@@ -2050,4 +2221,224 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Output::i()->sendOutput( $this->getHtmlContent(), ( $httpStatusCode ? $httpStatusCode : 200 ), $this->getContentType(), ( $httpHeaders ? $httpHeaders : \IPS\Output::i()->httpHeaders ) );
}
}
/**
* Write HTML pages to disk for designer's mode
*
* @param NULL|int $pageId Single page to export
* @return void
*/
public static function exportDesignersMode( $pageId=NULL)
{
$where = array( array( 'page_type=?', 'html' ) );
$seen = array();
if ( $pageId )
{
$where[] = array( 'page_id=?', $pageId );
}
foreach( \IPS\Db::i()->select( '*', 'cms_pages', $where ) as $page )
{
/* We could use recursive mode but it wouldn't correctly chmod the intermediate dirs */
$bits = explode( '/', "/themes/cms/pages/" . $page['page_full_path'] );
$dir = '';
$filename = array_pop( $bits );
foreach( $bits as $part )
{
$dir .= $part . '/';
if ( ! is_dir( \IPS\ROOT_PATH . '/' . trim( $dir, '/' ) ) )
{
mkdir( \IPS\ROOT_PATH . '/' . trim( $dir, '/' ), \IPS\IPS_FOLDER_PERMISSION );
chmod( \IPS\ROOT_PATH . '/' . trim( $dir, '/' ), \IPS\IPS_FOLDER_PERMISSION );
}
}
$headers = array();
foreach( array( 'page_seo_name', 'page_ipb_wrapper', 'page_title') as $field )
{
$headers[ $field ] = $field . '="' . str_replace( '"', '\\"', $page[ $field ] ) . '"';
}
$header = "<ips:pages " . implode( " ", $headers ) . " />";
try
{
\file_put_contents( \IPS\ROOT_PATH . '/' . trim( $dir, '/' ) . '/' . $filename, $header . "\n" . $page['page_content'] );
@chmod( \IPS\ROOT_PATH . '/' . trim( $dir, '/' ) . '/' . $filename, \IPS\IPS_FILE_PERMISSION );
}
catch( \RuntimeException $e ) { }
}
/* Clear out any older designer mode files */
if ( ! $pageId )
{
static::cleanUpDesignersModeFiles();
}
}
/**
* Remove any old designer mode files
*
* @return void
*/
public static function cleanUpDesignersModeFiles()
{
$diskPaths = array();
static::getCurrentDesignersModeFilePaths( $diskPaths, \IPS\ROOT_PATH . "/themes/cms/pages/" );
$databasePaths = array();
foreach( \IPS\Db::i()->select( '*', 'cms_pages', array( 'page_type=?', 'html' ) ) as $page )
{
$databasePaths[] = $page['page_full_path'];
}
if ( count( $diskPaths ) )
{
foreach( $diskPaths as $path )
{
if ( ! in_array( $path, $databasePaths ) )
{
@unlink( \IPS\ROOT_PATH . "/themes/cms/pages/" . $path );
}
}
}
}
/**
* Get existing designer's mode page paths
*
* @param array $paths Array of processed page paths
* @param string $path Path to look into
* @return void
*/
public static function getCurrentDesignersModeFilePaths( &$paths, $path )
{
if ( is_dir( $path ) )
{
foreach ( new \DirectoryIterator( $path ) as $dir )
{
if ( $dir->isDot() || mb_substr( $dir->getFilename(), 0, 1 ) === '.' )
{
continue;
}
if ( $dir->isDir() )
{
static::getCurrentDesignersModeFilePaths( $paths, $dir->getRealPath() );
}
else
{
$paths[] = trim( str_replace( \IPS\ROOT_PATH . '/themes/cms/pages/', '', $dir->getRealPath() ), '/' );
}
}
}
}
/**
* Import media from disk for designer's mode
*
* @return void
*/
public static function importDesignersMode()
{
$path = \IPS\ROOT_PATH . '/themes/cms/pages';
$seen = array();
/* Grab folder data */
if ( is_dir( $path ) )
{
static::importDesignersModeRecurse( $seen, $path );
}
\IPS\Db::i()->delete( 'cms_pages', array( 'page_type=? and ' . \IPS\Db::i()->in( 'page_id', $seen, TRUE ), 'html' ) );
}
/**
* Import media from disk for designer's mode recursive method
*
* @param array $seen Array of processed page IDs
* @param string $path Path to look into
* @return void
*/
public static function importDesignersModeRecurse( &$seen, $path )
{
if ( is_dir( $path ) )
{
foreach ( new \DirectoryIterator( $path ) as $dir )
{
if ( $dir->isDot() || mb_substr( $dir->getFilename(), 0, 1 ) === '.' )
{
continue;
}
if ( $dir->isDir() )
{
static::importDesignersModeRecurse( $seen, $dir->getRealPath() );
}
else
{
$folders = \IPS\cms\Pages\Folder::roots();
$contents = \file_get_contents( $dir->getRealPath() );
$params = array();
/* Parse the header tag */
preg_match( '#^<ips:pages(.+?)/>(\r\n?|\n)#', $contents, $params );
/* Strip it */
$contents = ( isset($params[0]) ) ? str_replace( $params[0], '', $contents ) : $contents;
/* Get fields */
preg_match_all( '#([a-z\-_]+?)="(.+?)"#', $params[1], $data, PREG_SET_ORDER );
$fields = array();
foreach( $data as $id => $matches )
{
$fields[ $data[ $id ][1] ] = $data[ $id ][2];
}
/* Existing page, or a new one? */
$fullPath = trim( str_replace( str_replace( '\\', '/', \IPS\ROOT_PATH ) . '/themes/cms/pages', '', str_replace( '\\', '/', $dir->getRealPath() ) ), '/' );
$bits = explode( '/', $fullPath );
$fileName = array_pop( $bits );
$path = implode( '/', $bits );
try
{
$page = \IPS\cms\Pages\Page::load( $fullPath, 'page_full_path' );
$page->content = $contents;
$page->save();
}
catch( \OutOfRangeException $e )
{
$folderId = 0;
foreach( $folders as $folder )
{
if ( $folder->path == $path )
{
$folderId = $folder->id;
}
}
/* Doesn't exist, so this is new */
$page = new \IPS\cms\Pages\Page;
$page->content = $contents;
$page->full_path = $fullPath;
$page->seo_name = $fileName;
$page->type = 'html';
$page->title = ( isset( $fields['page_title'] ) ) ? $fields['page_title'] : $fileName;
$page->ipb_wrapper = ( isset( $fields['page_ipb_wrapper'] ) ) ? $fields['page_ipb_wrapper'] : 1;
$page->folder_id = $folderId;
$page->save();
\IPS\Lang::saveCustom( 'cms', "cms_page_" . $page->id, $page->title );
}
$seen[] = $page->id;
}
}
}
}
}