PluginProbe
WPComplete / 1.0
WPComplete v1.0
2.9.5.7 2.9.5.6 trunk 1.0 1.1 1.2 1.4 1.4.6 2.3 2.9.1 2.9.2 2.9.5 2.9.5.1 2.9.5.3 2.9.5.4 2.9.5.5
wpcomplete / admin / class-wpcomplete-admin.php

class-wpcomplete-admin.php in WPComplete 1.0, at admin/class-wpcomplete-admin.php

726 lines 20.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The admin-specific functionality of the plugin.
5 *
6 * @link https://wpcomplete.co
7 * @since 1.0.0
8 *
9 * @package WPComplete
10 * @subpackage wpcomplete/admin
11 */
12
13 /**
14 * The admin-specific functionality of the plugin.
15 *
16 * Defines the plugin name, version, and two examples hooks for how to
17 * enqueue the admin-specific stylesheet and JavaScript.
18 *
19 * @package WPComplete
20 * @subpackage wpcomplete/admin
21 * @author Zack Gilbert <zack@zackgilbert.com>
22 */
23 class WPComplete_Admin {
24
25 /**
26 * The ID of this plugin.
27 *
28 * @since 1.0.0
29 * @access private
30 * @var string $plugin_name The ID of this plugin.
31 */
32 private $plugin_name;
33
34 /**
35 * The version of this plugin.
36 *
37 * @since 1.0.0
38 * @access private
39 * @var string $version The current version of this plugin.
40 */
41 private $version;
42
43 /**
44 * Initialize the class and set its properties.
45 *
46 * @since 1.0.0
47 * @param string $plugin_name The name of this plugin.
48 * @param string $version The version of this plugin.
49 */
50 public function __construct( $plugin_name, $version ) {
51
52 $this->plugin_name = $plugin_name;
53 $this->version = $version;
54
55 }
56
57 /**
58 * Register the stylesheets for the admin area.
59 *
60 * @since 1.0.0
61 */
62 public function enqueue_styles() {
63
64 /**
65 * This function is provided for demonstration purposes only.
66 *
67 * An instance of this class should be passed to the run() function
68 * defined in Plugin_Name_Loader as all of the hooks are defined
69 * in that particular class.
70 *
71 * The WPComplete_Loader will then create the relationship
72 * between the defined hooks and the functions defined in this
73 * class.
74 */
75
76 wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/wpcomplete-admin.css', array('wp-color-picker'), $this->version, 'all' );
77
78 }
79
80 /**
81 * Register the JavaScript for the admin area.
82 *
83 * @since 1.0.0
84 */
85 public function enqueue_scripts() {
86
87 /**
88 * This function is provided for demonstration purposes only.
89 *
90 * An instance of this class should be passed to the run() function
91 * defined in Plugin_Name_Loader as all of the hooks are defined
92 * in that particular class.
93 *
94 * The WPComplete_Loader will then create the relationship
95 * between the defined hooks and the functions defined in this
96 * class.
97 */
98 wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/wpcomplete-admin.js', array( 'jquery', 'wp-color-picker', 'inline-edit-post' ), $this->version, true );
99
100 wp_localize_script( $this->plugin_name, 'WPComplete', array( 'url' => admin_url( 'admin-ajax.php' ) ) );
101 }
102
103 /**
104 * Add options to the bulk menu for posts and pages.
105 *
106 * @since 1.0.0
107 */
108 public function add_bulk_actions() {
109 global $post_type;
110
111 if ( $post_type == 'post' || $post_type == 'page' ) {
112 ?>
113 <script type="text/javascript">
114 jQuery(document).ready(function() {
115 jQuery('<option>').val('completable').text("<?php _e('Can Complete', $this->plugin_name)?>").appendTo("select[name='action'],select[name='action2']");
116 });
117 </script>
118 <?php
119 }
120 }
121
122 /**
123 * Add WPComplete specific page under the Settings submenu.
124 *
125 * @since 1.0.0
126 */
127 public function add_options_page() {
128
129 $this->plugin_screen_hook_suffix = add_options_page(
130 __( 'WPComplete Settings', $this->plugin_name ),
131 __( 'WPComplete', $this->plugin_name ),
132 'manage_options',
133 $this->plugin_name,
134 array( $this, 'display_settings_page' )
135 );
136
137 }
138
139 /**
140 * Render the WPComplete specific settings page for plugin.
141 *
142 * @since 1.0.0
143 */
144 public function display_settings_page() {
145 include_once 'partials/wpcomplete-admin-display.php';
146 }
147
148 /**
149 * Build all the settings for plugin on the WPComplete settings page.
150 *
151 * @since 1.0.0
152 */
153 public function register_settings() {
154 // Section related to students:
155 add_settings_section(
156 $this->plugin_name . '_students',
157 __( 'Student Settings', $this->plugin_name ),
158 array( $this, 'settings_section_cb' ),
159 $this->plugin_name
160 );
161
162 add_settings_field(
163 $this->plugin_name . '_role',
164 __( 'Role Type', $this->plugin_name ),
165 array( $this, 'settings_role_cb' ),
166 $this->plugin_name,
167 $this->plugin_name . '_students',
168 array( 'label_for' => $this->plugin_name . '_role' )
169 );
170
171 // Section related to the Mark as Complete button:
172 add_settings_section(
173 $this->plugin_name . '_incomplete_button',
174 __( 'Mark Complete Button', $this->plugin_name ),
175 array( $this, 'settings_section_cb' ),
176 $this->plugin_name
177 );
178
179 add_settings_field(
180 $this->plugin_name . '_incomplete_text',
181 __( 'Button Text', $this->plugin_name ),
182 array( $this, 'settings_incomplete_text_cb' ),
183 $this->plugin_name,
184 $this->plugin_name . '_incomplete_button',
185 array( 'label_for' => $this->plugin_name . '_incomplete_text' )
186 );
187 register_setting( $this->plugin_name, $this->plugin_name . '_incomplete_text', 'sanitize_text_field' );
188
189 add_settings_field(
190 $this->plugin_name . '_incomplete_background',
191 __( 'Button Color', $this->plugin_name ),
192 array( $this, 'settings_incomplete_background_cb' ),
193 $this->plugin_name,
194 $this->plugin_name . '_incomplete_button',
195 array( 'label_for' => $this->plugin_name . '_incomplete_background' )
196 );
197
198 add_settings_field(
199 $this->plugin_name . '_incomplete_color',
200 __( 'Button Text Color', $this->plugin_name ),
201 array( $this, 'settings_incomplete_color_cb' ),
202 $this->plugin_name,
203 $this->plugin_name . '_incomplete_button',
204 array( 'label_for' => $this->plugin_name . '_incomplete_color' )
205 );
206
207 // Section related to the Completed! button:
208 add_settings_section(
209 $this->plugin_name . '_completed_button',
210 __( 'Completed Button', $this->plugin_name ),
211 array( $this, 'settings_section_cb' ),
212 $this->plugin_name
213 );
214
215 add_settings_field(
216 $this->plugin_name . '_completed_text',
217 __( 'Button Text', $this->plugin_name ),
218 array( $this, 'settings_completed_text_cb' ),
219 $this->plugin_name,
220 $this->plugin_name . '_completed_button',
221 array( 'label_for' => $this->plugin_name . '_completed_text' )
222 );
223 register_setting( $this->plugin_name, $this->plugin_name . '_completed_text', 'sanitize_text_field' );
224
225 add_settings_field(
226 $this->plugin_name . '_completed_background',
227 __( 'Button Color', $this->plugin_name ),
228 array( $this, 'settings_completed_background_cb' ),
229 $this->plugin_name,
230 $this->plugin_name . '_completed_button',
231 array( 'label_for' => $this->plugin_name . '_completed_background' )
232 );
233
234 add_settings_field(
235 $this->plugin_name . '_completed_color',
236 __( 'Button Text Color', $this->plugin_name ),
237 array( $this, 'settings_completed_color_cb' ),
238 $this->plugin_name,
239 $this->plugin_name . '_completed_button',
240 array( 'label_for' => $this->plugin_name . '_completed_color' )
241 );
242
243 // PREMIUM: Section related to the graphs:
244 add_settings_section(
245 $this->plugin_name . '_graphs',
246 __( 'Graph Settings', $this->plugin_name ),
247 array( $this, 'settings_section_cb' ),
248 $this->plugin_name
249 );
250
251 add_settings_field(
252 $this->plugin_name . '_graph_primary',
253 __( 'Primary Color', $this->plugin_name ),
254 array( $this, 'settings_graph_primary_cb' ),
255 $this->plugin_name,
256 $this->plugin_name . '_graphs',
257 array( 'label_for' => $this->plugin_name . '_graph_primary' )
258 );
259
260 add_settings_field(
261 $this->plugin_name . '_graph_secondary',
262 __( 'Secondary Color', $this->plugin_name ),
263 array( $this, 'settings_graph_secondary_cb' ),
264 $this->plugin_name,
265 $this->plugin_name . '_graphs',
266 array( 'label_for' => $this->plugin_name . '_graph_secondary' )
267 );
268
269 }
270
271 /**
272 * Render extra text for sections.
273 *
274 * @since 1.0.0
275 */
276 public function settings_section_cb() {
277 }
278
279 /**
280 * Render text field for assigning license key for plugin.
281 *
282 * @since 1.0.0
283 */
284 public function settings_license_key_cb() {
285 $name = $this->plugin_name . '_license_key';
286 $text = get_option( $name );
287 $class = '';
288 $disabled = false;
289
290 include 'partials/wpcomplete-admin-settings-input.php';
291 }
292
293 /**
294 * Sanitation helper for license field.
295 *
296 * @since 1.0.0
297 */
298 public function sanitize_license( $new ) {
299 $old = get_option( $this->plugin_name . '_license_key' );
300 if ( $old && $old != $new ) {
301 delete_option( $this->plugin_name . '_license_status' ); // new license has been entered, so must reactivate
302 wp_cache_delete( $this->plugin_name . '_license_status' );
303 }
304 return $new;
305 }
306
307 /**
308 * Render license key status for plugin.
309 *
310 * @since 1.0.0
311 */
312 public function settings_license_status_cb() {
313 $status = get_option( $this->plugin_name . '_license_status' );
314 $name = $this->plugin_name . '_license_activate';
315
316 include 'partials/wpcomplete-admin-settings-license-status.php';
317 }
318
319 /**
320 * Render select menu for assigning which type of user roles should be tracked as students.
321 *
322 * @since 1.0.0
323 */
324 public function settings_role_cb() {
325 $selected_role = get_option( $this->plugin_name . '_role', 'subscriber' );
326 $disabled = true;
327
328 include 'partials/wpcomplete-admin-settings-role.php';
329 }
330
331 /**
332 * Render the Mark as Complete button text setting field.
333 *
334 * @since 1.0.0
335 */
336 public function settings_incomplete_text_cb() {
337 $name = $this->plugin_name . '_incomplete_text';
338 $text = get_option( $name, 'Mark as complete' );
339 $class = '';
340 $disabled = false;
341
342 include 'partials/wpcomplete-admin-settings-input.php';
343 }
344
345 /**
346 * Render the Mark as Complete button background color setting field.
347 *
348 * @since 1.0.0
349 */
350 public function settings_incomplete_background_cb() {
351 $name = $this->plugin_name . '_incomplete_background';
352 $text = get_option( $name, '#ff0000' );
353 $class = 'color-picker';
354 $disabled = true;
355
356 include 'partials/wpcomplete-admin-settings-input.php';
357 }
358
359 /**
360 * Render the Mark as Complete button text color setting field.
361 *
362 * @since 1.0.0
363 */
364 public function settings_incomplete_color_cb() {
365 $name = $this->plugin_name . '_incomplete_color';
366 $text = get_option( $name, '#ffffff' );
367 $class = 'color-picker';
368 $disabled = true;
369
370 include 'partials/wpcomplete-admin-settings-input.php';
371 }
372
373 /**
374 * Render the Completed! button text setting field.
375 *
376 * @since 1.0.0
377 */
378 public function settings_completed_text_cb() {
379 $name = $this->plugin_name . '_completed_text';
380 $text = get_option( $name, 'COMPLETED!' );
381 $class = '';
382 $disabled = false;
383
384 include 'partials/wpcomplete-admin-settings-input.php';
385 }
386
387 /**
388 * Render the Completed! button background color setting field.
389 *
390 * @since 1.0.0
391 */
392 public function settings_completed_background_cb() {
393 $name = $this->plugin_name . '_completed_background';
394 $text = get_option( $name, '#666666' );
395 $class = 'color-picker';
396 $disabled = true;
397
398 include 'partials/wpcomplete-admin-settings-input.php';
399 }
400
401 /**
402 * Render the Completed! button text color setting field.
403 *
404 * @since 1.0.0
405 */
406 public function settings_completed_color_cb() {
407 $name = $this->plugin_name . '_completed_color';
408 $text = get_option( $name, '#ffffff' );
409 $class = 'color-picker';
410 $disabled = true;
411
412 include 'partials/wpcomplete-admin-settings-input.php';
413 }
414
415 /**
416 * PREMIUM:
417 * Render graph primary color setting field.
418 *
419 * @since 1.0.0
420 */
421 public function settings_graph_primary_cb() {
422 $name = $this->plugin_name . '_graph_primary';
423 $text = get_option( $name, '#97a71d' );
424 $class = 'color-picker';
425 $disabled = true;
426
427 include 'partials/wpcomplete-admin-settings-input.php';
428 }
429
430 /**
431 * PREMIUM:
432 * Render graph secondary color setting field.
433 *
434 * @since 1.0.0
435 */
436 public function settings_graph_secondary_cb() {
437 $name = $this->plugin_name . '_graph_secondary';
438 $text = get_option( $name, '#ebebeb' );
439 $class = 'color-picker';
440 $disabled = true;
441
442 include 'partials/wpcomplete-admin-settings-input.php';
443 }
444
445 /* END SETTINGS PAGE HELPERS */
446
447 /**
448 * Render the meta box for this plugin enabling completion functionality
449 *
450 * @since 1.0.0
451 */
452 public function add_completable_metabox() {
453 $screens = array( 'post', 'page' );
454 foreach ( $screens as $screen ) {
455 add_meta_box(
456 'completable', // Unique ID
457 __( 'WPComplete', $this->plugin_name ), // Box title
458 array( $this, 'add_completable_metabox_cb' ), // Content callback
459 $screen // post type
460 );
461 }
462 }
463
464 /**
465 * Callback which renders the actual html for completable metabox. Includes enabling completability and redirect url.
466 *
467 * @since 1.0.0
468 */
469 public function add_completable_metabox_cb( $post ) {
470 // get the variables we need to build the form:
471 $completable = get_post_meta( $post->ID, 'completable', true );
472 $redirect_json = get_post_meta( $post->ID, 'completion-redirect', true );
473 $redirect = ($redirect_json && !empty($redirect_json)) ? (array) json_decode($redirect_json) : array('title' => '', 'url' => '');
474 // include a nonce to ensure we can save:
475 wp_nonce_field( $this->plugin_name, 'completable_nonce' );
476
477 include 'partials/wpcomplete-admin-metabox.php';
478 }
479
480 /**
481 * Save script for saving an individual post/page, enabling it as completable.
482 *
483 * @since 1.0.0
484 */
485 public function save_completable( $post_id ) {
486 if ( isset( $_POST['completable_nonce'] ) && isset( $_POST['completable'] ) && isset( $_POST['post_type'] ) ) {
487 // Don't save if the user hasn't submitted the changes
488 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
489 //echo '<!-- Autosave -->';
490 return;
491 } // end if
492
493 // Verify that the input is coming from the proper form
494 if ( ! wp_verify_nonce( $_POST['completable_nonce'], $this->plugin_name ) ) {
495 //echo '<!-- NONCE FAILED -->';
496 return;
497 } // end if
498
499 // Make sure the user has permissions to posts and pages
500 if ( $_POST['post_type'] == 'post' ) {
501 if ( ! current_user_can( 'edit_post', $post_id ) ) {
502 //echo '<!-- User cant edit posts -->';
503 return;
504 } // end if
505 } else if ( $_POST['post_type'] == 'page') {
506 if ( ! current_user_can( 'edit_page', $post_id ) ) {
507 //echo '<!-- User cant edit pages -->';
508 return;
509 } // end if
510 } else {
511 return;
512 } // end if/else
513
514 $is_completable = $_POST['completable'];
515
516 if ($is_completable == 'true') {
517
518 // Update it for this post.
519 update_post_meta( $post_id, 'completable', $is_completable );
520
521 } else {
522
523 // If the value exists, delete it.
524 delete_post_meta( $post_id, 'completable' );
525
526 }
527
528 }
529 }
530
531 /**
532 * Save script for the bulk action that marks multiple pages/posts as completable.
533 *
534 * @since 1.0.0
535 */
536 public function save_bulk_completable() {
537 global $typenow;
538 $post_type = $typenow;
539
540 if ( ($post_type == 'post' || $post_type == 'page') && isset($_REQUEST['post']) && (($_REQUEST['action'] == 'completable') || ($_REQUEST['action2'] == 'completable')) ) {
541 // security check
542 check_admin_referer( 'bulk-posts' );
543
544 $action = ($_REQUEST['action'] == '-1') ? $_REQUEST['action2'] : $_REQUEST['action'];
545
546 // make sure ids are submitted. depending on the resource type, this may be 'media' or 'ids'
547 if ( isset($_REQUEST['post'] ) ) {
548 $post_ids = array_map( 'intval', $_REQUEST['post'] );
549 }
550
551 if ( empty( $post_ids ) ) return;
552
553 // this is based on wp-admin/edit.php
554 $sendback = remove_query_arg( array('exported', 'untrashed', 'deleted', 'ids'), wp_get_referer() );
555 if ( ! $sendback )
556 $sendback = admin_url( "edit.php?post_type=$post_type" );
557
558 // do the marking as complete!
559 $marked = 0;
560 foreach ( $post_ids as $post_id ) {
561 // Update it for this post.
562 update_post_meta( $post_id, 'completable', 'true' );
563 $marked++;
564 }
565
566 $sendback = add_query_arg( array('completable' => $marked, 'ids' => join(',', $post_ids) ), $sendback );
567 $sendback = remove_query_arg( array('action', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view'), $sendback );
568
569 wp_redirect( $sendback );
570 exit();
571 }
572 }
573
574 /**
575 * Add a notice message for completed bulk actions.
576 *
577 * @since 1.0.0
578 */
579 public function show_bulk_action_notice() {
580 global $post_type, $pagenow;
581
582 if ( $pagenow == 'edit.php' && $post_type == 'post' && isset($_REQUEST['completable']) && (int) $_REQUEST['completable']) {
583 $message = sprintf( _n( 'Post marked completable by students.', '%s posts marked as completable by students.', $_REQUEST['completable'] ), number_format_i18n( $_REQUEST['completable'] ) );
584 echo "<div class=\"updated\"><p>{$message}</p></div>";
585 }
586 }
587
588 /**
589 * Add the new custom column header, "User Completion" to pages and posts edit.php page.
590 *
591 * @since 1.0.0
592 */
593 public function add_custom_column_header( $columns ) {
594 return array_merge( $columns, array( 'completable' => __( 'User Completion', $this->plugin_name) ));
595 }
596
597 /**
598 * Add the values for each post/page of the new custom "Completion %" column.
599 * If post/page isn't enabled to be completed, it shows — in column.
600 * If wordpress install doesn't have any subscribers (students), it shows "0 Students".
601 * Otherwise, it'll show the ratio and percentage of how many students have completed it.
602 *
603 * @since 1.0.0
604 */
605 public function add_custom_column_value( $column_name, $post_id ) {
606 if ( $column_name == 'completable' ) {
607 $completable = ((get_post_meta( $post_id, 'completable', true )) ? 'true' : 'false');
608
609 if ($completable == 'true') {
610 // - Get total student count
611 $users_of_blog = count_users();
612 //var_dump($users_of_blog['avail_roles']);
613 //var_dump(get_users(array('role' => 'administrator')));
614 $selected_role = get_option( $this->plugin_name . '_role', 'subscriber' );
615
616 if ($selected_role == 'all') {
617 $avail_users = $users_of_blog['total_users'];
618 } else {
619 $avail_users = (isset($users_of_blog['avail_roles'][$selected_role])) ? $users_of_blog['avail_roles'][$selected_role] : 0;
620 }
621
622 if ($avail_users > 0) {
623 $completion = '';
624 $args = array('fields' => 'id');
625
626 if ($selected_role != 'all') $args['role'] = $selected_role;
627 $args['meta_query'] = array(
628 array(
629 'key' => 'wp_completed',
630 'value' => "\"$post_id\"",
631 'compare' => 'LIKE'
632 )
633 );
634
635 $users = get_users($args);
636
637 $completed_users = count($users);
638
639 $completion = ("$completed_users/$avail_users");
640 // - Display percentage
641 $completion .= (' (' . round(100 * ($completed_users / $avail_users), 1) . '%)');
642 } else {
643 $completion = "0 Students";
644 }
645 } else {
646 $completion = '';
647 }
648
649 echo '<div id="completable-' . $post_id . '">' . $completion . '</div>';
650 }
651 }
652
653 /**
654 * Add custom field for quick edit of posts and pages.
655 *
656 * @since 1.0.0
657 */
658 public function add_custom_quick_edit( $column_name, $post_type ) {
659 include 'partials/wpcomplete-admin-quickedit.php';
660 }
661
662 /**
663 * Helper method to query for all pages and posts that are completable.
664 *
665 * @since 1.0.0
666 */
667 public function get_meta_posts( $key = '', $status = 'publish' ) {
668 global $wpdb;
669
670 if( empty( $key ) )
671 return;
672
673 $r = $wpdb->get_col( $wpdb->prepare( "
674 SELECT pm.post_id FROM {$wpdb->postmeta} pm
675 LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
676 WHERE pm.meta_key = '%s'
677 AND p.post_status = '%s'
678 AND (p.post_type = 'post' OR p.post_type = 'page')
679 ", $key, $status) );
680
681 return $r;
682 }
683
684 /**
685 * Add the new custom column header, "Lesson Completion" to users page.
686 *
687 * @since 1.0.0
688 */
689 public function add_user_column_header( $columns ) {
690 if ( count($this->get_meta_posts('completable')) > 0 ) {
691 return array_merge( $columns, array( 'completable' => __( 'Lesson Completion', $this->plugin_name) ));
692 } else {
693 return $columns;
694 }
695 }
696
697 /**
698 * Add the values for each user of the new custom "Completion" column.
699 * If user is not in a student role, it shows — in column.
700 * Otherwise, it'll show the ratio and percentage of student's completion.
701 *
702 * @since 1.0.0
703 */
704 public function add_user_column_value( $value, $column_name, $user_id ) {
705 if ( $column_name == 'completable' ) {
706 $selected_role = get_option( $this->plugin_name . '_role', 'subscriber' );
707 $user = get_userdata( $user_id );
708
709 if (($selected_role == 'all') || in_array($selected_role, $user->roles)) {
710 $total_posts = count($this->get_meta_posts('completable'));
711
712 $user_completed_json = get_user_meta( $user_id, 'wp_completed', true );
713 $user_completed = ( $user_completed_json ) ? json_decode( $user_completed_json ) : array();
714
715 $completed_posts = count($user_completed);
716
717 return '<div id="completable-' . $user_id . '">' . $completed_posts . '/' . $total_posts . ' (' . round(100 * ($completed_posts / $total_posts), 1) . '%)</div>';
718 } else {
719 return '<div id="completable-' . $user_id . '">—</div>';
720 }
721
722 }
723 }
724
725 }
726