Version 4.2.0

This commit is contained in:
Neo committed 2025-12-19 05:44:59 -08:00
1 parent 0dc2aee5ed
commit 96997ddd8e
2074 files changed
+125454 -55780

No files matched your search

+119
View File
@@ -0,0 +1,119 @@
<?php
/**
* @brief Base API endpoint for Nodes
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 3 Apr 2017
*/
namespace IPS\Node\Api;
/* 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 Base API endpoint for Nodes
*/
class _NodeController extends \IPS\Api\Controller
{
/**
* List
*
* @param array $where Extra WHERE clause
* @return \IPS\Api\PaginatedResponse
*/
protected function _list( $where = array() )
{
$class = $this->class;
/* Return */
return new \IPS\Api\PaginatedResponse(
200,
\IPS\Db::i()->select( '*', $class::$databaseTable, $where, $class::$databaseColumnOrder ? $class::$databaseColumnOrder . " asc" : NULL ),
isset( \IPS\Request::i()->page ) ? \IPS\Request::i()->page : 1,
$class,
\IPS\Db::i()->select( 'COUNT(*)', $class::$databaseTable, $where )->first()
);
}
/**
* View
*
* @param int $id ID Number
* @return \IPS\Api\Response
*/
protected function _view( $id )
{
$class = $this->class;
return new \IPS\Api\Response( 200, $class::load( $id )->apiOutput() );
}
/**
* View
*
* @param int $id ID Number
* @throws 1S359/1 INVALID_ID The member ID does not exist
* @return \IPS\Api\Response
*/
protected function _delete( $id )
{
$class = $this->class;
try
{
$class::load( $id )->delete();
return new \IPS\Api\Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '1S359/1', 404 );
}
}
/**
* Create or update node
*
* @param \IPS\node\Model $node The node
* @return \IPS\node\Model
*/
protected function _createOrUpdate( \IPS\node\Model $node )
{
$node->save();
/* Return */
return $node;
}
/**
* Create
*
* @return \IPS\Content\Node
*/
protected function _create()
{
$class = $this->class;
/* Create item */
$node = new $class;
if( isset( $node::$databaseColumnOrder ) AND $node::$automaticPositionDetermination === TRUE )
{
$orderColumn = $node::$databaseColumnOrder;
$node->$orderColumn = \IPS\Db::i()->select( 'MAX(' . $node::$databasePrefix . $orderColumn . ')', $node::$databaseTable )->first() + 1;
}
$node->save();
$node = $this->_createOrUpdate( $node );
/* Output */
return $node;
}
}
+162
View File
@@ -0,0 +1,162 @@
<?php
/**
* @brief Colorize Node Titles Trait
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 5 April 2017
*/
namespace IPS\Node;
/* 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;
}
/**
* Colorize Trait
*/
trait Colorize
{
/**
* @brief Table column name that holds the feature color hex
*/
public static $featureColumnName = 'feature_color';
/**
* @brief Cache the calculated formatted title for this node
*/
protected $formattedTitle = NULL;
/**
* @brief Cache the formatted text colour for this node
*/
protected $featureTextColor = NULL;
/**
* Get HTML formatted title. Allows apps or nodes to format the title, such as adding different colours, etc
*
* @return string
*/
public function get__formattedTitle()
{
if ( $this->formattedTitle === NULL )
{
$columnName = static::$featureColumnName;
if ( ! $this->$columnName )
{
$this->formattedTitle = $this->_title;
}
else
{
$this->formattedTitle = \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->formattedTitle( $this );
}
}
return $this->formattedTitle;
}
/**
* Get the featured text color for use in CSS
*
* @return string
*/
public function get__featureTextColor()
{
if ( $this->featureTextColor === NULL )
{
if ( ! $this->feature_color )
{
return NULL;
}
else
{
$columnName = static::$featureColumnName;
$this->featureTextColor = static::featureTextColor( $this->$columnName );
}
}
return $this->featureTextColor;
}
/**
* Static method to fetch the text colour based on the the contrast from the background color
*
* @return string
*/
public static function featureTextColor( $featureColor )
{
$hexColor = str_replace( '#', '', $featureColor );
$blackColor = '000000';
$textColor = '#ffffff';
/* Use luminosity contrast algorithm to determine font color */
$r1 = hexdec( \substr( $hexColor, 0, 2 ) );
$g1 = hexdec( \substr( $hexColor, 2, 2 ) );
$b1 = hexdec( \substr( $hexColor, 4, 2 ) );
$r2 = hexdec( \substr( $blackColor, 0, 2 ) );
$g2 = hexdec( \substr( $blackColor, 2, 2 ) );
$b2 = hexdec( \substr( $blackColor, 4, 2 ) );
$l1 = 0.2126 * pow( $r1 / 255, 2.2 ) + 0.7152 * pow( $g1 / 255, 2.2 ) + 0.0722 * pow( $b1 / 255, 2.2 );
$l2 = 0.2126 * pow( $r2 / 255, 2.2 ) + 0.7152 * pow( $g2 / 255, 2.2 ) + 0.0722 * pow( $b2 / 255, 2.2 );
$contrastRatio = 0;
if ( $l1 > $l2 )
{
$contrastRatio = (int) ( ( $l1 + 0.05 ) / ( $l2 + 0.05 ) );
}
else
{
$contrastRatio = (int) ( ( $l2 + 0.05 ) / ( $l1 + 0.05 ) );
}
if ( $contrastRatio > 5 )
{
$textColor = '#000000';
}
return $textColor;
}
/**
* Get URL from index data
*
* @param array $indexData Data from the search index
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
* @return \IPS\Http\Url
*/
public static function titleFromIndexData( $indexData, $itemData, $containerData )
{
if ( ! isset( $containerData[ static::$featureColumnName ] ) )
{
return parent::titleFromIndexData( $indexData, $itemData, $containerData );
}
$node = $containerData;
$node['title'] = \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $indexData['index_container_id'], 'NULL', array( 'escape' => true ) );
$node['text_color'] = static::featureTextColor( $node[ static::$featureColumnName ] );
/* Normalize */
$node['feature_color'] = $node[ static::$featureColumnName ];
$title = \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->formattedTitle( $node );
if ( $indexData['index_club_id'] and isset( $containerData['_club'] ) )
{
return \IPS\Member::loggedIn()->language()->addToStack( 'club_container_title', FALSE, array( 'htmlsprintf' => array( $containerData['_club']['name'], $title ) ) );
}
else
{
return $title;
}
}
}
+209 -11
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Node Controller
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Node;
@@ -121,12 +120,21 @@ class _Controller extends \IPS\Dispatcher\Controller
if ( $nodeClass::canAddRoot() )
{
return array( 'add' => array(
$add = array(
'icon' => 'plus',
'title' => 'add',
'link' => $this->url->setQueryString( 'do', 'form' ),
'data' => ( $nodeClass::$modalForms ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('add') ) : array() )
) );
);
if ( \IPS\Request::i()->isAjax() )
{
return array( 'add' => $add );
}
else
{
\IPS\Output::i()->sidebar['actions']['add'] = ( array( 'primary' => true ) + $add );
}
}
return array();
}
@@ -270,7 +278,7 @@ class _Controller extends \IPS\Dispatcher\Controller
/* Load the node being edited */
try
{
$node = call_user_func( "{$nodeClass}::load", \IPS\Request::i()->id );
$node = $nodeClass::load( \IPS\Request::i()->id );
\IPS\Output::i()->title = $node->_title;
}
catch ( \OutOfRangeException $e )
@@ -368,7 +376,7 @@ class _Controller extends \IPS\Dispatcher\Controller
try
{
$new = !$node->_id;
if ( $new and isset( $node::$databaseColumnOrder ) )
if ( $new and isset( $node::$databaseColumnOrder ) AND $node::$automaticPositionDetermination === TRUE )
{
$orderColumn = $node::$databaseColumnOrder;
$node->$orderColumn = \IPS\Db::i()->select( 'MAX(' . $node::$databasePrefix . $orderColumn . ')', $node::$databaseTable )->first() + 1;
@@ -1181,10 +1189,10 @@ class _Controller extends \IPS\Dispatcher\Controller
/* Do we have any children or content? */
if ( $node->hasChildren( NULL, NULL, TRUE ) or $node->showDeleteOrMoveForm() )
{
$form = $node->deleteOrMoveForm();
$form = $node->deleteOrMoveForm( FALSE, TRUE );
if ( $values = $form->values() )
{
$node->deleteOrMoveFormSubmit( $values, \IPS\Request::i()->deleteNode );
$node->deleteOrMoveFormSubmit( $values );
\IPS\Output::i()->redirect( $this->url->setQueryString( array( 'root' => ( $node->parent() ? $node->parent()->_id : '' ) ) ), 'deleted' );
}
else
@@ -1221,6 +1229,196 @@ class _Controller extends \IPS\Dispatcher\Controller
}
}
/**
* Mass Move/Delete Content
*
* @return void
*/
protected function massManageContent()
{
/* Get node */
$nodeClass = $this->nodeClass;
if ( \IPS\Request::i()->subnode )
{
$nodeClass = $nodeClass::$subnodeClass;
}
try
{
$node = call_user_func( "{$nodeClass}::load", \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2S101/X', 404, '' );
}
/* Permission check */
if( !$node->canMassManageContent() )
{
\IPS\Output::i()->error( 'node_noperm_delete', '2S101/Y', 403, '' );
}
/* Is there any content? */
if ( !isset( $nodeClass::$contentItemClass ) or !$node->getContentItemCount() )
{
\IPS\Output::i()->error( 'node_mass_content_none', '2S101/Z' );
}
$contentItemClass = $nodeClass::$contentItemClass;
/* Build Wizard */
\IPS\Output::i()->title = $node->_title;
\IPS\Output::i()->output = new \IPS\Helpers\Wizard(
array(
'node_mass_content_form' => function( $data ) use( $nodeClass, $node, $contentItemClass )
{
/* Build Form */
$form = new \IPS\Helpers\Form( 'delete_node_form', 'continue', $this->url->setQueryString( array( 'do' => 'massManageContent', 'id' => $node->_id, '_step' => 'node_mass_content_form' ) ) );
$form->addHeader('node_mass_move_delete_if');
$form->add( new \IPS\Helpers\Form\Member( 'node_move_author', isset( $data['additional']['author'] ) ? array_map( function( $id ) {
return \IPS\Member::load( $id );
}, $data['additional']['author'] ) : NULL, FALSE, array( 'nullLang' => 'node_mass_move_anyone', 'multiple' => NULL ) ) );
$form->add( new \IPS\Helpers\Form\Date( 'node_move_date', isset( $data['additional']['date'] ) ? $data['additional']['date'] : 0, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'node_mass_move_any_time' ) ) );
if ( isset( $contentItemClass::$commentClass ) )
{
$form->add( new \IPS\Helpers\Form\Number( 'node_move_comments', isset( $data['additional']['num_comments'] ) ? $data['additional']['num_comments'] : -1, FALSE, array( 'unlimited' => -1 ), NULL, NULL, NULL, 'node_move_comments_less' ) );
$form->add( new \IPS\Helpers\Form\Date( 'node_move_last_post', isset( $data['additional']['last_post'] ) ? $data['additional']['last_post'] : 0, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'node_mass_move_any_time' ) ) );
}
if ( in_array( 'IPS\Content\Lockable', class_implements( $contentItemClass ) ) )
{
$form->add( new \IPS\Helpers\Form\Radio( 'node_move_state', isset( $data['additional']['state'] ) ? $data['additional']['state'] : 'any', FALSE, array( 'options' => array( 'locked' => 'locked', 'open' => 'unlocked', 'any' => 'node_mass_move_either' ) ) ) );
}
if ( in_array( 'IPS\Content\Pinnable', class_implements( $contentItemClass ) ) )
{
$form->add( new \IPS\Helpers\Form\Radio( 'node_move_pinned', isset( $data['additional']['pinned'] ) ? $data['additional']['pinned'] : 'any', FALSE, array( 'options' => array( '1' => 'pinned', '0' => 'node_move_pinned_not_pinned', 'any' => 'node_mass_move_either' ) ) ) );
}
if ( in_array( 'IPS\Content\Featurable', class_implements( $contentItemClass ) ) )
{
$form->add( new \IPS\Helpers\Form\Radio( 'node_move_featured', isset( $data['additional']['featured'] ) ? $data['additional']['featured'] : 'any', FALSE, array( 'options' => array( '1' => 'featured', '0' => 'node_move_pinned_not_featured', 'any' => 'node_mass_move_either' ) ) ) );
}
$form->addHeader('node_mass_move_delete_then');
$form->add( new \IPS\Helpers\Form\Node( 'node_move_content', isset( $data['moveTo'] ) ? call_user_func( array( $data['moveToClass'], 'load' ), $data['moveTo'] ) : 0, TRUE, array( 'class' => $nodeClass, 'disabled' => array( $node->_id ), 'disabledLang' => 'node_move_delete', 'zeroVal' => 'node_delete_content', 'subnodes' => FALSE, 'permissionCheck' => function( $node )
{
return array_key_exists( 'add', $node->permissionTypes() );
} ) ) );
/* Handle submissions */
if ( $values = $form->values() )
{
$data['deleteWhenDone'] = FALSE;
$data['class'] = get_class( $node );
$data['id'] = $node->_id;
if ( is_object( $values['node_move_content'] ) )
{
$data['moveToClass'] = get_class( $values['node_move_content'] );
$data['moveTo'] = $values['node_move_content']->_id;
}
else
{
unset( $data['moveToClass'] );
unset( $data['moveTo'] );
}
if ( count( $values['node_move_author'] ) )
{
$data['additional']['author'] = array_keys( $values['node_move_author'] );
}
else
{
unset( $data['additional']['author'] );
}
if ( $values['node_move_date'] )
{
$data['additional']['date'] = $values['node_move_date']->setTime( 23, 59, 59 )->getTimestamp();
}
else
{
unset( $data['additional']['date'] );
}
if ( isset( $values['node_move_comments'] ) and $values['node_move_comments'] > -1 )
{
$data['additional']['num_comments'] = $values['node_move_comments'];
}
else
{
unset( $data['additional']['num_comments'] );
}
if ( isset( $values['node_move_last_post'] ) and $values['node_move_last_post'] )
{
$data['additional']['last_post'] = $values['node_move_last_post']->setTime( 23, 59, 59 )->getTimestamp();
}
else
{
unset( $data['additional']['last_post'] );
}
if ( isset( $values['node_move_state'] ) and $values['node_move_state'] != 'any' )
{
$data['additional']['state'] = $values['node_move_state'];
}
else
{
unset( $data['additional']['state'] );
}
if ( isset( $values['node_move_pinned'] ) and $values['node_move_pinned'] != 'any' )
{
$data['additional']['pinned'] = $values['node_move_pinned'];
}
else
{
unset( $data['additional']['pinned'] );
}
if ( isset( $values['node_move_featured'] ) and $values['node_move_featured'] != 'any' )
{
$data['additional']['featured'] = $values['node_move_featured'];
}
else
{
unset( $data['additional']['featured'] );
}
return $data;
}
/* Display Form */
return (string) $form;
},
'node_mass_content_confirm' => function( $data ) use ( $node, $contentItemClass )
{
if ( isset( \IPS\Request::i()->confirm ) )
{
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', $data );
if ( isset( $data['moveTo'] ) )
{
$newNode = $data['moveToClass']::load( $data['moveTo'] );
\IPS\Session::i()->log( 'acplog__node_mass_move', array( $this->title => TRUE, $node->titleForLog() => FALSE, $newNode->titleForLog() => FALSE ) );
\IPS\Output::i()->redirect( $this->url->setQueryString( array( 'root' => ( $node->parent() ? $node->parent()->_id : '' ) ) ), 'node_mass_content_moving' );
}
else
{
\IPS\Session::i()->log( 'acplog__node_mass_delete', array( $this->title => TRUE, $node->titleForLog() => FALSE ) );
\IPS\Output::i()->redirect( $this->url->setQueryString( array( 'root' => ( $node->parent() ? $node->parent()->_id : '' ) ) ), 'node_mass_content_deleting' );
}
}
else
{
$number = $node->getContentItems( NULL, NULL, $node->massMoveorDeleteWhere( $data ), TRUE );
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->nodeMoveDeleteContent( $this->url->setQueryString( array( 'do' => 'massManageContent', 'id' => $node->_id ) ), \IPS\Member::loggedIn()->language()->addToStack( $contentItemClass::$title . '_pl_lc' ), $number, isset( $data['moveTo'] ) ? call_user_func( array( $data['moveToClass'], 'load' ), $data['moveTo'] ) : NULL );
}
}
),
$this->url->setQueryString( array( 'do' => 'massManageContent', 'id' => $node->_id ) )
);
}
/**
* Search
*
+393 -177
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Node Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Node;
@@ -41,6 +40,11 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
*/
public static $databaseColumnOrder = NULL;
/**
* @brief [Node] Automatically set position for new nodes
*/
public static $automaticPositionDetermination = TRUE;
/**
* @brief [Node] Enabled/Disabled Column
*/
@@ -103,13 +107,14 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
'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'
'add' => 'foo_add',
'edit' => 'foo_edit',
'permissions' => 'foo_perms',
'massManageContent' => 'foo_massManageContent',
'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"
'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/massManageContent/delete"
* @endcode
*/
protected static $restrictions = NULL;
@@ -131,40 +136,69 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
*/
public static function roots( $permissionCheck='view', $member=NULL, $where=array() )
{
/* Will we need to check permissions? */
$usingPermssions = ( in_array( 'IPS\Node\Permissions', class_implements( get_called_class() ) ) and $permissionCheck !== NULL );
if ( $usingPermssions )
{
$member = $member ?: \IPS\Member::loggedIn();
}
/* Have we got a cached result we can use? */
if ( $usingPermssions )
{
$cacheKey = md5( get_called_class() . $permissionCheck . $member->member_id . json_encode( $where ) );
}
else
{
$cacheKey = md5( get_called_class() . $permissionCheck . json_encode( $where ) );
}
/* Check the cache first */
if( !$where and isset( static::$rootsResult[ $cacheKey ] ) )
if( isset( static::$rootsResult[ $cacheKey ] ) )
{
return static::$rootsResult[ $cacheKey ];
}
/* Specify that we only want the ones without a parent */
if( static::$databaseColumnParent !== NULL )
{
$where[] = array( static::$databasePrefix . static::$databaseColumnParent . '=?', static::$databaseColumnParentRootValue );
}
/* Permission check? */
if ( $usingPermssions )
/* And aren't in clubs */
if ( \IPS\IPS::classUsesTrait( get_called_class(), 'IPS\Content\ClubContainer' ) )
{
$where[] = array( '(' . \IPS\Db::i()->findInSet( 'core_permission_index.perm_' . static::$permissionMap[ $permissionCheck ], $member->groups ) . ' OR ' . 'core_permission_index.perm_' . static::$permissionMap[ $permissionCheck ] . '=? )', '*' );
$where[] = array( static::$databasePrefix . static::clubIdColumn() . ' IS NULL' );
}
/* Fetch */
$nodes = static::nodesWithPermission( $usingPermssions ? $permissionCheck : NULL, $member, $where );
/* Set cache */
static::$rootsResult[ $cacheKey ] = $nodes;
/* Return */
return static::$rootsResult[ $cacheKey ];
}
/**
* 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
*/
protected static function nodesWithPermission( $permissionCheck, $member, $where=array() )
{
/* Permission check? */
if ( $permissionCheck )
{
$where[] = array( '(' . \IPS\Db::i()->findInSet( 'core_permission_index.perm_' . static::$permissionMap[ $permissionCheck ], $member->permissionArray() ) . ' OR ' . 'core_permission_index.perm_' . static::$permissionMap[ $permissionCheck ] . '=? )', '*' );
if ( static::$databaseColumnEnabledDisabled )
{
$where[] = array( static::$databasePrefix . static::$databaseColumnEnabledDisabled . '=1' );
}
}
/* Specify the order */
$order = NULL;
if( static::$databaseColumnOrder !== NULL )
@@ -174,8 +208,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
/* Select */
$select = \IPS\Db::i()->select( '*', static::$databaseTable, $where, $order );
if ( $usingPermssions )
if ( $permissionCheck )
{
$select->join( 'core_permission_index', array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . static::$databaseTable . "." . static::$databasePrefix . static::$databaseColumnId, static::$permApp, static::$permType ) );
}
@@ -191,12 +224,9 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
}
catch ( \Exception $e ) { }
}
/* Set cache */
static::$rootsResult[ $cacheKey ] = $nodes;
/* Return */
return static::$rootsResult[ $cacheKey ];
return $nodes;
}
/**
@@ -389,7 +419,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
$order = static::$databaseColumnOrder !== NULL ? static::$databasePrefix . static::$databaseColumnOrder : NULL;
if ( in_array( 'IPS\Node\Permissions', class_implements( get_called_class() ) ) and $permissionCheck !== NULL )
{
$where[] = array( '(' . \IPS\Db::i()->findInSet( 'perm_' . static::$permissionMap[ $permissionCheck ], $member->groups ) . ' OR ' . 'perm_' . static::$permissionMap[ $permissionCheck ] . '=? )', '*' );
$where[] = array( '(' . \IPS\Db::i()->findInSet( 'perm_' . static::$permissionMap[ $permissionCheck ], $member->permissionArray() ) . ' OR ' . 'perm_' . static::$permissionMap[ $permissionCheck ] . '=? )', '*' );
$select = \IPS\Db::i()->select( '*', static::$databaseTable, $where, $order, NULL, NULL, NULL, \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS )
->join( 'core_permission_index', array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . static::$databaseTable . "." . static::$databasePrefix . static::$databaseColumnId, static::$permApp, static::$permType ) );
@@ -426,7 +456,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
/* Put into tree */
$obj->_childrenResults[ $cacheKey ] = array();
if ( $row[ static::$databaseTable ][ static::$databasePrefix . static::$databaseColumnParent ] === static::$databaseColumnParentRootValue )
if ( static::$databaseColumnParent === NULL or $row[ static::$databaseTable ][ static::$databasePrefix . static::$databaseColumnParent ] === static::$databaseColumnParentRootValue )
{
static::$rootsResult[ $rootsCacheKey ][ $obj->_id ] = $obj;
}
@@ -473,7 +503,15 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
*/
public static function basicDataColumns()
{
return array( static::$databasePrefix . static::$databaseColumnId, static::$databasePrefix . static::$seoTitleColumn );
$return = array( static::$databasePrefix . static::$databaseColumnId, static::$databasePrefix . static::$seoTitleColumn );
/* Using colorize trait? We can't check the object but we can check the added class variable */
if ( isset( static::$featureColumnName ) )
{
$return[] = static::$featureColumnName;
}
return $return;
}
/**
@@ -499,20 +537,62 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
*/
public static function titleFromIndexData( $indexData, $itemData, $containerData )
{
return \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $indexData['index_container_id'] );
if ( $indexData['index_club_id'] and isset( $containerData['_club'] ) )
{
return \IPS\Member::loggedIn()->language()->addToStack( 'club_container_title', FALSE, array( 'sprintf' => array( $containerData['_club']['name'], \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $indexData['index_container_id'], 'NULL', array( 'escape' => true ) ) ) ) );
}
else
{
return \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $indexData['index_container_id'], 'NULL', array( 'escape' => true ) );
}
}
/* !Getters */
/**
* [Node] Get ID Number
* [Node] Fetches the only node if only one exists
* One Node to rule them all, One Node to find them, One Node to bring them all and in the darkness bind them
*
* @return int
* @param $properties Array of property=>value i.e. array( 'redirect_url' => FALSE, 'password' => FALSE );
* @param $returnRoots Enable to check and return the root node
* @param $subNodes Enable to check subnodes
* @return \IPS\Node\Model|NULL
*/
protected function get__id()
public static function theOnlyNode( $properties=array(), $returnRoots=TRUE, $subNodes=TRUE )
{
$idColumn = static::$databaseColumnId;
return $this->$idColumn;
if ( count( static::roots() ) === 1 )
{
foreach ( static::roots() as $root )
{
if ( $root->childrenCount( 'view', NULL, $subNodes ) === 1 )
{
foreach ( $root->children( 'view', NULL, $subNodes ) as $node )
{
/* Check properties */
foreach( $properties as $name => $bool )
{
if( $node->$name != $bool )
{
continue 2;
}
}
/* If we're just checking root objects, we don't want to return the child */
if( $returnRoots )
{
return NULL;
}
return $node;
}
}
/* There are no children */
elseif( $root->childrenCount( 'view', NULL, $subNodes ) === 0 and $returnRoots )
{
return $root;
}
}
}
return NULL;
}
/**
@@ -539,6 +619,19 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
}
}
/* !Getters */
/**
* [Node] Get ID Number
*
* @return int
*/
protected function get__id()
{
$idColumn = static::$databaseColumnId;
return $this->$idColumn;
}
/**
* [Node] Get Title
*
@@ -580,6 +673,16 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
}
return '';
}
/**
* Get HTML formatted title. Allows apps or nodes to format the title, such as adding different colours, etc
*
* @return string
*/
public function get__formattedTitle()
{
return $this->_title;
}
/**
* [Node] Get Node Description
@@ -952,7 +1055,6 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
$working = $this;
while ( $working = $working->parent() )
{
if( ! $working instanceof \IPS\Node\Model )
{
return $stack;
@@ -1223,24 +1325,23 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
);
}
if( $this->canMassManageContent() )
{
$buttons['content'] = array(
'icon' => 'arrow-right',
'title' => 'mass_manage_content',
'link' => $url->setQueryString( array( 'do' => 'massManageContent', 'id' => $this->_id, '_new' => 1 ) ),
'hotkey'=> 'm'
);
}
if( $this->canDelete() )
{
if ( isset( static::$contentItemClass ) AND $this->getContentItemCount() )
{
$buttons['empty'] = array(
'icon' => 'trash-o',
'title' => 'empty',
'link' => $url->setQueryString( array( 'do' => 'delete', 'id' => $this->_id, 'deleteNode' => 0 ) ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('empty') ),
'hotkey'=> 'd'
);
}
$buttons['delete'] = array(
'icon' => 'times-circle',
'title' => 'delete',
'link' => $url->setQueryString( array( 'do' => 'delete', 'id' => $this->_id, 'deleteNode' => 1 ) ),
'data' => ( $this->hasChildren( NULL, NULL, TRUE ) or ( isset( static::$contentItemClass ) AND $this->getContentItemCount() ) ) ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('delete') ) : array( 'delete' => '' ),
'link' => $url->setQueryString( array( 'do' => 'delete', 'id' => $this->_id ) ),
'data' => ( $this->hasChildren( NULL, NULL, TRUE ) or $this->showDeleteOrMoveForm() ) ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('delete') ) : array( 'delete' => '' ),
'hotkey'=> 'd'
);
}
@@ -1283,7 +1384,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
return FALSE;
}
return \IPS\Member::loggedIn()->hasAcpRestriction( static::$restrictions['app'], static::$restrictions['module'], $_key );
}
@@ -1391,6 +1492,31 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
return ( static::$permApp !== NULL and static::$permType !== NULL and static::restrictionCheck( 'permissions' ) );
}
/**
* [Node] Does the currently logged in user have permission to mass move/delete content in this node?
*
* @return bool
*/
public function canMassManageContent()
{
if ( !isset( static::$contentItemClass ) )
{
return FALSE;
}
if ( $this->deleteOrMoveQueued() === TRUE )
{
return FALSE;
}
if( static::restrictionCheck( 'massManageContent' ) )
{
return TRUE;
}
return FALSE;
}
/**
* [Node] Does the currently logged in user have permission to delete this node?
@@ -1777,7 +1903,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
'perm_view' => ''
) );
$this->_permissions = array( 'perm_id' => $permId, 'perm_view' => '' );
$this->_permissions = array( 'perm_id' => $permId, 'perm_view' => '', 'perm_2' => NULL, 'perm_3' => NULL, 'perm_4' => NULL, 'perm_5' => NULL, 'perm_6' => NULL, 'perm_7' => NULL );
}
}
return $this->_permissions;
@@ -1907,6 +2033,19 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
$level--;
}
}
/**
* Can View
*
* @param \IPS\Member|\IPS\Member\Group|NULL $member The member or group to check (NULL for currently logged in member)
* @return bool
* @throws \OutOfRangeException
* @note This is just a quick wrapper to brings things consistent between Content Items and Nodes for things like Reactions, which may support both
*/
public function canView( $member=NULL )
{
return $this->can( 'view', $member );
}
/**
* Check permissions
@@ -1995,10 +2134,39 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
return ( $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] === '*' or ( $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] and in_array( $member->g_id, explode( ',', $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] ) ) ) );
}
else
{
return ( $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] === '*' or ( $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] and $member->inGroup( explode( ',', $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] ) ) ) );
{
return ( $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] === '*' or ( $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] and array_intersect( explode( ',', $permissions[ 'perm_' . static::$permissionMap[ $permission ] ] ), $member->permissionArray() ) ) );
}
}
/**
* Check Moderator Permission
*
* @param string $type 'edit', 'hide', 'unhide', 'delete', etc.
* @param \IPS\Member|NULL $member The member to check for or NULL for the currently logged in member
* @return bool
*/
public function modPermission( $type, \IPS\Member $member )
{
if ( isset( static::$modPerm ) )
{
$itemClass = static::$contentItemClass;
$title = $itemClass::$title;
if ( $member->modPermission( "can_{$type}_{$title}" ) )
{
if ( $member->modPermission( static::$modPerm ) === -1 )
{
return TRUE;
}
if ( is_array( $member->modPermission( static::$modPerm ) ) and in_array( $this->_id, $member->modPermission( static::$modPerm ) ) )
{
return TRUE;
}
}
}
return FALSE;
}
/**
* @brief Disable the copy button - useful when the forms are very distinctly different
@@ -2034,6 +2202,102 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
}
}
}
/**
* Get where clause for a mass move/delete
*
* @param array|null $data Additional filters to mass move by
* @return array
*/
public function massMoveorDeleteWhere( $data=NULL )
{
$contentItemClass = static::$contentItemClass;
$where = array();
if ( isset( $data['additional'] ) AND count( $data['additional'] ) )
{
/* Author */
if ( isset( $data['additional']['author'] ) )
{
if ( is_array( $data['additional']['author'] ) )
{
if ( count( $data['additional']['author'] ) )
{
$where[] = array( \IPS\Db::i()->in( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['author'], $data['additional']['author'] ) );
}
}
else
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['author'] . '=?', $data['additional']['author'] );
}
}
/* Posted before */
if ( isset( $data['additional']['date'] ) AND $data['additional']['date'] )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['date'] . '<=?', $data['additional']['date'] );
}
/* Number of comments is less than */
if ( isset( $data['additional']['num_comments'] ) AND $data['additional']['num_comments'] > 0 )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['num_comments'].'<=?', $data['additional']['num_comments'] );
}
/* Last post was before */
$lastCommentField = $contentItemClass::$databaseColumnMap['last_comment'];
$field = is_array( $lastCommentField ) ? array_pop( $lastCommentField ) : $lastCommentField;
if ( isset( $data['additional']['no_comments'] ) AND $data['additional']['no_comments'] > 0 ) // Legacy, may still be in queue
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['num_comments'] . '<=? AND ' . $contentItemClass::$databasePrefix . $field . '<?', $contentItemClass::$firstCommentRequired ? 1 : 0, $data['additional']['no_comments'] );
}
if ( isset( $data['additional']['last_post'] ) AND $data['additional']['last_post'] )
{
$where[] = array( $contentItemClass::$databasePrefix . $field . '<=?', $data['additional']['last_post'] );
}
/* Locked/Unlocked */
if ( isset( $data['additional']['state'] ) )
{
if ( isset( $contentItemClass::$databaseColumnMap['locked'] ) )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['locked'].'=?', $data['additional']['state'] == 'locked' ? 1 : 0 );
}
else
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['status'].'=?', $data['additional']['state'] == 'locked' ? 'closed' : 'open' );
}
}
/* Pinned/Unpinned */
if ( isset( $data['additional']['pinned'] ) )
{
if ( $data['additional']['pinned'] === TRUE ) // Legacy, may still be in queue
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['pinned'].'!=?', 1 );
}
else
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['pinned'].'=?', $data['additional']['pinned'] );
}
}
/* Featured/Unfeatured */
if ( isset( $data['additional']['featured'] ) )
{
if ( $data['additional']['featured'] === TRUE ) // Legacy, may still be in queue
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['featured'].'!=?', 1 );
}
else
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['featured'].'=?', $data['additional']['featured'] );
}
}
}
return $where;
}
/**
* Mass move content items in this node to another node
@@ -2044,52 +2308,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
*/
public function massMoveorDelete( $node=NULL, $data=NULL )
{
$contentItemClass = static::$contentItemClass;
$where = array();
if ( isset( $data['additional'] ) AND count( $data['additional'] ) )
{
if ( isset( $data['additional']['author'] ) )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['author'] . '=?', $data['additional']['author'] );
}
if ( isset( $data['additional']['no_comments'] ) AND $data['additional']['no_comments'] > 0 )
{
$lastCommentField = $contentItemClass::$databaseColumnMap['last_comment'];
$field = is_array( $lastCommentField ) ? array_pop( $lastCommentField ) : $lastCommentField;
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['num_comments'] . '<=? AND ' . $contentItemClass::$databasePrefix . $field . '<?', $contentItemClass::$firstCommentRequired ? 1 : 0, $data['additional']['no_comments'] );
}
if ( isset( $data['additional']['num_comments'] ) AND $data['additional']['num_comments'] > 0 )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['num_comments'].'<?', $data['additional']['num_comments'] );
}
if ( isset( $data['additional']['state'] ) )
{
if ( isset( $contentItemClass::$databaseColumnMap['locked'] ) )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['locked'].'=?', $data['additional']['state'] == 'locked' ? 1 : 0 );
}
else
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['status'].'=?', $data['additional']['state'] == 'locked' ? 'closed' : 'open' );
}
}
if ( isset( $data['additional']['pinned'] ) AND $data['additional']['pinned'] === TRUE )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['pinned'].'!=?', 1 );
}
if ( isset( $data['additional']['featured'] ) AND $data['additional']['featured'] === TRUE )
{
$where[] = array( $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnMap['featured'].'!=?', 1 );
}
}
$select = $this->getContentItems( 100, 0, $where );
$select = $this->getContentItems( 100, 0, $this->massMoveorDeleteWhere( $data ) );
if ( count( $select ) )
{
@@ -2168,6 +2387,18 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
array( $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['container'] . '=?', $this->_id )
);
if ( in_array( 'IPS\Content\Hideable', class_implements( $itemClass ) ) )
{
if ( isset( $itemClass::$databaseColumnMap['approved'] ) )
{
$commentWhere[] = array( $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['approved'] . '=?', 1 );
}
elseif ( isset( $itemClass::$databaseColumnMap['hidden'] ) )
{
$commentWhere[] = array( $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['hidden'] . '=?', 0 );
}
}
if ( isset( $commentClass::$databaseColumnMap['approved'] ) )
{
$commentWhere[] = array( $commentClass::$databaseTable . '.' . $commentClass::$databasePrefix . $commentClass::$databaseColumnMap['approved'] . '=?', 1 );
@@ -2183,6 +2414,28 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
), $commentWhere )->first();
}
if ( $this->_reviews !== NULL AND $reviewClass !== NULL )
{
$reviewWhere = array(
array( $reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['item'] . ' = ' . $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemIdColumn ),
array( $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnMap['container'] . '=?', $this->_id )
);
if ( isset( $reviewClass::$databaseColumnMap['approved'] ) )
{
$reviewWhere[] = array( $reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['approved'] . '=?', 1 );
}
elseif ( isset( $reviewClass::$databaseColumnMap['hidden'] ) )
{
$reviewWhere[] = array( $reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['hidden'] . '=?', 0 );
}
$this->_reviews = \IPS\Db::i()->select( 'COUNT(*)', array(
array( $reviewClass::$databaseTable, $reviewClass::$databaseTable ),
array( $itemClass::$databaseTable, $itemClass::$databaseTable )
), $reviewWhere )->first();
}
if ( in_array( 'IPS\Content\Hideable', class_implements( $itemClass ) ) )
{
if ( $this->_unapprovedItems !== NULL )
@@ -2279,13 +2532,14 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
/**
* Retrieve content items (if applicable) for a node.
*
* @param int $limit The limit
* @param int $offset The offset
* @param array $additionalWhere Additional where clauses
* @return \IPS\Patterns\ActiveRecordIterator
* @param int $limit The limit
* @param int $offset The offset
* @param array $additional Where Additional where clauses
* @param int $countOnly If TRUE, will get the number of results
* @return \IPS\Patterns\ActiveRecordIterator|int
* @throws \BadMethodCallException
*/
public function getContentItems( $limit, $offset, $additionalWhere = array() )
public function getContentItems( $limit, $offset, $additionalWhere = array(), $countOnly=FALSE )
{
if ( !isset( static::$contentItemClass ) )
{
@@ -2304,10 +2558,17 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
$where[] = $clause;
}
}
$contentItemClass = static::$contentItemClass;
$limit = ( $offset !== NULL ) ? array( $offset, $limit ) : NULL;
return new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', $contentItemClass::$databaseTable, $where, $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnId, $limit ), $contentItemClass );
if ( $countOnly )
{
return \IPS\Db::i()->select( 'COUNT(*)', $contentItemClass::$databaseTable, $where )->first();
}
else
{
$contentItemClass = static::$contentItemClass;
$limit = ( $offset !== NULL ) ? array( $offset, $limit ) : NULL;
return new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', $contentItemClass::$databaseTable, $where, $contentItemClass::$databasePrefix . $contentItemClass::$databaseColumnId, $limit ), $contentItemClass );
}
}
/**
@@ -2525,7 +2786,18 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
$this->updateSearchIndexPermissions();
}
}
/**
* Can promote this comment/item?
*
* @param \IPS\Member|NULL $member The member to check for (NULL for currently logged in member)
* @return boolean
*/
public function canPromoteToSocialMedia( $member=NULL )
{
return \IPS\core\Promote::canPromote( $member );
}
/**
* [ActiveRecord] Duplicate
*
@@ -2614,7 +2886,10 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
\IPS\Lang::deleteCustom( ( static::$permApp !== NULL ) ? static::$permApp : 'core', static::$titleLangPrefix . $this->_id . static::$descriptionLangSuffix );
}
/* Remove any entries in the promotions table */
\IPS\Db::i()->delete( 'core_social_promote', array( 'promote_class=? AND promote_class_id=?', get_called_class(), $this->_id ) );
return parent::delete();
}
@@ -2776,7 +3051,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
$hasContent = (bool) $this->getContentItemCount();
}
$form = new \IPS\Helpers\Form( 'form', 'delete' );
$form = new \IPS\Helpers\Form( 'delete_node_form', 'delete' );
$form->addMessage( 'node_delete_blurb' );
if ( $showMoveToChildren or $this->hasChildren( NULL, NULL, TRUE ) )
{
@@ -2790,32 +3065,6 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
return array_key_exists( 'add', $node->permissionTypes() );
} ) ) );
if ( \IPS\Request::i()->deleteNode != 1 )
{
$form->add( new \IPS\Helpers\Form\Member( 'node_move_author', NULL, FALSE ) );
if ( isset( $contentItemClass::$commentClass ) )
{
$form->add( new \IPS\Helpers\Form\Date( 'node_move_no_comments', NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\Number( 'node_move_comments_less', NULL, FALSE ) );
}
if ( in_array( 'IPS\Content\Lockable', class_implements( $contentItemClass ) ) )
{
$form->add( new \IPS\Helpers\Form\Select( 'node_move_state', 'any', FALSE, array( 'options' => array( 'open' => 'open', 'locked' => 'locked', 'any' => 'any' ) ) ) );
}
if ( in_array( 'IPS\Content\Pinnable', class_implements( $contentItemClass ) ) )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'node_move_not_pinned', FALSE, FALSE ) );
}
if ( in_array( 'IPS\Content\Featurable', class_implements( $contentItemClass ) ) )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'node_move_not_featured', FALSE, FALSE ) );
}
}
}
return $form;
@@ -2825,10 +3074,9 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
* Handle submissions of form to delete or move content
*
* @param array $values Values from form
* @param bool $deleteWhenDone Delete the node when done?
* @return void
*/
public function deleteOrMoveFormSubmit( $values, $deleteWhenDone=TRUE )
public function deleteOrMoveFormSubmit( $values )
{
$nodesToQueue = array( $this );
@@ -2866,52 +3114,20 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
foreach ( $nodesToQueue as $_node )
{
if ( $deleteWhenDone and in_array( 'IPS\Node\Permissions', class_implements( $_node ) ) )
if ( in_array( 'IPS\Node\Permissions', class_implements( $_node ) ) )
{
\IPS\Db::i()->update( 'core_permission_index', array( 'perm_view' => '' ), array( "app=? AND perm_type=? AND perm_type_id=?", $_node::$permApp, $_node::$permType, $_node->_id ) );
}
$additional = array();
if ( !$deleteWhenDone )
{
if ( isset( $values['node_move_author'] ) AND $values['node_move_author'] instanceof \IPS\Member )
{
$additional['author'] = $values['node_move_author']->member_id;
}
if ( isset( $values['node_move_no_comments'] ) AND $values['node_move_no_comments'] instanceof \IPS\DateTime )
{
$additional['no_comments'] = $values['node_move_no_comments']->getTimestamp();
}
if ( isset( $values['node_move_comments_less'] ) AND $values['node_move_comments_less'] > 0 )
{
$additional['num_comments'] = $values['node_move_comments_less'];
}
if ( isset( $values['node_move_state'] ) AND $values['node_move_state'] != 'any' )
{
$additional['state'] = $values['node_move_state'];
}
if ( isset( $values['node_move_not_pinned'] ) AND $values['node_move_not_pinned'] )
{
$additional['pinned'] = TRUE;
}
if ( isset( $values['node_move_not_featured'] ) AND $values['node_move_not_featured'] )
{
$additional['featured'] = TRUE;
}
}
if ( isset( $values['node_move_content'] ) and $values['node_move_content'] )
{
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', array( 'class' => get_class( $_node ), 'id' => $_node->_id, 'moveToClass' => get_class( $values['node_move_content'] ), 'moveTo' => $values['node_move_content']->_id, 'deleteWhenDone' => $deleteWhenDone, 'additional' => $additional ) );
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', array( 'class' => get_class( $_node ), 'id' => $_node->_id, 'moveToClass' => get_class( $values['node_move_content'] ), 'moveTo' => $values['node_move_content']->_id, 'deleteWhenDone' => TRUE, 'additional' => $additional ) );
}
else
{
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', array( 'class' => get_class( $_node ), 'id' => $_node->_id, 'deleteWhenDone' => $deleteWhenDone, 'additional' => $additional ) );
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', array( 'class' => get_class( $_node ), 'id' => $_node->_id, 'deleteWhenDone' => TRUE, 'additional' => $additional ) );
}
}
}
+4 -5
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Permissions Interface for Nodes
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 2 Aug 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Node;
+4 -5
View File
@@ -1,12 +1,11 @@
<?php
/**
* @brief Rating Interface for Nodes
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 25 Mar 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Node;