Completed
Branch FET/asset-manager (433489)
by
unknown
32:42 queued 18:11
created

BatchRequestProcessor   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 202
Duplicated Lines 16.34 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 33
loc 202
rs 10
wmc 16
lcom 1
cbo 4

5 Methods

Rating   Name   Duplication   Size   Complexity  
B create_job() 17 36 4
B continue_job() 8 27 4
B instantiate_batch_job_handler_from_classname() 0 27 3
B cleanup_job() 8 27 3
A _get_error_response() 0 20 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace EventEspressoBatchRequest;
4
5
use EventEspressoBatchRequest\JobHandlerBaseClasses\JobHandlerInterface;
6
use EventEspressoBatchRequest\Helpers\BatchRequestException;
7
use EventEspressoBatchRequest\Helpers\JobParameters;
8
use EventEspressoBatchRequest\Helpers\JobStepResponse;
9
10
/**
11
 * Class BatchRequetProcessor
12
 * Responsible for receiving a request to start a job and assign it a job Id.
13
 * Then when subsequent requests come in to continue that job, dispatches
14
 * the request to the appropriate JobHandler, which processes a step of the batch,
15
 * and then returns the job's new status.
16
 * This class is used by controller code, and the controller code is sent HTTP
17
 * requests from the batch_runner.js library
18
 *
19
 * @package               Event Espresso
20
 * @subpackage            batch
21
 * @author                Mike Nelson
22
 * @since                 4.8.26
23
 */
24
class BatchRequestProcessor
25
{
26
    // phpcs:disable PSR2.Classes.PropertyDeclaration.Underscore
27
    // phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
28
    /**
29
     * Current job's ID (if assigned)
30
     *
31
     * @var string|null
32
     */
33
    protected $_job_id;
34
35
    /**
36
     * Current job's parameters
37
     *
38
     * @var JobParameters|null
39
     */
40
    protected $_job_parameters;
41
42
    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
43
    /**
44
     * Creates a job for the specified batch handler class (which should be autoloaded)
45
     * and the specified request data
46
     *
47
     * @param string $batch_job_handler_class of an auto-loaded class implementing JobHandlerInterface
48
     * @param array  $request_data            to be used by the batch job handler
49
     * @return JobStepResponse
50
     */
51
    public function create_job($batch_job_handler_class, $request_data)
52
    {
53
        try {
54
            $this->_job_id = wp_generate_password(15, false);
55
            $obj = $this->instantiate_batch_job_handler_from_classname($batch_job_handler_class);
56
            $this->_job_parameters = new JobParameters($this->_job_id, $batch_job_handler_class, $request_data);
57
            $response = $obj->create_job($this->_job_parameters);
58 View Code Duplication
            if (! $response instanceof JobStepResponse) {
59
                throw new BatchRequestException(
60
                    sprintf(
61
                        __(
62
                            'The class implementing JobHandlerInterface did not return a JobStepResponse when create_job was called with %1$s. It needs to return one or throw an Exception',
63
                            'event_espresso'
64
                        ),
65
                        wp_json_encode($request_data)
66
                    )
67
                );
68
            }
69
            $success = $this->_job_parameters->save(true);
70 View Code Duplication
            if (! $success) {
71
                throw new BatchRequestException(
72
                    sprintf(
73
                        __(
74
                            'Could not save job %1$s to the Wordpress Options table. These were the arguments used: %2$s',
75
                            'event_espresso'
76
                        ),
77
                        $this->_job_id,
78
                        wp_json_encode($request_data)
79
                    )
80
                );
81
            }
82
        } catch (\Exception $e) {
83
            $response = $this->_get_error_response($e, 'create_job');
84
        }
85
        return $response;
86
    }
87
88
89
    /**
90
     * Retrieves the job's arguments
91
     *
92
     * @param string $job_id
93
     * @param int    $batch_size
94
     * @return JobStepResponse
95
     */
96
    public function continue_job($job_id, $batch_size = 50)
97
    {
98
        try {
99
            $this->_job_id = $job_id;
100
            $batch_size = defined('EE_BATCHRUNNER_BATCH_SIZE') ? EE_BATCHRUNNER_BATCH_SIZE : $batch_size;
101
            // get the corresponding WordPress option for the job
102
            $this->_job_parameters = JobParameters::load($this->_job_id);
103
            $handler_obj = $this->instantiate_batch_job_handler_from_classname($this->_job_parameters->classname());
104
            // continue it
105
            $response = $handler_obj->continue_job($this->_job_parameters, $batch_size);
106 View Code Duplication
            if (! $response instanceof JobStepResponse) {
107
                throw new BatchRequestException(
108
                    sprintf(
109
                        __(
110
                            'The class implementing JobHandlerInterface did not return a JobStepResponse when continue_job was called with job %1$s. It needs to return one or throw an Exception',
111
                            'event_espresso'
112
                        ),
113
                        $this->_job_id
114
                    )
115
                );
116
            }
117
            $this->_job_parameters->save();
118
        } catch (\Exception $e) {
119
            $response = $this->_get_error_response($e, 'continue_job');
120
        }
121
        return $response;
122
    }
123
124
125
    /**
126
     * Instantiates an object of type $classname, which implements
127
     * JobHandlerInterface
128
     *
129
     * @param string $classname
130
     * @return JobHandlerInterface
131
     * @throws BatchRequestException
132
     */
133
    public function instantiate_batch_job_handler_from_classname($classname)
134
    {
135
        if (! class_exists($classname)) {
136
            throw new BatchRequestException(
137
                sprintf(
138
                    __(
139
                        'The class %1$s does not exist, and so could not be used for running a job. It should implement JobHandlerInterface.',
140
                        'event_espresso'
141
                    ),
142
                    $classname
143
                )
144
            );
145
        }
146
        $obj = new $classname;
147
        if (! $obj instanceof JobHandlerInterface) {
148
            throw new BatchRequestException(
149
                sprintf(
150
                    __(
151
                        'The class %1$s does not implement JobHandlerInterface and so could not be used for running a job',
152
                        'event_espresso'
153
                    ),
154
                    $classname
155
                )
156
            );
157
        }
158
        return $obj;
159
    }
160
161
162
    /**
163
     * Forces a job to be cleaned up
164
     *
165
     * @param string $job_id
166
     * @return JobStepResponse
167
     * @throws BatchRequestException
168
     */
169
    public function cleanup_job($job_id)
170
    {
171
        try {
172
            $this->_job_id = $job_id;
173
            $job_parameters = JobParameters::load($this->_job_id);
174
            $handler_obj = $this->instantiate_batch_job_handler_from_classname($job_parameters->classname());
175
            // continue it
176
            $response = $handler_obj->cleanup_job($job_parameters);
177 View Code Duplication
            if (! $response instanceof JobStepResponse) {
178
                throw new BatchRequestException(
179
                    sprintf(
180
                        __(
181
                            'The class implementing JobHandlerInterface did not return a JobStepResponse when cleanup_job was called with job %1$s. It needs to return one or throw an Exception',
182
                            'event_espresso'
183
                        ),
184
                        $this->_job_id
185
                    )
186
                );
187
            }
188
            $job_parameters->set_status(JobParameters::status_cleaned_up);
189
            $job_parameters->delete();
190
            return $response;
191
        } catch (\Exception $e) {
192
            $response = $this->_get_error_response($e, 'cleanup_job');
193
        }
194
        return $response;
195
    }
196
197
198
    /**
199
     * Creates a valid JobStepResponse object from an exception and method name.
200
     *
201
     * @param \Exception $exception
202
     * @param string     $method_name
203
     * @return JobStepResponse
204
     */
205
    protected function _get_error_response(\Exception $exception, $method_name)
206
    {
207
        if (! $this->_job_parameters instanceof JobParameters) {
208
            $this->_job_parameters = new JobParameters($this->_job_id, __('__Unknown__', 'event_espresso'), array());
209
        }
210
        $this->_job_parameters->set_status(JobParameters::status_error);
211
        return new JobStepResponse(
212
            $this->_job_parameters,
213
            sprintf(
214
                __(
215
                    'An exception of type %1$s occurred while running %2$s. Its message was %3$s and had trace %4$s',
216
                    'event_espresso'
217
                ),
218
                get_class($exception),
219
                'BatchRunner::' . $method_name . '()',
220
                $exception->getMessage(),
221
                $exception->getTraceAsString()
222
            )
223
        );
224
    }
225
}
226