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

+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 ) );
}
}
}