Passed
Branch master (a4e902)
by Daimona
01:39
created

TaskBase::run()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 17
nc 4
nop 0
dl 0
loc 23
rs 9.7
c 0
b 0
f 0
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme\Task;
4
5
use BotRiconferme\TaskResult;
6
use BotRiconferme\ContextSource;
7
use BotRiconferme\TaskDataProvider;
8
9
/**
10
 * Base framework for all kind of tasks and subtasks
11
 */
12
abstract class TaskBase extends ContextSource {
13
	// Status codes. GOOD = everything fine, NOTHING = nothing to do, ERROR = found non-fatal errors
14
	const STATUS_GOOD = 0;
15
	const STATUS_NOTHING = 1;
16
	const STATUS_ERROR = 2;
17
	/** @var string[] */
18
	protected $errors = [];
19
	/** @var TaskDataProvider */
20
	protected $dataProvider;
21
22
	/**
23
	 * Final to keep calls linear in the TaskManager
24
	 *
25
	 * @param TaskDataProvider $dataProvider
26
	 */
27
	final public function __construct( TaskDataProvider $dataProvider ) {
28
		set_exception_handler( [ $this, 'handleException' ] );
29
		set_error_handler( [ $this, 'handleError' ] );
30
		parent::__construct();
31
		$this->dataProvider = $dataProvider;
32
	}
33
34
	public function __destruct() {
35
		restore_error_handler();
36
		restore_exception_handler();
37
	}
38
39
	/**
40
	 * Entry point
41
	 *
42
	 * @return TaskResult
43
	 */
44
	final public function run() : TaskResult {
45
		$task = static::class;
46
		$this->getLogger()->info( "Starting task $task" );
47
48
		$status = $this->runInternal();
49
50
		switch ( $status ) {
51
			case self::STATUS_GOOD:
52
				$msg = "Task $task completed successfully.";
53
				break;
54
			case self::STATUS_NOTHING:
55
				$msg = "Task $task: nothing to do.";
56
				break;
57
			case self::STATUS_ERROR:
58
				// We're fine with it, but don't run other tasks
59
				$msg = "Task $task completed with warnings.";
60
				break;
61
			default:
62
				throw new \LogicException( "Unexpected status: $status." );
63
		}
64
65
		$this->getLogger()->info( $msg );
66
		return new TaskResult( $status, $this->errors );
67
	}
68
69
	/**
70
	 * Actual main routine.
71
	 *
72
	 * @return int One of the STATUS_* constants
73
	 */
74
	abstract protected function runInternal() : int;
75
76
	/**
77
	 * Exception handler.
78
	 *
79
	 * @param \Throwable $ex
80
	 * @protected
81
	 */
82
	public function handleException( \Throwable $ex ) {
83
		$this->getLogger()->error(
84
			get_class( $ex ) . ': ' .
85
			$ex->getMessage() . "\nTrace:\n" .
86
			$ex->getTraceAsString()
87
		);
88
	}
89
90
	/**
91
	 * Error handler. As default, always throw
92
	 *
93
	 * @param int $errno
94
	 * @param string $errstr
95
	 * @param string $errfile
96
	 * @param int $errline
97
	 * @protected
98
	 */
99
	public function handleError( $errno, $errstr, $errfile, $errline ) {
100
		throw new \ErrorException( $errstr, 0, $errno, $errfile, $errline );
101
	}
102
103
	/**
104
	 * @return TaskDataProvider
105
	 */
106
	protected function getDataProvider() : TaskDataProvider {
107
		return $this->dataProvider;
108
	}
109
}
110