Invision Power Services, Inc. * @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc. * @license http://www.invisionpower.com/legal/standards/ * @package IPS Social Suite * @since 28 Jan 2015 * @version SVN_VERSION_NUMBER */ namespace IPS\core\modules\admin\system; /* 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; } /** * Background processes 'Run Now' */ class _background extends \IPS\Dispatcher\Controller { /** * Execute * * @return void */ public function execute() { parent::execute(); } /** * Manage * * @return void */ protected function manage() { \IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('background_process_run_title'); \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->backgroundProcessesRunNow(); } /** * Process * * @return void */ protected function process() { $self = $this; $multiRedirect = new \IPS\Helpers\MultipleRedirect( \IPS\Http\Url::internal('app=core&module=system&controller=background&do=process'), function( $data ) use ( $self ) { /* Make sure the task is locked */ $task = \IPS\Task::load('queue', 'key'); $task->running = TRUE; $task->next_run = time() + 900; $task->save(); if ( ! is_array( $data ) ) { $count = $self->getCount(); return array( array( 'count' => $count, 'done' => 0 ), 'Starting...' ); } else { try { $queueData = \IPS\Db::i()->select( '*', 'core_queue', NULL, 'priority ASC, RAND()', 1 )->first(); $newOffset = 0; try { $extensions = \IPS\Application::load( $queueData['app'] )->extensions( 'core', 'Queue', FALSE ); if ( !isset( $extensions[ $queueData['key'] ] ) ) { throw new \OutOfRangeException; } $class = new $extensions[ $queueData['key'] ]; $json = json_decode( $queueData['data'], TRUE ); $newOffset = $class->run( $json, $queueData['offset'] ); if ( is_null( $newOffset ) ) { \IPS\Log::i( LOG_ERR )->write( "Finished " . json_encode( $queueData ), 'runQueue_log' ); \IPS\Db::i()->delete( 'core_queue', array( 'id=?', $queueData['id'] ) ); /* Update count */ $data['count'] = $self->getCount(); } else { \IPS\Db::i()->update( 'core_queue', array( 'offset' => $newOffset ), array( 'id=?', $queueData['id'] ) ); $newData = json_encode( $json ); /* Did it change?? */ if ( $newData !== $json ) { \IPS\Db::i()->update( 'core_queue', array( 'data' => $newData ), array( 'id=?', $queueData['id'] ) ); } } } catch ( \OutOfRangeException $e ) { \IPS\Log::i( LOG_ERR )->write( "Finished " . json_encode( $queueData ), 'runQueue_log' ); \IPS\Db::i()->delete( 'core_queue', array( 'id=?', $queueData['id'] ) ); /* Update count */ $data['count'] = $self->getCount(); } } catch ( \UnderflowException $e ) { /* All done */ return NULL; } $data['done'] = $data['done'] + ( $newOffset - $queueData['offset'] ); $lang = array( $queueData['key'] ); if ( isset( $json['class'] ) ) { $lang[] = $json['class']; } else if ( isset( $json['extension'] ) ) { $lang[] = $json['extension']; } else if ( isset( $json['storageExtension'] ) ) { $lang[] = $json['storageExtension']; } if ( isset( $json['count'] ) ) { $lang[] = " " . intval( $newOffset ) . ' / ' . $json['count']; } return array( $data, \IPS\Member::loggedIn()->language()->addToStack('background_processes_processing', FALSE, array( 'sprintf' => array( implode( ' - ', $lang ) ) ) ), ( $data['count'] ) ? round( ( 100 / $data['count'] * $data['done'] ), 2 ) : 100 ); } }, function() { /* Make sure the task is unlocked */ $task = \IPS\Task::load('queue', 'key'); $task->running = FALSE; $task->next_run = time() + 60; $task->save(); \IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=overview&controller=dashboard'), 'completed' ); } ); \IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('background_process_run_title'); \IPS\Output::i()->output = $multiRedirect; } /** * Get the count of items to process * * @return int */ public function getCount() { $count = 0; foreach( \IPS\Db::i()->select( '*', 'core_queue' ) as $row ) { if ( ! empty( $row['data'] ) ) { $data = json_decode( $row['data'], TRUE ); if ( isset( $data['count'] ) ) { $count += intval( $data['count'] ); } else { $count++; } } } return $count; } }