Passed
Push — master ( 08cc3a...76b0e0 )
by Thomas
12:40 queued 15s
created

CronJob::getCMSActions()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 6
c 1
b 0
f 1
nc 2
nop 0
dl 0
loc 10
rs 10
1
<?php
2
3
namespace LeKoala\SimpleJobs;
4
5
use Exception;
6
use Cron\CronExpression;
7
use LeKoala\CmsActions\CustomAction;
0 ignored issues
show
Bug introduced by
The type LeKoala\CmsActions\CustomAction was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use SilverStripe\ORM\DataList;
9
use SilverStripe\Core\ClassInfo;
10
use SilverStripe\Core\Config\Config;
11
use SilverStripe\ORM\DataObject;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Security\Member;
14
use SilverStripe\Forms\GridField\GridField;
15
use SilverStripe\CronTask\Interfaces\CronTask;
16
use SilverStripe\Forms\GridField\GridFieldConfig_RecordViewer;
17
use SilverStripe\Security\Permission;
18
19
/**
20
 * Class \LeKoala\SimpleJobs\CronJob
21
 *
22
 * @property string $TaskClass
23
 * @property string $Title
24
 * @property string $Category
25
 * @property string $Description
26
 * @property bool $Disabled
27
 */
28
class CronJob extends DataObject
29
{
30
    /**
31
     * @var string
32
     */
33
    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...
34
35
    /**
36
     * @var string
37
     */
38
    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...
39
40
    /**
41
     * @var string
42
     */
43
    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...
44
45
    /**
46
     * @var array<string, string>
47
     */
48
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
49
        'TaskClass' => 'Varchar(255)',
50
        'Title' => 'Varchar(255)',
51
        'Category' => 'Varchar(255)',
52
        'Description' => 'Varchar(255)',
53
        'Disabled' => 'Boolean',
54
    ];
55
56
    /**
57
     * @var string
58
     */
59
    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...
60
61
    /**
62
     * @var array<string, string>
63
     */
64
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
65
        'Title' => 'Title',
66
        'Category' => 'Category',
67
        'Description' => 'Description',
68
        'LastResult.Created' => 'Last Run',
69
        'NextRun' => 'Next Run',
70
    ];
71
72
    /**
73
     * @param Member $member
74
     * @return boolean
75
     */
76
    public function canDelete($member = null)
77
    {
78
        return false;
79
    }
80
81
    /**
82
     * @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...
83
     */
84
    public static function allTasks(): array
85
    {
86
        return ClassInfo::implementorsOf(CronTask::class);
87
    }
88
89
    public function triggerManually(): string
90
    {
91
        $inst = $this->TaskInstance();
92
        /** @var void|null|string|bool $result */
93
        $result = $inst->process();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $result is correct as $inst->process() targeting SilverStripe\CronTask\In...ces\CronTask::process() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
94
        if ($result !== null) {
95
            if ($result === false) {
96
                return 'Task failed';
97
            }
98
            if (is_string($result)) {
99
                return $result;
100
            }
101
        }
102
        return "Task has been triggered";
103
    }
104
105
    public function getCMSActions()
106
    {
107
        $actions = parent::getCMSActions();
108
        if (class_exists(CustomAction::class) && Permission::check('ADMIN')) {
109
            $triggerManually = new CustomAction('triggerManually', 'Trigger manually');
110
            $triggerManually->setConfirmation("Are you sure you want to trigger the task?");
111
            //@phpstan-ignore-next-line
112
            $actions->push($triggerManually);
113
        }
114
        return $actions;
115
    }
116
117
    /**
118
     * @return FieldList
119
     */
120
    public function getCMSFields()
121
    {
122
        $fields = parent::getCMSFields();
123
        $fields->makeFieldReadonly('Title');
124
        $fields->makeFieldReadonly('Category');
125
        $fields->makeFieldReadonly('Description');
126
        $fields->makeFieldReadonly('TaskClass');
127
        if ($this->IsSystemDisabled()) {
128
            $fields->makeFieldReadonly('Disabled');
129
        }
130
131
        // Display results
132
        $resultsGridConfig = GridFieldConfig_RecordViewer::create();
133
        $resultsGrid = new GridField('Results', 'Results', $this->AllResults(), $resultsGridConfig);
134
        $fields->addFieldToTab('Root.Results', $resultsGrid);
135
136
        // Optionally provide a list of to be affected items
137
        $taskClass = $this->TaskClass;
138
        if (method_exists($taskClass, 'getJobRecords')) {
139
            $records = $taskClass::getJobRecords();
140
            if ($records) {
141
                $recordsGridConfig = GridFieldConfig_RecordViewer::create();
142
                $recordsGrid = new GridField('Records', 'Records', $records, $recordsGridConfig);
143
                $fields->addFieldToTab('Root.Records', $recordsGrid);
144
            }
145
        }
146
147
        return $fields;
148
    }
149
150
    public static function regenerateFromClasses(bool $update = false): void
151
    {
152
        $list = self::allTasks();
153
        foreach ($list as $class) {
154
            $obj = self::getByTaskClass($class);
155
            if ($obj && $update === false) {
156
                continue;
157
            }
158
            if (!$obj) {
159
                $obj = new CronJob();
160
            }
161
            $obj->TaskClass = $class;
162
            $obj->Title =  method_exists($class, 'getJobTitle') ? $class::getJobTitle() : $class;
163
            $obj->Category = method_exists($class, 'getJobCategory') ? $class::getJobCategory() : 'general';
164
            $obj->Description = method_exists($class, 'getJobDescription') ? $class::getJobDescription() : '';
165
            $obj->write();
166
        }
167
    }
168
169
    public static function getByTaskClass(string $class): ?CronJob
170
    {
171
        /** @var CronJob|null $obj */
172
        $obj = self::get()->filter('TaskClass', $class)->first();
173
        return $obj;
174
    }
175
176
    public function IsDisabled(): bool
177
    {
178
        if ($this->IsSystemDisabled()) {
179
            return true;
180
        }
181
        return $this->Disabled;
182
    }
183
184
    public function IsTaskDisabled(): bool
185
    {
186
        $taskClass = $this->TaskClass;
187
        if ($taskClass && method_exists($taskClass, 'IsDisabled')) {
188
            return $taskClass::IsDisabled();
189
        }
190
        return false;
191
    }
192
193
    public function IsSystemDisabled(): bool
194
    {
195
        if ($this->IsTaskDisabled()) {
196
            return true;
197
        }
198
        $disabledTask = Config::inst()->get(SimpleJobsController::class, 'disabled_tasks');
199
        if (in_array($this->TaskClass, $disabledTask)) {
200
            return true;
201
        }
202
        return false;
203
    }
204
205
    /**
206
     * @return CronTask
207
     */
208
    public function TaskInstance(): CronTask
209
    {
210
        /** @var class-string $class */
211
        $class = $this->TaskClass;
212
        $inst = new $class;
213
        if ($inst instanceof CronTask) {
214
            return $inst;
215
        }
216
        throw new Exception("Invalid class $class");
217
    }
218
219
    public function NextRun(): string
220
    {
221
        if ($this->IsDisabled()) {
222
            return '';
223
        }
224
        $task = $this->TaskInstance();
225
        $cron = new CronExpression($task->getSchedule());
226
        return $cron->getNextRunDate()->format('Y-m-d H:i:s');
227
    }
228
229
    /**
230
     * @return DataList
231
     */
232
    public function AllResults()
233
    {
234
        $result = CronTaskResult::get()->filter([
235
            'TaskClass' => $this->TaskClass
236
        ])->Sort('Created DESC');
237
        return $result;
238
    }
239
240
    public function LastResult(): ?CronTaskResult
241
    {
242
        /** @var CronTaskResult|null $result */
243
        $result = CronTaskResult::get()->filter([
244
            'TaskClass' => $this->TaskClass
245
        ])->Sort('Created DESC')->first();
246
        return $result;
247
    }
248
249
    public function LastFailedResult(): ?CronTaskResult
250
    {
251
        /** @var CronTaskResult|null $result */
252
        $result = CronTaskResult::get()->filter([
253
            'TaskClass' => $this->TaskClass,
254
            'Failed' => 1
255
        ])->Sort('Created DESC')->first();
256
        return $result;
257
    }
258
}
259