Completed
Branch BUG/batch-strings-overridden (c36a9a)
by
unknown
10:01 queued 01:18
created

BatchRequestProcessor   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 214
Duplicated Lines 15.42 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 33
loc 214
rs 10
c 0
b 0
f 0
wmc 17
lcom 1
cbo 5

6 Methods

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