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:
Complex classes like Sensei_Updates often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Sensei_Updates, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class Sensei_Updates |
||
14 | { |
||
15 | public $token = 'woothemes-sensei'; |
||
16 | public $version; |
||
17 | public $updates_run; |
||
18 | public $updates; |
||
19 | private $parent; |
||
20 | |||
21 | /** |
||
22 | * Constructor. |
||
23 | * |
||
24 | * @access public |
||
25 | * @since 1.1.0 |
||
26 | * @param string $parent The main Sensei object by Ref. |
||
27 | * @return void |
||
28 | */ |
||
29 | public function __construct($parent) |
||
30 | { |
||
31 | |||
32 | // Setup object data |
||
33 | $this->parent = $parent; |
||
34 | $this->updates_run = get_option( 'woothemes-sensei-upgrades', array() ); |
||
35 | |||
36 | // The list of upgrades to run |
||
37 | $this->updates = array('1.1.0' => array('auto' => array('assign_role_caps' => array('title' => __('Assign role capabilities', 'woothemes-sensei'), 'desc' => __('Assigns Sensei capabilites to the relevant user roles.', 'woothemes-sensei'), 'product' => 'Sensei')), |
||
38 | 'manual' => array() |
||
39 | ), |
||
40 | '1.3.0' => array('auto' => array('set_default_quiz_grade_type' => array('title' => __('Set default quiz grade type', 'woothemes-sensei'), 'desc' => __('Sets all quizzes to the default \'auto\' grade type.', 'woothemes-sensei')), |
||
41 | 'set_default_question_type' => array('title' => __('Set default question type', 'woothemes-sensei'), 'desc' => __('Sets all questions to the default \'multiple choice\' type.', 'woothemes-sensei')) |
||
42 | ), |
||
43 | 'manual' => array('update_question_answer_data' => array('title' => __('Update question answer data', 'woothemes-sensei'), 'desc' => __('Updates questions to use the new question types structure.', 'woothemes-sensei'))) |
||
44 | ), |
||
45 | '1.4.0' => array('auto' => array('update_question_grade_points' => array('title' => __('Update question grade points', 'woothemes-sensei'), 'desc' => __('Sets all question grade points to the default value of \'1\'.', 'woothemes-sensei'))), |
||
46 | 'manual' => array() |
||
47 | ), |
||
48 | '1.5.0' => array('auto' => array('convert_essay_paste_questions' => array('title' => __('Convert essay paste questions into multi-line questions', 'woothemes-sensei'), 'desc' => __('Converts all essay paste questions into multi-line questions as the essay paste question type was removed in v1.5.0.', 'woothemes-sensei'))), |
||
49 | 'manual' => array('set_random_question_order' => array('title' => __('Set all quizzes to have a random question order', 'woothemes-sensei'), 'desc' => __('Sets the order all of questions in all quizzes to a random order, which can be switched off per quiz.', 'woothemes-sensei')), |
||
50 | 'set_default_show_question_count' => array('title' => __('Set all quizzes to show all questions', 'woothemes-sensei'), 'desc' => __('Sets all quizzes to show all questions - this can be changed per quiz.', 'woothemes-sensei')), |
||
51 | 'remove_deleted_user_activity' => array('title' => __('Remove Sensei activity for deleted users', 'woothemes-sensei'), 'desc' => __('Removes all course, lesson & quiz activity for users that have already been deleted from the database. This will fix incorrect learner counts in the Analysis section.', 'woothemes-sensei'))) |
||
52 | ), |
||
53 | '1.6.0' => array('auto' => array('add_teacher_role' => array('title' => __('Add \'Teacher\' role', 'woothemes-sensei'), 'desc' => __('Adds a \'Teacher\' role to your WordPress site that will allow users to mange the Grading and Analysis pages.', 'woothemes-sensei')), |
||
54 | 'add_sensei_caps' => array('title' => __('Add administrator capabilities', 'woothemes-sensei'), 'desc' => __('Adds the \'manage_sensei\' and \'manage_sensei_grades\' capabilities to the Administrator role.', 'woothemes-sensei')), |
||
55 | 'restructure_question_meta' => array('title' => __('Restructure question meta data', 'woothemes-sensei'), 'desc' => __('Restructures the question meta data as it relates to quizzes - this accounts for changes in the data structure in v1.6+.', 'woothemes-sensei')), |
||
56 | 'update_quiz_settings' => array('title' => __('Add new quiz settings', 'woothemes-sensei'), 'desc' => __('Adds new settings to quizzes that were previously registered as global settings.', 'woothemes-sensei')), |
||
57 | 'reset_lesson_order_meta' => array('title' => __('Set default order of lessons', 'woothemes-sensei'), 'desc' => __('Adds data to lessons to ensure that they show up on the \'Order Lessons\' screen - if this update has been run once before then it will reset all lessons to the default order.', 'woothemes-sensei')),), |
||
58 | 'manual' => array() |
||
59 | ), |
||
60 | '1.7.0' => array('auto' => array('add_editor_caps' => array('title' => __('Add Editor capabilities', 'woothemes-sensei'), 'desc' => __('Adds the \'manage_sensei_grades\' capability to the Editor role.', 'woothemes-sensei')),), |
||
61 | 'forced' => array('update_question_gap_fill_separators' => array('title' => __('Update Gap Fill questions', 'woothemes-sensei'), 'desc' => __('Updates the format of gap fill questions to allow auto grading and greater flexibility in matching.', 'woothemes-sensei')), |
||
62 | 'update_quiz_lesson_relationship' => array('title' => __('Restructure quiz lesson relationship', 'woothemes-sensei'), 'desc' => __('Adds data to quizzes and lessons to ensure that they maintain their 1 to 1 relationship.', 'woothemes-sensei')), |
||
63 | 'status_changes_fix_lessons' => array('title' => __('Update lesson statuses', 'woothemes-sensei'), 'desc' => __('Update existing lesson statuses.', 'woothemes-sensei')), |
||
64 | 'status_changes_convert_lessons' => array('title' => __('Convert lesson statuses', 'woothemes-sensei'), 'desc' => __('Convert to new lesson statuses.', 'woothemes-sensei')), |
||
65 | 'status_changes_convert_courses' => array('title' => __('Convert course statuses', 'woothemes-sensei'), 'desc' => __('Convert to new course statuses.', 'woothemes-sensei')), |
||
66 | 'status_changes_convert_questions' => array('title' => __('Convert question statuses', 'woothemes-sensei'), 'desc' => __('Convert to new question statuses.', 'woothemes-sensei')), |
||
67 | 'update_legacy_sensei_comments_status' => array('title' => __('Convert legacy Sensei activity types', 'woothemes-sensei'), 'desc' => __('Convert all legacy Sensei activity types such as \'sensei_lesson_start\' and \'sensei_user_answer\' to new status format.', 'woothemes-sensei')), |
||
68 | 'update_comment_course_lesson_comment_counts' => array('title' => __('Update comment counts', 'woothemes-sensei'), 'desc' => __('Update comment counts on Courses and Lessons due to status changes.', 'woothemes-sensei')),), |
||
69 | ), |
||
70 | '1.7.2' => array('auto' => array('index_comment_status_field' => array('title' => __('Add database index to comment statuses', 'woothemes-sensei'), 'desc' => __('This indexes the comment statuses in the database, which will speed up all Sensei activity queries.', 'woothemes-sensei')),), |
||
71 | /*'manual' => array( 'remove_legacy_comments' => array( 'title' => __( 'Remove legacy Sensei activity types', 'woothemes-sensei' ), 'desc' => __( 'This removes all legacy (pre-1.7) Sensei activity types - only run this update once the update to v1.7 is complete and everything is stable.', 'woothemes-sensei' ) ) )*/ |
||
72 | ), |
||
73 | '1.8.0' => array('auto' => array('enhance_teacher_role' => array('title' => 'Enhance the \'Teacher\' role', 'desc' => 'Adds the ability for a \'Teacher\' to create courses, lessons , quizes and manage their learners.'),), |
||
74 | 'manual' => array() |
||
75 | ), |
||
76 | ); |
||
77 | |||
78 | $this->updates = apply_filters( 'sensei_upgrade_functions', $this->updates, $this->updates ); |
||
79 | $this->version = get_option( 'woothemes-sensei-version' ); |
||
80 | |||
81 | // Manual Update Screen |
||
82 | add_action('admin_menu', array($this, 'add_update_admin_screen'), 50); |
||
83 | |||
84 | } // End __construct() |
||
85 | |||
86 | /** |
||
87 | * add_update_admin_screen Adds admin screen to run manual udpates |
||
88 | * |
||
89 | * @access public |
||
90 | * @since 1.3.7 |
||
91 | * @return void |
||
92 | */ |
||
93 | public function add_update_admin_screen() |
||
94 | { |
||
95 | if (current_user_can('manage_options')) { |
||
96 | add_submenu_page('sensei', __('Sensei Updates', 'woothemes-sensei'), __('Data Updates', 'woothemes-sensei'), 'manage_options', 'sensei_updates', array($this, 'sensei_updates_page')); |
||
97 | } |
||
98 | } // End add_update_admin_screen() |
||
99 | |||
100 | /** |
||
101 | * sensei_updates_page HTML output for manual update screen |
||
102 | * |
||
103 | * @access public |
||
104 | * @since 1.3.7 |
||
105 | * @return void |
||
106 | */ |
||
107 | public function sensei_updates_page() { |
||
108 | |||
109 | // Only allow admins to load this page and run the update functions |
||
110 | if ( ! current_user_can('manage_options')) { |
||
111 | |||
112 | return; |
||
113 | |||
114 | } |
||
115 | ?> |
||
116 | |||
117 | <div class="wrap"> |
||
118 | |||
119 | <div id="icon-woothemes-sensei" class="icon32"><br></div> |
||
120 | <h2><?php _e('Sensei Updates', 'woothemes-sensei'); ?></h2> |
||
121 | |||
122 | <?php |
||
123 | $function_name= ''; |
||
124 | if ( isset($_GET['action']) && $_GET['action'] == 'update' |
||
125 | && isset($_GET['n']) && intval($_GET['n']) >= 0 |
||
126 | && ( (isset($_POST['checked'][0]) && '' != $_POST['checked'][0]) || (isset($_GET['functions']) && '' != $_GET['functions']))) { |
||
127 | |||
128 | // Setup the data variables |
||
129 | $n = intval($_GET['n']); |
||
130 | $functions_list = ''; |
||
131 | $done_processing = false; |
||
132 | |||
133 | // Check for updates to run |
||
134 | if (isset($_POST['checked'][0]) && '' != $_POST['checked'][0]) { |
||
135 | |||
136 | View Code Duplication | foreach ($_POST['checked'] as $key => $function_name) { |
|
137 | |||
138 | if( ! isset( $_POST[ $function_name.'_nonce_field' ] ) |
||
139 | || ! wp_verify_nonce( $_POST[ $function_name.'_nonce_field' ] , 'run_'.$function_name ) ){ |
||
140 | |||
141 | wp_die( |
||
142 | '<h1>' . __( 'Cheatin’ uh?' ) . '</h1>' . |
||
143 | '<p>' . __( 'The nonce supplied in order to run this update function is invalid','woothemes-sensei') . '</p>', |
||
144 | 403 |
||
145 | ); |
||
146 | |||
147 | } |
||
148 | |||
149 | // Dynamic function call |
||
150 | if (method_exists($this, $function_name)) { |
||
151 | |||
152 | $done_processing = call_user_func_array(array($this, $function_name), array(50, $n)); |
||
153 | |||
154 | } elseif ($this->function_in_whitelist($function_name)) { |
||
155 | |||
156 | $done_processing = call_user_func_array($function_name, array(50, $n)); |
||
157 | |||
158 | } else { |
||
159 | |||
160 | _doing_it_wrong( esc_html( $function_name) , 'Is not a valid Sensei updater function', 'Sensei 1.9.0'); |
||
161 | return; |
||
162 | |||
163 | }// End If Statement |
||
164 | |||
165 | // Add to functions list get args |
||
166 | if ('' == $functions_list) { |
||
167 | $functions_list .= $function_name; |
||
168 | } else { |
||
169 | $functions_list .= '+' . $function_name; |
||
170 | } // End If Statement |
||
171 | |||
172 | // Mark update has having been run |
||
173 | $this->set_update_run($function_name); |
||
174 | |||
175 | } // End For Loop |
||
176 | |||
177 | } // End If Statement |
||
178 | |||
179 | // Check for updates to run |
||
180 | if (isset($_GET['functions']) && '' != $_GET['functions']) { |
||
181 | |||
182 | // Existing functions from GET variables instead of POST |
||
183 | $functions_array = $_GET['functions']; |
||
184 | |||
185 | View Code Duplication | foreach ($functions_array as $key => $function_name) { |
|
186 | |||
187 | if( ! isset( $_GET[ $function_name.'_nonce' ] ) |
||
188 | || ! wp_verify_nonce( $_GET[ $function_name.'_nonce' ] , 'run_'.$function_name ) ){ |
||
189 | |||
190 | wp_die( |
||
191 | '<h1>' . __( 'Cheatin’ uh?' ) . '</h1>' . |
||
192 | '<p>' . __( 'The nonce supplied in order to run this update function is invalid','woothemes-sensei') . '</p>', |
||
193 | 403 |
||
194 | ); |
||
195 | |||
196 | } |
||
197 | |||
198 | // Dynamic function call |
||
199 | if (method_exists($this, $function_name)) { |
||
200 | |||
201 | $done_processing = call_user_func_array(array($this, $function_name), array(50, $n)); |
||
202 | |||
203 | } elseif ($this->function_in_whitelist($function_name)) { |
||
204 | |||
205 | $done_processing = call_user_func_array($function_name, array(50, $n)); |
||
206 | |||
207 | } else { |
||
208 | |||
209 | _doing_it_wrong( esc_html( $function_name) , 'Is not a valid Sensei updater function', 'Sensei 1.9.0'); |
||
210 | return; |
||
211 | |||
212 | } // End If Statement |
||
213 | |||
214 | // Add to functions list get args |
||
215 | if ('' == $functions_list) { |
||
216 | $functions_list .= $function_name; |
||
217 | } else { |
||
218 | $functions_list .= '+' . $function_name; |
||
219 | } // End If Statement |
||
220 | |||
221 | $this->set_update_run($function_name); |
||
222 | |||
223 | } // End For Loop |
||
224 | |||
225 | } // End If Statement |
||
226 | |||
227 | if (!$done_processing) { ?> |
||
228 | |||
229 | <h3><?php _e('Processing Updates...', 'woothemes-sensei'); ?></h3> |
||
230 | |||
231 | <p> |
||
232 | |||
233 | <?php _e( "If your browser doesn't start loading the next page automatically, click this button:", 'woothemes-sensei' ); ?> |
||
234 | |||
235 | <?php |
||
236 | $next_action_url = add_query_arg( array( |
||
237 | 'page' => 'sensei_updates', |
||
238 | 'action' => 'update', |
||
239 | 'n' => $n + 50, |
||
240 | 'functions' => array( $functions_list ), |
||
241 | $function_name.'_nonce' => wp_create_nonce( 'run_'. $function_name ), |
||
242 | ), admin_url( 'admin.php' ) ); |
||
243 | ?> |
||
244 | |||
245 | <a class="button" href="<?php echo esc_url( $next_action_url ); ?>"> |
||
246 | |||
247 | <?php _e( 'Next', 'woothemes-sensei' ); ?> |
||
248 | |||
249 | </a> |
||
250 | |||
251 | </p> |
||
252 | <script type='text/javascript'> |
||
253 | <!-- |
||
254 | function js_sensei_nextpage() { |
||
255 | location.href = "<?php echo esc_url_raw( $next_action_url );?>"; |
||
256 | } |
||
257 | setTimeout( "js_sensei_nextpage()", 250 ); |
||
258 | //--> |
||
259 | </script> |
||
260 | |||
261 | <?php } else { ?> |
||
262 | |||
263 | <p><strong><?php _e('Update completed successfully!', 'woothemes-sensei'); ?></strong></p> |
||
264 | <p> |
||
265 | <a href="<?php echo admin_url('edit.php?post_type=lesson'); ?>"><?php _e('Create a new lesson', 'woothemes-sensei'); ?></a> |
||
266 | or <a |
||
267 | href="<?php echo admin_url('admin.php?page=sensei_updates'); ?>"><?php _e('run some more updates', 'woothemes-sensei'); ?></a>. |
||
268 | </p> |
||
269 | |||
270 | <?php } // End If Statement |
||
271 | |||
272 | } else { ?> |
||
273 | |||
274 | <h3><?php _e('Updates', 'woothemes-sensei'); ?></h3> |
||
275 | <p><?php printf(__('These are updates that have been made available as new Sensei versions have been released. Updates of type %1$sAuto%2$s will run as you update Sensei to the relevant version - other updates need to be run manually and you can do that here.', 'woothemes-sensei'), '<code>', '</code>'); ?></p> |
||
276 | |||
277 | <div class="updated"><p> |
||
278 | <strong><?php _e('Only run these updates if you have been instructed to do so by WooThemes support staff.', 'woothemes-sensei'); ?></strong> |
||
279 | </p></div> |
||
280 | |||
281 | <table class="widefat" cellspacing="0" id="update-plugins-table"> |
||
282 | |||
283 | <thead> |
||
284 | <tr> |
||
285 | <th scope="col" class="manage-column"><?php _e('Update', 'woothemes-sensei'); ?></th> |
||
286 | <th scope="col" class="manage-column"><?php _e('Type', 'woothemes-sensei'); ?></th> |
||
287 | <th scope="col" class="manage-column"><?php _e('Action', 'woothemes-sensei'); ?></th> |
||
288 | </tr> |
||
289 | </thead> |
||
290 | |||
291 | <tfoot> |
||
292 | <tr> |
||
293 | <th scope="col" class="manage-column"><?php _e('Update', 'woothemes-sensei'); ?></th> |
||
294 | <th scope="col" class="manage-column"><?php _e('Type', 'woothemes-sensei'); ?></th> |
||
295 | <th scope="col" class="manage-column"><?php _e('Action', 'woothemes-sensei'); ?></th> |
||
296 | </tr> |
||
297 | </tfoot> |
||
298 | |||
299 | <tbody class="updates"> |
||
300 | <?php |
||
301 | // Sort updates with the latest at the top |
||
302 | uksort($this->updates, array($this, 'sort_updates')); |
||
303 | $this->updates = array_reverse($this->updates, true); |
||
304 | $class = 'alternate'; |
||
305 | foreach ($this->updates as $version => $version_updates) { |
||
306 | foreach ($version_updates as $type => $updates) { |
||
307 | foreach ($updates as $update => $data) { |
||
308 | $update_run = $this->has_update_run($update); |
||
309 | $product = 'Sensei'; |
||
310 | if (isset($data['product']) && '' != $data['product']) { |
||
311 | $product = $data['product']; |
||
312 | } // End If Statement |
||
313 | ?> |
||
314 | <form method="post" action="admin.php?page=sensei_updates&action=update&n=0" |
||
315 | name="update-sensei" class="upgrade"> |
||
316 | <tr class="<?php echo $class; ?>"> |
||
317 | <td> |
||
318 | <p> |
||
319 | <input type="hidden" name="checked[]" value="<?php echo $update; ?>"> |
||
320 | <strong><?php echo $data['title']; ?></strong><br><?php echo $data['desc']; ?> |
||
321 | <br> |
||
322 | <em><?php printf(__('Originally included in %s v%s', 'woothemes-sensei'), $product, $version); ?></em> |
||
323 | </p> |
||
324 | </td> |
||
325 | <?php |
||
326 | $type_label = __('Auto', 'woothemes-sensei'); |
||
327 | if ($type != 'auto') { |
||
328 | $type_label = __('Manual', 'woothemes-sensei'); |
||
329 | } |
||
330 | ?> |
||
331 | <td><p><?php echo $type_label; ?></p></td> |
||
332 | <td> |
||
333 | <p> |
||
334 | <input onclick="javascript:return confirm('<?php echo addslashes( sprintf( __( 'Are you sure you want to run the \'%s\' update?', 'woothemes-sensei' ), $data['title'] ) ); ?>');" |
||
335 | id="update-sensei" |
||
336 | class="button<?php if( ! $update_run ) { echo ' button-primary'; } ?>" |
||
337 | type="submit" |
||
338 | value="<?php if( $update_run ) { _e( 'Re-run Update', 'woothemes-sensei' ); } else { _e( 'Run Update', 'woothemes-sensei' ); } ?>" |
||
339 | name="update"> |
||
340 | |||
341 | <?php |
||
342 | $nonce_action = 'run_'.$update; |
||
343 | $nonce_field_name = $update.'_nonce_field'; |
||
344 | wp_nonce_field( $nonce_action, $nonce_field_name, false, true ); |
||
345 | ?> |
||
346 | </p> |
||
347 | </td> |
||
348 | </tr> |
||
349 | </form> |
||
350 | <?php |
||
351 | if ('alternate' == $class) { |
||
352 | $class = ''; |
||
353 | } else { |
||
354 | $class = 'alternate'; |
||
355 | } |
||
356 | } |
||
357 | } |
||
358 | } |
||
359 | ?> |
||
360 | </tbody> |
||
361 | |||
362 | </table> |
||
363 | |||
364 | </div> |
||
365 | |||
366 | <?php |
||
367 | } // End If Statement |
||
368 | } // End sensei_updates_page() |
||
369 | |||
370 | /** |
||
371 | * Since 1.9.0 |
||
372 | * |
||
373 | * A list of safe to execute functions withing the |
||
374 | * updater context. |
||
375 | * |
||
376 | * @param string $function_name |
||
377 | */ |
||
378 | public function function_in_whitelist( $function_name ){ |
||
379 | |||
380 | $function_whitelist = array( |
||
381 | 'status_changes_convert_questions', |
||
382 | 'status_changes_fix_lessons', |
||
383 | 'status_changes_convert_courses', |
||
384 | 'status_changes_convert_lessons', |
||
385 | 'status_changes_repair_course_statuses', |
||
386 | |||
387 | ); |
||
388 | |||
389 | return in_array($function_name, $function_whitelist ); |
||
390 | |||
391 | }// end function_in_whitelist |
||
392 | |||
393 | /** |
||
394 | * Sort updates list by version number |
||
395 | * |
||
396 | * @param string $a First key |
||
397 | * @param string $b Second key |
||
398 | * @return integer |
||
399 | */ |
||
400 | private function sort_updates( $a, $b ) { |
||
403 | |||
404 | /** |
||
405 | * update Calls the functions for updating |
||
406 | * |
||
407 | * @param string $type specifies if the update is 'auto' or 'manual' |
||
408 | * @since 1.1.0 |
||
409 | * @access public |
||
410 | * @return boolean |
||
411 | */ |
||
412 | public function update ( $type = 'auto' ) { |
||
413 | |||
414 | // Only allow admins to run update functions |
||
415 | if( ! current_user_can( 'manage_options' ) ) { |
||
416 | return false; |
||
417 | } |
||
418 | |||
419 | $this->force_updates(); |
||
420 | |||
421 | // Run through all functions |
||
422 | foreach ( $this->updates as $version => $value ) { |
||
423 | foreach ( $this->updates[$version] as $upgrade_type => $function_to_run ) { |
||
424 | if ( $upgrade_type == $type ) { |
||
425 | $updated = false; |
||
426 | // Run the update function |
||
427 | foreach ( $function_to_run as $function_name => $update_data ) { |
||
428 | if ( isset( $function_name ) && '' != $function_name ) { |
||
429 | if ( ! in_array( $function_name, $this->updates_run ) ) { |
||
430 | $updated = false; |
||
431 | if ( method_exists( $this, $function_name ) ) { |
||
432 | |||
433 | $this->updates_run = array_unique( $this->updates_run ); // we only need one reference per update |
||
434 | update_option( Sensei()->token . '-upgrades', $this->updates_run ); |
||
435 | return true; |
||
436 | |||
437 | } elseif( $this->function_in_whitelist( $function_name ) ) { |
||
438 | |||
439 | $updated = call_user_func( $function_name ); |
||
440 | |||
441 | } // End If Statement |
||
442 | |||
443 | if ( $updated ) { |
||
444 | array_push( $this->updates_run, $function_name ); |
||
445 | } // End If Statement |
||
446 | } |
||
447 | } // End If Statement |
||
448 | } // End For Loop |
||
449 | } // End If Statement |
||
450 | } // End For Loop |
||
451 | } // End For Loop |
||
452 | |||
453 | $this->updates_run = array_unique( $this->updates_run ); // we only need one reference per update |
||
454 | update_option( $this->token . '-upgrades', $this->updates_run ); |
||
455 | |||
456 | return true; |
||
457 | |||
458 | } // End update() |
||
459 | |||
460 | private function force_updates() { |
||
461 | |||
462 | if( ! isset( $_GET['page'] ) || 'sensei_updates' != $_GET['page'] ) { |
||
463 | |||
464 | // $skip_forced_updates = false; |
||
465 | // if( ! get_option( 'woothemes-sensei-force-updates', false ) ) { |
||
466 | // $skip_forced_updates = true; |
||
467 | // } |
||
468 | |||
469 | // Force critical updates if only if lessons already exist |
||
470 | $skip_forced_updates = false; |
||
471 | $lesson_posts = wp_count_posts( 'lesson' ); |
||
472 | if( ! isset( $lesson_posts->publish ) || ! $lesson_posts->publish ) { |
||
473 | $skip_forced_updates = true; |
||
474 | } |
||
475 | |||
476 | $use_the_force = false; |
||
477 | |||
478 | $updates_to_run = array(); |
||
479 | |||
480 | foreach ( $this->updates as $version => $value ) { |
||
481 | foreach ( $this->updates[$version] as $upgrade_type => $function_to_run ) { |
||
482 | if ( $upgrade_type == 'forced' ) { |
||
483 | foreach ( $function_to_run as $function_name => $update_data ) { |
||
484 | |||
485 | if( $skip_forced_updates ) { |
||
486 | $this->set_update_run( $function_name ); |
||
487 | continue; |
||
488 | } |
||
489 | |||
490 | $update_run = $this->has_update_run( $function_name ); |
||
491 | |||
492 | if( ! $update_run ) { |
||
493 | $use_the_force = true; |
||
494 | $updates_to_run[ $function_name ] = $update_data; |
||
495 | } |
||
496 | } |
||
497 | } |
||
498 | } |
||
499 | } |
||
500 | |||
501 | if( $skip_forced_updates ) { |
||
502 | return; |
||
503 | } |
||
504 | |||
505 | if( $use_the_force && 0 < count( $updates_to_run ) ) { |
||
506 | |||
507 | $update_title = __( 'Important Sensei updates required', 'woothemes-sensei' ); |
||
508 | |||
509 | $update_message = '<h1>' . __( 'Important Sensei upgrades required!', 'woothemes-sensei' ) . '</h1>' . "\n"; |
||
510 | |||
511 | // $update_message .= '<h4>' . sprintf( __( 'These updates are only required if you are updating from a previous version of Sensei. If you are installing Sensei for the first time, %1$syou can dismiss this page by clicking here%2$s.', 'woothemes-sensei' ), '<a href="' . add_query_arg( array( 'sensei_skip_forced_updates' => 'true' ) ) . '">', '</a>' ) . '</h4>' ."\n"; |
||
512 | |||
513 | $update_message .= '<p>' . __( 'The latest version of Sensei requires some important database upgrades. In order to run these upgrades you will need to follow the step by step guide below. Your site will not function correctly unless you run these critical updates.', 'woothemes-sensei' ) . '</p>' . "\n"; |
||
514 | |||
515 | $update_message .= '<p><b>' . __( 'To run the upgrades click on each of the links below in the order that they appear.', 'woothemes-sensei' ) . '</b></p>' . "\n"; |
||
516 | |||
517 | $update_message .= '<p>' . __( 'Clicking each link will open up a new window/tab - do not close that window/tab until you see the message \'Update completed successfully\'. Once you see that message you can close the window/tab and start the next upgrade by clicking on the next link in the list.', 'woothemes-sensei' ) . '</p>' . "\n"; |
||
518 | |||
519 | $update_message .= '<p><b>' . __( 'Once all the upgrades have been completed you will be able to use your WordPress site again.', 'woothemes-sensei' ) . '</b></p>' . "\n"; |
||
520 | |||
521 | $update_message .= '<ol>' . "\n"; |
||
522 | |||
523 | foreach( $updates_to_run as $function => $data ) { |
||
524 | |||
525 | if( ! isset( $data['title'] ) ) { |
||
526 | break; |
||
527 | } |
||
528 | |||
529 | $update_message .= '<li style="margin:5px 0;"><a href="' . admin_url( 'admin.php?page=sensei_updates&action=update&n=0&functions[]=' . $function ) . '" target="_blank">' . $data['title'] . '</a></li>'; |
||
530 | } |
||
531 | |||
532 | $update_message .= '</ol>' . "\n"; |
||
533 | |||
534 | switch( $version ) { |
||
535 | |||
536 | case '1.7.0': |
||
537 | $update_message .= '<p><em>' . sprintf( __( 'Want to know what these upgrades are all about? %1$sFind out more here%2$s.', 'woothemes-sensei' ), '<a href="http://develop.woothemes.com/sensei/2014/12/03/important-information-about-sensei-1-7" target="_blank">', '</a>' ) . '</em></p>' . "\n"; |
||
538 | break; |
||
539 | |||
540 | } |
||
541 | |||
542 | wp_die( $update_message, $update_title ); |
||
543 | } |
||
544 | } |
||
545 | } |
||
546 | |||
547 | /** |
||
548 | * Check if specified update has already been run |
||
549 | * |
||
550 | * @param string $update Update to check |
||
551 | * @since 1.4.0 |
||
552 | * @return boolean |
||
553 | */ |
||
554 | private function has_update_run( $update ) { |
||
555 | if ( in_array( $update, $this->updates_run ) ) { |
||
556 | return true; |
||
557 | } |
||
558 | return false; |
||
559 | } |
||
560 | |||
561 | /** |
||
562 | * Mark update as having been run |
||
563 | * |
||
564 | * @param string $update Update to process |
||
565 | * @since 1.4.0 |
||
566 | */ |
||
567 | private function set_update_run( $update ) { |
||
568 | array_push( $this->updates_run, $update ); |
||
569 | $this->updates_run = array_unique( $this->updates_run ); // we only need one reference per update |
||
570 | update_option( Sensei()->token . '-upgrades', $this->updates_run ); |
||
571 | } |
||
572 | |||
573 | /** |
||
574 | * Sets the role capabilities for WordPress users. |
||
575 | * |
||
576 | * @since 1.1.0 |
||
577 | * @access public |
||
578 | * @return void |
||
579 | */ |
||
580 | public function assign_role_caps() { |
||
581 | foreach ( $this->parent->post_types->role_caps as $role_cap_set ) { |
||
582 | foreach ( $role_cap_set as $role_key => $capabilities_array ) { |
||
583 | /* Get the role. */ |
||
584 | $role = get_role( $role_key ); |
||
585 | foreach ( $capabilities_array as $cap_name ) { |
||
586 | /* If the role exists, add required capabilities for the plugin. */ |
||
587 | if ( !empty( $role ) ) { |
||
588 | if ( !$role->has_cap( $cap_name ) ) { |
||
589 | $role->add_cap( $cap_name ); |
||
590 | } // End If Statement |
||
591 | } // End If Statement |
||
592 | } // End For Loop |
||
593 | } // End For Loop |
||
594 | } // End For Loop |
||
595 | } // End assign_role_caps |
||
596 | |||
597 | /** |
||
598 | * Set default quiz grade type |
||
599 | * |
||
600 | * @since 1.3.0 |
||
601 | * @access public |
||
602 | * @return void |
||
603 | */ |
||
604 | View Code Duplication | public function set_default_quiz_grade_type() { |
|
605 | $args = array( 'post_type' => 'quiz', |
||
606 | 'posts_per_page' => -1, |
||
607 | 'post_status' => 'publish', |
||
608 | 'suppress_filters' => 0 |
||
609 | ); |
||
610 | $quizzes = get_posts( $args ); |
||
611 | |||
612 | foreach( $quizzes as $quiz ) { |
||
613 | update_post_meta( $quiz->ID, '_quiz_grade_type', 'auto' ); |
||
614 | update_post_meta( $quiz->ID, '_quiz_grade_type_disabled', '' ); |
||
615 | } |
||
616 | } // End set_default_quiz_grade_type |
||
617 | |||
618 | /** |
||
619 | * Set default question type |
||
620 | * |
||
621 | * @since 1.3.0 |
||
622 | * @access public |
||
623 | * @return void |
||
624 | */ |
||
625 | public function set_default_question_type() { |
||
626 | $args = array( 'post_type' => 'question', |
||
627 | 'posts_per_page' => -1, |
||
628 | 'post_status' => 'publish', |
||
629 | 'suppress_filters' => 0 |
||
630 | ); |
||
631 | $questions = get_posts( $args ); |
||
632 | |||
633 | $already_run = true; |
||
634 | foreach( $questions as $question ) { |
||
635 | if( $already_run ) { |
||
636 | $terms = wp_get_post_terms( $question->ID, 'question-type' ); |
||
637 | if( is_array( $terms ) && count( $terms ) > 0 ) { |
||
638 | break; |
||
639 | } |
||
640 | } |
||
641 | $already_run = false; |
||
642 | wp_set_post_terms( $question->ID, array( 'multiple-choice' ), 'question-type' ); |
||
643 | } |
||
644 | |||
645 | } // End set_default_question_type |
||
646 | |||
647 | /** |
||
648 | * Update question answers to use new data structure |
||
649 | * |
||
650 | * @since 1.3.0 |
||
651 | * @access public |
||
652 | * @return boolean |
||
653 | */ |
||
654 | public function update_question_answer_data( $n = 50, $offset = 0 ) { |
||
655 | |||
656 | // Get Total Number of Updates to run |
||
657 | $quiz_count_object = wp_count_posts( 'quiz' ); |
||
658 | $quiz_count_published = $quiz_count_object->publish; |
||
659 | |||
660 | // Calculate if this is the last page |
||
661 | if ( 0 == $offset ) { |
||
662 | $current_page = 1; |
||
663 | } else { |
||
664 | $current_page = intval( $offset / $n ); |
||
665 | } // End If Statement |
||
666 | $total_pages = intval( $quiz_count_published / $n ); |
||
667 | |||
668 | |||
669 | $args = array( 'post_type' => 'quiz', |
||
670 | 'posts_per_page' => $n, |
||
671 | 'offset' => $offset, |
||
672 | 'post_status' => 'publish', |
||
673 | 'suppress_filters' => 0 |
||
674 | ); |
||
675 | $quizzes = get_posts( $args ); |
||
676 | |||
677 | $old_answers = array(); |
||
678 | $right_answers = array(); |
||
679 | $old_user_answers = array(); |
||
680 | |||
681 | if( is_array( $quizzes ) ) { |
||
682 | foreach( $quizzes as $quiz ) { |
||
683 | $quiz_id = $quiz->ID; |
||
684 | |||
685 | // Get current user answers |
||
686 | $comments = Sensei_Utils::sensei_check_for_activity( array( 'post_id' => $quiz_id, 'type' => 'sensei_quiz_answers' ), true ); |
||
687 | // Need to always return an array, even with only 1 item |
||
688 | if ( !is_array($comments) ) { |
||
689 | $comments = array( $comments ); |
||
690 | } |
||
691 | foreach ( $comments as $comment ) { |
||
692 | $user_id = $comment->user_id; |
||
693 | $content = maybe_unserialize( base64_decode( $comment->comment_content ) ); |
||
694 | $old_user_answers[ $quiz_id ][ $user_id ] = $content; |
||
695 | } |
||
696 | |||
697 | // Get correct answers |
||
698 | $questions = Sensei_Utils::sensei_get_quiz_questions( $quiz_id ); |
||
699 | if( is_array( $questions ) ) { |
||
700 | foreach( $questions as $question ) { |
||
701 | $right_answer = get_post_meta( $question->ID, '_question_right_answer', true ); |
||
702 | $right_answers[ $quiz_id ][ $question->ID ] = $right_answer; |
||
703 | } |
||
704 | } |
||
705 | } |
||
706 | } |
||
707 | |||
708 | if( is_array( $right_answers ) ) { |
||
709 | foreach( $right_answers as $quiz_id => $question ) { |
||
710 | $count = 0; |
||
711 | if( is_array( $question ) ) { |
||
712 | foreach( $question as $question_id => $answer ) { |
||
713 | ++$count; |
||
714 | if( isset( $old_user_answers[ $quiz_id ] ) ) { |
||
715 | $answers_linkup[ $quiz_id ][ $count ] = $question_id; |
||
716 | } |
||
717 | } |
||
718 | } |
||
719 | } |
||
720 | } |
||
721 | |||
722 | if( is_array( $old_user_answers ) ) { |
||
723 | foreach( $old_user_answers as $quiz_id => $user_answers ) { |
||
724 | foreach( $user_answers as $user_id => $answers ) { |
||
725 | foreach( $answers as $answer_id => $user_answer ) { |
||
726 | $question_id = $answers_linkup[ $quiz_id ][ $answer_id ]; |
||
727 | $new_user_answers[ $question_id ] = $user_answer; |
||
728 | Sensei_Utils::sensei_grade_question_auto( $question_id, '', $user_answer, $user_id ); |
||
729 | } |
||
730 | $lesson_id = get_post_meta( $quiz_id, '_quiz_lesson', true ); |
||
731 | Sensei_Utils::sensei_start_lesson( $lesson_id, $user_id ); |
||
732 | Sensei_Utils::sensei_save_quiz_answers( $new_user_answers, $user_id ); |
||
733 | } |
||
734 | } |
||
735 | } |
||
736 | |||
737 | if ( $current_page == $total_pages ) { |
||
738 | return true; |
||
739 | } else { |
||
740 | return false; |
||
741 | } // End If Statement |
||
742 | |||
743 | } // End update_question_answer_data |
||
744 | |||
745 | /** |
||
746 | * Add default question grade points for v1.4.0 |
||
747 | * |
||
748 | * @since 1.4.0 |
||
749 | * @return boolean |
||
750 | */ |
||
751 | View Code Duplication | public function update_question_grade_points() { |
|
752 | $args = array( 'post_type' => 'question', |
||
753 | 'posts_per_page' => -1, |
||
754 | 'post_status' => 'publish', |
||
755 | 'suppress_filters' => 0 |
||
756 | ); |
||
757 | $questions = get_posts( $args ); |
||
758 | |||
759 | foreach( $questions as $question ) { |
||
760 | update_post_meta( $question->ID, '_question_grade', '1' ); |
||
761 | } |
||
762 | return true; |
||
763 | } // End update_question_grade_points |
||
764 | |||
765 | /** |
||
766 | * Convert all essay paste questions into multi-line for v1.5.0 |
||
767 | * |
||
768 | * @since 1.5.0 |
||
769 | * @return boolean |
||
770 | */ |
||
771 | public function convert_essay_paste_questions() { |
||
772 | $args = array( 'post_type' => 'question', |
||
773 | 'posts_per_page' => -1, |
||
774 | 'post_status' => 'publish', |
||
775 | 'tax_query' => array( |
||
776 | array( |
||
777 | 'taxonomy' => 'question-type', |
||
778 | 'terms' => 'essay-paste', |
||
779 | 'field' => 'slug' |
||
780 | ) |
||
781 | ), |
||
782 | 'suppress_filters' => 0 |
||
783 | ); |
||
784 | $questions = get_posts( $args ); |
||
785 | |||
786 | foreach( $questions as $question ) { |
||
787 | wp_set_object_terms( $question->ID, 'multi-line', 'question-type', false ); |
||
788 | |||
789 | $quiz_id = get_post_meta( $question->ID, '_quiz_id', true ); |
||
790 | if( 0 < intval( $quiz_id ) ) { |
||
791 | add_post_meta( $question->ID, '_quiz_question_order' . $quiz_id, $quiz_id . '0000', true ); |
||
792 | } |
||
793 | } |
||
794 | return true; |
||
795 | } // End convert_essay_paste_questions |
||
796 | |||
797 | /** |
||
798 | * Set all quizzes to have a random question order |
||
799 | * |
||
800 | * @since 1.5.0 |
||
801 | * @return boolean |
||
802 | */ |
||
803 | public function set_random_question_order( $n = 50, $offset = 0 ) { |
||
804 | |||
805 | // Get Total Number of Updates to run |
||
806 | $quiz_count_object = wp_count_posts( 'quiz' ); |
||
807 | $quiz_count_published = $quiz_count_object->publish; |
||
808 | |||
809 | // Calculate if this is the last page |
||
810 | if ( 0 == $offset ) { |
||
811 | $current_page = 1; |
||
812 | } else { |
||
813 | $current_page = intval( $offset / $n ); |
||
814 | } // End If Statement |
||
815 | $total_pages = intval( $quiz_count_published / $n ); |
||
816 | |||
817 | $args = array( 'post_type' => 'quiz', |
||
818 | 'post_status' => 'any', |
||
819 | 'posts_per_page' => $n, |
||
820 | 'offset' => $offset, |
||
821 | 'suppress_filters' => 0 |
||
822 | ); |
||
823 | $quizzes = get_posts( $args ); |
||
824 | |||
825 | foreach( $quizzes as $quiz ) { |
||
826 | update_post_meta( $quiz->ID, '_random_question_order', 'yes' ); |
||
827 | } |
||
828 | |||
829 | if ( $current_page == $total_pages ) { |
||
830 | return true; |
||
831 | } else { |
||
832 | return false; |
||
833 | } // End If Statement |
||
834 | |||
835 | } // End set_random_question_order() |
||
836 | |||
837 | /** |
||
838 | * Set all quizzes to display all questions |
||
839 | * |
||
840 | * @since 1.5.0 |
||
841 | * @return boolean |
||
842 | */ |
||
843 | public function set_default_show_question_count( $n = 50, $offset = 0 ) { |
||
844 | |||
845 | $args = array( 'post_type' => 'quiz', |
||
846 | 'post_status' => 'any', |
||
847 | 'posts_per_page' => $n, |
||
848 | 'offset' => $offset, |
||
849 | 'meta_key' => '_show_questions', |
||
850 | 'suppress_filters' => 0 |
||
851 | ); |
||
852 | $quizzes = get_posts( $args ); |
||
853 | |||
854 | $total_quizzes = count( $quizzes ); |
||
855 | |||
856 | if( 0 == intval( $total_quizzes ) ) { |
||
857 | return true; |
||
858 | } |
||
859 | |||
860 | foreach( $quizzes as $quiz ) { |
||
861 | delete_post_meta( $quiz->ID, '_show_questions' ); |
||
862 | } |
||
863 | |||
864 | $total_pages = intval( $total_quizzes / $n ); |
||
865 | |||
866 | // Calculate if this is the last page |
||
867 | if ( 0 == $offset ) { |
||
868 | $current_page = 1; |
||
869 | } else { |
||
870 | $current_page = intval( $offset / $n ); |
||
871 | } // End If Statement |
||
872 | |||
873 | if ( $current_page == $total_pages ) { |
||
874 | return true; |
||
875 | } else { |
||
876 | return false; |
||
877 | } // End If Statement |
||
878 | |||
879 | } |
||
880 | |||
881 | public function remove_deleted_user_activity( $n = 50, $offset = 0 ) { |
||
882 | |||
883 | $all_activity = get_comments( array( 'status' => 'approve' ) ); |
||
884 | $activity_count = array(); |
||
885 | foreach( $all_activity as $activity ) { |
||
886 | if( '' == $activity->comment_type ) continue; |
||
887 | if( strpos( 'sensei_', $activity->comment_type ) != 0 ) continue; |
||
888 | if( 0 == $activity->user_id ) continue; |
||
889 | $activity_count[] = $activity->comment_ID; |
||
890 | } |
||
891 | |||
892 | $args = array( |
||
893 | 'number' => $n, |
||
894 | 'offset' => $offset, |
||
895 | 'status' => 'approve' |
||
896 | ); |
||
897 | |||
898 | $activities = get_comments( $args ); |
||
899 | |||
900 | foreach( $activities as $activity ) { |
||
901 | if( '' == $activity->comment_type ) continue; |
||
902 | if( strpos( 'sensei_', $activity->comment_type ) != 0 ) continue; |
||
903 | if( 0 == $activity->user_id ) continue; |
||
904 | |||
905 | $user_exists = get_userdata( $activity->user_id ); |
||
906 | |||
907 | if( ! $user_exists ) { |
||
908 | wp_delete_comment( intval( $activity->comment_ID ), true ); |
||
909 | wp_cache_flush(); |
||
910 | } |
||
911 | } |
||
912 | |||
913 | $total_activities = count( $activity_count ); |
||
914 | |||
915 | $total_pages = intval( $total_activities / $n ); |
||
916 | |||
917 | // Calculate if this is the last page |
||
918 | if ( 0 == $offset ) { |
||
919 | $current_page = 1; |
||
920 | } else { |
||
921 | $current_page = intval( $offset / $n ); |
||
922 | } // End If Statement |
||
923 | |||
924 | if ( $current_page >= $total_pages ) { |
||
925 | return true; |
||
926 | } else { |
||
927 | return false; |
||
928 | } // End If Statement |
||
929 | |||
930 | } |
||
931 | |||
932 | public function add_teacher_role() { |
||
936 | |||
937 | public function add_sensei_caps() { |
||
938 | $role = get_role( 'administrator' ); |
||
939 | |||
940 | if( ! is_null( $role ) ) { |
||
941 | $role->add_cap( 'manage_sensei' ); |
||
942 | $role->add_cap( 'manage_sensei_grades' ); |
||
943 | } |
||
944 | |||
945 | return true; |
||
946 | } |
||
947 | |||
948 | public function restructure_question_meta() { |
||
949 | $args = array( |
||
950 | 'post_type' => 'question', |
||
951 | 'posts_per_page' => -1, |
||
952 | 'post_status' => 'any', |
||
953 | 'suppress_filters' => 0 |
||
954 | ); |
||
955 | |||
956 | $questions = get_posts( $args ); |
||
957 | |||
958 | foreach( $questions as $question ) { |
||
959 | |||
960 | if( ! isset( $question->ID ) ) continue; |
||
961 | |||
962 | $quiz_id = get_post_meta( $question->ID, '_quiz_id', true ); |
||
963 | |||
964 | $question_order = get_post_meta( $question->ID, '_quiz_question_order', true ); |
||
965 | update_post_meta( $question->ID, '_quiz_question_order' . $quiz_id, $question_order ); |
||
966 | |||
967 | } |
||
968 | |||
969 | return true; |
||
970 | } |
||
971 | |||
972 | public function update_quiz_settings() { |
||
973 | |||
974 | $settings = get_option( 'woothemes-sensei-settings', array() ); |
||
975 | |||
976 | $lesson_completion = false; |
||
977 | if( isset( $settings['lesson_completion'] ) ) { |
||
978 | $lesson_completion = $settings['lesson_completion']; |
||
979 | } |
||
980 | |||
981 | $reset_quiz_allowed = false; |
||
982 | if( isset( $settings['quiz_reset_allowed'] ) ) { |
||
983 | $reset_quiz_allowed = $settings['quiz_reset_allowed']; |
||
984 | } |
||
985 | |||
986 | $args = array( |
||
987 | 'post_type' => 'quiz', |
||
988 | 'posts_per_page' => -1, |
||
989 | 'post_status' => 'any', |
||
990 | 'suppress_filters' => 0 |
||
991 | ); |
||
992 | |||
993 | $quizzes = get_posts( $args ); |
||
994 | |||
995 | foreach( $quizzes as $quiz ) { |
||
996 | |||
997 | if( ! isset( $quiz->ID ) ) continue; |
||
998 | |||
999 | if( isset( $lesson_completion ) && 'passed' == $lesson_completion ) { |
||
1000 | update_post_meta( $quiz->ID, '_pass_required', 'on' ); |
||
1001 | } else { |
||
1002 | update_post_meta( $quiz->ID, '_quiz_passmark', 0 ); |
||
1003 | } |
||
1004 | |||
1005 | if( isset( $reset_quiz_allowed ) && $reset_quiz_allowed ) { |
||
1006 | update_post_meta( $quiz->ID, '_enable_quiz_reset', 'on' ); |
||
1007 | } |
||
1008 | } |
||
1009 | |||
1010 | return true; |
||
1011 | } |
||
1012 | |||
1013 | public function reset_lesson_order_meta() { |
||
1014 | $args = array( |
||
1015 | 'post_type' => 'lesson', |
||
1016 | 'posts_per_page' => -1, |
||
1017 | 'post_status' => 'any', |
||
1018 | 'suppress_filters' => 0 |
||
1019 | ); |
||
1020 | |||
1021 | $lessons = get_posts( $args ); |
||
1022 | |||
1023 | foreach( $lessons as $lesson ) { |
||
1024 | |||
1025 | if( ! isset( $lesson->ID ) ) continue; |
||
1026 | |||
1027 | $course_id = get_post_meta( $lesson->ID, '_lesson_course', true); |
||
1028 | |||
1029 | if( $course_id ) { |
||
1030 | update_post_meta( $lesson->ID, '_order_' . $course_id, 0 ); |
||
1031 | } |
||
1032 | |||
1033 | $module = Sensei()->modules->get_lesson_module( $lesson->ID ); |
||
1034 | |||
1035 | if( $module ) { |
||
1036 | update_post_meta( $lesson->ID, '_order_module_' . $module->term_id, 0 ); |
||
1037 | } |
||
1038 | |||
1039 | } |
||
1040 | |||
1041 | return true; |
||
1042 | } |
||
1043 | |||
1044 | public function add_editor_caps() { |
||
1045 | $role = get_role( 'editor' ); |
||
1046 | |||
1047 | if( ! is_null( $role ) ) { |
||
1048 | $role->add_cap( 'manage_sensei_grades' ); |
||
1049 | } |
||
1050 | |||
1051 | return true; |
||
1052 | } |
||
1053 | |||
1054 | /** |
||
1055 | * Updates all gap fill questions, converting the | separator to || matching the changes in code. Using || allows the use of | within the pre, gap or post field. |
||
1056 | * |
||
1057 | * @global type $wpdb |
||
1058 | * @return boolean |
||
1059 | */ |
||
1060 | public function update_question_gap_fill_separators() { |
||
1061 | global $wpdb; |
||
1062 | |||
1063 | $sql = "UPDATE $wpdb->postmeta AS m, $wpdb->term_relationships AS tr, $wpdb->term_taxonomy AS tt, $wpdb->terms AS t SET m.meta_value = replace(m.meta_value, '|', '||') |
||
1064 | WHERE m.meta_key = '_question_right_answer' AND m.meta_value LIKE '%|%' AND m.meta_value NOT LIKE '%||%' |
||
1065 | AND m.post_id = tr.object_id AND tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.term_id = t.term_id |
||
1066 | AND tt.taxonomy = 'question-type' AND t.slug = 'gap-fill'"; |
||
1067 | $wpdb->query( $sql ); |
||
1068 | |||
1069 | return true; |
||
1070 | } |
||
1071 | |||
1072 | public function update_quiz_lesson_relationship( $n = 50, $offset = 0 ) { |
||
1073 | $count_object = wp_count_posts( 'quiz' ); |
||
1074 | |||
1075 | $count_published = 0; |
||
1076 | foreach ( $count_object AS $status => $count ) { |
||
1077 | $count_published += $count; |
||
1078 | } |
||
1079 | |||
1080 | // Calculate if this is the last page |
||
1081 | if ( 0 == $offset ) { |
||
1082 | $current_page = 1; |
||
1083 | } else { |
||
1084 | $current_page = intval( $offset / $n ); |
||
1085 | } |
||
1086 | $total_pages = ceil( $count_published / $n ); |
||
1087 | |||
1088 | $args = array( |
||
1089 | 'post_type' => 'quiz', |
||
1090 | 'posts_per_page' => $n, |
||
1091 | 'offset' => $offset, |
||
1092 | 'post_status' => 'any' |
||
1093 | ); |
||
1094 | |||
1095 | $quizzes = get_posts( $args ); |
||
1096 | |||
1097 | foreach( $quizzes as $quiz ) { |
||
1098 | |||
1099 | if( ! isset( $quiz->ID ) || 0 != $quiz->post_parent ) continue; |
||
1100 | |||
1101 | $lesson_id = get_post_meta( $quiz->ID, '_quiz_lesson', true ); |
||
1102 | |||
1103 | if( empty( $lesson_id ) ) continue; |
||
1104 | |||
1105 | $data = array( |
||
1106 | 'ID' => $quiz->ID, |
||
1107 | 'post_parent' => $lesson_id, |
||
1108 | ); |
||
1109 | wp_update_post( $data ); |
||
1110 | |||
1111 | update_post_meta( $lesson_id, '_lesson_quiz', $quiz->ID ); |
||
1112 | } |
||
1113 | |||
1114 | if ( $current_page == $total_pages || 0 == $total_pages ) { |
||
1115 | return true; |
||
1116 | } else { |
||
1117 | return false; |
||
1118 | } |
||
1119 | } |
||
1120 | |||
1121 | function status_changes_fix_lessons( $n = 50, $offset = 0 ) { |
||
1122 | global $wpdb; |
||
1123 | |||
1124 | $count_object = wp_count_posts( 'lesson' ); |
||
1125 | $count_published = 0; |
||
1126 | foreach ( $count_object AS $status => $count ) { |
||
1127 | $count_published += $count; |
||
1128 | } |
||
1129 | |||
1130 | if ( 0 == $count_published ) { |
||
1131 | return true; |
||
1132 | } |
||
1133 | |||
1134 | // Calculate if this is the last page |
||
1135 | if ( 0 == $offset ) { |
||
1136 | $current_page = 1; |
||
1137 | } else { |
||
1138 | $current_page = intval( $offset / $n ); |
||
1139 | } |
||
1140 | $total_pages = ceil( $count_published / $n ); |
||
1141 | |||
1142 | // Get all Lessons with (and without) Quizzes... |
||
1143 | $args = array( |
||
1144 | 'post_type' => 'lesson', |
||
1145 | 'post_status' => 'any', |
||
1146 | 'posts_per_page' => $n, |
||
1147 | 'offset' => $offset, |
||
1148 | 'fields' => 'ids' |
||
1149 | ); |
||
1150 | $lesson_ids = get_posts( $args ); |
||
1151 | |||
1152 | // ...get all Quiz IDs for the above Lessons |
||
1153 | $id_list = join( ',', $lesson_ids ); |
||
1154 | $meta_list = $wpdb->get_results( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '_quiz_lesson' AND meta_value IN ($id_list)", ARRAY_A ); |
||
1155 | $lesson_quiz_ids = array(); |
||
1156 | View Code Duplication | if ( !empty($meta_list) ) { |
|
1157 | foreach ( $meta_list as $metarow ) { |
||
1158 | $lesson_id = $metarow['meta_value']; |
||
1159 | $quiz_id = $metarow['post_id']; |
||
1160 | $lesson_quiz_ids[ $lesson_id ] = $quiz_id; |
||
1161 | } |
||
1162 | } |
||
1163 | |||
1164 | // ...check all Quiz IDs for questions |
||
1165 | $id_list = join( ',', array_values($lesson_quiz_ids) ); |
||
1166 | $meta_list = $wpdb->get_results( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = '_quiz_id' AND meta_value IN ($id_list)", ARRAY_A ); |
||
1167 | $lesson_quiz_ids_with_questions = array(); |
||
1168 | if ( !empty($meta_list) ) { |
||
1169 | foreach ( $meta_list as $metarow ) { |
||
1170 | $quiz_id = $metarow['meta_value']; |
||
1171 | $lesson_quiz_ids_with_questions[] = $quiz_id; |
||
1172 | } |
||
1173 | } |
||
1174 | |||
1175 | // For each quiz check there are questions, if not remove the corresponding meta keys from Quizzes and Lessons |
||
1176 | // if there are questions on the quiz add the corresponding meta keys to Quizzes and Lessons |
||
1177 | $d_count = $a_count =0; |
||
1178 | foreach ( $lesson_quiz_ids AS $lesson_id => $quiz_id ) { |
||
1179 | if ( !in_array( $quiz_id, $lesson_quiz_ids_with_questions ) ) { |
||
1180 | |||
1181 | // Quiz has no questions, drop the corresponding data |
||
1182 | delete_post_meta( $quiz_id, '_pass_required' ); |
||
1183 | delete_post_meta( $quiz_id, '_quiz_passmark' ); |
||
1184 | delete_post_meta( $lesson_id, '_quiz_has_questions' ); |
||
1185 | $d_count++; |
||
1186 | } |
||
1187 | else if ( in_array( $quiz_id, $lesson_quiz_ids_with_questions ) ) { |
||
1188 | |||
1189 | // Quiz has no questions, drop the corresponding data |
||
1190 | update_post_meta( $lesson_id, '_quiz_has_questions', true ); |
||
1191 | $a_count++; |
||
1192 | } |
||
1193 | } |
||
1194 | |||
1195 | if ( $current_page == $total_pages ) { |
||
1196 | return true; |
||
1197 | } else { |
||
1198 | return false; |
||
1199 | } |
||
1200 | } |
||
1201 | |||
1202 | function status_changes_convert_lessons( $n = 50, $offset = 0 ) { |
||
1399 | |||
1400 | function status_changes_convert_courses( $n = 50, $offset = 0 ) { |
||
1401 | global $wpdb; |
||
1402 | |||
1403 | wp_defer_comment_counting( true ); |
||
1404 | |||
1405 | $user_count_result = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->users " ); |
||
1406 | |||
1407 | if ( 0 == $user_count_result ) { |
||
1408 | return true; |
||
1409 | } |
||
1410 | |||
1411 | if ( 0 == $offset ) { |
||
1412 | $current_page = 1; |
||
1413 | } else { |
||
1414 | $current_page = intval( $offset / $n ); |
||
1415 | } |
||
1416 | |||
1417 | $total_pages = ceil( $user_count_result / $n ); |
||
1418 | |||
1419 | // Get all Lesson => Course relationships |
||
1420 | $meta_list = $wpdb->get_results( "SELECT $wpdb->postmeta.post_id, $wpdb->postmeta.meta_value FROM $wpdb->postmeta INNER JOIN $wpdb->posts ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE $wpdb->posts.post_type = 'lesson' AND $wpdb->postmeta.meta_key = '_lesson_course'", ARRAY_A ); |
||
1421 | $course_lesson_ids = array(); |
||
1422 | View Code Duplication | if ( !empty($meta_list) ) { |
|
1423 | foreach ( $meta_list as $metarow ) { |
||
1424 | $lesson_id = $metarow['post_id']; |
||
1538 | |||
1539 | /** |
||
1540 | * Force the re-calculation of all Course statuses working from all Lesson statuses |
||
1541 | * |
||
1542 | * @global type $woothemes_sensei |
||
1543 | * @global type $wpdb |
||
1544 | * @param type $n |
||
1545 | * @param type $offset |
||
1546 | * @return boolean |
||
1547 | */ |
||
1548 | function status_changes_repair_course_statuses( $n = 50, $offset = 0 ) { |
||
1659 | |||
1660 | function status_changes_convert_questions( $n = 50, $offset = 0 ) { |
||
1766 | |||
1767 | /** |
||
1768 | * Updates all pre-existing Sensei activity types with a new status value |
||
1769 | * |
||
1770 | * @global type $wpdb |
||
1771 | * @return boolean |
||
1772 | */ |
||
1773 | public function update_legacy_sensei_comments_status() { |
||
1784 | |||
1785 | /** |
||
1786 | * Update the comment counts for all Courses and Lessons now that sensei comments will no longer be counted. |
||
1787 | * |
||
1788 | * @global type $wpdb |
||
1789 | * @param type $n |
||
1790 | * @param type $offset |
||
1791 | * @return boolean |
||
1792 | */ |
||
1793 | public function update_comment_course_lesson_comment_counts( $n = 50, $offset = 0 ) { |
||
1827 | |||
1828 | public function remove_legacy_comments () { |
||
1835 | |||
1836 | public function index_comment_status_field () { |
||
1846 | |||
1847 | /** |
||
1848 | * WooThemes_Sensei_Updates::enhance_teacher_role |
||
1849 | * |
||
1850 | * This runs the update to create the teacher role |
||
1851 | * @access public |
||
1852 | * @since 1.8.0 |
||
1853 | * @return bool; |
||
1854 | */ |
||
1855 | public function enhance_teacher_role ( ) { |
||
1863 | |||
1864 | } // End Class |
||
1865 | |||
1872 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.