Version 4.2.0
This commit is contained in:
1 parent
0dc2aee5ed
commit
96997ddd8e
2074 files changed
+125454
-55780
No files matched your search
+393
-177
@@ -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 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user