Version 4.1.19
This commit is contained in:
1 parent
28bd025b35
commit
2bd5025018
2674 files changed
+233518
-77766
No files matched your search
+249
-128
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Abstract Content Model
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @package IPS Community Suite
|
||||
* @since 3 Oct 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -98,22 +98,28 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
public static function constructFromData( $data, $updateMultitonStoreIfExists = TRUE )
|
||||
{
|
||||
if ( isset( $data[ static::$databaseTable ] ) and is_array( $data[ static::$databaseTable ] ) )
|
||||
{
|
||||
/* Add author data to multiton storeto prevent ->author() running another query later */
|
||||
{
|
||||
/* Add author data to multiton store to prevent ->author() running another query later */
|
||||
if ( isset( $data['author'] ) and is_array( $data['author'] ) )
|
||||
{
|
||||
$author = \IPS\Member::constructFromData( $data['author'], FALSE );
|
||||
|
||||
|
||||
if ( isset( $data['author_pfields'] ) )
|
||||
{
|
||||
unset( $data['author_pfields']['member_id'] );
|
||||
$author->contentProfileFields();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Load content */
|
||||
$obj = parent::constructFromData( $data[ static::$databaseTable ], $updateMultitonStoreIfExists );
|
||||
|
||||
|
||||
/* Add reputation if it was passed*/
|
||||
if ( isset( $data['core_reputation_index'] ) and is_array( $data['core_reputation_index'] ) )
|
||||
{
|
||||
$obj->_data = array_merge( $obj->_data, $data['core_reputation_index'] );
|
||||
}
|
||||
|
||||
/* Return */
|
||||
return $obj;
|
||||
}
|
||||
@@ -248,8 +254,8 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
*/
|
||||
public function truncated( $oneLine=FALSE )
|
||||
{
|
||||
/* Specifically remove quotes, and any scripts (which someone with HTML posting allowed may have legitimately enabled */
|
||||
$text = \IPS\Text\Parser::removeElements( $this->content(), array( 'blockquote', 'script' ) );
|
||||
/* Specifically remove quotes, any scripts (which someone with HTML posting allowed may have legitimately enabled, and spoilers (to prevent contents from being revealed) */
|
||||
$text = \IPS\Text\Parser::removeElements( $this->content(), array( 'blockquote', 'script', 'div[class=ipsSpoiler]' ) );
|
||||
|
||||
/* Convert headers and paragraphs into line breaks or just spaces */
|
||||
$text = str_replace( array( '</p>', '</h1>', '</h2>', '</h3>', '</h4>', '</h5>', '</h6>' ), ( $oneLine ? ' ' : '<br>' ), $text );
|
||||
@@ -261,7 +267,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$text = strip_tags( $text, '<br>' );
|
||||
|
||||
/* Remove any <br>s from the start so there isn't just blank space at the top, but maintaining <br>s elsewhere */
|
||||
$text = preg_replace( '/^[(\s)(<br>)\x{00a0}]*/u', '', $text );
|
||||
$text = preg_replace( '/^(\s|<br>|' . chr(0xC2) . chr(0xA0) . ')+?/', '', $text );
|
||||
|
||||
/* Return */
|
||||
return $text;
|
||||
@@ -376,7 +382,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
*/
|
||||
public static function canSeeMultiModTools( \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL )
|
||||
{
|
||||
return static::modPermission( 'edit', $member, $container ) or static::modPermission( 'hide', $member, $container ) or static::modPermission( 'unhide', $member, $container ) or static::modPermission( 'delete', $member, $container );
|
||||
return static::modPermission( 'pin', $member, $container ) or static::modPermission( 'unpin', $member, $container ) or static::modPermission( 'feature', $member, $container ) or static::modPermission( 'unfeature', $member, $container ) or static::modPermission( 'edit', $member, $container ) or static::modPermission( 'hide', $member, $container ) or static::modPermission( 'unhide', $member, $container ) or static::modPermission( 'delete', $member, $container );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,11 +564,11 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Hide
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member doing the action (NULL for currently logged in member)
|
||||
* @param string $reason Reason
|
||||
* @param \IPS\Member|NULL|FALSE $member The member doing the action (NULL for currently logged in member, FALSE for no member)
|
||||
* @param string $reason Reason
|
||||
* @return void
|
||||
*/
|
||||
public function hide( \IPS\Member $member = NULL, $reason = NULL )
|
||||
public function hide( $member, $reason = NULL )
|
||||
{
|
||||
if ( isset( static::$databaseColumnMap['hidden'] ) )
|
||||
{
|
||||
@@ -585,7 +591,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
$this->$column = -1;
|
||||
$this->save();
|
||||
$this->onHide();
|
||||
$this->onHide( $member );
|
||||
|
||||
if ( static::$hideLogKey )
|
||||
{
|
||||
@@ -594,7 +600,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
\IPS\Db::i()->insert( 'core_soft_delete_log', array(
|
||||
'sdl_obj_id' => $this->$idColumn,
|
||||
'sdl_obj_key' => static::$hideLogKey,
|
||||
'sdl_obj_member_id' => intval( $member ? $member->member_id : \IPS\Member::loggedIn()->member_id ),
|
||||
'sdl_obj_member_id' => $member === FALSE ? 0 : intval( $member ? $member->member_id : \IPS\Member::loggedIn()->member_id ),
|
||||
'sdl_obj_date' => time(),
|
||||
'sdl_obj_reason' => $reason,
|
||||
|
||||
@@ -618,17 +624,17 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Unhide
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member doing the action (NULL for currently logged in member)
|
||||
* @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 unhide( $member=NULL )
|
||||
public function unhide( $member )
|
||||
{
|
||||
/* If we're approving, we have to do extra stuff */
|
||||
$approving = FALSE;
|
||||
if ( $this->hidden() === 1 )
|
||||
{
|
||||
$approving = TRUE;
|
||||
if ( isset( static::$databaseColumnMap['approved_by'] ) )
|
||||
if ( isset( static::$databaseColumnMap['approved_by'] ) and $member !== FALSE )
|
||||
{
|
||||
$column = static::$databaseColumnMap['approved_by'];
|
||||
$this->$column = $member ? $member->member_id : \IPS\Member::loggedIn()->member_id;
|
||||
@@ -639,8 +645,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$this->$column = time();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Now do the actual stuff */
|
||||
if ( isset( static::$databaseColumnMap['hidden'] ) )
|
||||
{
|
||||
@@ -671,7 +676,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
throw new \RuntimeException;
|
||||
}
|
||||
$this->save();
|
||||
$this->onUnhide( $approving );
|
||||
$this->onUnhide( $approving, $member );
|
||||
|
||||
/* And update the tags perm cache */
|
||||
if ( $this instanceof \IPS\Content\Tags )
|
||||
@@ -690,10 +695,9 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
$this->sendApprovedNotification();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send
|
||||
$this->expireWidgetCaches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Blurb for when/why/by whom this content was hidden
|
||||
@@ -783,6 +787,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
try
|
||||
{
|
||||
$index = \IPS\core\Reports\Report::load( $this->$idColumn, 'content_id', array( 'class=?', get_called_class() ) );
|
||||
$index->num_reports = $index->num_reports + 1;
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
@@ -792,10 +797,18 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$index->perm_id = $this->permId();
|
||||
$index->first_report_by = (int) \IPS\Member::loggedIn()->member_id;
|
||||
$index->first_report_date = time();
|
||||
$index->last_updated = time();
|
||||
$index->author = (int) $this->author()->member_id;
|
||||
$index->num_reports = 1;
|
||||
$index->num_comments = 0;
|
||||
}
|
||||
|
||||
/* Only set this to a new report if it is not already under review */
|
||||
if( $index->status != 2 )
|
||||
{
|
||||
$index->status = 1;
|
||||
}
|
||||
|
||||
$index->status = 1;
|
||||
$index->save();
|
||||
|
||||
/* Create a report */
|
||||
@@ -809,10 +822,6 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
\IPS\Db::i()->insert( 'core_rc_reports', $reportInsert );
|
||||
|
||||
|
||||
/* Rebuild */
|
||||
$index->rebuild();
|
||||
|
||||
/* Send notification to mods */
|
||||
$moderators = array( 'm' => array(), 'g' => array() );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_moderators' ) as $mod )
|
||||
@@ -869,14 +878,15 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
break;
|
||||
|
||||
case 'author_name':
|
||||
$this->$col = $newAuthor->member_id ? $newAuthor->name : '';
|
||||
/* Real name will contain the custom guest name if available or '' if not */
|
||||
$this->$col = $newAuthor->member_id ? $newAuthor->name : $newAuthor->real_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->save();
|
||||
|
||||
if ( \IPS\Dispatcher::hasInstance() )
|
||||
if ( \IPS\Dispatcher::hasInstance() and \IPS\Dispatcher::i()->controllerLocation == 'front' )
|
||||
{
|
||||
\IPS\Session::i()->modLog( 'modlog__action_changeauthor', array( static::$title => TRUE, $this->url()->__toString() => FALSE, $this->mapped('title') ?: ( method_exists( $this, 'item' ) ? $this->item()->mapped('title') : NULL ) => FALSE ), ( $this instanceof \IPS\Content\Item ) ? $this : $this->item() );
|
||||
}
|
||||
@@ -888,15 +898,17 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the author. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param bool $iPostedIn If the user has posted in the item
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @param bool $asItem Displaying results as items?
|
||||
* @param bool $canIgnoreComments Can ignore comments in the result stream? Activity stream can, but search results cannot.
|
||||
* @param array $template Optional custom template
|
||||
* @return string
|
||||
*/
|
||||
public static function searchResult( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating, $iPostedIn, $view, $asItem )
|
||||
public static function searchResult( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating, $iPostedIn, $view, $asItem, $canIgnoreComments=FALSE, $template=NULL )
|
||||
{
|
||||
/* Item details */
|
||||
$itemClass = $indexData['index_class'];
|
||||
@@ -913,6 +925,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
/* Object URL */
|
||||
$indefiniteArticle = static::_indefiniteArticle( $containerData );
|
||||
$definiteArticle = static::_definiteArticle( $containerData );
|
||||
if ( in_array( 'IPS\Content\Comment', class_parents( get_called_class() ) ) )
|
||||
{
|
||||
if ( in_array( 'IPS\Content\Review', class_parents( get_called_class() ) ) )
|
||||
@@ -927,22 +940,23 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
|
||||
$indefiniteArticle = $itemClass::_indefiniteArticle( $containerData );
|
||||
$definiteArticle = $itemClass::_definiteArticle( $containerData );
|
||||
}
|
||||
else
|
||||
{
|
||||
$objectUrl = $itemUrl;
|
||||
$showRepUrl = $itemUrl->setQueryString( 'do', 'showRep' );
|
||||
}
|
||||
$articles = array( 'indefinite' => $indefiniteArticle, 'definite' => \IPS\Member::loggedIn()->language()->addToStack( $itemClass::$title, FALSE, array( 'strtolower' => TRUE ) ) );
|
||||
$articles = array( 'indefinite' => $indefiniteArticle, 'definite' => $definiteArticle );
|
||||
|
||||
/* Container details */
|
||||
$containerUrl = NULL;
|
||||
$containerTitle = NULL;
|
||||
if ( isset( $itemClass::$containerNodeClass ) )
|
||||
{
|
||||
$containerClass = $itemClass::$containerNodeClass;
|
||||
$containerTitle = \IPS\Member::loggedIn()->language()->addToStack( $containerClass::$titleLangPrefix . $indexData['index_container_id'] );
|
||||
$containerUrl = $containerClass::urlFromIndexData( $indexData, $itemData, $containerData );
|
||||
$containerClass = $itemClass::$containerNodeClass;
|
||||
$containerTitle = $containerClass::titleFromIndexData( $indexData, $itemData, $containerData );
|
||||
$containerUrl = $containerClass::urlFromIndexData( $indexData, $itemData, $containerData );
|
||||
}
|
||||
|
||||
/* Reputation */
|
||||
@@ -950,9 +964,14 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
/* Snippet */
|
||||
$snippet = static::searchResultSnippet( $indexData, $authorData, $itemData, $containerData, $reputationData, $reviewRating, $view );
|
||||
|
||||
/* Return */
|
||||
return \IPS\Theme::i()->getTemplate( 'system', 'core', 'front' )->searchResult( $indexData, $articles, $authorData, $itemData, $unread, $asItem ? $itemUrl : $objectUrl, $itemUrl, $containerUrl, $containerTitle, $repCount, $showRepUrl, $snippet, $iPostedIn, $view );
|
||||
|
||||
if ( $template === NULL )
|
||||
{
|
||||
$template = array( \IPS\Theme::i()->getTemplate( 'system', 'core', 'front' ), 'searchResult' );
|
||||
}
|
||||
|
||||
/* Return */
|
||||
return call_user_func_array( $template, array( $indexData, $articles, $authorData, $itemData, $unread, $asItem ? $itemUrl : $objectUrl, $itemUrl, $containerUrl, $containerTitle, $repCount, $showRepUrl, $snippet, $iPostedIn, $view, $canIgnoreComments ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -961,7 +980,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the author. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
@@ -1138,7 +1157,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
$idColumn = static::$databaseColumnId;
|
||||
\IPS\Db::i()->delete( 'core_reputation_index', array( 'app=? AND type=? AND member_id=? AND type_id=?', static::$application, static::$reputationType, $member->member_id, $this->$idColumn ) );
|
||||
|
||||
|
||||
if ( $this->repGiven( $member ) )
|
||||
{
|
||||
if ( $this->reputation !== NULL )
|
||||
@@ -1148,7 +1167,6 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
$limit = ( $type === 1 ) ? $member->group['g_rep_max_positive'] : $member->group['g_rep_max_negative'];
|
||||
|
||||
if ( $limit !== 999 )
|
||||
@@ -1161,13 +1179,16 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
|
||||
\IPS\Db::i()->insert( 'core_reputation_index', array(
|
||||
'member_id' => $member->member_id,
|
||||
'app' => static::$application,
|
||||
'type' => static::$reputationType,
|
||||
'type_id' => $this->$idColumn,
|
||||
'rep_date' => time(),
|
||||
'rep_rating' => $type,
|
||||
'member_received' => (int) $this->author()->member_id
|
||||
'member_id' => $member->member_id,
|
||||
'app' => static::$application,
|
||||
'type' => static::$reputationType,
|
||||
'type_id' => $this->$idColumn,
|
||||
'rep_date' => time(),
|
||||
'rep_rating' => $type,
|
||||
'member_received' => (int) $this->author()->member_id,
|
||||
'class_type_id_hash' => md5( get_class( $this ) . ':' . $this->$idColumn ),
|
||||
'rep_class' => get_class( $this ),
|
||||
'item_id' => (int) $this->mapped('item')
|
||||
) );
|
||||
|
||||
/* Send Notification */
|
||||
@@ -1275,59 +1296,84 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
*/
|
||||
public function likeBlurb()
|
||||
{
|
||||
if( $this->likeBlurb !== NULL )
|
||||
if( $this->likeBlurb === NULL )
|
||||
{
|
||||
return $this->likeBlurb;
|
||||
}
|
||||
|
||||
$reputation = $this->reputation();
|
||||
$people = array();
|
||||
|
||||
/* Nobody */
|
||||
if ( !$reputation )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/* You */
|
||||
if ( $this->repGiven() === 1 )
|
||||
{
|
||||
$reputation--;
|
||||
if ( $reputation )
|
||||
/* Did anyone like it? */
|
||||
$numberOfLikes = $this->reputation(); # int
|
||||
if ( $numberOfLikes )
|
||||
{
|
||||
$people[] = \IPS\Member::loggedIn()->language()->addToStack('like_blurb_you_and_others');
|
||||
/* Is it just us? */
|
||||
$userLiked = ( $this->repGiven() === 1 );
|
||||
if ( $userLiked and $numberOfLikes < 2 )
|
||||
{
|
||||
$this->likeBlurb = \IPS\Member::loggedIn()->language()->addToStack('like_blurb_just_you');
|
||||
}
|
||||
|
||||
/* Nope, we need to display a number... */
|
||||
else
|
||||
{
|
||||
$peopleToDisplayInMainView = array();
|
||||
$andXOthers = $numberOfLikes;
|
||||
|
||||
/* If the user liked, we always show "You" first */
|
||||
if ( $userLiked )
|
||||
{
|
||||
$peopleToDisplayInMainView[] = \IPS\Member::loggedIn()->language()->addToStack('like_blurb_you_and_others');
|
||||
$andXOthers--;
|
||||
}
|
||||
|
||||
/* If we have permission to see who the others are, we need to do that... */
|
||||
if ( \IPS\Member::loggedIn()->group['gbw_view_reps'] )
|
||||
{
|
||||
$peopleToDisplayInSecondaryView = array();
|
||||
|
||||
/* Some random names */
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$i = 0;
|
||||
$peopleToDisplayInSecondaryView = array();
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array( 'app=? AND type=? AND type_id=? AND member_id!=? AND rep_rating=?', static::$application, static::$reputationType, $this->$idColumn, ( \IPS\Member::loggedIn()->member_id ) ?: 0, 1 ), 'RAND()', $userLiked ? 17 : 18 ) as $rep )
|
||||
{
|
||||
if ( $i < ( $userLiked ? 2 : 3 ) )
|
||||
{
|
||||
$peopleToDisplayInMainView[] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( \IPS\Member::load( $rep['member_id'] ) );
|
||||
$andXOthers--;
|
||||
}
|
||||
else
|
||||
{
|
||||
$peopleToDisplayInSecondaryView[] = htmlspecialchars( \IPS\Member::load( $rep['member_id'] )->name, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
/* If there's people to display in the secondary view, add that */
|
||||
if ( $peopleToDisplayInSecondaryView )
|
||||
{
|
||||
if ( count( $peopleToDisplayInSecondaryView ) < $andXOthers )
|
||||
{
|
||||
$peopleToDisplayInSecondaryView[] = \IPS\Member::loggedIn()->language()->addToStack( 'like_blurb_others_secondary', FALSE, array( 'pluralize' => array( $andXOthers - count( $peopleToDisplayInSecondaryView ) ) ) );
|
||||
}
|
||||
$peopleToDisplayInMainView[] = \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->reputationOthers( $this->url( 'showRep' ), \IPS\Member::loggedIn()->language()->addToStack( 'like_blurb_others', FALSE, array( 'pluralize' => array( $andXOthers ) ) ), json_encode( $peopleToDisplayInSecondaryView ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise the "and X others" will just be static */
|
||||
else
|
||||
{
|
||||
$peopleToDisplayInMainView[] = \IPS\Member::loggedIn()->language()->addToStack( empty( $peopleToDisplayInMainView ) ? 'like_blurb_generic' : 'like_blurb_others', FALSE, array( 'pluralize' => array( $andXOthers ) ) );
|
||||
}
|
||||
|
||||
/* Put it all together */
|
||||
$this->likeBlurb = \IPS\Member::loggedIn()->language()->addToStack( 'like_blurb', FALSE, array( 'pluralize' => array( $numberOfLikes ), 'htmlsprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $peopleToDisplayInMainView ) ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
/* Nobody liked it - show nothing */
|
||||
else
|
||||
{
|
||||
$this->likeBlurb = \IPS\Member::loggedIn()->language()->addToStack('like_blurb_just_you');
|
||||
return $this->likeBlurb;
|
||||
$this->likeBlurb = '';
|
||||
}
|
||||
}
|
||||
|
||||
if( \IPS\Member::loggedIn()->group['gbw_view_reps'] )
|
||||
{
|
||||
/* 3 random names */
|
||||
$idColumn = static::$databaseColumnId;
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_reputation_index', array( 'app=? AND type=? AND type_id=? AND member_id!=? AND rep_rating=?', static::$application, static::$reputationType, $this->$idColumn, ( \IPS\Member::loggedIn()->member_id ) ?: 0, 1 ), 'RAND()', 3 ) as $rep )
|
||||
{
|
||||
$people[] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( \IPS\Member::load( $rep['member_id'] ) );
|
||||
$reputation--;
|
||||
}
|
||||
}
|
||||
|
||||
/* X others */
|
||||
$count = count( $people ) + $reputation;
|
||||
if ( $reputation )
|
||||
{
|
||||
$others = \IPS\Member::loggedIn()->language()->addToStack( empty( $people ) ? 'like_blurb_generic' : 'like_blurb_others', FALSE, array( 'pluralize' => array( $reputation ) ) );
|
||||
if ( \IPS\Member::loggedIn()->group['gbw_view_reps'] )
|
||||
{
|
||||
$others = \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->reputationOthers( $this, $others );
|
||||
}
|
||||
$people[] = $others;
|
||||
}
|
||||
|
||||
$this->likeBlurb = \IPS\Member::loggedIn()->language()->addToStack( 'like_blurb', FALSE, array( 'pluralize' => array( $count ), 'htmlsprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $people ) ) ) );
|
||||
|
||||
return $this->likeBlurb;
|
||||
}
|
||||
|
||||
@@ -1405,7 +1451,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$idColumn = $this::$databaseColumnId;
|
||||
try
|
||||
{
|
||||
$count = $this->notificationRecipients()->count( TRUE );
|
||||
$count = $this->notificationRecipients( NULL, NULL, TRUE );
|
||||
}
|
||||
catch ( \BadMethodCallException $e )
|
||||
{
|
||||
@@ -1415,7 +1461,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
/* Queue if there's lots, or just send them */
|
||||
if ( $count > static::NOTIFICATIONS_PER_BATCH )
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'Follow', array( 'class' => get_class( $this ), 'item' => $this->$idColumn, 'exclude' => array_keys( $sentTo ) ), 1 );
|
||||
\IPS\Task::queue( 'core', 'Follow', array( 'class' => get_class( $this ), 'item' => $this->$idColumn, 'sentTo' => $sentTo ), 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1427,11 +1473,11 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
* Send notifications batch
|
||||
*
|
||||
* @param int $offset Current offset
|
||||
* @param array $exclude IDs to exclude
|
||||
* @param array $sentTo Members who have already received a notification and how - e.g. array( 1 => array( 'inline', 'email' )
|
||||
* @param string|NULL $extra Additional data
|
||||
* @return int|null New offset or NULL if complete
|
||||
*/
|
||||
public function sendNotificationsBatch( $offset=0, $exclude=array(), $extra=NULL )
|
||||
public function sendNotificationsBatch( $offset=0, &$sentTo=array(), $extra=NULL )
|
||||
{
|
||||
$followIds = array();
|
||||
$followers = $this->notificationRecipients( array( $offset, static::NOTIFICATIONS_PER_BATCH ), $extra );
|
||||
@@ -1442,19 +1488,20 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
foreach ( $followers as $follower )
|
||||
{
|
||||
$member = \IPS\Member::load( $follower['follow_member_id'] );
|
||||
if ( $member != $this->author() and $this->canView( $member ) and !in_array( $follower['follow_member_id'], $exclude ) )
|
||||
if ( $member != $this->author() and $this->canView( $member ) )
|
||||
{
|
||||
$followIds[] = $follower['follow_id'];
|
||||
$notification->recipients->attach( $member, $follower );
|
||||
}
|
||||
}
|
||||
$notification->send();
|
||||
|
||||
|
||||
/* Log that we sent it */
|
||||
if( count( $followIds ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_follow', array( 'follow_notify_sent' => time() ), \IPS\Db::i()->in( 'follow_id', $followIds ) );
|
||||
}
|
||||
|
||||
$sentTo = $notification->send( $sentTo );
|
||||
|
||||
/* Update the queue */
|
||||
$newOffset = $offset + static::NOTIFICATIONS_PER_BATCH;
|
||||
@@ -1486,29 +1533,59 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_moderators' ) AS $mod )
|
||||
{
|
||||
$canView = FALSE;
|
||||
$canApprove = FALSE;
|
||||
if ( $mod['perms'] == '*' )
|
||||
{
|
||||
$canView = TRUE;
|
||||
$canApprove = TRUE;
|
||||
}
|
||||
if ( $canView === FALSE )
|
||||
else
|
||||
{
|
||||
$perms = json_decode( $mod['perms'], TRUE );
|
||||
|
||||
if ( isset( $perms['can_view_hidden_content'] ) AND $perms['can_view_hidden_content'] )
|
||||
|
||||
foreach ( array( 'canView' => 'can_view_hidden_', 'canApprove' => 'can_unhide_' ) as $varKey => $modPermKey )
|
||||
{
|
||||
$canView = TRUE;
|
||||
}
|
||||
else if ( isset( $perms['can_view_hidden_' . static::$title ] ) AND $perms['can_view_hidden_' . static::$title ] )
|
||||
{
|
||||
$canView = TRUE;
|
||||
if ( isset( $perms[ $modPermKey . 'content' ] ) AND $perms[ $modPermKey . 'content' ] )
|
||||
{
|
||||
$$varKey = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
$container = ( $this instanceof \IPS\Content\Comment ) ? $this->item()->container() : $this->container();
|
||||
$containerClass = get_class( $container );
|
||||
$title = static::$title;
|
||||
if
|
||||
(
|
||||
isset( $containerClass::$modPerm )
|
||||
and
|
||||
(
|
||||
$perms[ $containerClass::$modPerm ] === -1
|
||||
or
|
||||
(
|
||||
is_array( $perms[ $containerClass::$modPerm ] )
|
||||
and
|
||||
in_array( $container->_id, $perms[ $containerClass::$modPerm ] )
|
||||
)
|
||||
)
|
||||
and
|
||||
$perms["{$modPermKey}{$title}"]
|
||||
)
|
||||
{
|
||||
$$varKey = TRUE;
|
||||
}
|
||||
}
|
||||
catch ( \BadMethodCallException $e ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $canView === TRUE )
|
||||
if ( $canView === TRUE and $canApprove === TRUE )
|
||||
{
|
||||
$moderators[ $mod['type'] ][] = $mod['id'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'unapproved_content', $this, array( $this, $this->author() ) );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', ( count( $moderators['m'] ) ? \IPS\Db::i()->in( 'member_id', $moderators['m'] ) . ' OR ' : '' ) . \IPS\Db::i()->in( 'member_group_id', $moderators['g'] ) . ' OR ' . \IPS\Db::i()->findInSet( 'mgroup_others', $moderators['g'] ) ) as $member )
|
||||
{
|
||||
@@ -1537,7 +1614,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
* Send quote and mention notifications
|
||||
*
|
||||
* @param array $exclude An array of member IDs *not* to send notifications to
|
||||
* @return array Member IDs sent to
|
||||
* @return array The members that were notified and how they were notified
|
||||
*/
|
||||
protected function sendQuoteAndMentionNotifications( $exclude=array() )
|
||||
{
|
||||
@@ -1549,7 +1626,7 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
*
|
||||
* @param array array( 'quotes' => array( ... member IDs ... ), 'mentions' => array( ... member IDs ... ) )
|
||||
* @param array $exclude An array of member IDs *not* to send notifications to
|
||||
* @return array Member IDs sent to
|
||||
* @return array The members that were notified and how they were notified
|
||||
*/
|
||||
protected function _sendQuoteAndMentionNotifications( $data, $exclude=array() )
|
||||
{
|
||||
@@ -1563,16 +1640,16 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
} );
|
||||
if ( !empty( $data['quotes'] ) )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'quote', ( $this instanceof \IPS\Content\Item ) ? $this : $this->item(), array( $this ), array( $this->author()->member_id ) );
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'quote', ( $this instanceof \IPS\Content\Item ) ? $this : $this->item(), array( $this ), array( $this->author()->member_id ), FALSE );
|
||||
foreach ( $data['quotes'] as $quote )
|
||||
{
|
||||
$member = \IPS\Member::load( $quote );
|
||||
if ( $member != $this->author() and $this->canView( $member ) )
|
||||
if ( $member->member_id and $member != $this->author() and $this->canView( $member ) )
|
||||
{
|
||||
$notification->recipients->attach( $member );
|
||||
}
|
||||
}
|
||||
$sentTo = array_merge( $notification->send(), $sentTo );
|
||||
$sentTo = $notification->send( $sentTo );
|
||||
}
|
||||
|
||||
/* Mentions */
|
||||
@@ -1582,16 +1659,16 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
} );
|
||||
if ( !empty( $data['mentions'] ) )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'mention', ( $this instanceof \IPS\Content\Item ) ? $this : $this->item(), array( $this ), array( $this->author()->member_id ) );
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'mention', ( $this instanceof \IPS\Content\Item ) ? $this : $this->item(), array( $this ), array( $this->author()->member_id ), FALSE );
|
||||
foreach ( $data['mentions'] as $mention )
|
||||
{
|
||||
$member = \IPS\Member::load( $mention );
|
||||
if ( $member != $this->author() and $this->canView( $member ) )
|
||||
if ( $member != $this->author() and $this->canView( $member ) and !$member->isIgnoring( $this->author(), 'mentions' ) )
|
||||
{
|
||||
$notification->recipients->attach( $member );
|
||||
}
|
||||
}
|
||||
$sentTo = array_merge( $notification->send(), $sentTo );
|
||||
$sentTo = $notification->send( $sentTo );
|
||||
}
|
||||
|
||||
/* Return */
|
||||
@@ -1608,9 +1685,8 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
$return = array( 'quotes' => array(), 'mentions' => array() );
|
||||
|
||||
$document = new \DOMDocument;
|
||||
libxml_use_internal_errors(TRUE);
|
||||
if ( @$document->loadHTML( '<div>' . $content . '</div>' ) !== FALSE )
|
||||
$document = new \IPS\Xml\DOMDocument( '1.0', 'UTF-8' );
|
||||
if ( @$document->loadHTML( \IPS\Xml\DOMDocument::wrapHtml( '<div>' . $content . '</div>' ) ) !== FALSE )
|
||||
{
|
||||
/* Quotes */
|
||||
foreach( $document->getElementsByTagName('blockquote') as $quote )
|
||||
@@ -1625,9 +1701,8 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
foreach( $document->getElementsByTagName('a') as $link )
|
||||
{
|
||||
if ( $link->getAttribute('data-mentionid') )
|
||||
{
|
||||
$path = explode( '/', $link->getNodePath() );
|
||||
if ( !in_array( 'blockquote', $path ) )
|
||||
{
|
||||
if ( !preg_match( '/\/blockquote(\[\d*\])?\//', $link->getNodePath() ) )
|
||||
{
|
||||
$return['mentions'][] = $link->getAttribute('data-mentionid');
|
||||
}
|
||||
@@ -1696,6 +1771,18 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the HTML parsing enabled flag for rebuilds?
|
||||
*
|
||||
* @note By default this will return FALSE, but classes can override
|
||||
* @see \IPS\forums\Topic\Post
|
||||
* @return bool
|
||||
*/
|
||||
public function htmlParsingEnforced()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return any custom multimod actions this content item supports
|
||||
*
|
||||
@@ -1753,4 +1840,38 @@ abstract class _Content extends \IPS\Patterns\ActiveRecord
|
||||
$lang = $lang ?: \IPS\Member::loggedIn()->language();
|
||||
return $lang->addToStack( '__indefart_' . static::$title, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Definite Article
|
||||
*
|
||||
* @param \IPS\Lang|NULL $language The language to use, or NULL for the language of the currently logged in member
|
||||
* @return string
|
||||
*/
|
||||
public function definiteArticle( \IPS\Lang $lang = NULL )
|
||||
{
|
||||
$container = ( $this instanceof \IPS\Content\Comment ) ? $this->item()->containerWrapper() : $this->containerWrapper();
|
||||
return static::_definiteArticle( $container ? $container->_data : array(), $lang );
|
||||
}
|
||||
|
||||
/**
|
||||
* Definite Article
|
||||
*
|
||||
* @param \IPS\Lang|NULL $language The language to use, or NULL for the language of the currently logged in member
|
||||
* @return string
|
||||
*/
|
||||
public static function _definiteArticle( array $containerData = NULL, \IPS\Lang $lang = NULL )
|
||||
{
|
||||
$lang = $lang ?: \IPS\Member::loggedIn()->language();
|
||||
return $lang->addToStack( '__defart_' . static::$title, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get preview image for share services
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function shareImage()
|
||||
{
|
||||
return (string) \IPS\Theme::i()->logo_sharer;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user