Completed
Pull Request — master (#93)
by
unknown
02:31
created

GridFieldRefreshButton::getQueuedJobService()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BringYourOwnIdeas\Maintenance\Forms;
4
5
use BringYourOwnIdeas\Maintenance\Jobs\CheckForUpdatesJob;
6
use SilverStripe\Core\Convert;
7
use SilverStripe\Core\Injector\Injector;
8
use SilverStripe\Forms\GridField\GridField;
9
use SilverStripe\Forms\GridField\GridField_ActionProvider;
10
use SilverStripe\Forms\GridField\GridField_FormAction;
11
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
12
use SilverStripe\Forms\GridField\GridField_URLHandler;
13
use SilverStripe\View\ArrayData;
14
use SilverStripe\View\Requirements;
15
use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;
16
use Symbiote\QueuedJobs\Services\QueuedJob;
17
use Symbiote\QueuedJobs\Services\QueuedJobService;
18
19
/**
20
 * Adds a "Refresh" button to the bottom or top of a GridField.
21
 *
22
 * @package forms
23
 * @subpackage fields-gridfield
24
 */
25
class GridFieldRefreshButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler
26
{
27
    /**
28
     * @var array
29
     * @config
30
     */
31
    private static $allowed_actions = ["check"];
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
32
33
    /**
34
     * Fragment to write the button to.
35
     * @var string
36
     */
37
    protected $targetFragment;
38
39
    /**
40
     * @param string $targetFragment The HTML fragment to write the button into
41
     */
42
    public function __construct($targetFragment)
43
    {
44
        $this->targetFragment = $targetFragment;
45
    }
46
47
    /**
48
     * @param GridField $gridField
49
     * @return array
50
     */
51
    public function getHTMLFragments($gridField)
52
    {
53
        Requirements::javascript('bringyourownideas/silverstripe-maintenance: client/dist/js/bundle.js');
54
55
        $button = GridField_FormAction::create(
56
            $gridField,
57
            'refresh',
58
            _t(__CLASS__ . '.REFRESH', 'Check for updates'),
59
            'refresh',
60
            null
61
        );
62
63
        $button->addExtraClass('btn btn-primary font-icon-sync');
64
65
        $button->setAttribute('data-check', $gridField->Link('check'));
66
        $button->setAttribute(
67
            'data-message',
68
            _t(
69
                __CLASS__ . '.MESSAGE',
70
                'Updating this list may take 2-3 minutes. You can continue to use the CMS while we run the update.'
71
            )
72
        );
73
74
        if ($this->hasPendingJob()) {
75
            $button->setTitle(_t(__CLASS__ . '.UPDATE', 'Updating...'));
76
            $button->setDisabled(true);
77
        }
78
79
        return [
80
            $this->targetFragment => ArrayData::create(['Button' => $button->Field()])
81
                ->renderWith(__CLASS__)
82
        ];
83
    }
84
85
    /**
86
     * Refresh is an action button.
87
     *
88
     * @param GridField $gridField
89
     *
90
     * @return array
91
     */
92
    public function getActions($gridField)
93
    {
94
        return ['refresh'];
95
    }
96
97
    /**
98
     * Handle the refresh action.
99
     *
100
     * @param GridField $gridField
101
     * @param string $actionName
102
     * @param array $arguments
103
     * @param array $data
104
     *
105
     * @return null
106
     */
107
    public function handleAction(GridField $gridField, $actionName, $arguments, $data)
108
    {
109
        if ($actionName == 'refresh') {
110
            return $this->handleRefresh($gridField);
0 ignored issues
show
Unused Code introduced by
The call to BringYourOwnIdeas\Mainte...Button::handleRefresh() has too many arguments starting with $gridField. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

110
            return $this->/** @scrutinizer ignore-call */ handleRefresh($gridField);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
Are you sure the usage of $this->handleRefresh($gridField) targeting BringYourOwnIdeas\Mainte...Button::handleRefresh() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

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

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

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

Loading history...
111
        }
112
    }
113
114
    /**
115
     * Refresh is accessible via the url
116
     *
117
     * @param GridField $gridField
118
     * @return array
119
     */
120
    public function getURLHandlers($gridField)
121
    {
122
        return [
123
            'check' => 'handleCheck'
124
        ];
125
    }
126
127
    /**
128
     * @see hasPendingJob
129
     * @return string JSON encoded value for whether there is a job pending or in process to update the report
130
     */
131
    public function handleCheck()
132
    {
133
        $isRunning = $this->hasPendingJob();
134
        return Convert::raw2json($isRunning);
135
    }
136
137
    /**
138
     * Check the queue for refresh jobs that are not 'done'
139
     * in one manner or another (e.g. stalled or cancelled)
140
     *
141
     * @return boolean
142
     */
143
    public function hasPendingJob()
144
    {
145
        /** @var QueuedJobDescriptor $job */
146
        $job = $this->getQueuedJobService()
147
            ->getJobList(QueuedJob::IMMEDIATE)
148
            ->filter([
149
                'Implementation' => CheckForUpdatesJob::class
150
            ])
151
            ->exclude([
152
                'JobStatus' => [
153
                    QueuedJob::STATUS_COMPLETE,
154
                    QueuedJob::STATUS_CANCELLED,
155
                    QueuedJob::STATUS_BROKEN
156
                ]
157
            ]);
158
159
        return $job->exists();
160
    }
161
162
    /**
163
     * Handle the refresh, for both the action button and the URL
164
     */
165
    public function handleRefresh()
166
    {
167
        if (!$this->hasPendingJob()) {
168
            // Queue the job in the immediate queue
169
            $job = Injector::inst()->create(CheckForUpdatesJob::class);
170
            $jobDescriptorId = $this->getQueuedJobService()->queueJob($job, null, null, QueuedJob::IMMEDIATE);
171
            
172
            // Check the job descriptor on the queue
173
            $jobDescriptor = QueuedJobDescriptor::get()->filter('ID', $jobDescriptorId)->first();
174
175
            // If the job is not immediate, change it to immediate and reschedule it to occur immediately
176
            if ($jobDescriptor->JobType !== QueuedJob::IMMEDIATE) {
177
                $jobDescriptor->JobType = QueuedJob::IMMEDIATE;
178
                $jobDescriptor->StartAfter = null;
179
                $jobDescriptor->write();
180
            }
181
        }
182
    }
183
184
    /**
185
     * @return QueuedJobService
186
     */
187
    protected function getQueuedJobService()
188
    {
189
        return Injector::inst()->get(QueuedJobService::class);
190
    }
191
}
192