Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -90,7 +90,7 @@ class _automaticmoderation extends \IPS\Task
|
||||
if ( $item and $item::$firstCommentRequired and $object->isFirst() )
|
||||
{
|
||||
/* Hide the item, not the object */
|
||||
$item->hide( FALSE, 'automaticmoderation_hide_reason' );
|
||||
$item->hide( FALSE, \IPS\core\Reports\Rules::getDefaultHideReason() );
|
||||
$hidden = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class _automaticmoderation extends \IPS\Task
|
||||
|
||||
if ( $hidden === FALSE )
|
||||
{
|
||||
$object->hide( FALSE, 'automaticmoderation_hide_reason' );
|
||||
$object->hide( FALSE, \IPS\core\Reports\Rules::getDefaultHideReason() );
|
||||
}
|
||||
|
||||
/* Remove from the pending queue */
|
||||
@@ -133,7 +133,7 @@ class _automaticmoderation extends \IPS\Task
|
||||
{
|
||||
$latestReport = \IPS\Db::i()->select( '*', 'core_rc_reports', array( 'rid=?', $report->id ), 'date_reported DESC' )->first();
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'automatic_moderation', $report, array( $report, $latestReport, $object ) );
|
||||
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 )
|
||||
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 )
|
||||
{
|
||||
$notification->recipients->attach( \IPS\Member::constructFromData( $member ) );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief chunkcleanup Task
|
||||
* @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 01 May 2020
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* chunkcleanup Task
|
||||
*/
|
||||
class _chunkcleanup extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* If ran successfully, should return anything worth logging. Only log something
|
||||
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
|
||||
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
|
||||
* Tasks should execute within the time of a normal HTTP request.
|
||||
*
|
||||
* @return mixed Message to log or NULL
|
||||
* @throws \IPS\Task\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$chunksCleanedUp = 0;
|
||||
|
||||
/* Loop over file storage configurations */
|
||||
foreach( \IPS\File::getConfigurations() as $configuration )
|
||||
{
|
||||
/* If this is a filesystem config... */
|
||||
if( $configuration['method'] == 'FileSystem' )
|
||||
{
|
||||
/* Get the configuration object */
|
||||
$fileStorageObject = \IPS\File::getClass( $configuration['id'] );
|
||||
|
||||
/* If we have a chunks folder */
|
||||
if( \is_dir( $fileStorageObject->configuration['dir'] . '/chunks' ) )
|
||||
{
|
||||
/* Loop over all the files in the directory */
|
||||
$iterator = new \DirectoryIterator( $fileStorageObject->configuration['dir'] . '/chunks' );
|
||||
|
||||
foreach( $iterator as $file )
|
||||
{
|
||||
/* If this is a file and the name isn't index.html... */
|
||||
if( $file->isFile() AND $file->getFilename() != 'index.html' )
|
||||
{
|
||||
/* If the last modification time is more than 12 hours old, prune */
|
||||
if( $file->getMTime() < time() - ( 60 * 60 * 12 ) )
|
||||
{
|
||||
@unlink( $file->getPathname() );
|
||||
$chunksCleanedUp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $chunksCleanedUp ? "Deleted {$chunksCleanedUp} orphaned chunks" : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* If your task takes longer than 15 minutes to run, this method
|
||||
* will be called before execute(). Use it to clean up anything which
|
||||
* may not have been done
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -32,20 +32,17 @@ class _cleanup extends \IPS\Task
|
||||
{
|
||||
/* Delete old password / security answer reset requests */
|
||||
\IPS\Db::i()->delete( 'core_validating', array( '( lost_pass=1 OR forgot_security=1 ) AND email_sent < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P1D' ) )->getTimestamp() ) );
|
||||
|
||||
/* Delete cancelled registration members */
|
||||
foreach( \IPS\Db::i()->select( 'member_id', 'core_validating', array( 'do_not_delete=0 and reg_cancelled > 0 and reg_cancelled < ?', time() - 86400 ) ) as $id )
|
||||
|
||||
/* If we are currently pruning any large tables via a bg task, find out so we don't try to prune them normally here as well. The bg task should finish first. */
|
||||
$currentlyPruning = array();
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_queue', array( '`key`=?', 'PruneLargeTable' ) ) as $pruneTask )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\Member::load( $id )->delete();
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=?', $id ) );
|
||||
}
|
||||
$data = json_decode( $pruneTask['data'], true );
|
||||
|
||||
$currentlyPruning[] = $data['table'];
|
||||
}
|
||||
|
||||
|
||||
/* Delete old validating members */
|
||||
if ( \IPS\Settings::i()->validate_day_prune )
|
||||
{
|
||||
@@ -53,11 +50,13 @@ class _cleanup extends \IPS\Task
|
||||
|
||||
foreach ( $select as $row )
|
||||
{
|
||||
try
|
||||
$member = \IPS\Member::load( $row['member_id'] );
|
||||
|
||||
if( $member->member_id )
|
||||
{
|
||||
\IPS\Member::load( $row['member_id'] )->delete();
|
||||
$member->delete();
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=?', $row['member_id'] ) );
|
||||
}
|
||||
@@ -104,6 +103,12 @@ class _cleanup extends \IPS\Task
|
||||
if( \IPS\Settings::i()->prune_log_error )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_error_logs', array( 'log_date < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_log_error . 'D' ) )->getTimestamp() ) );
|
||||
|
||||
/* If we don't have any logs left, remove any notifications */
|
||||
if( \IPS\Db::i()->select( 'count(log_id)', 'core_error_logs' )->first() === 0 )
|
||||
{
|
||||
\IPS\core\AdminNotification::remove( 'core', 'Error' );
|
||||
}
|
||||
}
|
||||
|
||||
/* ...and spam service logs */
|
||||
@@ -128,9 +133,19 @@ class _cleanup extends \IPS\Task
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_statistics', array( 'type=? AND time < ?', 'keyword', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->stats_keywords_prune . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
if( \IPS\Settings::i()->stats_search_prune )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_statistics', array( 'type=? AND time < ?', 'search', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->stats_search_prune . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
if( \IPS\Settings::i()->prune_log_emailstats > 0 )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_statistics', array( "type IN('emails_sent','email_views','email_clicks') AND time < ?", \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_log_emailstats . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
/* ...and geoip cache */
|
||||
\IPS\Db::i()->delete( 'core_geoip_cache', array( 'date < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'PT12H' ) )->getTimestamp() ) );
|
||||
\IPS\Db::i()->delete( 'core_geoip_cache', array( 'date < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P7D' ) )->getTimestamp() ) );
|
||||
|
||||
/* ...and API logs */
|
||||
if( \IPS\Settings::i()->api_log_prune )
|
||||
@@ -139,32 +154,66 @@ class _cleanup extends \IPS\Task
|
||||
}
|
||||
|
||||
/* ...and member history */
|
||||
if( \IPS\Settings::i()->prune_member_history )
|
||||
if( \IPS\Settings::i()->prune_member_history AND !\in_array( 'core_member_history', $currentlyPruning ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_member_history', array( 'log_date < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_member_history . 'D' ) )->getTimestamp(), 0 ) );
|
||||
\IPS\Db::i()->delete( 'core_member_history', array( 'log_date < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_member_history . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
/* ...and promote response logs */
|
||||
\IPS\Db::i()->delete( 'core_social_promote_content', array( 'response_date < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P6M' ) )->getTimestamp() ) );
|
||||
|
||||
/* ...and webhook logs */
|
||||
if( \IPS\Settings::i()->webhook_logs_success )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_api_webhook_fires', array( "status='successful' AND time < ?", \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->webhook_logs_success . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
if( \IPS\Settings::i()->webhook_logs_fail )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_api_webhook_fires', array( "status='failed' AND time < ?", \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->webhook_logs_fail . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
/* Delete old notifications */
|
||||
if ( \IPS\Settings::i()->prune_notifications )
|
||||
{
|
||||
$memberIds = array();
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'member', 'core_notifications', array( 'sent_time < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_notifications . 'M' ) )->getTimestamp() ) ) as $member )
|
||||
foreach( \IPS\Db::i()->select( '`member`', 'core_notifications', array( 'sent_time < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_notifications . 'D' ) )->getTimestamp() ) ) as $member )
|
||||
{
|
||||
$memberIds[ $member ] = $member;
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'sent_time < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_notifications . 'M' ) )->getTimestamp() ) );
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'sent_time < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_notifications . 'D' ) )->getTimestamp() ) );
|
||||
|
||||
foreach( $memberIds as $member )
|
||||
{
|
||||
\IPS\Member::load( $member )->recountNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Delete old follows */
|
||||
if ( \IPS\Settings::i()->prune_follows AND !\in_array( 'core_follow', $currentlyPruning ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_member_id IN(?)', \IPS\Db::i()->select( 'member_id', 'core_members', array( 'last_activity < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_follows . 'D' ) )->getTimestamp() ) ) ) );
|
||||
}
|
||||
|
||||
/* Delete old item markers */
|
||||
if ( \IPS\Settings::i()->prune_item_markers AND !\in_array( 'core_item_markers', $currentlyPruning ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_item_markers', array( 'item_member_id IN(?)', \IPS\Db::i()->select( 'member_id', 'core_members', array( 'last_activity < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_item_markers . 'D' ) )->getTimestamp() ) ) ) );
|
||||
}
|
||||
|
||||
/* Delete old seen IP addresses */
|
||||
if ( \IPS\Settings::i()->prune_known_ips AND !\in_array( 'core_members_known_ip_addresses', $currentlyPruning ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_members_known_ip_addresses', array( 'last_seen < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_known_ips . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
/* Delete old seen devices */
|
||||
if ( \IPS\Settings::i()->prune_known_devices AND !\in_array( 'core_members_known_devices', $currentlyPruning ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_members_known_devices', array( 'last_seen < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->prune_known_devices . 'D' ) )->getTimestamp() ) );
|
||||
}
|
||||
|
||||
/* Delete moved links */
|
||||
if ( \IPS\Settings::i()->topic_redirect_prune )
|
||||
{
|
||||
@@ -191,12 +240,6 @@ class _cleanup extends \IPS\Task
|
||||
$warning->save();
|
||||
}
|
||||
|
||||
/* Delete any incompleted accounts (for example, someone has clicked "Sign in with Twitter" and never provided a username or email */
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( array( '(name=? OR email=?)', '', '' ), array( '! (members_bitoptions2 & 16384 ) AND joined<? AND last_visit=0', \IPS\DateTime::create()->sub( new \DateInterval( 'PT1H' ) )->getTimestamp() ) ) ), 'IPS\Member' ) as $incompleteMember )
|
||||
{
|
||||
$incompleteMember->delete();
|
||||
}
|
||||
|
||||
/* Remove widgets */
|
||||
if ( \IPS\Application::appIsEnabled('cms') )
|
||||
{
|
||||
@@ -224,6 +267,26 @@ class _cleanup extends \IPS\Task
|
||||
\IPS\Db::i()->delete( 'core_oauth_server_authorization_codes', array( 'expires<?', time() ) );
|
||||
\IPS\Db::i()->delete( 'core_oauth_server_access_tokens', array( 'refresh_token_expires<?', time() ) );
|
||||
\IPS\Db::i()->delete( 'core_oauth_authorize_prompts', array( 'timestamp<?', ( time() - 300 ) ) );
|
||||
|
||||
/* Delete any unfinished "Post before register" posts */
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_post_before_registering', array( "`member` IS NULL AND followup IS NOT NULL AND followup<" . ( time() - ( 86400 * 6 ) ) ), 'followup ASC' ) as $row )
|
||||
{
|
||||
$class = $row['class'];
|
||||
try
|
||||
{
|
||||
$class::load( $row['id'] )->delete();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
|
||||
\IPS\Db::i()->delete( 'core_post_before_registering', array( 'class=? AND id=?', $row['class'], $row['id'] ) );
|
||||
}
|
||||
|
||||
/* Delete old core follow caches */
|
||||
\IPS\Db::i()->delete( 'core_follow_count_cache', array( 'added < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'P30D' ) )->getTimestamp() ) );
|
||||
|
||||
|
||||
/* Truncate the output caches table */
|
||||
\IPS\Output\Cache::i()->deleteExpired( TRUE );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -37,6 +37,13 @@ class _clearcache extends \IPS\Task
|
||||
{
|
||||
/* Note: We previously disabled the task if the caching method was disabled however this lead to people re-enabling through a constants edit which would not re-enabled the task */
|
||||
\IPS\Db::i()->delete( 'core_cache', array( 'cache_expire<?', time() ) );
|
||||
\IPS\Output\Cache::i()->deleteExpired();
|
||||
|
||||
/* If we are using Redis, ensure that core_store is empty. We may have switched over to Redis from MySQL and if we switch back, we do not want stale data being used */
|
||||
if ( \IPS\STORE_METHOD !== 'Database' )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_store' );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief clearincompletemembers Task
|
||||
* @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 08 May 2019
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* clearincompletemembers Task
|
||||
*/
|
||||
class _clearincompletemembers extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* If ran successfully, should return anything worth logging. Only log something
|
||||
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
|
||||
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
|
||||
* Tasks should execute within the time of a normal HTTP request.
|
||||
*
|
||||
* @return mixed Message to log or NULL
|
||||
* @throws \IPS\Task\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/* Delete cancelled registration members */
|
||||
foreach( \IPS\Db::i()->select( 'member_id', 'core_validating', array( 'do_not_delete=0 and reg_cancelled > 0 and reg_cancelled < ?', \IPS\DateTime::create()->sub( new \DateInterval( 'PT1H' ) )->getTimestamp() ) ) as $id )
|
||||
{
|
||||
$member = \IPS\Member::load( $id );
|
||||
|
||||
if( $member->member_id )
|
||||
{
|
||||
$member->delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=?', $id ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete any incompleted accounts (for example, someone has clicked "Sign in with Twitter" and never provided a username or email */
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( array( '(name=? OR email=?)', '', '' ), array( '! (members_bitoptions2 & 16384 ) AND joined<? AND (last_visit=0 OR last_visit IS NULL)', \IPS\DateTime::create()->sub( new \DateInterval( 'PT1H' ) )->getTimestamp() ) ) ), 'IPS\Member' ) as $incompleteMember )
|
||||
{
|
||||
$incompleteMember->delete();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* If your task takes longer than 15 minutes to run, this method
|
||||
* will be called before execute(). Use it to clean up anything which
|
||||
* may not have been done
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -35,13 +35,7 @@ class _clearsessions extends \IPS\Task
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$timeout = 1440;
|
||||
|
||||
if( function_exists('ini_get') )
|
||||
{
|
||||
$phpTimeout = @ini_get('session.gc_maxlifetime');
|
||||
$timeout = $phpTimeout ?: $timeout;
|
||||
}
|
||||
$timeout = \IPS\Session::sessionLifetime();
|
||||
|
||||
\IPS\Db::i()->delete( 'core_sys_cp_sessions', array( 'session_running_time<?', ( time() - $timeout ) ) );
|
||||
$class = \IPS\Session\Store::i();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -52,7 +52,8 @@ class _clubrebuild extends \IPS\Task
|
||||
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( $select, 'IPS\Member\Club' ) as $club )
|
||||
{
|
||||
$club->content = 0;
|
||||
$club->content = 0;
|
||||
$club->last_activity = 0;
|
||||
|
||||
foreach ( $club->nodes() as $node )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -47,7 +47,14 @@ class _deletecontent extends \IPS\Task
|
||||
$class = $log->content_class;
|
||||
if ( class_exists ( $class ) )
|
||||
{
|
||||
$content = $class::load( $log->content_id );
|
||||
$content = $class::load( $log->content_id );
|
||||
|
||||
/* Make sure that the content is flagged for deletion */
|
||||
if( $content->hidden() !== -2 )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
|
||||
$content->delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -35,51 +35,10 @@ class _digest extends \IPS\Task
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/* Doing daily or weekly this run? */
|
||||
$frequencies = array( 'daily', 'weekly' );
|
||||
$frequency = $frequencies[ array_rand( $frequencies ) ];
|
||||
|
||||
/* Grab some members to send digests to. */
|
||||
$members = \IPS\Db::i()->select( 'follow_member_id, follow_notify_sent', 'core_follow', array( 'follow_notify_do=1 AND follow_notify_freq = ? AND follow_notify_sent < ?', $frequency, ( $frequency == 'daily' ) ? time() - 86400 : time() - 604800 ), 'follow_notify_sent ASC', array( 0, 50 ), NULL, NULL, \IPS\Db::SELECT_DISTINCT );
|
||||
|
||||
if( !count( $members ) )
|
||||
$this->runUntilTimeout( function()
|
||||
{
|
||||
/* Nothing to send */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$memberIDs = array();
|
||||
foreach( $members as $member )
|
||||
{
|
||||
$memberIDs[] = $member['follow_member_id'];
|
||||
}
|
||||
|
||||
/* Fetch the member's follows so we can build their digest */
|
||||
$follows = \IPS\Db::i()->select( '*', 'core_follow', array( 'follow_notify_do=1 AND follow_notify_freq=? AND follow_notify_sent < ? AND ' . \IPS\Db::i()->in( 'follow_member_id', $memberIDs ), $frequency, time() - 86400 ), 'follow_notify_sent ASC, follow_app ASC, follow_area ASC' );
|
||||
|
||||
$groupedFollows = array();
|
||||
foreach( $follows as $follow )
|
||||
{
|
||||
$groupedFollows[ $follow['follow_member_id'] ][ $follow['follow_app'] ][ $follow['follow_area'] ][] = $follow;
|
||||
}
|
||||
|
||||
foreach( $groupedFollows as $id => $data )
|
||||
{
|
||||
$member = \IPS\Member::load( $id );
|
||||
if( !$member->email )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Build it */
|
||||
$digest = new \IPS\core\Digest\Digest;
|
||||
$digest->member = $member;
|
||||
$digest->frequency = $frequency;
|
||||
$digest->build( $data );
|
||||
|
||||
/* Send it */
|
||||
$digest->send();
|
||||
}
|
||||
return \IPS\core\Digest\Digest::sendDigestBatch( 'daily' );
|
||||
});
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -76,8 +76,12 @@ class _leaderboard extends \IPS\Task
|
||||
/* As this can run multiple times, and the unique constraint is member_id, position, it is possible to end up with multiple members with the same positon */
|
||||
$date = $startDate->setTime( 12, 0 )->getTimeStamp();
|
||||
\IPS\Db::i()->delete( 'core_reputation_leaderboard_history', array( 'leader_date BETWEEN ? and ?', $date - 4, $date ) );
|
||||
|
||||
$where = array();
|
||||
$where[] = array( 'member_received > 0 AND rep_date BETWEEN ? and ?', $startDate->setTime( 0, 0, 1 )->getTimeStamp(), $startDate->setTime( 23, 59, 59 )->getTimeStamp() );
|
||||
$where[] = \IPS\Db::i()->in( 'member_group_id', explode( ',', \IPS\Settings::i()->leaderboard_excluded_groups ), TRUE );
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', array( 'member_received > 0 AND rep_date BETWEEN ? and ?', $startDate->setTime( 0, 0, 1 )->getTimeStamp(), $startDate->setTime( 23, 59, 59 )->getTimeStamp() ), 'rep DESC', 4, 'member' )->setKeyField('member')->setValueField('rep') as $member => $rep )
|
||||
foreach( \IPS\Db::i()->select( 'core_reputation_index.member_received as themember, SUM(rep_rating) as rep', 'core_reputation_index', $where, 'rep DESC, themember ASC', 4, 'themember' )->join( 'core_members', 'core_members.member_id=core_reputation_index.member_received' )->setKeyField('themember')->setValueField('rep') as $member => $rep )
|
||||
{
|
||||
if ( $member and $rep )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief postBeforeRegisterFollowup Task
|
||||
* @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 24 Sep 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* postBeforeRegisterFollowup Task
|
||||
*/
|
||||
class _postBeforeRegisterFollowup extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* If ran successfully, should return anything worth logging. Only log something
|
||||
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
|
||||
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
|
||||
* Tasks should execute within the time of a normal HTTP request.
|
||||
*
|
||||
* @return mixed Message to log or NULL
|
||||
* @throws \IPS\Task\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->runUntilTimeout( function()
|
||||
{
|
||||
/* Get the email */
|
||||
try
|
||||
{
|
||||
$userData = \IPS\Db::i()->select( array( 'email', 'language', 'secret' ), 'core_post_before_registering', array( "`member` IS NULL and followup IS NULL and timestamp<" . ( time() - ( 86400 * 2 ) ) ), 'timestamp ASC', 1 )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
/* Disable the task if there is nothing at all left to process */
|
||||
if( \IPS\Db::i()->select( 'COUNT(*)', 'core_post_before_registering', array( "`member` IS NULL") )->first() === 0 )
|
||||
{
|
||||
$this->enabled = FALSE;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get the associated content */
|
||||
$content = array();
|
||||
foreach ( \IPS\Db::i()->select( array( 'class', 'id' ), 'core_post_before_registering', array( 'email=?', $userData['email'] ) ) as $contentRow )
|
||||
{
|
||||
$class = $contentRow['class'];
|
||||
try
|
||||
{
|
||||
/* Remove any data if the content class doesn't exist any more */
|
||||
if ( !class_exists( $class ) )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
|
||||
$content[] = $class::load( $contentRow['id'] );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_post_before_registering', array( 'class=? AND id=?', $contentRow['class'], $contentRow['id'] ) );
|
||||
}
|
||||
}
|
||||
if ( !$content )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Build the email */
|
||||
try
|
||||
{
|
||||
$language = \IPS\Lang::load( $userData['language'] );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$language = \IPS\Lang::load( \IPS\Lang::defaultLanguage() );
|
||||
}
|
||||
$email = \IPS\Email::buildFromTemplate( 'core', 'postBeforeRegisterFollowup', array( $content, $userData['secret'] ), \IPS\Email::TYPE_TRANSACTIONAL );
|
||||
$email->language = $language;
|
||||
$email->setUnsubscribe( 'core', 'unsubscribeNotNeeded' );
|
||||
$email->send( $userData['email'] );
|
||||
|
||||
/* Update the row */
|
||||
\IPS\Db::i()->update( 'core_post_before_registering', array( 'followup' => time() ), array( 'email=?', $userData['email'] ) );
|
||||
|
||||
/* Return */
|
||||
return TRUE;
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* If your task takes longer than 15 minutes to run, this method
|
||||
* will be called before execute(). Use it to clean up anything which
|
||||
* may not have been done
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -29,7 +29,25 @@ class _profilesync extends \IPS\Task
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$totalToSync = \IPS\Db::i()->select( 'count(*)', 'core_members', array( "temp_ban=0 AND profilesync_lastsync > 0" ) )->first();
|
||||
/* Do we have any login methods that even support syncing enabled? */
|
||||
if( !$this->canSync() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$where = array( array( "temp_ban=?", 0 ), array( "profilesync_lastsync > ?", 0 ) );
|
||||
|
||||
/* Only check accounts that have visited in the last 6 months */
|
||||
$where[] = array( "GREATEST(last_activity, last_visit) > ?", \IPS\DateTime::create()->sub( new \DateInterval('P6M') )->getTimestamp() );
|
||||
|
||||
/* And only check accounts that are actually synchronizing, UNLESS the admin is also forcing synchronization for any login methods */
|
||||
if( !$this->hasForcedSync() )
|
||||
{
|
||||
$where[] = array( "profilesync IS NOT NULL and profilesync != ?", '[]' );
|
||||
}
|
||||
|
||||
|
||||
$totalToSync = \IPS\Db::i()->select( 'count(*)', 'core_members', $where )->first();
|
||||
|
||||
if( !$totalToSync )
|
||||
{
|
||||
@@ -42,11 +60,14 @@ class _profilesync extends \IPS\Task
|
||||
$accounts = ceil( $totalToSync / 12 );
|
||||
}
|
||||
|
||||
$this->runUntilTimeout( function()
|
||||
/* Only sync accounts we haven't synced in the last 12 hours */
|
||||
$where[] = array( "profilesync_lastsync < ?", ( time() - ( 60 * 60 * 12 ) ) );
|
||||
|
||||
$this->runUntilTimeout( function() use( $where )
|
||||
{
|
||||
try
|
||||
{
|
||||
$member = \IPS\Db::i()->select( '*', 'core_members', array( "temp_ban=0 AND profilesync_lastsync > 0 AND profilesync_lastsync < ?", ( time() - ( 60 * 60 * 12 ) ) ), 'profilesync_lastsync ASC', 1 )->first();
|
||||
$member = \IPS\Db::i()->select( '*', 'core_members', $where, 'profilesync_lastsync ASC', 1 )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
@@ -61,4 +82,40 @@ class _profilesync extends \IPS\Task
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we can even sync
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function canSync()
|
||||
{
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
if( $method->hasSyncOptions() )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any login handlers force syncing
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasForcedSync()
|
||||
{
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
if( \count( $method->forceSync() ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -45,7 +45,7 @@ class _publish extends \IPS\Task
|
||||
}
|
||||
}
|
||||
|
||||
if( count( $types ) )
|
||||
if( \count( $types ) )
|
||||
{
|
||||
foreach( $types as $class )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief rssimport Task
|
||||
* @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
|
||||
* @subpackage Forums
|
||||
* @since 05 Feb 2014
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* rssimport Task
|
||||
*/
|
||||
class _rssimport extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* If ran successfully, should return anything worth logging. Only log something
|
||||
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
|
||||
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
|
||||
* Tasks should execute within the time of a normal HTTP request.
|
||||
*
|
||||
* @return mixed Message to log or NULL
|
||||
* @throws \IPS\Task\Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$timeCheck = new \IPS\DateTime;
|
||||
$timeCheck->sub( new \DateInterval( 'PT10M' ) );
|
||||
|
||||
$this->runUntilTimeout(function() use ( $timeCheck ) {
|
||||
try
|
||||
{
|
||||
$feed = \IPS\core\Rss\Import::constructFromData( \IPS\Db::i()->select( '*', 'core_rss_import', array( 'rss_import_enabled=1 AND rss_import_last_import<?', $timeCheck->getTimestamp() ), 'rss_import_last_import ASC', 1 )->first() );
|
||||
$feed->run();
|
||||
}
|
||||
/* There's nothing more left to process */
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
/* Check to see if there are any feeds.. If no feed, we can disable the task */
|
||||
if( !\IPS\Db::i()->select( 'count(rss_import_id)', 'core_rss_import', array( 'rss_import_enabled=1' ), NULL, 1 )->first() )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( '`key`=?', 'rssimport' ) );
|
||||
}
|
||||
|
||||
/* No further processing needed */
|
||||
return FALSE;
|
||||
}
|
||||
/* Any other exception means an error which should be logged */
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
/* If there is an error, we need to log it but the error should not prevent other feeds from importing */
|
||||
if ( isset( $feed ) AND ( $feed instanceof \IPS\core\Rss\Import ) )
|
||||
{
|
||||
$feed->last_import = time();
|
||||
$feed->save();
|
||||
}
|
||||
throw new \IPS\Task\Exception( $this, $e->getMessage() );
|
||||
}
|
||||
|
||||
/* Run again to see if there's anything left */
|
||||
return TRUE;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* If your task takes longer than 15 minutes to run, this method
|
||||
* will be called before execute(). Use it to clean up anything which
|
||||
* may not have been done
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief s3Delete Task
|
||||
* @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 23 Jul 2020
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* s3_delete Task
|
||||
*/
|
||||
class _s3Delete extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* If ran successfully, should return anything worth logging. Only log something
|
||||
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
|
||||
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
|
||||
* Tasks should execute within the time of a normal HTTP request.
|
||||
*
|
||||
* @return mixed Message to log or NULL
|
||||
* @throws \IPS\Task\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
$s3 = \IPS\Db::i()->select( '*', 'core_s3_deletions' )->first();
|
||||
|
||||
$keys = \IPS\File::getClass('core_Theme')->getContainerKeys( $s3['s3_container'], 101, '', $s3['s3_marker'] );
|
||||
|
||||
if ( \count( $keys ) )
|
||||
{
|
||||
/* Get the 51st key, which will be the marker for the next iteration if we have 51 keys, otherwise, make marker null so it's removed in the next iteration */
|
||||
if ( \count( $keys ) < 101 )
|
||||
{
|
||||
$marker = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
end( $keys );
|
||||
$marker = key( $keys );
|
||||
reset( $keys );
|
||||
array_pop( $keys );
|
||||
}
|
||||
|
||||
foreach( $keys as $key => $time )
|
||||
{
|
||||
if ( $time <= $s3['s3_added'] )
|
||||
{
|
||||
\IPS\File::getClass('core_Theme')->deleteByKey( $key );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $marker )
|
||||
{
|
||||
/* Update the marker, there may be more to go */
|
||||
\IPS\Db::i()->update( 'core_s3_deletions', array( 's3_marker' => $marker ), array( 's3_container=?', $s3['s3_container'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Last batch, possible some keys not deleted if time didn't match */
|
||||
\IPS\Db::i()->delete( 'core_s3_deletions', array( 's3_container=?', $s3['s3_container'] ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If no keys, delete container row from s3_deletions */
|
||||
\IPS\Db::i()->delete( 'core_s3_deletions', array( 's3_container=?', $s3['s3_container'] ) );
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $ex )
|
||||
{
|
||||
/* Nothing to do, so switch off the task */
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( '`key`=?', 's3_delete' ) );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* If your task takes longer than 15 minutes to run, this method
|
||||
* will be called before execute(). Use it to clean up anything which
|
||||
* may not have been done
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -29,18 +29,24 @@ class _sitemapgenerator extends \IPS\Task
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
$generator = new \IPS\Sitemap;
|
||||
$generator->buildNextSitemap();
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'sitemap_generator' );
|
||||
return $e->getMessage();
|
||||
}
|
||||
$generator = new \IPS\Sitemap;
|
||||
|
||||
if( count( $generator->log ) )
|
||||
$this->runUntilTimeout( function() use( $generator )
|
||||
{
|
||||
try
|
||||
{
|
||||
/* If it returns false, we're done for now */
|
||||
return $generator->buildNextSitemap();
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'sitemap_generator' );
|
||||
$generator->log[] = $e->getMessage();
|
||||
return FALSE;
|
||||
}
|
||||
} );
|
||||
|
||||
if( \count( $generator->log ) )
|
||||
{
|
||||
return $generator->log;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -44,7 +44,7 @@ class _unlockmembers extends \IPS\Task
|
||||
{
|
||||
$failedLogins = $member->failed_logins;
|
||||
|
||||
if ( is_array( $failedLogins ) )
|
||||
if ( \is_array( $failedLogins ) )
|
||||
{
|
||||
foreach ( $failedLogins as $ipAddress => $times )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -26,6 +26,11 @@ class _updatecheck extends \IPS\Task
|
||||
* @brief Type to send to update server
|
||||
*/
|
||||
public $type = 'task';
|
||||
|
||||
/**
|
||||
* @brief Cache marketplace controller
|
||||
*/
|
||||
protected $_marketplaceController = null;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
@@ -54,30 +59,40 @@ class _updatecheck extends \IPS\Task
|
||||
{
|
||||
$url = $url->setQueryString( 'development', 1 );
|
||||
}
|
||||
if ( \IPS\IPS_ALPHA_BUILD )
|
||||
{
|
||||
$url = $url->setQueryString( 'alpha', 1 );
|
||||
}
|
||||
try
|
||||
{
|
||||
$response = $url->setQueryString( 'version', $version )->request()->get()->decodeJson();
|
||||
|
||||
$coreApp = \IPS\Application::load('core');
|
||||
$currentDetails = json_decode( $coreApp->update_version, TRUE );
|
||||
|
||||
$coreApp->update_version = json_encode( $response );
|
||||
$coreApp->update_last_check = time();
|
||||
$coreApp->save();
|
||||
|
||||
/* Send a notification email if the last available release just changed */
|
||||
if ( $updates = $coreApp->availableUpgrade() and count( $updates ) and \IPS\Settings::i()->upgrade_email AND $currentDetails['version'] != $response['version'] )
|
||||
/* Send a notification if new version is available */
|
||||
if ( $updates = $coreApp->availableUpgrade() and \count( $updates ) )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'upgrade', array( $updates, $coreApp->availableUpgrade( TRUE )['version'] ), \IPS\Email::TYPE_LIST )->send( explode( ',', \IPS\Settings::i()->upgrade_email ) );
|
||||
\IPS\core\AdminNotification::send( 'core', 'NewVersion', NULL, FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\core\AdminNotification::remove( 'core', 'NewVersion' );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
$updateChecked = [];
|
||||
|
||||
/* Do everything else */
|
||||
foreach ( \IPS\Db::i()->union(
|
||||
array(
|
||||
\IPS\Db::i()->select( "'core_applications' AS `table`, app_directory AS `id`, app_update_check AS `url`, app_update_last_check AS `last`, app_long_version AS `current`", 'core_applications', "( app_update_check<>'' AND app_update_check IS NOT NULL )" ),
|
||||
\IPS\Db::i()->select( "'core_plugins' AS `table`, plugin_id AS id, plugin_update_check as url, plugin_update_check_last AS last, plugin_version_long AS `current`", 'core_plugins', "plugin_update_check<>'' AND plugin_update_check IS NOT NULL" ),
|
||||
\IPS\Db::i()->select( "'core_themes' AS `table`, set_id AS `id`, set_update_check AS `url`, set_update_last_check AS `last`, set_long_version AS `current`", 'core_themes', "set_update_check<>'' AND set_update_check IS NOT NULL" )
|
||||
\IPS\Db::i()->select( "'core_applications' AS `table`, app_directory AS `id`, app_update_check AS `url`, app_update_last_check AS `last`, app_long_version AS `current`, app_marketplace_id as `marketplace_id`", 'core_applications', "( app_update_check<>'' AND app_update_check IS NOT NULL ) OR app_marketplace_id IS NOT NULL" ),
|
||||
\IPS\Db::i()->select( "'core_plugins' AS `table`, plugin_id AS id, plugin_update_check as url, plugin_update_check_last AS last, plugin_version_long AS `current`, plugin_marketplace_id as `marketplace_id`", 'core_plugins', "(plugin_update_check<>'' AND plugin_update_check IS NOT NULL ) OR plugin_marketplace_id IS NOT NULL" ),
|
||||
\IPS\Db::i()->select( "'core_themes' AS `table`, set_id AS `id`, set_update_check AS `url`, set_update_last_check AS `last`, set_long_version AS `current`, set_marketplace_id as `marketplace_id`", 'core_themes', "(set_update_check<>'' AND set_update_check IS NOT NULL ) OR set_marketplace_id IS NOT NULL" ),
|
||||
\IPS\Db::i()->select( "'core_sys_lang' AS `table`, lang_id AS `id`, `lang_update_url` AS `url`, `lang_update_check` AS `last`, `lang_version_long` AS `current`, `lang_marketplace_id` as `marketplace_id`", "core_sys_lang", "(lang_update_url<>'' AND lang_update_url IS NOT NULL ) OR lang_marketplace_id IS NOT NULL" )
|
||||
),
|
||||
'last ASC',
|
||||
3
|
||||
@@ -89,6 +104,8 @@ class _updatecheck extends \IPS\Task
|
||||
$dataColumn = 'app_update_version';
|
||||
$timeColumn = 'app_update_last_check';
|
||||
$idColumn = 'app_directory';
|
||||
$updateChecked[] = 'applications';
|
||||
$object = \IPS\Application::load( $row['id'] );
|
||||
|
||||
/* Account for legacy applications */
|
||||
try
|
||||
@@ -110,7 +127,9 @@ class _updatecheck extends \IPS\Task
|
||||
$dataColumn = 'plugin_update_check_data';
|
||||
$timeColumn = 'plugin_update_check_last';
|
||||
$idColumn = 'plugin_id';
|
||||
$source = \IPS\Plugin::load( $row['id'] )->name;
|
||||
$object = \IPS\Plugin::load( $row['id'] );
|
||||
$source = $object->name;
|
||||
$updateChecked[] = 'plugins';
|
||||
break;
|
||||
|
||||
case 'core_themes':
|
||||
@@ -119,14 +138,55 @@ class _updatecheck extends \IPS\Task
|
||||
$idColumn = 'set_id';
|
||||
$key = "core_theme_set_title_{$row['id']}";
|
||||
$source = \IPS\Lang::load( \IPS\Lang::defaultLanguage() )->get( $key );
|
||||
$updateChecked[] = 'themes';
|
||||
break;
|
||||
|
||||
case 'core_sys_lang':
|
||||
$dataColumn = 'lang_update_data';
|
||||
$timeColumn = 'lang_update_check';
|
||||
$idColumn = 'lang_id';
|
||||
$source = \IPS\Lang::load( $row['id'] )->name;
|
||||
$updateChecked[] = 'languages';
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
/* Query the marketplace */
|
||||
if( $row['marketplace_id'] )
|
||||
{
|
||||
if( $this->_marketplaceController === null )
|
||||
{
|
||||
$this->_marketplaceController = new \IPS\core\modules\admin\marketplace\marketplace;
|
||||
}
|
||||
|
||||
/* Get update information */
|
||||
try
|
||||
{
|
||||
$response = $this->_marketplaceController->_updateCheck( $row['marketplace_id'], $row['current'] );
|
||||
}
|
||||
catch( \Throwable $e )
|
||||
{
|
||||
throw new \RuntimeException( $e->getMessage(), $e->getCode() );
|
||||
}
|
||||
|
||||
/* Use a local update URL */
|
||||
$response['updateurl'] = (string) \IPS\Http\Url::internal("app=core&module=marketplace&controller=marketplace&do=viewFile&id={$row['marketplace_id']}");
|
||||
if( isset( $object ) AND isset( $response['disableresource'] ) AND $response['disableresource'] === TRUE )
|
||||
{
|
||||
$object->_enabled = FALSE;
|
||||
$object->save();
|
||||
}
|
||||
}
|
||||
/* Query the applications update URL */
|
||||
$url = \IPS\Http\Url::external( $row['url'] )->setQueryString( array( 'version' => $row['current'], 'ips_version' => $version ) );
|
||||
$response = $url->request()->get()->decodeJson();
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::external( $row['url'] )->setQueryString( array( 'version' => $row['current'], 'ips_version' => $version ) );
|
||||
$response = $url->request()->get()->decodeJson();
|
||||
}
|
||||
|
||||
/* Unset the object so it isn't present for next update check. */
|
||||
unset( $object );
|
||||
|
||||
/* Did we get all the information we need? */
|
||||
if ( !isset( $response['version'], $response['longversion'], $response['released'], $response['updateurl'] ) )
|
||||
@@ -157,6 +217,61 @@ class _updatecheck extends \IPS\Task
|
||||
), array( "{$idColumn}=?", $row['id'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Menu Cache */
|
||||
foreach( $updateChecked as $type )
|
||||
{
|
||||
$key = 'updatecount_' . $type;
|
||||
unset( \IPS\Data\Store::i()->$key, \IPS\Data\Store::i()->$type );
|
||||
}
|
||||
|
||||
/* Check for bulletins while we're here */
|
||||
try
|
||||
{
|
||||
$bulletins = \IPS\Http\Url::ips('bulletin')->request()->get()->decodeJson();
|
||||
$knownBulletins = iterator_to_array( \IPS\Db::i()->select( 'id', 'core_ips_bulletins' ) );
|
||||
|
||||
foreach ( $bulletins as $id => $bulletin )
|
||||
{
|
||||
if ( \in_array( $id, $knownBulletins ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ( @eval( $bulletin['conditions'] ) )
|
||||
{
|
||||
\IPS\core\AdminNotification::send( 'core', 'Bulletin', $id, FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\core\AdminNotification::remove( 'core', 'Bulletin', $id );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'bulletin' );
|
||||
}
|
||||
catch ( \Throwable $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'bulletin' );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->insert( 'core_ips_bulletins', array(
|
||||
'id' => $id,
|
||||
'title' => $bulletin['title'],
|
||||
'body' => $bulletin['body'],
|
||||
'severity' => $bulletin['severity'],
|
||||
'style' => $bulletin['style'],
|
||||
'dismissible' => $bulletin['dismissible'],
|
||||
'link' => $bulletin['link'],
|
||||
'conditions' => $bulletin['conditions'],
|
||||
'cached' => time()
|
||||
) );
|
||||
}
|
||||
}
|
||||
catch( \RuntimeException $e ) { }
|
||||
|
||||
if ( !empty( $fails ) )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -52,7 +52,7 @@ class _usagereporting extends \IPS\Task
|
||||
/* Send the report */
|
||||
try
|
||||
{
|
||||
$response = \IPS\Http\Url::external('https://invisionpowerdiagnostics.com/usage')->request()->post( $this->buildReport() );
|
||||
$response = \IPS\Http\Url::external('https://invisionpowerdiagnostics.com/usage/')->request(2)->post( $this->buildReport() ); // Timeout is deliberately very low because we don't care if it times out (but not 0 because we still need to let the DNS resolve)
|
||||
|
||||
/* If the server has asked us to stop sending reports, then turn it off */
|
||||
if ( $response->httpResponseCode == 410 )
|
||||
@@ -61,7 +61,10 @@ class _usagereporting extends \IPS\Task
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( '`key`=?', 'usagereporting' ) );
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Http\Url\Exception $e ) { }
|
||||
catch ( \IPS\Http\Request\Exception $e )
|
||||
{
|
||||
// It will probably time out, but that's okay
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -122,7 +125,7 @@ class _usagereporting extends \IPS\Task
|
||||
$settings = array();
|
||||
foreach ( $theme->settings as $k => $v )
|
||||
{
|
||||
if ( in_array( $k, array( 'responsive', 'rounded_photos', 'social_links', 'sidebar_position', 'sidebar_responsive', 'enable_fluid_width', 'fluid_width_size', 'js_incclude', 'ajax_pagination', 'cm_store_view', 'body_font', 'headline_font' ) ) )
|
||||
if ( \in_array( $k, array( 'responsive', 'rounded_photos', 'social_links', 'sidebar_position', 'sidebar_responsive', 'enable_fluid_width', 'fluid_width_size', 'js_incclude', 'ajax_pagination', 'cm_store_view', 'body_font', 'headline_font' ) ) )
|
||||
{
|
||||
$settings[ $k ] = $v;
|
||||
}
|
||||
@@ -151,7 +154,7 @@ class _usagereporting extends \IPS\Task
|
||||
/* Settings */
|
||||
foreach ( \IPS\Db::i()->select( array( 'conf_key', 'conf_value', 'conf_default', 'conf_app', 'conf_report' ), 'core_sys_conf_settings', 'conf_report IS NOT NULL' ) as $row )
|
||||
{
|
||||
if ( in_array( $row['conf_app'], \IPS\Application::$ipsApps ) and \IPS\Application::appIsEnabled( $row['conf_app'] ) )
|
||||
if ( \in_array( $row['conf_app'], \IPS\Application::$ipsApps ) and \IPS\Application::appIsEnabled( $row['conf_app'] ) )
|
||||
{
|
||||
if ( $row['conf_report'] == 'full' )
|
||||
{
|
||||
@@ -185,7 +188,7 @@ class _usagereporting extends \IPS\Task
|
||||
{
|
||||
try
|
||||
{
|
||||
$class = \strtolower( \substr( get_class( \IPS\File::getClass( $k ) ), 9 ) );
|
||||
$class = \strtolower( \substr( \get_class( \IPS\File::getClass( $k ) ), 9 ) );
|
||||
|
||||
if ( isset( $report['files'][ $class ] ) )
|
||||
{
|
||||
@@ -220,7 +223,7 @@ class _usagereporting extends \IPS\Task
|
||||
$report['login']['other'] = 0;
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
$class = get_class( $method );
|
||||
$class = \get_class( $method );
|
||||
if ( array_key_exists( $class, $loginMethods ) )
|
||||
{
|
||||
$report['login'][ $loginMethods[ $class ] ]++;
|
||||
@@ -238,7 +241,7 @@ class _usagereporting extends \IPS\Task
|
||||
$report['paymethods'] = array( 'authorizenet_aim' => 0, 'authorizenet_dpm' => 0, 'manual' => 0, 'paypal_standard' => 0, 'paypal_pro' => 0, 'stripe_card' => 0, 'stripe_native' => 0, 'stripe_alipay' => 0, 'stripe_amex' => 0, 'stripe_bancontact' => 0, 'stripe_giropay' => 0, 'stripe_ideal' => 0, 'stripe_sofort' => 0, 'test' => 0, 'twocheckout' => 0, 'other' => 0 );
|
||||
foreach ( \IPS\nexus\Gateway::roots() as $gateway )
|
||||
{
|
||||
$class = \strtolower( \substr( get_class( $gateway ), 18 ) );
|
||||
$class = \strtolower( \substr( \get_class( $gateway ), 18 ) );
|
||||
$settings = json_decode( $gateway->settings, TRUE );
|
||||
|
||||
if ( $class === 'authorizenet' )
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -44,15 +44,15 @@ class _userAgentStatistics extends \IPS\Task
|
||||
{
|
||||
$userAgent = \IPS\Http\Useragent::parse( $row['browser'] );
|
||||
|
||||
if( in_array( $userAgent->platform, array( 'iPhone', 'Windows Phone OS', 'BlackBerry', 'Android', 'Tizen' ) ) )
|
||||
if( \in_array( $userAgent->platform, array( 'iPhone', 'Windows Phone OS', 'BlackBerry', 'Android', 'Tizen' ) ) )
|
||||
{
|
||||
$mobiles++;
|
||||
}
|
||||
elseif( in_array( $userAgent->platform, array( 'iPad / iPod Touch', 'Kindle', 'Kindle Fire', 'Playbook' ) ) )
|
||||
elseif( \in_array( $userAgent->platform, array( 'iPad / iPod Touch', 'Kindle', 'Kindle Fire', 'Playbook' ) ) )
|
||||
{
|
||||
$tablets++;
|
||||
}
|
||||
elseif( in_array( $userAgent->platform, array( 'Nintendo 3DS', 'New Nintendo 3DS', 'Nintendo Wii', 'Nintendo WiiU', 'PlayStation 3', 'PlayStation 4', 'PlayStation Vita', 'Xbox 360', 'Xbox One' ) ) )
|
||||
elseif( \in_array( $userAgent->platform, array( 'Nintendo 3DS', 'New Nintendo 3DS', 'Nintendo Wii', 'Nintendo WiiU', 'PlayStation 3', 'PlayStation 4', 'PlayStation Vita', 'Xbox 360', 'Xbox One' ) ) )
|
||||
{
|
||||
$consoles++;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -40,7 +40,7 @@ class _viewupdates extends \IPS\Task
|
||||
|
||||
try
|
||||
{
|
||||
$database = \IPS\Db::i()->select( 'classname, id, COUNT(*) AS count', 'core_view_updates', NULL, NULL, 20, array( 'classname', 'id' ), NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER );
|
||||
$database = \IPS\Db::i()->select( 'classname, id, count(*) AS count', 'core_view_updates', NULL, NULL, 20, array( 'classname', 'id' ), NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER );
|
||||
$redis = array();
|
||||
|
||||
/* Database results first */
|
||||
@@ -77,7 +77,7 @@ class _viewupdates extends \IPS\Task
|
||||
|
||||
try
|
||||
{
|
||||
$this->update( $class, $id, intval( $count ) );
|
||||
$this->update( $class, $id, \intval( $count ) );
|
||||
}
|
||||
catch( \OutOfRangeException $e ) { }
|
||||
|
||||
@@ -109,7 +109,7 @@ class _viewupdates extends \IPS\Task
|
||||
*/
|
||||
protected function update( $class, $id, $count )
|
||||
{
|
||||
if ( class_exists( $class ) and in_array( 'IPS\Content\Views', class_implements( $class ) ) AND isset( $class::$databaseColumnMap['views'] ) )
|
||||
if ( class_exists( $class ) and \in_array( 'IPS\Content\Views', class_implements( $class ) ) AND isset( $class::$databaseColumnMap['views'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -118,8 +118,6 @@ class _viewupdates extends \IPS\Task
|
||||
"`{$class::$databasePrefix}{$class::$databaseColumnMap['views']}`=`{$class::$databasePrefix}{$class::$databaseColumnMap['views']}`+{$count}",
|
||||
array( "{$class::$databasePrefix}{$class::$databaseColumnId}=?", $id )
|
||||
);
|
||||
|
||||
\IPS\Content\Search\Index::i()->updateViewCounts( $class, $id, $count );
|
||||
}
|
||||
catch( \IPS\Db\Exception $e )
|
||||
{
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief webhooks Task
|
||||
* @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 13 Apr 2020
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* webhooks Task
|
||||
*/
|
||||
class _webhooks extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* If ran successfully, should return anything worth logging. Only log something
|
||||
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
|
||||
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
|
||||
* Tasks should execute within the time of a normal HTTP request.
|
||||
*
|
||||
* @return mixed Message to log or NULL
|
||||
* @throws \IPS\Task\Exception
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/* Get our webhooks */
|
||||
$webhooks = iterator_to_array( \IPS\Db::i()->select( '*', 'core_api_webhooks', array('enabled=1') )->setKeyField('id') );
|
||||
|
||||
/* Run through the queue */
|
||||
$this->runUntilTimeout( function() use ( $webhooks ) {
|
||||
/* Try and get a queue item */
|
||||
try
|
||||
{
|
||||
$fire = \IPS\Db::i()->select( '*', 'core_api_webhook_fires', array( "status='pending'" ), '`time` ASC', 1 )->first();
|
||||
|
||||
try
|
||||
{
|
||||
if ( !isset( $webhooks[ $fire['webhook'] ] ) )
|
||||
{
|
||||
throw new \DomainException("Webhook Disabled");
|
||||
}
|
||||
|
||||
$response = \IPS\Http\Url::external( $webhooks[ $fire['webhook'] ]['url'] )->request()->login( $webhooks[ $fire['webhook'] ]['api_key'], '' )->post( $fire['data'] );
|
||||
|
||||
if ( \IPS\Settings::i()->webhook_logs_success )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_api_webhook_fires', [
|
||||
'status' => 'successful',
|
||||
'response_code' => $response->httpResponseCode,
|
||||
'response_body' => $response->content
|
||||
], [ 'id=?', $fire['id'] ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_api_webhook_fires', [ 'id=?', $fire['id'] ] );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$update = [
|
||||
'response_code' => NULL,
|
||||
'response_body' => \IPS\IPS::getExceptionDetails( $e ),
|
||||
'fails' => $fire['fails'] + 1,
|
||||
];
|
||||
if ( $fire['fails'] >= ( \IPS\Settings::i()->webhooks_allowed_fails - 1 ) )
|
||||
{
|
||||
$update['status'] = 'failed';
|
||||
}
|
||||
|
||||
if ( isset( $update['status'] ) and $update['status'] === 'failed' and !\IPS\Settings::i()->webhook_logs_fail )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_api_webhook_fires', [ 'id=?', $fire['id'] ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_api_webhook_fires', $update, [ 'id=?', $fire['id'] ] );
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/* If there's no queue items left, disable this task and return */
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$this->enabled = FALSE;
|
||||
$this->save();
|
||||
return FALSE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* If your task takes longer than 15 minutes to run, this method
|
||||
* will be called before execute(). Use it to clean up anything which
|
||||
* may not have been done
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief imageproxy Task
|
||||
* @brief weeklydigest Task
|
||||
* @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 20 Nov 2015
|
||||
* @since 31 October 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\tasks;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* imageproxy Task
|
||||
* digest Task
|
||||
*/
|
||||
class _imageproxy extends \IPS\Task
|
||||
class _weeklydigest extends \IPS\Task
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
@@ -35,33 +35,12 @@ class _imageproxy extends \IPS\Task
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( !\IPS\Settings::i()->remote_image_proxy or !\IPS\Settings::i()->image_proxy_cache_period )
|
||||
$this->runUntilTimeout( function()
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( '`key`=?', 'imageproxy' ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$this->runUntilTimeout(function()
|
||||
{
|
||||
$select = \IPS\Db::i()->select( 'location', 'core_image_proxy', array( 'cache_time<?', \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->image_proxy_cache_period . 'D' ) )->getTimestamp() ), 'cache_time ASC', 10 );
|
||||
if ( !$select->count() )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
foreach ( $select as $location )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\File::get( 'core_Imageproxycache', $location )->delete();
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
\IPS\Db::i()->delete( 'core_image_proxy', array( 'location=?', $location ) );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return \IPS\core\Digest\Digest::sendDigestBatch( 'weekly' );
|
||||
});
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Reference in new issue
Block a user