Version 4.0.13.1
This commit is contained in:
1 parent
f9e857d255
commit
c6a86f0d9b
7517 files changed
+597400
-668041
No files matched your search
@@ -0,0 +1,939 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Block Model
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @since 19 Feb 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\cms\Blocks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Block Model
|
||||
*/
|
||||
class _Block extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
{
|
||||
/**
|
||||
* @brief Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Table
|
||||
*/
|
||||
public static $databaseTable = 'cms_blocks';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'block_';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] ID Database Column
|
||||
*/
|
||||
public static $databaseColumnId = 'id';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database ID Fields
|
||||
*/
|
||||
protected static $databaseIdFields = array('block_key');
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent ID Database Column
|
||||
*/
|
||||
public static $databaseColumnParent = null;
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent Node ID Database Column
|
||||
*/
|
||||
public static $parentNodeColumnId = 'category';
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent Node Class
|
||||
*/
|
||||
public static $parentNodeClass = 'IPS\cms\Blocks\Container';
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent ID Database Column
|
||||
*/
|
||||
public static $databaseColumnOrder = 'position';
|
||||
|
||||
/**
|
||||
* @brief [Node] Show forms modally?
|
||||
*/
|
||||
public static $modalForms = TRUE;
|
||||
|
||||
/**
|
||||
* @brief [Node] Sortable?
|
||||
*/
|
||||
public static $nodeSortable = TRUE;
|
||||
|
||||
/**
|
||||
* @brief [Node] Title
|
||||
*/
|
||||
public static $nodeTitle = 'block';
|
||||
|
||||
/**
|
||||
* @brief [Node] Title prefix. If specified, will look for a language key with "{$key}_title" as the key
|
||||
*/
|
||||
public static $titleLangPrefix = 'content_block_name_';
|
||||
|
||||
/**
|
||||
* @brief [Node] Description suffix. If specified, will look for a language key with "{$titleLangPrefix}_{$id}_{$descriptionLangSuffix}" as the key
|
||||
*/
|
||||
public static $descriptionLangSuffix = '_desc';
|
||||
|
||||
/**
|
||||
* @brief [Node] ACP Restrictions
|
||||
* @code
|
||||
array(
|
||||
'app' => 'core', // The application key which holds the restrictrions
|
||||
'module' => 'foo', // The module key which holds the restrictions
|
||||
'map' => array( // [Optional] The key for each restriction - can alternatively use "prefix"
|
||||
'add' => 'foo_add',
|
||||
'edit' => 'foo_edit',
|
||||
'permissions' => 'foo_perms',
|
||||
'delete' => 'foo_delete'
|
||||
),
|
||||
'all' => 'foo_manage', // [Optional] The key to use for any restriction not provided in the map (only needed if not providing all 4)
|
||||
'prefix' => 'foo_', // [Optional] Rather than specifying each key in the map, you can specify a prefix, and it will automatically look for restrictions with the key "[prefix]_add/edit/permissions/delete"
|
||||
* @endcode
|
||||
*/
|
||||
protected static $restrictions = array(
|
||||
'app' => 'cms',
|
||||
'module' => 'pages',
|
||||
'prefix' => 'block_'
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief [Node] App for permission index
|
||||
*/
|
||||
public static $permApp = 'cms';
|
||||
|
||||
/**
|
||||
* @brief [Node] Type for permission index
|
||||
*/
|
||||
public static $permType = 'blocks';
|
||||
|
||||
/**
|
||||
* @brief The map of permission columns
|
||||
*/
|
||||
public static $permissionMap = array(
|
||||
'view' => 'view'
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief [Node] Prefix string that is automatically prepended to permission matrix language strings
|
||||
*/
|
||||
public static $permissionLangPrefix = 'perm_cms_block_';
|
||||
|
||||
/**
|
||||
* @brief Templates already loaded and evald via getTemplate()
|
||||
*/
|
||||
public static $calledTemplates = array();
|
||||
|
||||
/**
|
||||
* Parse a block for display
|
||||
* Wrapped in a static method so we can catch the OutOfRangeException and take action.
|
||||
*
|
||||
* @param string|int|\IPS\cms\Blocks\Block $block Block ID
|
||||
* @param string $orientation Orientation
|
||||
* @return string Ready to display HTML
|
||||
*/
|
||||
public static function display( $block, $orientation=NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( is_numeric( $block ) )
|
||||
{
|
||||
$block = static::load( $block );
|
||||
}
|
||||
else if ( ! $block instanceof \IPS\cms\Blocks\Block )
|
||||
{
|
||||
$block = static::load( $block, 'block_key' );
|
||||
}
|
||||
|
||||
if ( !$block->active )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We gots the perms to see this? */
|
||||
if ( !$block->can( 'view' ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( $block->type === 'custom' )
|
||||
{
|
||||
$functionName = 'content_blocks_' . $block->id;
|
||||
|
||||
if ( ! isset( \IPS\Data\Store::i()->$functionName ) )
|
||||
{
|
||||
$content = $block->content;
|
||||
|
||||
if( $block->getConfig('editor') == 'php' )
|
||||
{
|
||||
ob_start();
|
||||
eval( $content );
|
||||
$content = ob_get_clean();
|
||||
}
|
||||
|
||||
\IPS\Data\Store::i()->$functionName = \IPS\Theme::compileTemplate( $content, $functionName, null, true );
|
||||
}
|
||||
|
||||
\IPS\Theme::runProcessFunction( \IPS\Data\Store::i()->$functionName, $functionName );
|
||||
|
||||
if( $block->getConfig('editor') == 'php' )
|
||||
{
|
||||
unset( \IPS\Data\Store::i()->$functionName );
|
||||
}
|
||||
|
||||
return call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
}
|
||||
else
|
||||
{
|
||||
$block->orientation = $orientation;
|
||||
|
||||
if ( $block->template OR $block->content )
|
||||
{
|
||||
$block->widget()->template( array( $block, 'getTemplate' ) );
|
||||
}
|
||||
|
||||
return $block->widget()->render();
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to overload standard widget templates
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getTemplate()
|
||||
{
|
||||
$args = func_get_args();
|
||||
$functionName = 'content_template_for_block_' . $this->id;
|
||||
|
||||
unset( \IPS\Data\Store::i()->$functionName );
|
||||
|
||||
/* Still here */
|
||||
if ( ! in_array( $functionName, array_keys( self::$calledTemplates ) ) )
|
||||
{
|
||||
if ( ! isset( \IPS\Data\Store::i()->$functionName ) )
|
||||
{
|
||||
if ( $this->content )
|
||||
{
|
||||
\IPS\Data\Store::i()->$functionName = \IPS\Theme::compileTemplate( $this->content, 'run', $this->template_params, true );
|
||||
|
||||
}
|
||||
else if ( $this->template )
|
||||
{
|
||||
try
|
||||
{
|
||||
$template = \IPS\cms\Templates::load( $this->template );
|
||||
return call_user_func_array( array( \IPS\cms\Theme::i()->getTemplate( $template->group, 'cms', $template->location ), $template->title ), $args );
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
/* @todo what to do here? */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Put them in a class */
|
||||
$template = <<<EOF
|
||||
class class_{$functionName}
|
||||
{
|
||||
|
||||
EOF;
|
||||
$template .= \IPS\Data\Store::i()->$functionName;
|
||||
|
||||
$template .= <<<EOF
|
||||
}
|
||||
EOF;
|
||||
|
||||
/* It lives! */
|
||||
\IPS\Theme::runProcessFunction( $template, $functionName );
|
||||
|
||||
$class = "\IPS\Theme\\class_{$functionName}";
|
||||
|
||||
/* Init */
|
||||
self::$calledTemplates[ $functionName ] = new $class();
|
||||
}
|
||||
|
||||
return call_user_func_array( array( self::$calledTemplates[ $functionName ], 'run' ), $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete compiled versions
|
||||
*
|
||||
* @param int|array $ids Integer ID or Array IDs to remove
|
||||
* @return void
|
||||
*/
|
||||
public static function deleteCompiled( $ids )
|
||||
{
|
||||
if ( is_numeric( $ids ) )
|
||||
{
|
||||
$ids = array( $ids );
|
||||
}
|
||||
|
||||
foreach( $ids as $id )
|
||||
{
|
||||
$functionName = 'content_blocks_' . $id;
|
||||
if ( isset( \IPS\Data\Store::i()->$functionName ) )
|
||||
{
|
||||
unset( \IPS\Data\Store::i()->$functionName );
|
||||
}
|
||||
|
||||
$functionName = 'content_template_for_block_' . $id;
|
||||
if ( isset( \IPS\Data\Store::i()->$functionName ) )
|
||||
{
|
||||
unset( \IPS\Data\Store::i()->$functionName );
|
||||
}
|
||||
}
|
||||
|
||||
/* We can also use blocks in per-page CSS */
|
||||
\IPS\cms\Pages\Page::deleteCompiledIncludes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Config json as array
|
||||
*/
|
||||
protected $_config = null;
|
||||
|
||||
/**
|
||||
* @brief Stores a \IPS\Widget object if this is a custom block with an embedded widget
|
||||
*/
|
||||
protected $widgetLoaded = NULL;
|
||||
|
||||
/**
|
||||
* @brief Orientation for an embedded widget
|
||||
*/
|
||||
protected $orientation = NULL;
|
||||
|
||||
/**
|
||||
* Get config as an array if no $key, or as whatever type corresponds to key
|
||||
*
|
||||
* @param string|null $key Config key to fetch
|
||||
* @return mixed
|
||||
*/
|
||||
public function getConfig( $key = NULL)
|
||||
{
|
||||
if ( $this->_config === NULL )
|
||||
{
|
||||
$this->_config = json_decode( $this->config, TRUE );
|
||||
|
||||
if ( $this->_config === FALSE )
|
||||
{
|
||||
$this->_config = array();
|
||||
}
|
||||
}
|
||||
|
||||
if ( $key )
|
||||
{
|
||||
if ( isset( $this->_config[ $key ] ) )
|
||||
{
|
||||
return $this->_config[ $key ];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return $this->_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config key and value
|
||||
*
|
||||
* @param string $key Config key
|
||||
* @param mixed $value Config value
|
||||
* @return mixed
|
||||
*/
|
||||
public function setConfig( $key, $value )
|
||||
{
|
||||
$this->_config[ $key ] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Return the custom badge for each row
|
||||
*
|
||||
* @return NULL|array Null for no badge, or an array of badge data (0 => CSS class type, 1 => language string, 2 => optional raw HTML to show instead of language string)
|
||||
*/
|
||||
protected function get__badge()
|
||||
{
|
||||
return array(
|
||||
0 => 'ipsBadge ipsBadge_intermediary ipsPos_right',
|
||||
1 => $this->type === 'custom' ? 'content_block_add_type_custom' : 'content_block_add_type_plugin',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Get description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get__description()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'content_block_name_' . $this->_id . '_desc' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get__plugin_config()
|
||||
{
|
||||
return ( $this->plugin_config ? ( is_array( $this->plugin_config ) ? $this->plugin_config : json_decode( $this->plugin_config, TRUE ) ) : array() );
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Get buttons to display in tree
|
||||
* Example code explains return value
|
||||
* @endcode
|
||||
* @param string $url Base URL
|
||||
* @param bool $subnode Is this a subnode?
|
||||
* @return array
|
||||
*/
|
||||
public function getButtons( $url, $subnode=FALSE )
|
||||
{
|
||||
$buttons = parent::getButtons( $url, $subnode );
|
||||
|
||||
if ( isset( $buttons['add'] ) )
|
||||
{
|
||||
unset( $buttons['add']['data'] );
|
||||
}
|
||||
|
||||
if ( isset( $buttons['edit'] ) )
|
||||
{
|
||||
unset( $buttons['edit']['data'] );
|
||||
}
|
||||
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Add/Edit Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @return void
|
||||
*/
|
||||
public function form( &$form )
|
||||
{
|
||||
$block_type = ( isset( \IPS\Request::i()->block_type ) ) ? \IPS\Request::i()->block_type : ( $this->id ? $this->type : null );
|
||||
$block_editor = ( isset( \IPS\Request::i()->block_editor ) ) ? \IPS\Request::i()->block_editor : ( $this->id ? $this->getConfig('editor') : null );
|
||||
$block_plugin = ( isset( \IPS\Request::i()->block_plugin ) ) ? \IPS\Request::i()->block_plugin : ( $this->id ? $this->plugin : null );
|
||||
|
||||
/* Build form */
|
||||
$form->addtab( 'content_block_form_tab__details' );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'block_name', NULL, TRUE, array(
|
||||
'app' => 'cms',
|
||||
'key' => ( $this->id ? "content_block_name_" . $this->id : NULL )
|
||||
) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'block_description', NULL, FALSE, array(
|
||||
'app' => 'cms',
|
||||
'key' => ( $this->id ? "content_block_name_" . $this->id . '_desc' : NULL )
|
||||
) ) );
|
||||
|
||||
$nodeContainer = $this->id ? $this->category :
|
||||
( \IPS\Request::i()->parent ?: \IPS\cms\Blocks\Container::load( ( $block_type == 'custom' ? 'block_custom' : 'block_plugins' ), 'container_key' )->id );
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'block_category', $nodeContainer, TRUE, array(
|
||||
'class' => '\IPS\cms\Blocks\Container',
|
||||
'subnodes' => false
|
||||
) ) );
|
||||
|
||||
$form->addHeader( 'cms_block_form_display' );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'block_key', $this->id ? $this->key : FALSE, FALSE, array(), function( $val )
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( ! $val )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$block = \IPS\cms\Blocks\Block::load( $val, 'block_key');
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
/* Doesn't exist? Good! */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* It's taken... */
|
||||
if ( \IPS\Request::i()->id == $block->id )
|
||||
{
|
||||
/* But it's this one so that's ok */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* and if we're here, it's not... */
|
||||
throw new \InvalidArgumentException('cms_block_key_not_unique');
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
/* Slug is OK as load failed */
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
} ) );
|
||||
|
||||
/* Do we have config? */
|
||||
if ( $block_type === 'plugin' and $block_plugin )
|
||||
{
|
||||
if ( ! $this->id )
|
||||
{
|
||||
$this->type = 'plugin';
|
||||
$this->plugin = $block_plugin;
|
||||
|
||||
if ( isset( \IPS\Request::i()->block_plugin_app ) )
|
||||
{
|
||||
$this->plugin_app = \IPS\Request::i()->block_plugin_app;
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->block_plugin_plugin ) )
|
||||
{
|
||||
$this->plugin_plugin = \IPS\Request::i()->block_plugin_plugin;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mb_substr( $block_plugin, 0, 8 ) === 'db_feed_' )
|
||||
{
|
||||
$databaseId = intval( mb_substr( $block_plugin, 8 ) );
|
||||
$this->plugin = 'RecordFeed';
|
||||
$this->plugin_config = array( 'cms_rf_database' => $databaseId );
|
||||
|
||||
/* JS needs this to produce the preview */
|
||||
$form->hiddenValues['cms_rf_database'] = $databaseId;
|
||||
}
|
||||
else if ( $this->id and $block_plugin === 'RecordFeed' )
|
||||
{
|
||||
$form->hiddenValues['cms_rf_database'] = $this->_plugin_config['cms_rf_database'];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$block_editor = 'html';
|
||||
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'cms_block_feed_form_message', FALSE, array( 'sprintf' => $this->widget()->title() ) ), 'information', NULL, FALSE );
|
||||
}
|
||||
catch ( \OutOfRangeException $ex )
|
||||
{
|
||||
throw new \LogicException( 'cms_error_block_plugin_not_found' );
|
||||
}
|
||||
|
||||
if ( is_callable( array( $this->widget(), 'configuration' ) ) )
|
||||
{
|
||||
$form->addtab( 'content_block_form_tab__feed' );
|
||||
$this->widget()->configuration( $form );
|
||||
}
|
||||
}
|
||||
|
||||
$form->addtab( 'content_block_form_tab__content');
|
||||
|
||||
if ( $block_type === 'plugin' )
|
||||
{
|
||||
$form->addHtml( \IPS\Theme::i()->getTemplate( 'blocks', 'cms', 'admin' )->previewBlock() );
|
||||
|
||||
$templates = array( '_default_' => \IPS\Member::loggedIn()->language()->addToStack('content_block_template_use_default') );
|
||||
|
||||
foreach( \IPS\cms\Templates::getTemplates( \IPS\cms\Templates::RETURN_BLOCK ) as $id => $obj )
|
||||
{
|
||||
if ( $obj->group == $this->widget()->key )
|
||||
{
|
||||
$templates[ $obj->key ] = $obj->title;
|
||||
}
|
||||
}
|
||||
|
||||
/* List of templates */
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'block_template_id', ( $this->id and $this->template ) ? $this->template : NULL, FALSE, array(
|
||||
'options' => $templates
|
||||
), NULL, NULL, \IPS\Theme::i()->getTemplate( 'blocks', 'cms', 'admin' )->previewTemplateLink( $block_plugin ), 'block_template_id' ) );
|
||||
|
||||
/* Use or copy to edit */
|
||||
$useHow = NULL;
|
||||
if ( $this->id )
|
||||
{
|
||||
if ( intval( $this->template ) or ( ! intval( $this->template ) and ! $this->content ) )
|
||||
{
|
||||
$useHow = 'use';
|
||||
}
|
||||
else
|
||||
{
|
||||
$useHow = 'copy';
|
||||
}
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'block_template_use_how', $useHow, FALSE, array(
|
||||
'options' => array(
|
||||
'use' => 'block_template_use_how_use',
|
||||
'copy' => 'block_template_use_how_copy'
|
||||
),
|
||||
'toggles' => array(
|
||||
'copy' => array( 'block_content', 'block_save_as_template' )
|
||||
)
|
||||
), NULL, NULL, NULL, 'block_template_use_how' ) );
|
||||
}
|
||||
|
||||
if ( $block_editor === 'editor' )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'block_content', $this->content, FALSE, array(
|
||||
'app' => 'cms',
|
||||
'key' => 'BlockContent',
|
||||
'autoSaveKey' => 'block-content-' . ( $this->id ? $this->id : 'new' ) ), NULL, NULL, NULL, 'block_content_editor' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Codemirror( 'block_content', $this->content, FALSE, array(), NULL, NULL, NULL, 'block_content' ) );
|
||||
}
|
||||
|
||||
if ( $block_type === 'plugin' and ! $this->id )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'block_save_as_template', FALSE, FALSE, array(
|
||||
'togglesOn' => array( 'block_save_as_template_name' )
|
||||
), NULL, NULL, NULL, 'block_save_as_template' ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'block_save_as_template_name', NULL, FALSE, array(), NULL, NULL, NULL, 'block_save_as_template_name' ) );
|
||||
}
|
||||
|
||||
if ( $block_type === 'custom' )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'block_cache', ( $this->id ) ? $this->cache : FALSE, FALSE, array(), NULL, NULL, NULL, 'block_cache' ) );
|
||||
}
|
||||
|
||||
$form->hiddenValues['block_type'] = $block_type;
|
||||
$form->hiddenValues['block_editor'] = $block_editor;
|
||||
$form->hiddenValues['block_plugin'] = $this->plugin;
|
||||
if ( $this->plugin_app )
|
||||
{
|
||||
$form->hiddenValues['block_plugin_app']= $this->plugin_app;
|
||||
}
|
||||
if ( $this->plugin_plugin )
|
||||
{
|
||||
$form->hiddenValues['block_plugin_plugin']= $this->plugin_plugin;
|
||||
}
|
||||
$form->hiddenValues['template_params'] = ( $this->id ) ? $this->template_params : '';
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'templates/view.css', 'cms', 'admin' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'blocks/form.css', 'cms', 'admin' ) );
|
||||
|
||||
\IPS\Output::i()->globalControllers[] = 'cms.admin.blocks.form';
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_blocks.js', 'cms' ) );
|
||||
\IPS\Output::i()->title = ( $this->id ) ? \IPS\Member::loggedIn()->language()->addToStack('content_block_block_editing', NULL, array( 'sprintf' => array( $this->_title ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('content_block_block_add');
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Format form values from add/edit form for save
|
||||
*
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
{
|
||||
if ( ! $this->id )
|
||||
{
|
||||
$this->active = 1;
|
||||
$this->save();
|
||||
|
||||
if ( \IPS\Request::i()->block_editor === 'editor' )
|
||||
{
|
||||
\IPS\File::claimAttachments( 'block-content/block-' . $this->id, $this->id );
|
||||
}
|
||||
}
|
||||
|
||||
$config = array();
|
||||
|
||||
if( isset( $values['block_name'] ) )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'cms', "content_block_name_" . $this->id, $values['block_name'] );
|
||||
}
|
||||
|
||||
if( isset( $values['block_description'] ) )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'cms', "content_block_name_" . $this->id . '_desc', $values['block_description'] );
|
||||
|
||||
unset ( $values['block_description'] );
|
||||
}
|
||||
|
||||
$this->type = \IPS\Request::i()->block_type;
|
||||
$values['type'] = $this->type;
|
||||
|
||||
if( isset( $values['block_key'] ) )
|
||||
{
|
||||
if ( ! $values['block_key'] )
|
||||
{
|
||||
if ( is_array( $values['block_name'] ) )
|
||||
{
|
||||
$values['block_key'] = \IPS\Http\Url::seoTitle( $values['block_name'][ key( $values['block_name'] ) ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['block_key'] = \IPS\Http\Url::seoTitle( $values['block_name'] );
|
||||
}
|
||||
|
||||
/* Now test it */
|
||||
try
|
||||
{
|
||||
$block = \IPS\cms\Blocks\Block::load( $this->key, 'block_key');
|
||||
|
||||
/* It's taken... */
|
||||
if ( $this->id != $block->id )
|
||||
{
|
||||
$values['block_key'] .= '_' . uniqid();
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
/* Doesn't exist? Good! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->block_type === 'plugin' )
|
||||
{
|
||||
$values['plugin_app'] = \IPS\Request::i()->block_plugin_app;
|
||||
|
||||
/* configure widget related values */
|
||||
if ( is_callable( array( $this->widget(), 'preConfig' ) ) )
|
||||
{
|
||||
$values = $this->widget()->preConfig( $values );
|
||||
}
|
||||
|
||||
/* Store config */
|
||||
foreach( $values as $k => $v )
|
||||
{
|
||||
if ( ! in_array( $k, array( 'block_name', 'block_key', 'block_description', 'block_category', 'block_template_id', 'block_template_use_how', 'block_content', 'block_save_as_template', 'block_save_as_template_name' ) ) )
|
||||
{
|
||||
if ( is_array( $v ) )
|
||||
{
|
||||
$theValue = NULL;
|
||||
foreach( $v as $eachKey => $eachValue )
|
||||
{
|
||||
if ( !( $eachValue instanceof \IPS\Node\Model ) AND $eachValue instanceof \IPS\Patterns\ActiveRecord )
|
||||
{
|
||||
$column = $eachValue::$databaseColumnId;
|
||||
$theValue[] = $eachValue->$column;
|
||||
}
|
||||
elseif( $eachValue instanceof \IPS\Node\Model )
|
||||
{
|
||||
$theValue[ $eachKey ] = $eachValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$theValue[] = $eachValue;
|
||||
}
|
||||
}
|
||||
$v = $theValue;
|
||||
}
|
||||
else if ( !( $v instanceof \IPS\Node\Model ) AND $v instanceof \IPS\Patterns\ActiveRecord )
|
||||
{
|
||||
$column = $v::$databaseColumnId;
|
||||
$v = $v->$column;
|
||||
}
|
||||
else if ( $v instanceof \IPS\Http\Url )
|
||||
{
|
||||
$v = (string) $v;
|
||||
}
|
||||
|
||||
$config[ $k ] = $v;
|
||||
|
||||
unset( $values[ $k ] );
|
||||
}
|
||||
}
|
||||
|
||||
$values['plugin'] = \IPS\Request::i()->block_plugin;
|
||||
$values['plugin_config'] = json_encode( $config );
|
||||
|
||||
/* Are we using the template as-is? */
|
||||
if ( $values['block_template_use_how'] === 'use' )
|
||||
{
|
||||
$values['content'] = null;
|
||||
|
||||
/* Not using default? */
|
||||
if ( $values['block_template_id'] != '_default_' )
|
||||
{
|
||||
$values['template'] = $values['block_template_id'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['template'] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We're using a copy */
|
||||
if ( isset( $values['block_save_as_template'] ) AND $values['block_save_as_template'] )
|
||||
{
|
||||
if ( $values['block_template_id'] == '_default_' )
|
||||
{
|
||||
/* Find it from the normal template system */
|
||||
$plugin = $this->widget();
|
||||
|
||||
$location = $plugin->getTemplateLocation();
|
||||
|
||||
$templateBits = \IPS\Theme::master()->getRawTemplates( $location['app'], $location['location'], $location['group'], \IPS\Theme::RETURN_ALL );
|
||||
$templateBit = $templateBits[ $location['app'] ][ $location['location'] ][ $location['group'] ][ $location['name'] ];
|
||||
|
||||
$templateArray = array(
|
||||
'key' => 'template_' . $templateBit['template_name'] . '.' . uniqid(),
|
||||
'title' => str_replace( '-', '_', \IPS\Http\Url::seoTitle( $values['block_save_as_template_name'] ? $values['block_save_as_template_name'] : $templateBit['template_name'] . '_' . \IPS\Member::loggedIn()->language()->get('copy_noun') ) ),
|
||||
'desc' => null,
|
||||
'content' => $values['block_content'],
|
||||
'location' => 'block',
|
||||
'group' => \IPS\Request::i()->block_plugin,
|
||||
'container' => null,
|
||||
'rel_id' => 0,
|
||||
'user_created' => 1,
|
||||
'user_edited' => 0,
|
||||
'params' => $templateBit['template_data']
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
$template = \IPS\cms\Templates::load( $values['block_template_id'] );
|
||||
|
||||
$templateArray = array(
|
||||
'key' => 'template_' . $template->name . '.' . uniqid(),
|
||||
'title' => str_replace( '-', '_', \IPS\Http\Url::seoTitle( $values['block_save_as_template_name'] ? $values['block_save_as_template_name'] : $template->name . '_' . \IPS\Member::loggedIn()->language()->get('copy_noun') ) ),
|
||||
'desc' => null,
|
||||
'content' => $values['block_content'],
|
||||
'location' => 'block',
|
||||
'group' => \IPS\Request::i()->block_plugin,
|
||||
'container' => null,
|
||||
'rel_id' => 0,
|
||||
'user_created' => 1,
|
||||
'user_edited' => 0,
|
||||
'params' => $template->params
|
||||
);
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
throw new \LogicException('cms_error_no_template_found');
|
||||
}
|
||||
}
|
||||
|
||||
/* Save */
|
||||
$newTemplate = \IPS\cms\Templates::add( $templateArray );
|
||||
|
||||
$values['content'] = null;
|
||||
$values['template'] = $newTemplate->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just use it this once */
|
||||
$values['content'] = $values['block_content'];
|
||||
$values['template'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( isset( $values['block_content'] ) )
|
||||
{
|
||||
$values['template'] = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['block_category'] ) AND ( ! empty( $values['block_category'] ) OR $values['block_category'] === 0 ) )
|
||||
{
|
||||
$values['block_category'] = ( $values['block_category'] === 0 ) ? 0 : $values['block_category'];
|
||||
|
||||
if( isset( $values['block_category'] ) AND $values['block_category'] instanceof \IPS\Node\Model )
|
||||
{
|
||||
$values['block_category'] = $values['block_category']->_id;
|
||||
}
|
||||
}
|
||||
|
||||
if( isset( \IPS\Request::i()->template_params ) )
|
||||
{
|
||||
$values['template_params'] = \IPS\Request::i()->template_params;
|
||||
}
|
||||
|
||||
/* Config */
|
||||
if( isset( \IPS\Request::i()->block_editor ) )
|
||||
{
|
||||
$this->setConfig( 'editor', \IPS\Request::i()->block_editor );
|
||||
}
|
||||
|
||||
foreach( array( 'block_name', 'block_description', 'block_save_as_template', 'block_template_id', 'block_template_use_how', 'block_save_as_template_name', 'block_editor', 'block_plugin_app', 'block_plugin' ) as $field )
|
||||
{
|
||||
if ( array_key_exists( $field, $values ) )
|
||||
{
|
||||
unset( $values[ $field ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
if ( $this->_config !== NULL )
|
||||
{
|
||||
$this->config = json_encode( $this->_config );
|
||||
}
|
||||
|
||||
if ( $this->id )
|
||||
{
|
||||
static::deleteCompiled( $this->id );
|
||||
\IPS\cms\Widget::deleteCachesForBlocks( $this->key );
|
||||
}
|
||||
|
||||
parent::save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the widget object associated with this custom block
|
||||
*
|
||||
* @return \IPS\Widget
|
||||
*/
|
||||
public function widget()
|
||||
{
|
||||
if ( $this->type === 'plugin' AND $this->plugin )
|
||||
{
|
||||
if ( mb_substr( $this->plugin, 0, 8 ) === 'db_feed_' )
|
||||
{
|
||||
$this->plugin = 'RecordFeed';
|
||||
}
|
||||
|
||||
if ( ! $this->widgetLoaded )
|
||||
{
|
||||
$this->widgetLoaded = \IPS\Widget::load( $this->plugin_app ? \IPS\Application::load( $this->plugin_app ) : \IPS\Plugin::load( $this->plugin_plugin ), $this->plugin, uniqid(), $this->_plugin_config, NULL, $this->orientation );
|
||||
}
|
||||
|
||||
return $this->widgetLoaded;
|
||||
}
|
||||
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Block Container Model
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @since 19 Feb 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\cms\Blocks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Block Container Model
|
||||
*/
|
||||
class _Container extends \IPS\Node\Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Table
|
||||
*/
|
||||
public static $databaseTable = 'cms_containers';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'container_';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] ID Database Column
|
||||
*/
|
||||
public static $databaseColumnId = 'id';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Database ID Fields
|
||||
*/
|
||||
protected static $databaseIdFields = array('container_key');
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent ID Database Column
|
||||
*/
|
||||
public static $databaseColumnParent = 'parent_id';
|
||||
|
||||
/**
|
||||
* @brief [Node] Parent ID Root Value
|
||||
* @note This normally doesn't need changing though some legacy areas use -1 to indicate a root node
|
||||
*/
|
||||
public static $databaseColumnParentRootValue = 0;
|
||||
|
||||
/**
|
||||
* @brief [Node] Order Database Column
|
||||
*/
|
||||
public static $databaseColumnOrder = 'order';
|
||||
|
||||
/**
|
||||
* @brief [Node] Node Title
|
||||
*/
|
||||
public static $nodeTitle = '';
|
||||
|
||||
/**
|
||||
* @brief [Node] Subnode class
|
||||
*/
|
||||
public static $subnodeClass = 'IPS\cms\Blocks\Block';
|
||||
|
||||
/**
|
||||
* @brief [Node] Show forms modally?
|
||||
*/
|
||||
public static $modalForms = TRUE;
|
||||
|
||||
/**
|
||||
* @brief [Node] Sortable?
|
||||
*/
|
||||
public static $nodeSortable = TRUE;
|
||||
|
||||
/**
|
||||
* [Node] Get Title
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function get__title()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch All Root Nodes
|
||||
*
|
||||
* @param string|NULL $permissionCheck The permission key to check for or NULl to not check permissions
|
||||
* @param \IPS\Member|NULL $member The member to check permissions for or NULL for the currently logged in member
|
||||
* @param mixed $where Additional WHERE clause
|
||||
* @return array
|
||||
*/
|
||||
public static function roots( $permissionCheck='view', $member=NULL, $where=array() )
|
||||
{
|
||||
return parent::roots( $permissionCheck, $member, array( array('container_type=?', 'block' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Get buttons to display in tree
|
||||
* Example code explains return value
|
||||
* @endcode
|
||||
* @param string $url Base URL
|
||||
* @param bool $subnode Is this a subnode?
|
||||
* @return array
|
||||
*/
|
||||
public function getButtons( $url, $subnode=FALSE )
|
||||
{
|
||||
$buttons = parent::getButtons( $url, $subnode );
|
||||
$return = array();
|
||||
|
||||
if ( isset( $buttons['copy'] ) )
|
||||
{
|
||||
unset( $buttons['copy'] );
|
||||
}
|
||||
|
||||
if ( isset( $buttons['add'] ) )
|
||||
{
|
||||
$buttons['add']['icon'] = 'folder-open';
|
||||
$buttons['add']['title'] = 'content_block_cat_add';
|
||||
$buttons['add']['data'] = array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('content_block_cat_add') );
|
||||
$buttons['add']['link'] = $url->setQueryString( array( 'subnode' => 0, 'do' => 'form', 'parent' => $this->_id ) );
|
||||
|
||||
$buttons['add_block'] = array(
|
||||
'icon' => 'plus-circle',
|
||||
'title' => 'content_block_block_add',
|
||||
'link' => $url->setQueryString( array( 'subnode' => 1, 'do' => 'addBlockType', 'parent' => $this->_id ) )
|
||||
);
|
||||
}
|
||||
|
||||
/* Re-arrange */
|
||||
if ( isset( $buttons['edit'] ) )
|
||||
{
|
||||
$return['edit'] = $buttons['edit'];
|
||||
}
|
||||
|
||||
if ( isset( $buttons['add_block'] ) )
|
||||
{
|
||||
$return['add_block'] = $buttons['add_block'];
|
||||
}
|
||||
|
||||
if ( isset( $buttons['add'] ) )
|
||||
{
|
||||
$return['add'] = $buttons['add'];
|
||||
}
|
||||
|
||||
if ( isset( $buttons['delete'] ) )
|
||||
{
|
||||
$return['delete'] = $buttons['delete'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Does the currently logged in user have permission to delete this node?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canDelete()
|
||||
{
|
||||
if ( $this->key == 'block_custom' OR $this->key == 'block_plugins' )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return parent::canDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Add/Edit Form
|
||||
*
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @return void
|
||||
*/
|
||||
public function form( &$form )
|
||||
{
|
||||
/* Build form */
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'container_name', $this->id ? $this->name : '', TRUE, array( 'maxLength' => 64 ) ) );
|
||||
|
||||
$class = get_called_class();
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'container_parent_id', $this->parent_id ? $this->parent_id : 0, FALSE, array(
|
||||
'class' => '\IPS\cms\Blocks\Container',
|
||||
'zeroVal' => 'node_no_parent',
|
||||
'permissionCheck' => function( $node ) use ( $class )
|
||||
{
|
||||
if( isset( $class::$subnodeClass ) AND $class::$subnodeClass AND $node instanceof $class::$subnodeClass )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return !isset( \IPS\Request::i()->id ) or ( $node->id != \IPS\Request::i()->id and !$node->isChildOf( $node::load( \IPS\Request::i()->id ) ) );
|
||||
}
|
||||
) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Format form values from add/edit form for save
|
||||
*
|
||||
* @param array $values Values from the form
|
||||
* @return array
|
||||
*/
|
||||
public function formatFormValues( $values )
|
||||
{
|
||||
if ( isset( $values['container_parent_id'] ) AND ( ! empty( $values['container_parent_id'] ) OR $values['container_parent_id'] === 0 ) )
|
||||
{
|
||||
$values['container_parent_id'] = ( $values['container_parent_id'] === 0 ) ? 0 : $values['container_parent_id']->id;
|
||||
}
|
||||
|
||||
$values['type'] = 'block';
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search
|
||||
*
|
||||
* @param string $column Column to search
|
||||
* @param string $query Search query
|
||||
* @param string|null $order Column to order by
|
||||
* @param mixed $where Where clause
|
||||
* @return array
|
||||
*/
|
||||
public static function search( $column, $query, $order, $where=array() )
|
||||
{
|
||||
if ( $column === '_title' )
|
||||
{
|
||||
$column = 'container_name';
|
||||
}
|
||||
|
||||
$where = array( array( 'container_type=?', 'block' ) );
|
||||
|
||||
return parent::search( $column, $query, 'container_name ASC', $where );
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
Reference in new issue
Block a user