Version 4.7.6
This commit is contained in:
1 parent
8ba7d43898
commit
7b7404e741
1085 files changed
+30590
-7837
No files matched your search
@@ -180,18 +180,23 @@ class _Recognize extends \IPS\Patterns\ActiveRecord
|
||||
try
|
||||
{
|
||||
$author = \IPS\Member::load( $this->member_id );
|
||||
|
||||
if ( $this->points )
|
||||
{
|
||||
/* Wade does it this way so I guess there's a reason. And let the reason be love */
|
||||
\IPS\Db::i()->update( 'core_members', "achievements_points = achievements_points - " . \intval( $this->points ), [ 'member_id=?', $this->member_id ] );
|
||||
\IPS\Db::i()->delete( 'core_points_log', [ 'recognize=?', $this->id ] );
|
||||
}
|
||||
|
||||
if ( $this->badge )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_member_badges', [ 'member_id=? and recognize_id=?', $this->member_id, $this->id ] );
|
||||
\IPS\Db::i()->delete( 'core_member_badges', [ 'member=? and recognize=?', $this->member_id, $this->id ] );
|
||||
}
|
||||
|
||||
/* Remove notifications */
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'item_class=? and notification_key=? and item_id=? and extra=?', 'IPS\Member', 'new_recognize', $this->member_id, '[' . $this->id . ']' ) );
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
catch( \Exception $e ) {}
|
||||
|
||||
parent::delete();
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ class _Alert extends \IPS\Content\Item
|
||||
$form = new \IPS\Helpers\Form( NULL, 'save' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_disable_pm == 2 )
|
||||
if ( ! \IPS\Member::loggedIn()->canUseMessenger() )
|
||||
{
|
||||
$form->addMessage( 'alert_you_cannot_receive_messages', 'ipsMessage ipsMessage_info' );
|
||||
}
|
||||
@@ -157,11 +157,38 @@ class _Alert extends \IPS\Content\Item
|
||||
{
|
||||
throw new \InvalidArgumentException( 'alert_no_recipient_selected' );
|
||||
}
|
||||
|
||||
if ( ! $member->canUseMessenger() and \IPS\Request::i()->alert_reply == 2 )
|
||||
{
|
||||
throw new \InvalidArgumentException( \IPS\Member::loggedIn()->language()->addToStack( 'alert_member_pm_disabled', NULL, [ 'sprintf' => $member->name ] ) );
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL, NULL, 'alert_recipient_user' ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'alert_recipient_group', ( $alert and $alert->recipient_group ) ? explode( ',', $alert->recipient_group ) : array(), FALSE, array( 'options' => $groups, 'multiple' => TRUE ), NULL, NULL, NULL, 'alert_recipient_group' ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'alert_recipient_group', ( $alert and $alert->recipient_group ) ? explode( ',', $alert->recipient_group ) : array(), FALSE, array( 'options' => $groups, 'multiple' => TRUE ), function( $groups )
|
||||
{
|
||||
if ( \IPS\Request::i()->alert_reply == 2 )
|
||||
{
|
||||
$module = \IPS\Application\Module::get( 'core', 'messaging' );
|
||||
$names = [];
|
||||
foreach( $groups as $group )
|
||||
{
|
||||
$group = \IPS\Member\Group::load( $group );
|
||||
if ( ! ( \IPS\Application::load( $module->application )->canAccess( $group ) and ( $module->protected or $module->can( 'view', $group ) ) ) )
|
||||
{
|
||||
$names[] = $group->name;
|
||||
}
|
||||
}
|
||||
|
||||
if ( \count( $names ) )
|
||||
{
|
||||
throw new \InvalidArgumentException( \IPS\Member::loggedIn()->language()->addToStack( 'alert_member_group_pm_disabled', NULL, [ 'htmlsprintf' => \IPS\Member::loggedIn()->language()->formatList( $names ) ] ) );
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL, NULL, 'alert_recipient_group' ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'alert_show_to', ( $alert and $alert->show_to ) ? $alert->show_to : 'all', FALSE, [
|
||||
'options' => [
|
||||
'all' => 'alert_show_to_all',
|
||||
@@ -170,10 +197,11 @@ class _Alert extends \IPS\Content\Item
|
||||
], NULL, NULL, NULL, 'alert_show_to' ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'alert_anonymous', ( $alert and $alert->anonymous ) ? TRUE : FALSE, TRUE, array( 'togglesOff' => array( 'alert_reply') ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'alert_reply', $alert ? $alert->reply : 0, TRUE, array( 'disabled' => (bool) \IPS\Member::loggedIn()->members_disable_pm, 'options' => array( '0' => 'alert_no_reply', '1' => 'alert_can_reply', '2' => 'alert_must_reply' ) ), NULL, NULL, NULL, 'alert_reply' ) );
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_disable_pm != 2 )
|
||||
if ( \IPS\Member::loggedIn()->members_disable_pm )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'alert_reply', $alert ? $alert->reply : 0, TRUE, array( 'options' => array( '0' => 'alert_no_reply', '1' => 'alert_can_reply', '2' => 'alert_must_reply' ) ), NULL, NULL, NULL, 'alert_reply' ) );
|
||||
\IPS\Member::loggedIn()->language()->words['alert_reply_desc'] = \IPS\Member::loggedIn()->language()->get('alert_reply__nopm_desc');
|
||||
}
|
||||
|
||||
return $form;
|
||||
@@ -191,7 +219,7 @@ class _Alert extends \IPS\Content\Item
|
||||
\IPS\Data\Store::i()->alerts = iterator_to_array( \IPS\Db::i()->select( '*', static::$databaseTable, [
|
||||
[ 'alert_enabled=?', 1 ],
|
||||
[ 'alert_start < ?', time() ],
|
||||
[ '( alert_end = 0 or alert_end < ? )', time() ]
|
||||
[ '( alert_end = 0 or alert_end > ? )', time() ]
|
||||
], "alert_start ASC" )->setKeyField( 'alert_id' ) );
|
||||
}
|
||||
|
||||
@@ -220,8 +248,8 @@ class _Alert extends \IPS\Content\Item
|
||||
$obj->title = $values['alert_title'];
|
||||
$obj->seo_title = \IPS\Http\Url\Friendly::seoTitle( $values['alert_title'] );
|
||||
$obj->content = $values['alert_content'];
|
||||
$obj->start = $values['alert_start'] ? ( $values['alert_start']->getTimestamp() < time() ) ? time() : $values['alert_start']->getTimestamp() : time();
|
||||
$obj->end = $values['alert_end'] ? $values['alert_end']->getTimestamp() : 0;
|
||||
$obj->start = !empty( $values['alert_start'] ) ? ( $values['alert_start']->getTimestamp() < time() ) ? time() : $values['alert_start']->getTimestamp() : time();
|
||||
$obj->end = !empty ($values['alert_end'] ) ? $values['alert_end']->getTimestamp() : 0;
|
||||
|
||||
$obj->recipient_type = $values['alert_recipient_type'];
|
||||
|
||||
@@ -242,7 +270,7 @@ class _Alert extends \IPS\Content\Item
|
||||
}
|
||||
|
||||
$obj->anonymous = $values['alert_anonymous'];
|
||||
$obj->reply = ( \IPS\Member::loggedIn()->members_disable_pm == 2 ) ? 0 : $values['alert_reply'];
|
||||
$obj->reply = ( ! \IPS\Member::loggedIn()->canUseMessenger() ) ? 0 : $values['alert_reply'];
|
||||
|
||||
$obj->save();
|
||||
|
||||
@@ -486,4 +514,65 @@ class _Alert extends \IPS\Content\Item
|
||||
|
||||
\IPS\Db::i()->delete( 'core_alerts_seen', [ 'seen_alert_id=?', $this->id ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of how many replies have been sent in via this alert
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function membersRepliedCount(): int
|
||||
{
|
||||
return (int) \IPS\Db::i()->select( 'COUNT(*)', 'core_message_topics', [ 'mt_alert=?', $this->id ] )->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current alert that messenger is being filtered by
|
||||
*
|
||||
* @param \IPS\Member|null $member
|
||||
* @return Alert|null
|
||||
*/
|
||||
public static function getAlertCurrentlyFilteringMessages( ?\IPS\Member $member = NULL ): ?\IPS\core\Alerts\Alert
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
|
||||
if ( isset( $_SESSION['mt_alert'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$alert = static::load( $_SESSION['mt_alert'] );
|
||||
|
||||
/* Only show details about this alert to the alert owner */
|
||||
if ( $alert->author()->member_id != $member->member_id )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return $alert;
|
||||
}
|
||||
catch( \Exception $e ) { }
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alert to currently filter by
|
||||
*
|
||||
* @param Alert $alert
|
||||
* @return void
|
||||
*/
|
||||
public static function setAlertCurrentlyFilteringMessages( \IPS\core\Alerts\Alert $alert )
|
||||
{
|
||||
$_SESSION['mt_alert'] = $alert->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset any messenger filters
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clearMessengerFilters()
|
||||
{
|
||||
unset( $_SESSION['mt_alert'] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Deletion Log Model
|
||||
* @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 10 Nov 2016
|
||||
*/
|
||||
|
||||
namespace IPS\core;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletion Log Model
|
||||
*/
|
||||
class _Approval extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
/**
|
||||
* @brief Database Table
|
||||
*/
|
||||
public static $databaseTable = 'core_approval_queue';
|
||||
|
||||
/**
|
||||
* @brief Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'approval_';
|
||||
|
||||
/**
|
||||
* @brief Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] ID Database Column
|
||||
*/
|
||||
public static $databaseColumnId = 'id';
|
||||
|
||||
/**
|
||||
* @brief [ActiveRecord] Multiton Map
|
||||
*/
|
||||
protected static $multitonMap = array();
|
||||
|
||||
/**
|
||||
* Set Held Data
|
||||
*
|
||||
* @param NULL|array $data The data indicating why the content was held for approval
|
||||
* @return void
|
||||
*/
|
||||
public function set_held_data( ?array $data )
|
||||
{
|
||||
if ( \is_array( $data ) )
|
||||
{
|
||||
$this->_data['held_data'] = json_encode( $data );
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_data['held_data'] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Held Data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_held_data(): ?array
|
||||
{
|
||||
if ( $this->_data['held_data'] )
|
||||
{
|
||||
return json_decode( $this->_data['held_data'], true );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Held Reason
|
||||
*
|
||||
* @param NULL|string $reason The reason for requiring approval.
|
||||
* @return void
|
||||
*/
|
||||
public function set_held_reason( ?string $reason )
|
||||
{
|
||||
if ( $reason AND \in_array( $reason, static::availableReasons() ) )
|
||||
{
|
||||
$this->_data['held_reason'] = $reason;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_data['held_reason'] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Held Reason
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member, or NULL for currently logged in.
|
||||
* #return NULL|string
|
||||
*/
|
||||
public function reason( ?\IPS\Member $member = NULL ): string
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
if ( $this->held_reason )
|
||||
{
|
||||
if ( $extra = $this->parseReason() )
|
||||
{
|
||||
return $member->language()->addToStack( $extra['lang'], TRUE, ( isset( $extra['sprintf'] ) ) ? array( 'sprintf' => $extra['sprintf'] ) : array() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return $member->language()->addToStack( "approval_reason_{$this->held_reason}" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return $member->language()->addToStack( "approval_reason_unknown" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Reason
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member, or NULL for currently logged in.
|
||||
* @return NULL|array
|
||||
*/
|
||||
public function parseReason( ?\IPS\Member $member = NULL ): ?array
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
if ( $this->held_reason )
|
||||
{
|
||||
switch( $this->held_reason )
|
||||
{
|
||||
case 'profanity':
|
||||
return array(
|
||||
'lang' => 'approval_reason_profanity',
|
||||
'sprintf' => array( $this->held_data['word'] )
|
||||
);
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
return array(
|
||||
'lang' => 'approval_reason_url',
|
||||
'sprintf' => array( $this->held_data['url'] )
|
||||
);
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
return array(
|
||||
'lang' => 'approval_reason_email',
|
||||
'sprintf' => array( $this->held_data['email'] )
|
||||
);
|
||||
break;
|
||||
|
||||
case 'node':
|
||||
$contentClass = $this->content_class;
|
||||
$content = $contentClass::load( $this->content_id );
|
||||
return array(
|
||||
'lang' => 'approval_reason_node',
|
||||
'sprintf' => array( $content->indefiniteArticle(), $content->container()->url(), $content->container()->getTitleForLanguage( $member->language() ), $content->definiteArticle( $member->language(), 2 ) )
|
||||
);
|
||||
break;
|
||||
|
||||
case 'item':
|
||||
$contentClass = $this->content_class;
|
||||
$content = $contentClass::load( $this->content_id );
|
||||
$title = ( $content instanceof \IPS\Content\Comment ) ? $content->item()->mapped('title') : $content->mapped('title');
|
||||
return array(
|
||||
'lang' => 'approval_reason_item',
|
||||
'sprintf' => array( $content->url(), $title )
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Available Reasons
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function availableReasons(): array
|
||||
{
|
||||
return array(
|
||||
'profanity',
|
||||
'url',
|
||||
'email',
|
||||
'user',
|
||||
'group',
|
||||
'node',
|
||||
'item'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load from Content
|
||||
*
|
||||
* @param string $class Content class
|
||||
* @param int $id Content ID
|
||||
* @return static
|
||||
*/
|
||||
public static function loadFromContent( string $class, int $id ): \IPS\core\Approval
|
||||
{
|
||||
try
|
||||
{
|
||||
return static::constructFromData( \IPS\Db::i()->select( '*', 'core_approval_queue', array( "approval_content_class=? AND approval_content_id=?", $class, $id ) )->first() );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Whitespace-only changes.
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Bulkmail central library
|
||||
* @brief Datalayer Class
|
||||
* @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/
|
||||
@@ -18,7 +18,7 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk mail central library
|
||||
* Datalayer Class
|
||||
*/
|
||||
class _DataLayer extends \IPS\Patterns\Singleton
|
||||
{
|
||||
|
||||
@@ -98,6 +98,8 @@ class _SocialProfiles extends \IPS\Helpers\Form\KeyValue
|
||||
'xing' => "siteprofilelink_xing",
|
||||
'weibo' => "siteprofilelink_weibo",
|
||||
'vk' => "siteprofilelink_vk",
|
||||
'discord' => "siteprofilelink_discord",
|
||||
'twitch' => "siteprofilelink_twitch",
|
||||
);
|
||||
|
||||
return $options;
|
||||
|
||||
@@ -85,7 +85,7 @@ class _Ignore extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( NULL, $ignore ? 'ignore_edit' : 'ignore_submit' );
|
||||
$form = new \IPS\Helpers\Form( 'ignore_form', $ignore ? 'ignore_edit' : 'ignore_submit' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Member( 'member', $ignore ? \IPS\Member::load( $ignore->ignore_id ) : NULL, TRUE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('ignore_placeholder') ) ) );
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class _IndexNow extends \IPS\Patterns\Singleton
|
||||
return;
|
||||
}
|
||||
|
||||
$url = \IPS\Http\Url::internal('');
|
||||
$url = \IPS\Http\Url::internal( '', 'front' );
|
||||
$data = array(
|
||||
'host' => \IPS\Http\Url::baseUrl(\IPS\Http\Url::PROTOCOL_WITHOUT ),
|
||||
'key' => \IPS\Settings::i()->indexnow_key,
|
||||
@@ -95,27 +95,30 @@ class _IndexNow extends \IPS\Patterns\Singleton
|
||||
'urlList' => $urls,
|
||||
);
|
||||
|
||||
$response = \IPS\Http\Url::external( static::$apiUrl )->request()
|
||||
->setHeaders( array( 'Content-Type' => 'application/json' ) )->post( json_encode( $data ) );
|
||||
|
||||
if( !$response->isSuccessful() )
|
||||
{
|
||||
switch ( $response->httpResponseCode )
|
||||
{
|
||||
case 400:
|
||||
$error = 'invalid_request';
|
||||
break;
|
||||
case 403:
|
||||
$error = 'invalid_api_key';
|
||||
breaK;
|
||||
case 422:
|
||||
$error = 'invalid_url';
|
||||
break;
|
||||
case 429:
|
||||
default:
|
||||
$error = 'unknown_error';
|
||||
try {
|
||||
$response = \IPS\Http\Url::external(static::$apiUrl)->request()
|
||||
->setHeaders(array('Content-Type' => 'application/json'))->post(json_encode($data));
|
||||
if (!$response->isSuccessful()) {
|
||||
switch ($response->httpResponseCode) {
|
||||
case 400:
|
||||
$error = 'invalid_request';
|
||||
break;
|
||||
case 403:
|
||||
$error = 'invalid_api_key';
|
||||
break;
|
||||
case 422:
|
||||
$error = 'invalid_url';
|
||||
break;
|
||||
case 429:
|
||||
default:
|
||||
$error = 'unknown_error';
|
||||
}
|
||||
\IPS\Log::log($response->httpResponseCode . ' ' . $error . ' ' . print_r($data, TRUE), 'IndexNow');
|
||||
}
|
||||
\IPS\Log::log( $response->httpResponseCode . ' ' . $error . ' ' . print_r($data, TRUE ), 'IndexNow');
|
||||
} catch (\IPS\Http\Request\CurlException $e)
|
||||
{
|
||||
\IPS\Log::log($e->getMessage(), 'IndexNow');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -313,23 +313,49 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
*
|
||||
* @param string $content The content to check
|
||||
* @param \IPS\Member|NULL $member The author of the content
|
||||
* @param array|NULL $filtersMatched What matched, passed by reference
|
||||
* @return bool
|
||||
*/
|
||||
public static function hiddenByFilters( $content, $member=NULL )
|
||||
public static function hiddenByFilters( $content, $member=NULL, array &$filtersMatched = array() )
|
||||
{
|
||||
$return = static::_checkProfanityFilters( $content, $member );
|
||||
|
||||
if ( $return == FALSE )
|
||||
if ( \is_string( $return ) )
|
||||
{
|
||||
$return = static::_checkUrlFilters( $content );
|
||||
}
|
||||
|
||||
if ( $return == FALSE )
|
||||
{
|
||||
$return = static::_checkEmailFilters( $content );
|
||||
$filtersMatched = array(
|
||||
'type' => 'profanity',
|
||||
'match' => $return
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return $return;
|
||||
$return = static::_checkUrlFilters( $content );
|
||||
|
||||
if ( \is_string( $return ) )
|
||||
{
|
||||
$filtersMatched = array(
|
||||
'type' => 'url',
|
||||
'match' => $return
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$return = static::_checkEmailFilters( $content );
|
||||
|
||||
if ( \is_string( $return ) )
|
||||
{
|
||||
/* Add to approval queue table */
|
||||
$filtersMatched = array(
|
||||
'type' => 'email',
|
||||
'match' => $return
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,12 +363,19 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
*
|
||||
* @param string $content The content to check
|
||||
* @param \IPS\Member|NULL $member The author of the content
|
||||
* @return bool
|
||||
* @return bool|string
|
||||
*/
|
||||
protected static function _checkProfanityFilters( $content, $member=NULL )
|
||||
{
|
||||
$looseProfanity = array();
|
||||
$exactProfanity = array();
|
||||
|
||||
/* Clean up profanity a little to remove citation details and inline data attributes.
|
||||
We don't want to remove <blockquotes> entirely as users can then hide profanity in a quote box to
|
||||
bypass the system. */
|
||||
$content = preg_replace( "#<blockquote\s+?class=\"ipsQuote\"[^>]+?>#", "<blockquote>", $content );
|
||||
$content = preg_replace( "#<div\s+?class=\"ipsQuote_citation\"([^>]+?)?>(.+?)</div>#s", "", $content );
|
||||
|
||||
foreach( static::getProfanity() AS $profanity )
|
||||
{
|
||||
if ( $profanity->action == 'moderate' )
|
||||
@@ -370,7 +403,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
{
|
||||
if ( mb_stristr( $content, $word ) )
|
||||
{
|
||||
return TRUE;
|
||||
return $word;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -393,7 +426,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
{
|
||||
if ( \in_array( mb_strtolower( $section ), array_map( 'mb_strtolower', $exactProfanity ) ) )
|
||||
{
|
||||
return TRUE;
|
||||
return $word;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -408,7 +441,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
* Check URL Filters
|
||||
*
|
||||
* @param string $content The content to check
|
||||
* @return bool
|
||||
* @return bool|string
|
||||
*/
|
||||
protected static function _checkUrlFilters( $content )
|
||||
{
|
||||
@@ -455,7 +488,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
{
|
||||
if ( \IPS\Settings::i()->ipb_url_filter_option == 'none' )
|
||||
{
|
||||
return TRUE;
|
||||
return $tag->hasAttribute( 'href' );
|
||||
}
|
||||
|
||||
$urlToCheck = $tag->hasAttribute( 'href' ) ? $tag->getAttribute( 'href' ) : ( $tag->hasAttribute( 'src' ) ? $tag->getAttribute( 'src' ) : $tag->getAttribute( 'data-embed-src' ) );
|
||||
@@ -481,7 +514,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
/* IF we are moderating all URL's and it's not an attachment, return here. */
|
||||
if ( $good !== TRUE AND \IPS\Settings::i()->ipb_url_filter_option == 'none' )
|
||||
{
|
||||
return TRUE;
|
||||
return $good;
|
||||
}
|
||||
|
||||
$url = preg_quote( $url, '/' );
|
||||
@@ -492,7 +525,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
{
|
||||
if ( preg_match( '/' . $url . '/i', $urlToCheck ) )
|
||||
{
|
||||
return TRUE;
|
||||
return $urlToCheck;
|
||||
}
|
||||
}
|
||||
/* If it's a whitelist, check that */
|
||||
@@ -501,7 +534,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
/* @note http:// is hard-coded here as we're simply validating that the URL is on the same domain, so the protocol doesn't matter for the base_url replacement */
|
||||
if ( !preg_match( '/' . $url . '/i', str_replace( '<___base_url___>', 'http://' . parse_url( \IPS\Settings::i()->base_url, PHP_URL_HOST ), $urlToCheck ), $matches ) )
|
||||
{
|
||||
$good = FALSE;
|
||||
$good = $urlToCheck;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -514,9 +547,9 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
}
|
||||
}
|
||||
|
||||
if ( $good === FALSE AND \IPS\Settings::i()->ipb_url_filter_option == 'white' )
|
||||
if ( $good !== TRUE AND \IPS\Settings::i()->ipb_url_filter_option == 'white' )
|
||||
{
|
||||
return TRUE;
|
||||
return $good;
|
||||
}
|
||||
}
|
||||
catch( \Exception $e ) {}
|
||||
@@ -530,7 +563,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
* Check Email Filters
|
||||
*
|
||||
* @param string $content The content to check
|
||||
* @return bool
|
||||
* @return bool|string
|
||||
*/
|
||||
protected static function _checkEmailFilters( $content )
|
||||
{
|
||||
@@ -578,7 +611,7 @@ class _Profanity extends \IPS\Patterns\ActiveRecord implements \JsonSerializable
|
||||
|
||||
if( preg_match( '/' . \IPS\Text\Parser::EMAIL_REGEX . '/u', $content, $matches ) )
|
||||
{
|
||||
return TRUE;
|
||||
return $matches[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -644,7 +644,8 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
$this->failed = ( $hasFailed ) ? $this->failed + 1 : 0;
|
||||
$this->returned = $returned;
|
||||
$this->save();
|
||||
}
|
||||
\IPS\Api\Webhook::fire( 'content_promoted', $this, $this->object()->webhookFilters() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Changed Columns
|
||||
@@ -737,7 +738,7 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Shorten URL.
|
||||
*
|
||||
* @param string $service Service key, (such as facebook or twitter)
|
||||
* @param string $service Service key, (such as twitter)
|
||||
* @return boolean
|
||||
*/
|
||||
public function serviceFailed( $service )
|
||||
@@ -755,7 +756,7 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Returns text sent to a named service
|
||||
*
|
||||
* @param string $service Service key (twitter, facebook)
|
||||
* @param string $service Service key (twitter)
|
||||
* @param boolean $forDisplay Is this for display in output?
|
||||
* @return string|NULL
|
||||
*/
|
||||
@@ -774,7 +775,7 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Sets text for a named service
|
||||
*
|
||||
* @param string $service Service key (twitter, facebook)
|
||||
* @param string $service Service key (twitter)
|
||||
* @param boolean $text Text to save
|
||||
* @return string|NULL
|
||||
*/
|
||||
@@ -788,7 +789,7 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Return the published URL for this post
|
||||
*
|
||||
* @param string $service Service key, (such as facebook or twitter)
|
||||
* @param string $service Service key, (such as twitter)
|
||||
* @return string|NULL
|
||||
*/
|
||||
public function getPublishedUrl( $service )
|
||||
@@ -806,7 +807,7 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
return $this->object()->url();
|
||||
}
|
||||
catch ( \InvalidArgumentException $e )
|
||||
catch ( \InvalidArgumentException|\RuntimeException $e )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -816,7 +817,7 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Attempt to get all responses for this ID
|
||||
*
|
||||
* @param string $service Service to return (twitter, facebook, etc)
|
||||
* @param string $service Service to return (facebook, etc)
|
||||
* @return array|NULL array( response_id => data )
|
||||
*/
|
||||
public function responses( $service )
|
||||
@@ -1399,4 +1400,27 @@ class _Promote extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get output for API
|
||||
*
|
||||
* @param \IPS\Member|NULL $authorizedMember The member making the API request or NULL for API Key / client_credentials
|
||||
*
|
||||
* @apiresponse \IPS\Member promotedBy The member who promoted the content item
|
||||
* @apiresponse string itemClass The FQN classname
|
||||
* @apiresponse string itemTitle Title
|
||||
* @apiresponse string itemDescription The content
|
||||
* @apiresponse object item The promoted content item
|
||||
*
|
||||
*/
|
||||
public function apiOutput( \IPS\Member $authorizedMember = NULL )
|
||||
{
|
||||
return [
|
||||
'promotedBy' => $this->author()->apiOutput($authorizedMember),
|
||||
'itemClass' => \get_class($this->object()),
|
||||
'itemTitle' => $this->objectTitle,
|
||||
'itemDescription' => $this->objectMetaDescription,
|
||||
'item' => $this->object()->apiOutput($authorizedMember),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,11 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
* @brief Title
|
||||
*/
|
||||
public static $title = 'report';
|
||||
|
||||
/**
|
||||
* @brief [Content\Item] Include these items in trending content
|
||||
*/
|
||||
public static $includeInTrending = FALSE;
|
||||
|
||||
/**
|
||||
* Should posting this increment the poster's post count?
|
||||
@@ -602,4 +607,113 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
'read', 'unread', 'report_status_1', 'report_status_2', 'report_status_3'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the where clause for finding reports
|
||||
*
|
||||
* @param \IPS\Member|null $member Member to base permissions on
|
||||
* @return array
|
||||
*/
|
||||
public static function where( \IPS\Member $member=NULL ): array
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$classWhere = [];
|
||||
$extensionWhere = [];
|
||||
$viewPermIds = [];
|
||||
$perms = $member->modPermissions();
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'app, perm_id', 'core_permission_index', \IPS\Db::i()->findInSet( 'perm_view', $member->permissionArray() ) . " OR perm_view='*'" ) as $perm )
|
||||
{
|
||||
$viewPermIds[ $perm['app'] ][] = $perm['perm_id'];
|
||||
}
|
||||
|
||||
foreach ( array_merge( ['IPS\core\Messenger\Conversation', 'IPS\core\Messenger\Message'], array_values( \IPS\Content::routedClasses( FALSE, TRUE ) ) ) as $class )
|
||||
{
|
||||
/* Got nodes? */
|
||||
$item = NULL;
|
||||
if ( is_subclass_of( $class, "IPS\Content\Item" ) )
|
||||
{
|
||||
$item = $class;
|
||||
}
|
||||
else if ( is_subclass_of( $class, "IPS\Content\Comment" ) or is_subclass_of( $class, "IPS\Content\Review" ) )
|
||||
{
|
||||
if ( isset( $class::$itemClass ) )
|
||||
{
|
||||
$item = $class::$itemClass;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $item )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$extensionWhereClause = '';
|
||||
if ( isset( $item::$containerNodeClass ) )
|
||||
{
|
||||
$container = $item::$containerNodeClass;
|
||||
if ( isset( $container::$modPerm ) )
|
||||
{
|
||||
if ( isset( $perms[$container::$modPerm] ) and $perms[$container::$modPerm] != '*' and $perms[$container::$modPerm] != '-1')
|
||||
{
|
||||
$extensionWhereClause = ' AND ' . \IPS\Db::i()->in( 'node_id', $perms[$container::$modPerm] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$workingClass = $class;
|
||||
if ( isset( $workingClass::$itemClass ) )
|
||||
{
|
||||
$workingClass = $workingClass::$itemClass;
|
||||
}
|
||||
if ( isset( $workingClass::$containerNodeClass ) )
|
||||
{
|
||||
$workingClass = $workingClass::$containerNodeClass;
|
||||
}
|
||||
if ( isset( $workingClass::$permissionMap ) and isset( $workingClass::$permissionMap['read'] ) and $workingClass::$permissionMap['read'] !== 'view' )
|
||||
{
|
||||
if ( !isset( $permIds[ $class::$application ][ $workingClass::$permissionMap['read'] ] ) )
|
||||
{
|
||||
$permIds[ $class::$application ][ $workingClass::$permissionMap['read'] ] = iterator_to_array( \IPS\Db::i()->select( 'perm_id', 'core_permission_index', "(" . \IPS\Db::i()->findInSet( 'perm_' . $workingClass::$permissionMap['read'], \IPS\Member::loggedIn()->permissionArray() ) . " OR perm_" . $workingClass::$permissionMap['read'] . "='*' ) AND app='{$class::$application}'" ) );
|
||||
}
|
||||
|
||||
if( isset( $viewPermIds[ $class::$application ] ) AND !empty( $permIds[ $class::$application ][ $workingClass::$permissionMap['read'] ] ) )
|
||||
{
|
||||
$classWhere[] = "( ( class='" . str_replace( '\\', '\\\\', $class ) . "' AND ( perm_id IN(" . implode( ',', array_intersect( $viewPermIds[ $class::$application ], $permIds[ $class::$application ][ $workingClass::$permissionMap['read'] ] ) ) . ") ) OR perm_id IS NULL )" . $extensionWhereClause . ")";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isset( $class::$application ) and isset( $viewPermIds[ $class::$application ] ) )
|
||||
{
|
||||
$classWhere[] = "( ( class='" . str_replace( '\\', '\\\\', $class ) . "' AND ( perm_id IN(" . implode( ',', $viewPermIds[ $class::$application ] ) . ") ) OR perm_id IS NULL )" . $extensionWhereClause . ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
$classWhere[] = "( class='" . str_replace( '\\', '\\\\', $class ) . "' )";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [ '(' . implode( ' OR ', array_values( $classWhere ) ) . ')' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Can view this entry
|
||||
*
|
||||
* @param \IPS\Member|NULL $member The member or NULL for currently logged in member.
|
||||
* @return bool
|
||||
*/
|
||||
public function canView( $member = NULL )
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
|
||||
$return = parent::canView($member);
|
||||
|
||||
if ( $return AND $member->modPermission('can_view_reports') )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -718,7 +718,6 @@ class _Upgrade
|
||||
{
|
||||
foreach( $_versionApps as $_versionApp )
|
||||
{
|
||||
\IPS\Application::installNewFeatures( $_versionApp, $_versionId );
|
||||
\IPS\Log::debug( "Running finish step for: {$_versionApp} version {$_versionId}", 'upgrade' );
|
||||
|
||||
/* Get the object */
|
||||
@@ -785,13 +784,6 @@ class _Upgrade
|
||||
*/
|
||||
protected function step3( $data )
|
||||
{
|
||||
/* Set administrator new features flags - if none were added, then it'll automatically reset back */
|
||||
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in('member_id', \array_keys( \IPS\Member::administrators()['m'] ) ) . " OR " . \IPS\Db::i()->in( 'member_group_id', \array_keys( \IPS\Member::administrators()['g'] ) ) . " OR " . \IPS\Db::i()->findInSet( 'mgroup_others', \array_keys( \IPS\Member::administrators()['g'] ) ) ) ), 'IPS\Member' ) AS $admin )
|
||||
{
|
||||
$admin->members_bitoptions['has_new_acp_features'] = TRUE;
|
||||
$admin->save();
|
||||
}
|
||||
|
||||
return $this->appLoop( $data, function( $app )
|
||||
{
|
||||
if ( !file_exists( \IPS\SITE_FILES_PATH . '/plugins/hooks.php' ) )
|
||||
|
||||
@@ -296,7 +296,7 @@ class _Status extends \IPS\Content\Item implements \IPS\Content\Lockable, \IPS\C
|
||||
$return = TRUE;
|
||||
|
||||
/* Can we access the module? */
|
||||
if( !( $member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) and \IPS\Settings::i()->profile_comments ) )
|
||||
if( !( $member->canAccessModule( \IPS\Application\Module::get( 'core', 'status', 'front' ) ) and \IPS\Settings::i()->profile_comments ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -420,7 +420,9 @@ class _Status extends \IPS\Content\Item implements \IPS\Content\Lockable, \IPS\C
|
||||
'key' => mb_ucfirst( static::$module ),
|
||||
'maxLength' => 65535,
|
||||
'autoSaveKey' => 'reply-' . static::$application . '/' . static::$module . '-' . $this->$idColumn,
|
||||
'minimize' => isset( \IPS\Request::i()->$submitted ) ? NULL : static::$formLangPrefix . '_comment_placeholder'
|
||||
'minimize' => isset( \IPS\Request::i()->$submitted ) ? NULL : static::$formLangPrefix . '_comment_placeholder',
|
||||
'contentClass' => \get_called_class(),
|
||||
'contentId' => $this->$idColumn
|
||||
), function() use( $self ) {
|
||||
if ( !$self->mergeConcurrentComment() )
|
||||
{
|
||||
@@ -875,4 +877,14 @@ class _Status extends \IPS\Content\Item implements \IPS\Content\Lockable, \IPS\C
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not to include in site search
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function includeInSiteSearch()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'core', 'status', 'front' ) );
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class _Subscription extends \IPS\Patterns\ActiveRecord
|
||||
foreach ( $subscriptions as $row )
|
||||
{
|
||||
$member = \IPS\Member::load( $row['member_id'] );
|
||||
if ( !$member->email )
|
||||
if ( !$member->email or $member->isBanned() )
|
||||
{
|
||||
/* Update sent time, so the batch doesn't get stuck in a loop */
|
||||
\IPS\Db::i()->update( 'core_stream_subscriptions', array( 'sent' => time() ), array( 'id=?', $row['id'] ) );
|
||||
|
||||
@@ -431,6 +431,8 @@ class _Warning extends \IPS\Content\Item
|
||||
/* Moderator log */
|
||||
\IPS\Session::i()->modLog( 'modlog__action_warn_user', array( $member->name => FALSE ) );
|
||||
|
||||
/* Webhook */
|
||||
\IPS\Api\Webhook::fire( 'member_warned', $this );
|
||||
parent::processAfterCreate( $comment, $values );
|
||||
}
|
||||
|
||||
@@ -603,7 +605,7 @@ class _Warning extends \IPS\Content\Item
|
||||
|
||||
if ( $values[ 'warn_' . $f ] instanceof \IPS\DateTime )
|
||||
{
|
||||
$difference = \IPS\DateTime::create()->diff( $values[ 'warn_' . $f ] );
|
||||
$difference = \IPS\DateTime::create()->setTimezone( $values[ 'warn_' . $f ]->getTimezone() )->diff( $values[ 'warn_' . $f ] );
|
||||
$period = 'P';
|
||||
foreach ( array( 'y' => 'Y', 'm' => 'M', 'd' => 'D' ) as $k => $v )
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user