Version 4.7.23
This commit is contained in:
1 parent
7124a02564
commit
25ddeb65d6
1791 files changed
+76990
-44452
No files matched your search
@@ -12,6 +12,9 @@
|
||||
namespace IPS\cms;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
|
||||
use IPS\Content\Comment;
|
||||
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
@@ -109,6 +112,11 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
* @breif Used by the dataLayer, overwritten by \IPS\cms\Application
|
||||
*/
|
||||
public static $containerType = 'pages_database_category';
|
||||
|
||||
/**
|
||||
* @brief SEO Title Column
|
||||
*/
|
||||
public static string $seoTitleColumn = 'furl_name';
|
||||
|
||||
/**
|
||||
* @brief [Node] ACP Restrictions
|
||||
@@ -331,7 +339,7 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
$path = trim( $path , '/');
|
||||
$bits = explode( '/', $path );
|
||||
$root = $bits[0];
|
||||
|
||||
|
||||
/* _ is here due to IP.Board 3.x using that to denote the articles database (eg. articles.html/_/category/record-r1/), which we need to redirect from for records and articles. */
|
||||
if ( \in_array( $root, array( 'submit', '_' ) ) )
|
||||
{
|
||||
@@ -612,6 +620,34 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
), NULL, NULL, NULL, 'category_fields' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See if a furl name is taken within a database
|
||||
*
|
||||
* @param string $furl The default FURL (of a category)
|
||||
* @param int $databaseId The database
|
||||
* @param int|null $excludeId Optional: an id to exclude from the query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function furlNameIsTaken( string $furl, int $databaseId, ?int $excludeId=null ) : bool
|
||||
{
|
||||
$where = array( ['category_database_id=?', $databaseId ] );
|
||||
if ( $excludeId )
|
||||
{
|
||||
$where[] = [ 'category_id <> ?', $excludeId ];
|
||||
}
|
||||
|
||||
foreach ( (new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'cms_database_categories', $where ), self::class )) as $cat )
|
||||
{
|
||||
if ( ( !empty( $cat->furl_name ) and $cat->furl_name == $furl ) or ( empty( $cat->furl_name ) AND !empty( $cat->name ) AND \IPS\Http\Url\Friendly::seoTitle( $cat->name ) == $furl ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Node] Format form values from add/edit form for save
|
||||
@@ -667,44 +703,14 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
if ( isset( $name ) AND empty( $values['category_furl_name'] ) )
|
||||
{
|
||||
$ok = FALSE;
|
||||
|
||||
try
|
||||
{
|
||||
$cat = \IPS\cms\Categories::load( \IPS\Http\Url\Friendly::seoTitle( $name ), 'category_furl_name' );
|
||||
|
||||
/* We have a cat, is it in a different database? */
|
||||
if ( $cat->database_id != \IPS\Request::i()->database_id )
|
||||
{
|
||||
$ok = TRUE;
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
if ( $cat->id == \IPS\Request::i()->id )
|
||||
{
|
||||
$ok = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$ok = TRUE;
|
||||
}
|
||||
$ok = static::furlNameIsTaken( \IPS\Http\Url\Friendly::seoTitle( $name ), $this->database_id, $this->id ?: null );
|
||||
|
||||
if ( \IPS\Request::i()->category_parent_id == 0 and \IPS\cms\Categories::isFurlCollision( \IPS\Http\Url\Friendly::seoTitle( $name ) ) )
|
||||
{
|
||||
$ok = FALSE;
|
||||
}
|
||||
|
||||
if ( $ok === TRUE )
|
||||
{
|
||||
$values['furl_name'] = \IPS\Http\Url\Friendly::seoTitle( $name );
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['furl_name'] = $this->id . '_' . \IPS\Http\Url\Friendly::seoTitle( $name );
|
||||
}
|
||||
$values['furl_name'] = $ok ? \IPS\Http\Url\Friendly::seoTitle( $name ) : $this->id . '_' . \IPS\Http\Url\Friendly::seoTitle( $name );
|
||||
}
|
||||
else if( isset( $values['category_furl_name'] ) )
|
||||
{
|
||||
@@ -962,8 +968,8 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
*/
|
||||
public function permissions()
|
||||
{
|
||||
/* Let the ACP/Setup use normal permissions or it'll get messy */
|
||||
if ( !\IPS\Dispatcher::hasInstance() OR \IPS\Dispatcher::i()->controllerLocation !== 'front' )
|
||||
/* Let the ACP/Setup use normal permissions or it'll get messy. Also use normal permissions for club categories */
|
||||
if ( !\IPS\Dispatcher::hasInstance() OR \IPS\Dispatcher::i()->controllerLocation !== 'front' OR $this->isClubCategory() )
|
||||
{
|
||||
$this->_permsMashed = true;
|
||||
return parent::permissions();
|
||||
@@ -1147,7 +1153,7 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
if ( $recordClass::database()->use_categories )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $indexData['index_container_id'], NULL, $escape ? array( 'escape' => $escape ) : array() );
|
||||
return parent::titleFromIndexData( $indexData, $itemData, $containerData, $escape );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1170,6 +1176,20 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
return $this->database()->pageTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the club of this category, or null if there is no club
|
||||
*
|
||||
* @return \IPS\Member\Club|null
|
||||
*/
|
||||
public function get__club() : \IPS\Member\Club|null
|
||||
{
|
||||
if ( $this->isClubCategory() )
|
||||
{
|
||||
return $this->club();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title of category
|
||||
*
|
||||
@@ -1178,8 +1198,8 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
protected function get__title()
|
||||
{
|
||||
/* If the DB is in a page, and we're not using categories, then return the page title, not the category title for continuity */
|
||||
$database = \IPS\cms\Databases::load( $this->database_id );
|
||||
if ( ! $database->use_categories )
|
||||
$database = static::database();
|
||||
if ( ! $database->use_categories and !$this->_club )
|
||||
{
|
||||
if ( ! $this->_catTitle )
|
||||
{
|
||||
@@ -1454,14 +1474,15 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
return static::database()->template_display;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set last comment
|
||||
*
|
||||
* @param \IPS\Content\Comment $comment The latest comment or NULL to work it out
|
||||
* @return void
|
||||
* @param Comment|null $comment The latest comment or NULL to work it out
|
||||
* @param Item|null $updatedItem We sometimes run setLastComment() when an item has been edited, if so, that item will be here
|
||||
* @return void
|
||||
*/
|
||||
public function setLastComment( \IPS\Content\Comment $comment=NULL )
|
||||
public function _setLastComment( \IPS\Content\Comment $comment=NULL, \IPS\Content\Item $updatedItem=NULL )
|
||||
{
|
||||
$database = \IPS\cms\Databases::load( $this->database_id );
|
||||
|
||||
@@ -1715,6 +1736,16 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
*/
|
||||
public function canManagePermissions()
|
||||
{
|
||||
/* For club categories, we don't want the permissions to be managed via the ACP */
|
||||
if ( $this->isClubCategory() and !( \IPS\Dispatcher::i() instanceof \IPS\Dispatcher\Front ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ( $this->isClubCategory() )
|
||||
{
|
||||
return $this->can( 'add' );
|
||||
}
|
||||
|
||||
$can = parent::canManagePermissions();
|
||||
|
||||
return ( $can === FALSE ) ? FALSE : (boolean) $this->has_perms;
|
||||
@@ -1864,6 +1895,90 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
{
|
||||
$_member = $member ?: \IPS\Member::loggedIn();
|
||||
|
||||
if ( $club = $this->_club )
|
||||
{
|
||||
if ( \in_array( $permission, [ 'add', 'edit', 'delete', 'reply', 'review' ] ) and $_member instanceof \IPS\Member )
|
||||
{
|
||||
if( \in_array( $club->memberStatus( $_member ), [
|
||||
\IPS\Member\Club::STATUS_MEMBER,
|
||||
\IPS\Member\Club::STATUS_LEADER,
|
||||
\IPS\Member\Club::STATUS_MODERATOR
|
||||
] ) or $_member->modPermission('can_access_all_clubs' ) )
|
||||
{
|
||||
return parent::can( $permission, $_member, $considerPostBeforeRegistering );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( \in_array( $permission, ['view', 'read' ] ) )
|
||||
{
|
||||
/* Check the database permission first */
|
||||
if( !static::database()->can( $permission, $_member ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Site moderators can see everything */
|
||||
if ( $_member instanceof \IPS\Member and $_member->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* If it's not approved, only moderators and the person who created it can see it */
|
||||
if ( \IPS\Settings::i()->clubs_require_approval and !$club->approved and $_member instanceof \IPS\Member )
|
||||
{
|
||||
return ( $_member->modPermission('can_access_all_clubs') or ( $club->owner AND $_member->member_id == $club->owner->member_id ) );
|
||||
}
|
||||
|
||||
/* Owner or leader? */
|
||||
if ( $_member instanceof \IPS\Member and ( $_member->member_id === $club->owner->member_id OR $club->memberStatus( $_member ) === \IPS\Member\Club::STATUS_LEADER ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$viewGroups = explode( ',', $this->club_view_permission );
|
||||
|
||||
/* Can literally anyone, guest included, view this and the club? */
|
||||
if ( $this->club_category_meta_index and $club->type !== \IPS\Member\Club::TYPE_PRIVATE and \in_array( 'nonmember', $viewGroups ) )
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Nonmembers */
|
||||
if ( \in_array( 'nonmember', $viewGroups ) and $_member instanceof \IPS\Member and $_member->member_id )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Moderators? */
|
||||
if ( \in_array( 'moderator', $viewGroups ) AND $club->memberStatus( $_member ) === \IPS\Member\Club::STATUS_MODERATOR )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Members */
|
||||
if (
|
||||
( \mb_strpos( '*', $this->club_view_permission ) !== false or \in_array( 'member', $viewGroups ) ) and
|
||||
\in_array(
|
||||
$club->memberStatus( $_member ),
|
||||
[
|
||||
\IPS\Member\Club::STATUS_MEMBER,
|
||||
\IPS\Member\Club::STATUS_INVITED,
|
||||
\IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT,
|
||||
\IPS\Member\Club::STATUS_EXPIRED_MODERATOR
|
||||
]
|
||||
)
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$_member->member_id and !$this->can_view_others )
|
||||
{
|
||||
return FALSE;
|
||||
@@ -1917,4 +2032,24 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
|
||||
return $this->_dataLayerProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if this category belongs to a club
|
||||
* @return bool
|
||||
*/
|
||||
public function isClubCategory() : bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$database = \IPS\cms\Databases::load( $this->database_id );
|
||||
$class = '\IPS\cms\Categories' . $this->database_id;
|
||||
if ( $database->allow_club_categories and \IPS\IPS::classUsesTrait( $class, 'IPS\Content\ClubContainer' ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch ( \OutOfBoundsException|\OutOfRangeException ) { }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user