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 |
||
26 | class EED_Batch extends EED_Module{ |
||
27 | |||
28 | /** |
||
29 | * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that |
||
30 | * processes data only |
||
31 | */ |
||
32 | const batch_job = 'job'; |
||
33 | /** |
||
34 | * Possibly value for $_REQUEST[ 'batch' ]. Indicates to run a job that |
||
35 | * produces a file for download |
||
36 | */ |
||
37 | const batch_file_job = 'file'; |
||
38 | /** |
||
39 | * Possibly value for $_REQUEST[ 'batch' ]. Indicates this request is NOT |
||
40 | * for a batch job. It's the same as not providing the $_REQUEST[ 'batch' ] |
||
41 | * at all |
||
42 | */ |
||
43 | const batch_not_job = 'none'; |
||
44 | |||
45 | /** |
||
46 | * |
||
47 | * @var string 'file', or 'job', or false to indicate its not a batch request at all |
||
48 | */ |
||
49 | protected $_batch_request_type = null; |
||
50 | |||
51 | /** |
||
52 | * Because we want to use the response in both the localized JS and in the body |
||
53 | * we need to make this response available between method calls |
||
54 | * @var \EventEspressoBatchRequest\Helpers\JobStepResponse |
||
55 | */ |
||
56 | protected $_job_step_response = null; |
||
57 | |||
58 | /** |
||
59 | * Gets the batch instance |
||
60 | * @return EED_Batch |
||
61 | */ |
||
62 | public static function instance() { |
||
65 | |||
66 | /** |
||
67 | * Sets hooks to enable batch jobs on the frontend. Disabled by default |
||
68 | * because it's an attack vector and there are currently no implementations |
||
69 | */ |
||
70 | public static function set_hooks() { |
||
71 | //because this is a possibel attack vector, let's have this disabled until |
||
72 | //we at least have a real use for it on the frontend |
||
73 | if( apply_filters( 'FHEE__EED_Batch__set_hooks__enable_frontend_batch', false ) ) { |
||
74 | add_action( 'wp_enqueue_scripts', array( self::instance(), 'enqueue_scripts' ) ); |
||
75 | add_filter( 'template_include', array( self::instance(), 'override_template' ), 99 ); |
||
76 | } |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * Initializes some hooks for the admin in order to run batch jobs |
||
81 | */ |
||
82 | public static function set_hooks_admin() { |
||
83 | add_action( 'admin_menu', array( self::instance(), 'register_admin_pages' ) ); |
||
84 | add_action( 'admin_enqueue_scripts', array( self::instance(), 'enqueue_scripts' ) ); |
||
85 | |||
86 | //ajax |
||
87 | add_action('wp_ajax_espresso_batch_continue',array(self::instance(),'batch_continue')); |
||
88 | add_action('wp_ajax_espresso_batch_cleanup',array(self::instance(),'batch_cleanup')); |
||
89 | add_action('wp_ajax_nopriv_espresso_batch_continue',array(self::instance(),'batch_continue')); |
||
90 | add_action('wp_ajax_nopriv_espresso_batch_cleanup',array(self::instance(),'batch_cleanup')); |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Enqueues batch scripts on the frontend or admin, and creates a job |
||
95 | */ |
||
96 | public function enqueue_scripts() { |
||
97 | if( isset( $_REQUEST[ 'espresso_batch' ] ) |
||
98 | || |
||
99 | ( |
||
100 | isset( $_REQUEST[ 'page' ] ) |
||
101 | && $_REQUEST[ 'page' ] == 'espresso_batch' |
||
102 | ) |
||
103 | ) { |
||
104 | switch( $this->batch_request_type() ) { |
||
105 | case self::batch_job: |
||
106 | $this->enqueue_scripts_styles_batch_create(); |
||
107 | break; |
||
108 | case self::batch_file_job: |
||
109 | $this->enqueue_scripts_styles_batch_file_create(); |
||
110 | break; |
||
111 | } |
||
112 | } |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Create a batch job, enqueues a script to run it, and localizes some data for it |
||
117 | */ |
||
118 | public function enqueue_scripts_styles_batch_create() { |
||
119 | $job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job(); |
||
120 | wp_enqueue_script( 'batch_runner_init', BATCH_URL . '/assets/batch_runner_init.js', array( 'batch_runner' ), EVENT_ESPRESSO_VERSION, true ); |
||
121 | wp_localize_script( 'batch_runner_init', 'ee_job_response', $job_response->to_array() ); |
||
122 | wp_localize_script( 'batch_runner_init', 'ee_job_i18n', |
||
123 | array( |
||
124 | 'return_url' => $_REQUEST['return_url' ], |
||
125 | )); |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Creates a batch job which will download a file, enqueues a script to run the job, and localizes some data for it |
||
130 | */ |
||
131 | public function enqueue_scripts_styles_batch_file_create() { |
||
132 | //creates a job based on the request variable |
||
133 | $job_response = $this->_enqueue_batch_job_scripts_and_styles_and_start_job(); |
||
134 | wp_enqueue_script( 'batch_file_runner_init', BATCH_URL . '/assets/batch_file_runner_init.js', array( 'batch_runner' ), EVENT_ESPRESSO_VERSION, true ); |
||
135 | wp_localize_script( 'batch_file_runner_init', 'ee_job_response', $job_response->to_array() ); |
||
136 | wp_localize_script( 'batch_file_runner_init', 'ee_job_i18n', |
||
137 | array( |
||
138 | 'download_and_redirecting' => sprintf( |
||
139 | __('File Generation complete. Downloading, and %1$sredirecting%2$s...', 'event_espresso'), |
||
140 | '<a href="' . $_REQUEST['return_url' ] .'">', |
||
141 | '</a>' ), |
||
142 | 'return_url' => $_REQUEST['return_url' ], |
||
143 | )); |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * Enqueues scripts and styles common to any batch job, and creates |
||
148 | * a job from the request data, and stores the response in the |
||
149 | * $this->_job_step_response property |
||
150 | * @return \EventEspressoBatchRequest\Helpers\JobStepResponse |
||
151 | */ |
||
152 | protected function _enqueue_batch_job_scripts_and_styles_and_start_job() { |
||
153 | wp_register_script( 'progress_bar', EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.js', array( 'jquery' ) ); |
||
154 | wp_enqueue_style( 'progress_bar', EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/progress_bar.css', array(), EVENT_ESPRESSO_VERSION ); |
||
155 | wp_enqueue_script( 'batch_runner', EE_PLUGIN_DIR_URL . 'core/libraries/batch/Assets/batch_runner.js', array( 'progress_bar' )); |
||
156 | //just copy the bits of EE admin's eei18n that we need in the JS |
||
157 | wp_localize_script( 'batch_runner', 'eei18n', array( 'ajax_url' => WP_AJAX_URL, 'is_admin' => (bool)is_admin() ) ); |
||
158 | $job_handler_classname = stripslashes( $_GET[ 'job_handler' ] ); |
||
159 | $request_data = array_diff_key( |
||
160 | $_REQUEST, |
||
161 | array_flip( array( 'action', 'page', 'ee', 'batch' ) ) ); |
||
162 | $batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor(); |
||
163 | //eg 'EventEspressoBatchRequest\JobHandlers\RegistrationsReport' |
||
164 | $job_response = $batch_runner->create_job( $job_handler_classname, $request_data ); |
||
165 | //remember the response for later. We need it to display the page body |
||
166 | $this->_job_step_response = $job_response; |
||
167 | return $job_response; |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * If we are doing a frontend batch job, this makes it so WP shows our template's HTML |
||
172 | * @param string $template |
||
173 | * @return string |
||
174 | */ |
||
175 | public function override_template( $template ) { |
||
176 | if( isset( $_REQUEST[ 'espresso_batch' ] ) && isset( $_REQUEST[ 'batch' ] ) ) { |
||
177 | return EE_MODULES . 'batch' . DS . 'templates' . DS . 'batch_frontend_wrapper.template.html'; |
||
178 | } |
||
179 | return $template; |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Adds an admin page which doesn't appear in the admin menu |
||
184 | */ |
||
185 | public function register_admin_pages() { |
||
186 | add_submenu_page( |
||
187 | '', //parent slug. we don't want this to actually appear in the menu |
||
188 | __( 'Batch Job', 'event_espresso' ), //page title |
||
189 | 'n/a', //menu title |
||
190 | 'read', //we want this page to actually be accessible to anyone, |
||
191 | 'espresso_batch', //menu slug |
||
192 | array( self::instance(), 'show_admin_page' ) |
||
193 | ); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Renders the admin page, after most of the work was already done during enqueuing scripts |
||
198 | * of creating the job and localizing some data |
||
199 | */ |
||
200 | public function show_admin_page() { |
||
201 | echo EEH_Template::locate_template( |
||
202 | EE_MODULES . 'batch' . DS . 'templates' . DS . 'batch_wrapper.template.html', |
||
203 | array( 'batch_request_type' => $this->batch_request_type() ) |
||
204 | ); |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * Receives ajax calls for continuing a job |
||
209 | */ |
||
210 | View Code Duplication | public function batch_continue() { |
|
|
|||
211 | $job_id = sanitize_text_field( $_REQUEST[ 'job_id' ] ); |
||
212 | $batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor(); |
||
213 | $response_obj = $batch_runner->continue_job( $job_id); |
||
214 | $this->_return_json( $response_obj->to_array() ); |
||
215 | } |
||
216 | |||
217 | /** |
||
218 | * Receives the ajax call to cleanup a job |
||
219 | * @return type |
||
220 | */ |
||
221 | View Code Duplication | public function batch_cleanup() { |
|
222 | $job_id = sanitize_text_field( $_REQUEST[ 'job_id' ] ); |
||
223 | $batch_runner = new EventEspressoBatchRequest\BatchRequestProcessor(); |
||
224 | $response_obj = $batch_runner->cleanup_job( $job_id ); |
||
225 | $this->_return_json( $response_obj->to_array() ); |
||
226 | } |
||
227 | |||
228 | |||
229 | /** |
||
230 | * Returns a json response |
||
231 | * |
||
232 | * @param array $data The data we want to send echo via in the JSON response's "data" element |
||
233 | * |
||
234 | * The returned json object is created from an array in the following format: |
||
235 | * array( |
||
236 | * 'notices' => '', // - contains any EE_Error formatted notices |
||
237 | * 'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js. We're also going to include the template args with every package (so js can pick out any specific template args that might be included in here) |
||
238 | * 'isEEajax' => true,//indicates this is a response from EE |
||
239 | * ) |
||
240 | */ |
||
241 | protected function _return_json( $data ) { |
||
260 | |||
261 | /** |
||
262 | * Gets the job step response which was done during the enqueuing of scripts |
||
263 | * @return \EventEspressoBatchRequest\Helpers\JobStepResponse |
||
264 | */ |
||
265 | public function job_step_response() { |
||
268 | /** |
||
269 | * Gets the batch request type indicated in the $_REQUEST |
||
270 | * @return string: EED_Batch::batch_job, EED_Batch::batch_file_job, EED_Batch::batch_not_job |
||
271 | */ |
||
272 | public function batch_request_type() { |
||
273 | if( $this->_batch_request_type === null ) { |
||
274 | if( isset( $_GET[ 'batch' ] ) ) { |
||
275 | if( $_GET[ 'batch' ] == self::batch_job ) { |
||
276 | $this->_batch_request_type = self::batch_job; |
||
277 | } elseif( $_GET[ 'batch' ] == self::batch_file_job ) { |
||
278 | $this->_batch_request_type = self::batch_file_job; |
||
279 | } |
||
280 | } |
||
281 | //if we didn't find that it was a batch request, indicate it wasn't |
||
282 | if( $this->_batch_request_type === null ) { |
||
283 | $this->_batch_request_type = self::batch_not_job; |
||
284 | } |
||
285 | } |
||
286 | return $this->_batch_request_type; |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Unnecessary |
||
291 | * @param type $WP |
||
292 | */ |
||
293 | public function run( $WP ) { |
||
296 | |||
297 | //put your code here |
||
298 | } |
||
299 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.