Passed
Push — master ( 47f2b8...f595ce )
by Thomas
02:22
created

CronJob::allTasks()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace LeKoala\SimpleJobs;
4
5
use Exception;
6
use Cron\CronExpression;
7
use SilverStripe\ORM\DataList;
8
use SilverStripe\Core\ClassInfo;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\ORM\DataObject;
11
use SilverStripe\Forms\FieldList;
12
use SilverStripe\Security\Member;
13
use SilverStripe\Forms\GridField\GridField;
14
use SilverStripe\CronTask\Interfaces\CronTask;
15
use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer;
16
17
/**
18
 * Class \LeKoala\SimpleJobs\CronJob
19
 *
20
 * @property string $TaskClass
21
 * @property string $Title
22
 * @property string $Category
23
 * @property string $Description
24
 * @property bool $Disabled
25
 */
26
class CronJob extends DataObject
27
{
28
    /**
29
     * @var string
30
     */
31
    private static $singular_name = 'Scheduled Job';
0 ignored issues
show
introduced by
The private property $singular_name is not used, and could be removed.
Loading history...
32
33
    /**
34
     * @var string
35
     */
36
    private static $plural_name = 'Scheduled Jobs';
0 ignored issues
show
introduced by
The private property $plural_name is not used, and could be removed.
Loading history...
37
38
    /**
39
     * @var string
40
     */
41
    private static $table_name = 'CronJob';
0 ignored issues
show
introduced by
The private property $table_name is not used, and could be removed.
Loading history...
42
43
    /**
44
     * @var array<string, string>
45
     */
46
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
47
        'TaskClass' => 'Varchar(255)',
48
        'Title' => 'Varchar(255)',
49
        'Category' => 'Varchar(255)',
50
        'Description' => 'Varchar(255)',
51
        'Disabled' => 'Boolean',
52
    ];
53
54
    /**
55
     * @var string
56
     */
57
    private static $default_sort = 'TaskClass ASC';
0 ignored issues
show
introduced by
The private property $default_sort is not used, and could be removed.
Loading history...
58
59
    /**
60
     * @var array<string, string>
61
     */
62
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
63
        'Title' => 'Title',
64
        'Category' => 'Category',
65
        'Description' => 'Description',
66
        'LastResult.Created' => 'Last Run',
67
        'NextRun' => 'Next Run',
68
    ];
69
70
    /**
71
     * @param Member $member
72
     * @return boolean
73
     */
74
    public function canDelete($member = null)
75
    {
76
        return false;
77
    }
78
79
    /**
80
     * @return array<class-string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string>.
Loading history...
81
     */
82
    public static function allTasks(): array
83
    {
84
        return ClassInfo::implementorsOf(CronTask::class);
85
    }
86
87
    /**
88
     * @return FieldList
89
     */
90
    public function getCMSFields()
91
    {
92
        $fields = parent::getCMSFields();
93
        $fields->makeFieldReadonly('Title');
94
        $fields->makeFieldReadonly('Category');
95
        $fields->makeFieldReadonly('Description');
96
        $fields->makeFieldReadonly('TaskClass');
97
        if ($this->IsSystemDisabled()) {
98
            $fields->makeFieldReadonly('Disabled');
99
        }
100
101
        // Display results
102
        $resultsGridConfig = GridFieldConfig_RecordViewer::create();
103
        $resultsGrid = new GridField('Results', 'Results', $this->AllResults(), $resultsGridConfig);
104
        $fields->addFieldToTab('Root.Results', $resultsGrid);
105
106
        // Optionally provide a list of to be affected items
107
        $taskClass = $this->TaskClass;
108
        if (method_exists($taskClass, 'getJobRecords')) {
109
            $records = $taskClass::getJobRecords();
110
            if ($records) {
111
                $recordsGridConfig = GridFieldConfig_RecordViewer::create();
112
                $recordsGrid = new GridField('Records', 'Records', $records, $recordsGridConfig);
113
                $fields->addFieldToTab('Root.Records', $recordsGrid);
114
            }
115
        }
116
117
        return $fields;
118
    }
119
120
    public static function regenerateFromClasses(bool $update = false): void
121
    {
122
        $list = self::allTasks();
123
        foreach ($list as $class) {
124
            $obj = self::getByTaskClass($class);
125
            if ($obj && $update === false) {
126
                continue;
127
            }
128
            if (!$obj) {
129
                $obj = new CronJob();
130
            }
131
            $obj->TaskClass = $class;
132
            $obj->Title =  method_exists($class, 'getJobTitle') ? $class::getJobTitle() : $class;
133
            $obj->Category = method_exists($class, 'getJobCategory') ? $class::getJobCategory() : 'general';
134
            $obj->Description = method_exists($class, 'getJobDescription') ? $class::getJobDescription() : '';
135
            $obj->write();
136
        }
137
    }
138
139
    public static function getByTaskClass(string $class): ?CronJob
140
    {
141
        /** @var CronJob|null $obj */
142
        $obj = self::get()->filter('TaskClass', $class)->first();
143
        return $obj;
144
    }
145
146
    public function IsDisabled(): bool
147
    {
148
        if ($this->IsSystemDisabled()) {
149
            return true;
150
        }
151
        return $this->Disabled;
152
    }
153
154
    public function IsTaskDisabled(): bool
155
    {
156
        $taskClass = $this->TaskClass;
157
        if ($taskClass && method_exists($taskClass, 'IsDisabled')) {
158
            return $taskClass::IsDisabled();
159
        }
160
        return false;
161
    }
162
163
    public function IsSystemDisabled(): bool
164
    {
165
        if ($this->IsTaskDisabled()) {
166
            return true;
167
        }
168
        $disabledTask = Config::inst()->get(SimpleJobsController::class, 'disabled_tasks');
169
        if (in_array($this->TaskClass, $disabledTask)) {
170
            return true;
171
        }
172
        return false;
173
    }
174
175
    /**
176
     * @return CronTask
177
     */
178
    public function TaskInstance(): CronTask
179
    {
180
        /** @var class-string $class */
181
        $class = $this->TaskClass;
182
        $inst = new $class;
183
        if ($inst instanceof CronTask) {
184
            return $inst;
185
        }
186
        throw new Exception("Invalid class $class");
187
    }
188
189
    public function NextRun(): string
190
    {
191
        if ($this->IsDisabled()) {
192
            return '';
193
        }
194
        $task = $this->TaskInstance();
195
        $cron = new CronExpression($task->getSchedule());
196
        return $cron->getNextRunDate()->format('Y-m-d H:i:s');
197
    }
198
199
    /**
200
     * @return DataList
201
     */
202
    public function AllResults()
203
    {
204
        $result = CronTaskResult::get()->filter([
205
            'TaskClass' => $this->TaskClass
206
        ])->Sort('Created DESC');
207
        return $result;
208
    }
209
210
    public function LastResult(): ?CronTaskResult
211
    {
212
        /** @var CronTaskResult|null $result */
213
        $result = CronTaskResult::get()->filter([
214
            'TaskClass' => $this->TaskClass
215
        ])->Sort('Created DESC')->first();
216
        return $result;
217
    }
218
219
    public function LastFailedResult(): ?CronTaskResult
220
    {
221
        /** @var CronTaskResult|null $result */
222
        $result = CronTaskResult::get()->filter([
223
            'TaskClass' => $this->TaskClass,
224
            'Failed' => 1
225
        ])->Sort('Created DESC')->first();
226
        return $result;
227
    }
228
}
229