Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
+155
-243
@@ -11,72 +11,78 @@
|
||||
namespace IPS\Content;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use BadMethodCallException;
|
||||
use IPS\Application;
|
||||
use IPS\Content\Search\Index;
|
||||
use IPS\Content\Search\SearchContent;
|
||||
use IPS\core\Approval;
|
||||
use IPS\DateTime;
|
||||
use IPS\Http\Url;
|
||||
use IPS\IPS;
|
||||
use IPS\Member;
|
||||
use IPS\Notification;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
use function get_called_class;
|
||||
use function get_class;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_null;
|
||||
use function json_encode;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Content Review Model
|
||||
*/
|
||||
abstract class _Review extends \IPS\Content\Comment
|
||||
abstract class Review extends Comment
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief [Content\Comment] Form Template
|
||||
*/
|
||||
public static $formTemplate = array( array( 'forms', 'core', 'front' ), 'reviewTemplate' );
|
||||
public static array $formTemplate = array( array( 'forms', 'core', 'front' ), 'reviewTemplate' );
|
||||
|
||||
/**
|
||||
* @brief [Content\Comment] Reviews Template
|
||||
*/
|
||||
public static $commentTemplate = array( array( 'global', 'core', 'front' ), 'reviewContainer' );
|
||||
public static array $commentTemplate = array( array( 'global', 'core', 'front' ), 'reviewContainer' );
|
||||
|
||||
public static string $moderationMenuIdPrefix = 'review_';
|
||||
|
||||
/**
|
||||
* Create first comment (created with content item)
|
||||
*
|
||||
* @param \IPS\Content\Item $item The content item just created
|
||||
* @param string $comment The comment
|
||||
* @param bool $first Is the first comment?
|
||||
* @param int $rating The rating (1-5)
|
||||
* @param string $guestName If author is a guest, the name to use
|
||||
* @param \IPS\Member|NULL $member The author of this comment. If NULL, uses currently logged in member.
|
||||
* @param \IPS\DateTime|NULL $time The time
|
||||
* @param string|NULL $ipAddress The IP address or NULL to detect automatically
|
||||
* @param int|NULL $hiddenStatus NULL to set automatically or override: 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
|
||||
* @param int|NULL $anonymous NULL for no value, 0 or 1 for a value (0=no, 1=yes)
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException
|
||||
* @param Item $item The content item just created
|
||||
* @param string $comment The comment
|
||||
* @param bool $first Is the first comment?
|
||||
* @param string|null $guestName If author is a guest, the name to use
|
||||
* @param bool|null $incrementPostCount
|
||||
* @param Member|null $member The author of this comment. If NULL, uses currently logged in member.
|
||||
* @param DateTime|null $time The time
|
||||
* @param string|null $ipAddress The IP address or NULL to detect automatically
|
||||
* @param int|null $hiddenStatus NULL to set automatically or override: 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
|
||||
* @param int|null $anonymous NULL for no value, 0 or 1 for a value (0=no, 1=yes)
|
||||
* @return Review|null
|
||||
*/
|
||||
public static function create( $item, $comment, $first=FALSE, $rating=NULL, $guestName=NULL, $member=NULL, \IPS\DateTime $time=NULL, $ipAddress=NULL, $hiddenStatus=NULL, $anonymous=NULL )
|
||||
public static function create( Item $item, string $comment, bool $first=false, string|null $guestName=null, bool|null $incrementPostCount= null, Member|null $member= null, DateTime|null $time= null, string|null $ipAddress= null, int|null $hiddenStatus= null, int|null $anonymous= null ): static|null
|
||||
{
|
||||
if ( !\is_int( $rating ) or $rating < 1 or $rating > \intval( \IPS\Settings::i()->reviews_rating_out_of ) )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
$obj = parent::create( $item, $comment, $first, $guestName, NULL, $member, $time, $ipAddress, $hiddenStatus );
|
||||
$obj = parent::create( $item, $comment, $first, $guestName, null, $member, $time, $ipAddress, $hiddenStatus );
|
||||
|
||||
foreach ( array( 'rating', 'votes_data' ) as $k )
|
||||
if ( isset( static::$databaseColumnMap['votes_data'] ) )
|
||||
{
|
||||
if ( isset( static::$databaseColumnMap[ $k ] ) )
|
||||
/* Make sure we start with a valid json array */
|
||||
$val = json_encode( [] );
|
||||
|
||||
foreach ( is_array( static::$databaseColumnMap['votes_data'] ) ? static::$databaseColumnMap['votes_data'] : array( static::$databaseColumnMap['votes_data'] ) as $column )
|
||||
{
|
||||
$val = NULL;
|
||||
switch ( $k )
|
||||
{
|
||||
case 'rating':
|
||||
$val = $rating;
|
||||
break;
|
||||
|
||||
case 'votes_data':
|
||||
$val = json_encode( array() );
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ( \is_array( static::$databaseColumnMap[ $k ] ) ? static::$databaseColumnMap[ $k ] : array( static::$databaseColumnMap[ $k ] ) as $column )
|
||||
{
|
||||
$obj->$column = $val;
|
||||
}
|
||||
$obj->$column = $val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +96,9 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
|
||||
/* Have to do these AFTER rating is set */
|
||||
$itemClass = static::$itemClass;
|
||||
/* @var array $databaseColumnMap */
|
||||
$ratingField = $itemClass::$databaseColumnMap['rating'];
|
||||
|
||||
|
||||
$obj->item()->$ratingField = $obj->item()->averageReviewRating() ?: 0;
|
||||
$obj->item()->save();
|
||||
|
||||
@@ -114,7 +121,7 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function postCreate()
|
||||
public function postCreate(): void
|
||||
{
|
||||
$item = $this->item();
|
||||
if ( !$this->hidden() )
|
||||
@@ -122,7 +129,7 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
if ( isset( $item::$databaseColumnMap['last_review'] ) )
|
||||
{
|
||||
$lastReviewField = $item::$databaseColumnMap['last_review'];
|
||||
if ( \is_array( $lastReviewField ) )
|
||||
if ( is_array( $lastReviewField ) )
|
||||
{
|
||||
foreach ( $lastReviewField as $column )
|
||||
{
|
||||
@@ -181,14 +188,14 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
/* Check we don't already have a reason from profanity / url / email filters */
|
||||
try
|
||||
{
|
||||
\IPS\core\Approval::loadFromContent( \get_called_class(), $this->$idColumn );
|
||||
Approval::loadFromContent( get_called_class(), $this->$idColumn );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
catch( OutOfRangeException $e )
|
||||
{
|
||||
/* If the user is mod-queued - that's why. These will cascade, so check in that order. */
|
||||
$foundReason = FALSE;
|
||||
$log = new \IPS\core\Approval;
|
||||
$log->content_class = \get_called_class();
|
||||
$log = new Approval;
|
||||
$log->content_class = get_called_class();
|
||||
$log->content_id = $this->$idColumn;
|
||||
if ( $this->author()->mod_posts )
|
||||
{
|
||||
@@ -215,11 +222,17 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
$foundReason = TRUE;
|
||||
}
|
||||
}
|
||||
catch( \BadMethodCallException $e ) { }
|
||||
catch( BadMethodCallException $e ) { }
|
||||
}
|
||||
|
||||
/* Finally if the item itself requires moderation, that's why */
|
||||
if ( $foundReason === FALSE AND \is_array( $item::supportedMetaDataTypes() ) AND \in_array('core_ItemModeration', $item::supportedMetaDataTypes() ) AND (bool) \IPS\Application::load('core')->extensions( 'core', 'MetaData' )['ItemModeration']->enabled( $item, $this->author() ) )
|
||||
if (
|
||||
$foundReason === FALSE AND
|
||||
IPS::classUsesTrait( $item, 'IPS\Content\MetaData' ) AND
|
||||
is_array( $item::supportedMetaDataTypes() ) AND
|
||||
in_array('core_ItemModeration', $item::supportedMetaDataTypes() ) AND
|
||||
Application::load('core')->extensions( 'core', 'MetaData' )['ItemModeration']->enabled( $item, $this->author() )
|
||||
)
|
||||
{
|
||||
$log->held_reason = 'item';
|
||||
$foundReason = TRUE;
|
||||
@@ -236,15 +249,15 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
/**
|
||||
* @brief Value to set for the 'tab' parameter when redirecting to the comment (via _find())
|
||||
*/
|
||||
public static $tabParameter = array( 'tab' => 'reviews' );
|
||||
public static ?array $tabParameter = array( 'tab' => 'reviews' );
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @param string|NULL $action Action
|
||||
* @return \IPS\Http\Url
|
||||
* @param string|null $action Action
|
||||
* @return Url
|
||||
*/
|
||||
public function url( $action='find' )
|
||||
public function url( string|null $action='find' ): Url
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
|
||||
@@ -259,9 +272,9 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function helpfulLine()
|
||||
public function helpfulLine(): string
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->reviewHelpful( $this->mapped('votes_helpful'), $this->mapped('votes_total') );
|
||||
return Theme::i()->getTemplate( 'global', 'core', 'front' )->reviewHelpful( $this->mapped('votes_helpful'), $this->mapped('votes_total') );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,8 +283,10 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
* @param int $rating The new rating
|
||||
* @return void
|
||||
*/
|
||||
public function editRating( $rating )
|
||||
public function editRating( int $rating ): void
|
||||
{
|
||||
/* @var array $databaseColumnMap */
|
||||
|
||||
/* Review */
|
||||
$ratingField = static::$databaseColumnMap['rating'];
|
||||
$this->$ratingField = $rating;
|
||||
@@ -286,100 +301,13 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
$item->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncing to run when hiding
|
||||
*
|
||||
* @param \IPS\Member|NULL|FALSE $member The member doing the action (NULL for currently logged in member, FALSE for no member)
|
||||
* @return void
|
||||
*/
|
||||
public function onHide( $member )
|
||||
{
|
||||
$item = $this->item();
|
||||
if ( $item->container()->_reviews !== NULL )
|
||||
{
|
||||
$item->container()->_reviews = $item->container()->_reviews - 1;
|
||||
$item->container()->setLastReview();
|
||||
$item->container()->save();
|
||||
}
|
||||
if ( isset( $item::$databaseColumnMap['hidden_reviews'] ) )
|
||||
{
|
||||
$column = $item::$databaseColumnMap['hidden_reviews'];
|
||||
$item->$column = $item->mapped('hidden_reviews') + 1;
|
||||
}
|
||||
|
||||
if ( isset( $item::$databaseColumnMap['num_reviews'] ) )
|
||||
{
|
||||
$column = $item::$databaseColumnMap['num_reviews'];
|
||||
$item->$column = $item->mapped('num_reviews') - 1;
|
||||
}
|
||||
|
||||
$ratingField = $item::$databaseColumnMap['rating'];
|
||||
$item->$ratingField = $item->averageReviewRating() ?: 0;
|
||||
|
||||
$item->resyncLastReview();
|
||||
$item->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncing to run when unhiding
|
||||
*
|
||||
* @param bool $approving If true, is being approved for the first time
|
||||
* @param \IPS\Member|NULL|FALSE $member The member doing the action (NULL for currently logged in member, FALSE for no member)
|
||||
* @return void
|
||||
*/
|
||||
public function onUnhide( $approving, $member )
|
||||
{
|
||||
$item = $this->item();
|
||||
|
||||
if ( $approving )
|
||||
{
|
||||
if ( isset( $item::$databaseColumnMap['unapproved_reviews'] ) )
|
||||
{
|
||||
$column = $item::$databaseColumnMap['unapproved_reviews'];
|
||||
$item->$column = $item->mapped('unapproved_reviews') - 1;
|
||||
}
|
||||
if ( $item->container()->_unapprovedReviews !== NULL )
|
||||
{
|
||||
$item->container()->_unapprovedReviews = $item->container()->_unapprovedReviews - 1;
|
||||
$item->container()->setLastReview();
|
||||
$item->container()->save();
|
||||
}
|
||||
}
|
||||
else if ( isset( $item::$databaseColumnMap['hidden_reviews'] ) )
|
||||
{
|
||||
$column = $item::$databaseColumnMap['hidden_reviews'];
|
||||
if ( $item->mapped('hidden_reviews') > 0 )
|
||||
{
|
||||
$item->$column = $item->mapped('hidden_reviews') - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $item::$databaseColumnMap['num_reviews'] ) )
|
||||
{
|
||||
$column = $item::$databaseColumnMap['num_reviews'];
|
||||
$item->$column = $item->mapped('num_reviews') + 1;
|
||||
}
|
||||
if ( $item->container()->_reviews !== NULL )
|
||||
{
|
||||
$item->container()->_reviews = $item->container()->_reviews + 1;
|
||||
$item->container()->setLastReview();
|
||||
$item->container()->save();
|
||||
}
|
||||
|
||||
$ratingField = $item::$databaseColumnMap['rating'];
|
||||
$item->$ratingField = $item->averageReviewRating() ?: 0;
|
||||
|
||||
$item->resyncLastReview();
|
||||
$item->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Can split this comment off?
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member to check for (NULL for currently logged in member)
|
||||
* @param Member|null $member The member to check for (NULL for currently logged in member)
|
||||
* @return bool
|
||||
*/
|
||||
public function canSplit( $member=NULL )
|
||||
public function canSplit( Member|null $member=null ): bool
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -387,17 +315,17 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
/**
|
||||
* Can view?
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member to check for or NULL for the currently logged in member
|
||||
* @param Member|null $member The member to check for or NULL for the currently logged in member
|
||||
* @return bool
|
||||
*/
|
||||
public function canView( $member=NULL )
|
||||
public function canView( Member|null $member= null ): bool
|
||||
{
|
||||
if( $member === NULL )
|
||||
{
|
||||
$member = \IPS\Member::loggedIn();
|
||||
$member = Member::loggedIn();
|
||||
}
|
||||
|
||||
if ( $this instanceof \IPS\Content\Hideable and $this->hidden() and !$this->item()->canViewHiddenReviews( $member ) and ( $this->hidden() !== 1 or $this->author() !== $member ) )
|
||||
if ( IPS::classUsesTrait( $this, 'IPS\Content\Hideable' ) and $this->hidden() and !$this->item()->canViewHiddenReviews( $member ) and ( $this->hidden() !== 1 or $this->author() !== $member ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -410,12 +338,12 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function warningRef()
|
||||
public function warningRef(): string
|
||||
{
|
||||
/* If the member cannot warn, return NULL so we're not adding ugly parameters to the profile URL unnecessarily */
|
||||
if ( !\IPS\Member::loggedIn()->modPermission('mod_can_warn') )
|
||||
/* If the member cannot warn, return NULL, so we're not adding ugly parameters to the profile URL unnecessarily */
|
||||
if ( !Member::loggedIn()->modPermission('mod_can_warn') )
|
||||
{
|
||||
return NULL;
|
||||
return '';
|
||||
}
|
||||
|
||||
$itemClass = static::$itemClass;
|
||||
@@ -428,7 +356,7 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attachmentIds()
|
||||
public function attachmentIds(): array
|
||||
{
|
||||
$item = $this->item();
|
||||
$idColumn = $item::$databaseColumnId;
|
||||
@@ -440,79 +368,56 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
* Create Notification
|
||||
*
|
||||
* @param string|NULL $extra Additional data
|
||||
* @return \IPS\Notification
|
||||
* @return Notification
|
||||
*/
|
||||
protected function createNotification( $extra=NULL )
|
||||
protected function createNotification( string|null $extra=NULL ): Notification
|
||||
{
|
||||
return new \IPS\Notification( \IPS\Application::load( 'core' ), 'new_review', $this->item(), array( $this ) );
|
||||
return new Notification( Application::load( 'core' ), 'new_review', $this->item(), array( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Review
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
public function delete(): void
|
||||
{
|
||||
parent::delete();
|
||||
$this->_recalculateRating();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log for deletion later
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member, NULL for currently logged in, or FALSE for no member
|
||||
* @return void
|
||||
*/
|
||||
public function logDelete( $member = NULL )
|
||||
{
|
||||
parent::logDelete( $member );
|
||||
$this->_recalculateRating();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore Content
|
||||
*
|
||||
* @param bool $hidden Restore as hidden?
|
||||
* @return void
|
||||
*/
|
||||
public function restore( $hidden = FALSE )
|
||||
{
|
||||
parent::restore( $hidden );
|
||||
$this->_recalculateRating();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate rating after review action
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _recalculateRating()
|
||||
protected function _recalculateRating(): void
|
||||
{
|
||||
$itemClass = static::$itemClass;
|
||||
/* @var array $databaseColumnMap */
|
||||
$ratingField = $itemClass::$databaseColumnMap['rating'];
|
||||
$this->item()->$ratingField = $this->item()->averageReviewRating() ?: 0;
|
||||
$this->item()->save();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get output for API
|
||||
*
|
||||
* @param \IPS\Member|NULL $authorizedMember The member making the API request or NULL for API Key / client_credentials
|
||||
* @return array
|
||||
* @apiresponse int id ID number
|
||||
* @apiresponse int item The ID number of the item this belongs to
|
||||
* @apiresponse \IPS\Member author Author
|
||||
* @apiresponse datetime date Date
|
||||
* @apiresponse int rating The number of stars this review gave
|
||||
* @apiresponse int votesTotal The number of users that have voted if this review was helpful or unhelpful
|
||||
* @apiresponse int votesHelpful The number of users that voted helpful
|
||||
* @apiresponse string content The content
|
||||
* @apiresponse bool hidden Is hidden?
|
||||
* @apiresponse string url URL to content
|
||||
* @apiresponse string|NULL authorResponse The content item's author's response to the review, if any
|
||||
* @param Member|null $authorizedMember The member making the API request or NULL for API Key / client_credentials
|
||||
* @return array
|
||||
* @apiresponse int id ID number
|
||||
* @apiresponse int item The ID number of the item this belongs to
|
||||
* @apiresponse \IPS\Member author Author
|
||||
* @apiresponse datetime date Date
|
||||
* @apiresponse int rating The number of stars this review gave
|
||||
* @apiresponse int votesTotal The number of users that have voted if this review was helpful or unhelpful
|
||||
* @apiresponse int votesHelpful The number of users that voted helpful
|
||||
* @apiresponse string content The content
|
||||
* @apiresponse bool hidden Is hidden?
|
||||
* @apiresponse string url URL to content
|
||||
* @apiresponse string|null authorResponse The content item's author's response to the review, if any
|
||||
*/
|
||||
public function apiOutput( \IPS\Member $authorizedMember = NULL )
|
||||
public function apiOutput( Member|null $authorizedMember = NULL ): array
|
||||
{
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$itemColumn = static::$databaseColumnMap['item'];
|
||||
@@ -520,29 +425,16 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
'id' => $this->$idColumn,
|
||||
'item_id' => $this->$itemColumn,
|
||||
'author' => $this->author()->apiOutput( $authorizedMember ),
|
||||
'date' => \IPS\DateTime::ts( $this->mapped('date') )->rfc3339(),
|
||||
'date' => DateTime::ts( $this->mapped('date') )->rfc3339(),
|
||||
'rating' => $this->mapped('rating'),
|
||||
'votesTotal' => $this->mapped('votes_total'),
|
||||
'votesHelpful' => $this->mapped('votes_helpful'),
|
||||
'content' => \IPS\Text\Parser::removeLazyLoad( $this->content() ),
|
||||
'content' => $this->content(),
|
||||
'hidden' => (bool) $this->hidden(),
|
||||
'url' => (string) $this->url(),
|
||||
'authorResponse' => $this->mapped('author_response')
|
||||
);
|
||||
}
|
||||
|
||||
/* !Embeddable */
|
||||
|
||||
/**
|
||||
* Get content for embed
|
||||
*
|
||||
* @param array $params Additional parameters to add to URL
|
||||
* @return string
|
||||
*/
|
||||
public function embedContent( $params )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->embedReview( $this->item(), $this, $this->url()->setQueryString( $params ), $this->item()->embedImage() );
|
||||
}
|
||||
|
||||
/* !Author responses */
|
||||
|
||||
@@ -551,21 +443,27 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAuthorResponse()
|
||||
public function hasAuthorResponse(): bool
|
||||
{
|
||||
return !\is_null( $this->mapped('author_response') );
|
||||
return !is_null( $this->mapped('author_response') );
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the specified user respond to the review?
|
||||
*
|
||||
* @note Only the author of the content item can respond by default, but this is abstracted so third parties can override
|
||||
* @param \IPS\Member|NULL $member Member to check or NULL for currently logged in member
|
||||
* @param Member|NULL $member Member to check or NULL for currently logged in member
|
||||
* @return bool
|
||||
*/
|
||||
public function canRespond( $member=NULL )
|
||||
public function canRespond( Member|null $member=NULL ): bool
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
/* Make sure it's supported */
|
||||
if( !isset( static::$databaseColumnMap['author_response'] ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$member = $member ?: Member::loggedIn();
|
||||
|
||||
/* If we have not responded... */
|
||||
if( !$this->hasAuthorResponse() )
|
||||
@@ -584,12 +482,12 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
/**
|
||||
* Can the specified user edit the response to this review?
|
||||
*
|
||||
* @param \IPS\Member|NULL $member Member to check or NULL for currently logged in member
|
||||
* @param Member|null $member Member to check or NULL for currently logged in member
|
||||
* @return bool
|
||||
*/
|
||||
public function canEditResponse( $member=NULL )
|
||||
public function canEditResponse( Member|null $member=null ): bool
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$member = $member ?: Member::loggedIn();
|
||||
|
||||
/* If there is an author response... */
|
||||
if( $this->hasAuthorResponse() )
|
||||
@@ -603,8 +501,13 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
}
|
||||
|
||||
/* Or maybe the member can edit their own content? */
|
||||
if ( $member->member_id and $member->member_id == $item->author()->member_id and ( $member->group['g_edit_posts'] == '1' or \in_array( \get_class( $item ), explode( ',', $member->group['g_edit_posts'] ) ) ) and ( !( $item instanceof \IPS\Content\Lockable ) or !$item->locked() ) )
|
||||
if ( $member->member_id and $member->member_id == $item->author()->member_id and ( $member->group['g_edit_posts'] == '1' or in_array( get_class( $item ), explode( ',', $member->group['g_edit_posts'] ) ) ) )
|
||||
{
|
||||
if ( IPS::classUsesTrait( $item, 'IPS\Content\Lockable' ) AND $item->locked() )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -616,12 +519,12 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
/**
|
||||
* Can the specified user delete the response to this review?
|
||||
*
|
||||
* @param \IPS\Member|NULL $member Member to check or NULL for currently logged in member
|
||||
* @param Member|NULL $member Member to check or NULL for currently logged in member
|
||||
* @return bool
|
||||
*/
|
||||
public function canDeleteResponse( $member=NULL )
|
||||
public function canDeleteResponse( Member|null $member=NULL ): bool
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$member = $member ?: Member::loggedIn();
|
||||
|
||||
/* If there is an author response... */
|
||||
if( $this->hasAuthorResponse() )
|
||||
@@ -632,7 +535,7 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
{
|
||||
$container = $this->item()->container();
|
||||
}
|
||||
catch ( \BadMethodCallException $e ) { }
|
||||
catch ( BadMethodCallException $e ) { }
|
||||
|
||||
/* Moderators who can delete content can delete responses */
|
||||
if( static::modPermission( 'delete', $member, $container ) )
|
||||
@@ -641,7 +544,7 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
}
|
||||
|
||||
/* Or maybe the author can delete their own content? */
|
||||
if( $member->member_id and $member->member_id == $this->item()->author()->member_id and ( $member->group['g_delete_own_posts'] == '1' or \in_array( \get_class( $this->item() ), explode( ',', $member->group['g_delete_own_posts'] ) ) ) )
|
||||
if( $member->member_id and $member->member_id == $this->item()->author()->member_id and ( $member->group['g_delete_own_posts'] == '1' or in_array( get_class( $this->item() ), explode( ',', $member->group['g_delete_own_posts'] ) ) ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -651,24 +554,33 @@ abstract class _Review extends \IPS\Content\Comment
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to a review
|
||||
*
|
||||
* @param string $response
|
||||
* @return void
|
||||
*/
|
||||
public function setResponse( string $response )
|
||||
{
|
||||
$this->checkProfanityFilters( FALSE, (bool) $this->hasAuthorResponse(), $response );
|
||||
|
||||
/**
|
||||
* Respond to a review
|
||||
*
|
||||
* @param string $response
|
||||
* @return void
|
||||
*/
|
||||
public function setResponse( string $response ) : void
|
||||
{
|
||||
$this->checkProfanityFilters( false, $this->hasAuthorResponse(), $response );
|
||||
$column = static::$databaseColumnMap['author_response'];
|
||||
$this->$column = $response;
|
||||
$this->save();
|
||||
|
||||
/* Reindex in case it was hidden by the profanity filters */
|
||||
if ( $this instanceof \IPS\Content\Searchable )
|
||||
if( SearchContent::isSearchable( $this ) )
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->index( $this );
|
||||
Index::i()->index( $this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feed id that should contain reviews
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_feedId() : string
|
||||
{
|
||||
return $this->item()->reviewFeedId;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user