PluginProbe
UpStream: a Project Management Plugin for WordPress / 2.1.0
UpStream: a Project Management Plugin for WordPress v2.1.0
trunk 1.39.0 1.39.1 1.39.2 1.39.3 2.0.7 2.1.0
upstream / includes / admin / class-upstream-admin.php

class-upstream-admin.php in UpStream: a Project Management Plugin for WordPress 2.1.0, at includes/admin/class-upstream-admin.php

915 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * UpStream Admin
4 *
5 * @class UpStream_Admin
6 * @author UpStream
7 * @category Admin
8 * @package UpStream/Admin
9 * @version 1.0.0
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * UpStream_Admin class.
19 */
20 class UpStream_Admin {
21
22 /**
23 * Framework
24 *
25 * @var \Allex\Core
26 */
27 protected $framework;
28
29 /**
30 * Constructor.
31 */
32 public function __construct() {
33 add_action( 'init', array( $this, 'includes' ) );
34 add_action( 'init', array( $this, 'init' ), 13 );
35 add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
36 add_filter( 'ajax_query_attachments_args', array( $this, 'filter_user_attachments' ), 10, 1 );
37 add_action( 'admin_menu', array( $this, 'limit_up_stream_user_access' ) );
38
39 add_action( 'show_user_profile', array( $this, 'render_additional_user_fields' ), 10, 1 );
40 add_action( 'edit_user_profile', array( $this, 'render_additional_user_fields' ), 10, 1 );
41 add_action( 'personal_options_update', array( $this, 'save_additional_user_fields' ), 10, 1 );
42 add_action( 'edit_user_profile_update', array( $this, 'save_additional_user_fields' ), 10, 1 );
43
44 global $pagenow;
45 if ( 'edit-comments.php' === $pagenow ) {
46 add_filter( 'comment_status_links', array( $this, 'comment_status_links' ), 10, 1 );
47 add_action( 'pre_get_comments', array( $this, 'pre_get_comments' ), 10, 1 );
48 }
49
50 add_action(
51 'wp_ajax_upstream:project.get_all_items_comments',
52 array( 'UpStream_Metaboxes_Projects', 'fetch_all_items_comments' )
53 );
54
55 add_action( 'cmb2_render_up_timestamp', array( $this, 'render_cmb2_timestamp_field' ), 10, 5 );
56 add_action( 'cmb2_sanitize_up_timestamp', array( $this, 'sanitize_cmb2_timestamp_field' ), 10, 5 );
57
58 add_action( 'cmb2_render_up_button', array( $this, 'render_cmb2_button_field' ), 10, 5 );
59 add_action( 'cmb2_sanitize_up_button', array( $this, 'sanitize_cmb2_button_field' ), 10, 5 );
60
61 add_action( 'cmb2_render_up_buttonsgroup', array( $this, 'render_cmb2_buttons_group_field' ), 10, 5 );
62 add_action( 'cmb2_sanitize_up_buttonsgroup', array( $this, 'sanitize_cmb2_buttons_group_field' ), 10, 5 );
63
64 add_filter(
65 'cmb2_override_option_get_upstream_general',
66 array( $this, 'filter_override_option_get_upstream_general' ),
67 10,
68 3
69 );
70
71 $this->framework = UpStream::instance()->get_container()['framework'];
72
73 add_action( 'wp_ajax_upstream.milestone-edit.editmenuorder', array( $this, 'edit_menu_order' ) );
74 add_action( 'wp_ajax_upstream.task-edit.gettaskpercent', array( $this, 'get_task_percent' ) );
75 add_action( 'wp_ajax_upstream.task-edit.gettaskstatus', array( $this, 'get_task_status' ) );
76 }
77
78 /**
79 * Edit Menu Order
80 *
81 * @since 1.24.5
82 * @static
83 */
84 public function edit_menu_order() {
85 $request_data = isset( $_REQUEST ) ? wp_unslash( $_REQUEST ) : array();
86 $cur_post = array(
87 'ID' => intval( $request_data['post_id'] ),
88 'menu_order' => intval( $request_data['item_val'] ),
89 );
90 wp_update_post( $cur_post );
91
92 return 'success';
93 }
94
95 /**
96 * Get Task Percent
97 *
98 * @since 1.24.5
99 * @static
100 */
101 public function get_task_percent() {
102 $request_data = isset( $_REQUEST ) ? wp_unslash( $_REQUEST ) : array();
103 $task_id = sanitize_text_field( $request_data['task_id'] );
104 $cur_per = intval( $request_data['cur_per'] );
105 $option = get_option( 'upstream_tasks' );
106 $statuses = isset( $option['statuses'] ) ? $option['statuses'] : '';
107
108 if ( $statuses ) {
109 foreach ( $statuses as $status ) {
110 if ( $status['id'] == $task_id ) {
111 if ( ! empty( $status['percent'] ) && (int) $status['percent'] > $cur_per ) {
112 echo (int) $status['percent'];
113 exit;
114 } else {
115 echo (int) $cur_per;
116 exit;
117 }
118 }
119 }
120 }
121 return 0;
122 }
123
124 /**
125 * Get Task Status
126 *
127 * @since 1.24.5
128 * @static
129 */
130 public function get_task_status() {
131 $request_data = isset( $_REQUEST ) ? wp_unslash( $_REQUEST ) : array();
132 $task_percent = (int) sanitize_text_field( $request_data['task_percent'] );
133
134 $option = get_option( 'upstream_tasks' );
135 $statuses = isset( $option['statuses'] ) ? $option['statuses'] : '';
136 $sort_arr = array();
137 $sel_status = '';
138
139 if ( $statuses ) {
140 foreach ( $statuses as $status ) {
141 $sort_arr[ $status['id'] ] = $status['percent'];
142 if ( '100' == $task_percent && '100' === $status['percent'] ) {
143 echo esc_attr( $status['id'] );
144 exit;
145 }
146 }
147 }
148 asort( $sort_arr );
149 if ( $sort_arr ) {
150 foreach ( $sort_arr as $id => $percent ) {
151 if ( $percent > $task_percent ) {
152 echo esc_attr( $sel_status );
153 exit;
154 }
155 $sel_status = $id;
156 }
157 }
158 return 0;
159 }
160
161 /**
162 * Filter comments for Comments.php page.
163 *
164 * @param array $query Query args array.
165 *
166 * @since 1.13.0
167 * @static
168 */
169 public static function pre_get_comments( $query ) {
170 if ( ! upstream_is_user_either_manager_or_admin() ) {
171 $user = wp_get_current_user();
172
173 if ( in_array( 'upstream_user', $user->roles ) || in_array( 'upstream_client_user', $user->roles ) ) {
174 // Limit comments visibility to projects user is participating in.
175 $allowed_projects = upstream_get_users_projects( $user );
176 $query->query_vars['post__in'] = array_keys( $allowed_projects );
177
178 $user_can_moderate_comments = user_can( $user, 'moderate_comments' );
179 $user_can_delete_comments = user_can( $user, 'delete_project_discussion' );
180
181 $query->query_vars['status'] = array( 'approve' );
182
183 if ( $user_can_moderate_comments ) {
184 $query->query_vars['status'][] = 'hold';
185 } elseif ( empty( $allowed_projects ) ) {
186 $query->query_vars['post__in'] = -1;
187 }
188 } else {
189 // Hide Projects comments from other user types.
190 $projects = get_posts(
191 array(
192 'post_type' => 'project',
193 'post_status' => 'any',
194 'posts_per_page' => -1,
195 )
196 );
197
198 $ids = array();
199 foreach ( $projects as $project ) {
200 $ids[] = $project->ID;
201 }
202
203 $query->query_vars['post__not_in'] = $ids;
204 }
205 }
206 }
207
208 /**
209 * Set up WP-Table filters links.
210 *
211 * @param array $links Associative array of table filters.
212 *
213 * @return array $links
214 * @since 1.13.0
215 * @static
216 */
217 public static function comment_status_links( $links ) {
218 if ( ! upstream_is_user_either_manager_or_admin() ) {
219 $user = wp_get_current_user();
220
221 if ( in_array( 'upstream_user', $user->roles ) || in_array( 'upstream_client_user', $user->roles ) ) {
222 $user_can_moderate_comments = user_can( $user, 'moderate_comments' );
223 $user_can_delete_comments = user_can( $user, 'delete_project_discussion' );
224
225 if ( ! $user_can_moderate_comments ) {
226 unset( $links['moderated'], $links['approved'], $links['spam'] );
227
228 if ( ! $user_can_delete_comments ) {
229 unset( $links['trash'] );
230 }
231 }
232
233 $projects = upstream_get_users_projects( $user );
234
235 $comments_query_args = array(
236 'post_type' => 'project',
237 'post__in' => array_keys( $projects ),
238 'count' => true,
239 );
240
241 $comments_count = new stdClass();
242 $comments_count->all = get_comments( $comments_query_args );
243
244 $links['all'] = preg_replace(
245 '/<span class="all-count">\d+<\/span>/',
246 '<span class="all-count">' . $comments_count->all . '</span>',
247 $links['all']
248 );
249
250 if ( isset( $links['moderated'] ) ) {
251 $comments_count->approved = get_comments(
252 array_merge(
253 $comments_query_args,
254 array( 'status' => 'approve' )
255 )
256 );
257
258 $links['approved'] = preg_replace(
259 '/<span class="approved-count">\d+<\/span>/',
260 '<span class="approved-count">' . $comments_count->approved . '</span>',
261 $links['approved']
262 );
263
264 $comments_count->pending = get_comments( array_merge( $comments_query_args, array( 'status' => 'hold' ) ) );
265
266 $links['moderated'] = preg_replace(
267 '/<span class="pending-count">\d+<\/span>/',
268 '<span class="pending-count">' . $comments_count->pending . '</span>',
269 $links['moderated']
270 );
271 }
272
273 if ( isset( $links['trash'] ) ) {
274 $comments_count->trash = get_comments( array_merge( $comments_query_args, array( 'status' => 'trash' ) ) );
275
276 $links['trash'] = preg_replace(
277 '/<span class="trash-count">\d+<\/span>/',
278 '<span class="trash-count">' . $comments_count->trash . '</span>',
279 $links['trash']
280 );
281 }
282 } else {
283 $projects = get_posts(
284 array(
285 'post_type' => 'project',
286 'posts_per_page' => -1,
287 )
288 );
289
290 $projects_ids = array();
291 foreach ( $projects as $project ) {
292 $projects_ids[] = $project->ID;
293 }
294
295 $comments_query_args = array(
296 'post__not_in' => $projects_ids,
297 'count' => true,
298 );
299
300 if ( isset( $links['all'] ) ) {
301 $count = get_comments( $comments_query_args );
302 $links['all'] = preg_replace(
303 '/<span class="all-count">\d+<\/span>/',
304 '<span class="all-count">' . $count . '</span>',
305 $links['all']
306 );
307 }
308
309 if ( isset( $links['moderated'] ) ) {
310 $count = get_comments( array_merge( $comments_query_args, array( 'status' => 'hold' ) ) );
311 $links['moderated'] = preg_replace(
312 '/<span class="pending-count">\d+<\/span>/',
313 '<span class="pending-count">' . $count . '</span>',
314 $links['moderated']
315 );
316 }
317
318 if ( isset( $links['approved'] ) ) {
319 $count = get_comments( array_merge( $comments_query_args, array( 'status' => 'approve' ) ) );
320 $links['approved'] = preg_replace(
321 '/<span class="approved-count">\d+<\/span>/',
322 '<span class="approved-count">' . $count . '</span>',
323 $links['approved']
324 );
325 }
326
327 if ( isset( $links['spam'] ) ) {
328 $count = get_comments( array_merge( $comments_query_args, array( 'status' => 'spam' ) ) );
329 $links['spam'] = preg_replace(
330 '/<span class="spam-count">\d+<\/span>/',
331 '<span class="spam-count">' . $count . '</span>',
332 $links['spam']
333 );
334 }
335
336 if ( isset( $links['trash'] ) ) {
337 $count = get_comments( array_merge( $comments_query_args, array( 'status' => 'trash' ) ) );
338 $links['trash'] = preg_replace(
339 '/<span class="trash-count">\d+<\/span>/',
340 '<span class="trash-count">' . $count . '</span>',
341 $links['trash']
342 );
343 }
344 }
345 }
346
347 return $links;
348 }
349
350 /**
351 * Render a button
352 *
353 * @param \CMB2_Field $field The current CMB2_Field object.
354 * @param string $value The field value passed through the escaping filter.
355 * @param mixed $object_id The object id.
356 * @param string $object_type The type of object being handled.
357 * @param \CMB2_Types $field_type Instance of the correspondent CMB2_Types object.
358 *
359 * @since 1.15.1
360 * @static
361 */
362 public static function render_cmb2_buttons_group_field( $field, $value, $object_id, $object_type, $field_type ) {
363 $count = (int) $field->args['count'];
364 $selectors = array();
365
366 for ( $i = 0; $i < $count; $i++ ) {
367 $id = $field->args['id'] . '_' . $i;
368 $selectors[] = '#' . $id;
369
370 printf(
371 '<button class="%s" id="%s" data-nonce="%s" data-slug="%s">%s</button>',
372 isset( $field->args['class'] ) ? esc_attr( $field->args['class'] ) : 'button-secondary',
373 esc_attr( $id ),
374 esc_attr( $field->args['nonce'] ),
375 esc_attr( $field->args['slugs'][ $i ] ),
376 esc_html( $field->args['labels'][ $i ] )
377 );
378 }
379
380 $selector = implode( ', ', $selectors );
381
382 ?>
383
384 <script type="text/javascript">
385 jQuery("<?php echo esc_html( $selector ); ?>").on( "click", function( event ) {
386 event.preventDefault();
387 <?php echo esc_js( $field->args['onclick'] ); ?>
388 } );
389 </script>';
390
391 <?php
392
393 if ( isset( $field->args['desc'] ) ) {
394 ?>
395 <p class="cmb2-metabox-description"><?php echo esc_html( $field->args['desc'] ); ?></p>
396 <?php
397 }
398 }
399
400 /**
401 * Ensure 'up_button' fills in missing button on newer CMB2.
402 *
403 * @param null $override_value Sanitization override value to return.
404 * @param mixed $value The actual field value.
405 * @param mixed $object_id The object id.
406 * @param string $object_type The type of object being handled.
407 * @param \CMB2_Sanitizer $sanitizer Sanitizer's instance.
408 *
409 * @return mixed
410 * @since 1.15.1
411 * @static
412 */
413 public static function sanitize_cmb2_buttons_group_field( $override_value, $value, $object_id, $object_type, $sanitizer ) { }
414
415 /**
416 * Render a button
417 *
418 * @param \CMB2_Field $field The current CMB2_Field object.
419 * @param string $value The field value passed through the escaping filter.
420 * @param mixed $object_id The object id.
421 * @param string $object_type The type of object being handled.
422 * @param \CMB2_Types $field_type Instance of the correspondent CMB2_Types object.
423 *
424 * @since 1.15.1
425 * @static
426 */
427 public static function render_cmb2_button_field( $field, $value, $object_id, $object_type, $field_type ) {
428 printf(
429 '<button class="%s" id="%s" data-nonce="%s">%s</button>',
430 isset( $field->args['class'] ) ? esc_attr( $field->args['class'] ) : 'button-secondary',
431 esc_attr( $field->args['id'] ),
432 esc_attr( $field->args['nonce'] ),
433 esc_html( $field->args['label'] )
434 );
435
436 if ( isset( $field->args['desc'] ) ) {
437 ?>
438 <p class="cmb2-metabox-description"><?php echo esc_html( $field->args['desc'] ); ?></p>
439 <?php
440 }
441
442 $selector = '#' . $field->_id();
443
444 ?>
445
446 <script>
447 jQuery("<?php echo esc_html( $selector ); ?>").on( "click", function( event ) {
448 event.preventDefault();
449 <?php echo esc_js( $field->args['onclick'] ); ?>
450 } );
451 </script>';
452
453 <?php
454 }
455
456 /**
457 * Ensure 'up_button' fills in missing button on newer CMB2.
458 *
459 * @param null $override_value Sanitization override value to return.
460 * @param mixed $value The actual field value.
461 * @param mixed $object_id The object id.
462 * @param string $object_type The type of object being handled.
463 * @param \CMB2_Sanitizer $sanitizer Sanitizer's instance.
464 *
465 * @return mixed
466 * @since 1.15.1
467 * @static
468 */
469 public static function sanitize_cmb2_button_field( $override_value, $value, $object_id, $object_type, $sanitizer ) { }
470
471 /**
472 * Render a modified 'text_date_timestamp' that will always use
473 * its date's time being as 12:00:00 AM.
474 *
475 * @param \CMB2_Field $field The current CMB2_Field object.
476 * @param string $value The field value passed through the escaping filter.
477 * @param mixed $object_id The object id.
478 * @param string $object_type The type of object being handled.
479 * @param \CMB2_Types $field_type Instance of the correspondent CMB2_Types object.
480 *
481 * @since 1.15.1
482 * @static
483 */
484 public static function render_cmb2_timestamp_field( $field, $value, $object_id, $object_type, $field_type ) {
485 $allowed_html_tags = array(
486 'input' => array(
487 'type' => array(),
488 'class' => array(),
489 'name' => array(),
490 'id' => array(),
491 'value' => array(),
492 'data-hash' => array(),
493 'data-disabled' => array(),
494 'data-datepicker' => array(),
495 'data-owner' => array(),
496 ),
497 );
498
499 echo wp_kses( $field_type->text_date_timestamp(), $allowed_html_tags );
500 }
501
502 /**
503 * Ensure 'up_timestamp' fields date's time are set to 12:00:00 AM before it is stored AS GMT/UTC.
504 *
505 * @param null $override_value Sanitization override value to return.
506 * @param mixed $value The actual field value.
507 * @param mixed $object_id The object id.
508 * @param string $field_args The type of object being handled.
509 * @param \CMB2_Sanitizer $sanitizer Sanitizer's instance.
510 *
511 * @return mixed
512 * @since 1.15.1
513 * @static
514 */
515 public static function sanitize_cmb2_timestamp_field( $override_value, $value, $object_id, $field_args, $sanitizer ) {
516 $value = trim( (string) $value );
517
518 if ( strlen( $value ) > 0 ) {
519 try {
520 $date = DateTime::createFromFormat( $field_args['date_format'], $value );
521
522 if ( false !== $date ) {
523 $date->setTime( 0, 0, 0 );
524 $value = (string) $date->format( 'U' );
525 $override_value = $value;
526 } else {
527 $value = '';
528 }
529 } catch ( \Exception $e ) {
530 $value = '';
531 }
532 }
533
534 return $value;
535 }
536
537 /**
538 * Escape Cmb2 Timestamp Field
539 *
540 * @param mixed $value Value.
541 * @param mixed $args Args.
542 * @param mixed $field Field.
543 */
544 public static function escape_cmb2_timestamp_field( $value, $args, $field ) {
545 $value = (int) $value;
546 if ( $value > 0 ) {
547 $date = new \DateTime( 'now' );
548 $date->setTimestamp( $value );
549
550 $value = $date->format( $args['date_format'] );
551 }
552
553 return $value;
554 }
555
556 /**
557 * Save Additional User Fields
558 *
559 * @param mixed $user_id User Id.
560 */
561 public static function save_additional_user_fields( $user_id ) {
562 $post_data = isset( $_POST ) ? wp_unslash( $_POST ) : array();
563 $nonce = isset( $post_data['_wpnonce'] ) ? $post_data['_wpnonce'] : null;
564
565 if ( ! current_user_can( 'edit_user', $user_id ) || ! isset( $post_data['upstream'] ) ) {
566 return false;
567 }
568
569 if ( ! wp_verify_nonce( $nonce, 'update-user_' . $user_id ) ) {
570 return;
571 }
572
573 $crn = isset( $post_data['upstream']['comment_replies_notification'] ) ? sanitize_text_field( $post_data['upstream']['comment_replies_notification'] ) : '';
574
575 if ( $crn ) {
576 $receive_notifications = 'no' !== $crn;
577 update_user_meta( $user_id, 'upstream_comment_replies_notification', $receive_notifications ? 'yes' : 'no' );
578 unset( $receive_notifications );
579 }
580 }
581
582 /**
583 * Render Additional User Fields
584 *
585 * @param mixed $user User.
586 * @return void
587 */
588 public static function render_additional_user_fields( $user ) {
589 $receive_notifications = upstream_user_can_receive_comment_replies_notification( $user->ID );
590 ?>
591 <h2><?php esc_html_e( 'UpStream', 'upstream' ); ?></h2>
592 <table class="form-table">
593 <tbody>
594 <tr>
595 <th>
596 <label for="upstream_comment_reply_notifications">
597 <?php
598 esc_html_e(
599 'Comment reply notifications',
600 'upstream'
601 );
602 ?>
603 </label>
604 </th>
605 <td>
606 <div>
607 <label>
608 <?php esc_html_e( 'Yes', 'upstream' ); ?>
609 <input type="radio" name="upstream[comment_replies_notification]"
610 value="1"<?php echo $receive_notifications ? ' checked' : ''; ?>>
611 </label>
612 <label>
613 <?php esc_html_e( 'No', 'upstream' ); ?>
614 <input type="radio" name="upstream[comment_replies_notification]"
615 value="no"<?php echo $receive_notifications ? '' : ' checked'; ?>>
616 </label>
617 </div>
618 <p class="description">
619 <?php
620 printf(
621 // translators: %s: upstream_project_label_plural.
622 esc_html__( 'Whether to be notified when someone reply to your comments within %s.', 'upstream' ),
623 esc_html( upstream_project_label_plural( true ) )
624 );
625 ?>
626 </p>
627 </td>
628 </tr>
629 </tbody>
630 </table>
631 <?php
632 }
633
634 /**
635 * Create id for newly added project/bugs/tasks statuses.
636 * This method is called right before field data is saved to db.
637 *
638 * @param array $value Array of the new data set.
639 * @param array $args Field arguments.
640 * @param \CMB2_Field $field The field object.
641 *
642 * @return array $value
643 * @since 1.17.0
644 * @static
645 */
646 public static function on_before_save( $value, $args, $field ) {
647 if ( is_array( $value ) ) {
648 $value = self::create_missing_ids_in_set( $value );
649 $value = self::create_missing_colors_in_set( $value );
650 $i = 0;
651 $count_value = is_array( $value ) ? count( $value ) : 0;
652
653 while ( $i < $count_value ) {
654 if ( ! isset( $value[ $i ]['name'] ) ) {
655 array_splice( $value, $i, 1 );
656 } else {
657 $i++;
658 }
659 }
660 }
661
662 return $value;
663 }
664
665 /**
666 * Create missing id in a rowset.
667 *
668 * @param array $rowset Data array.
669 *
670 * @return array
671 * @since 1.17.0
672 * @static
673 */
674 public static function create_missing_ids_in_set( $rowset ) {
675 if ( ! is_array( $rowset ) ) {
676 return false;
677 }
678
679 if ( count( $rowset ) > 0 ) {
680 $indexes_missing_id = array();
681 $ids_map = array();
682
683 foreach ( $rowset as $row_index => $row ) {
684 if ( ! isset( $row['id'] )
685 || empty( $row['id'] )
686 ) {
687 $indexes_missing_id[] = $row_index;
688 } else {
689 $ids_map[ $row['id'] ] = $row_index;
690 }
691 }
692
693 if ( count( $indexes_missing_id ) > 0 ) {
694 $new_ids_length = 5;
695 $new_ids_chars_pool = 'abcdefghijklmnopqrstuvwxyz0123456789';
696
697 foreach ( $indexes_missing_id as $row_index ) {
698 do {
699 $id = upstream_generate_random_string( $new_ids_length, $new_ids_chars_pool );
700 } while ( isset( $ids_map[ $id ] ) );
701
702 $rowset[ $row_index ]['id'] = $id;
703 $ids_map[ $id ] = $row_index;
704 }
705 }
706 }
707
708 return $rowset;
709 }
710
711 /**
712 * Create missing color in a rowset.
713 *
714 * @param array $rowset Data array.
715 *
716 * @return array
717 * @since 2.0.0
718 * @static
719 */
720 public static function create_missing_colors_in_set( $rowset ) {
721 if ( ! is_array( $rowset ) ) {
722 return false;
723 }
724
725 if ( count( $rowset ) > 0 ) {
726 foreach ( $rowset as $row_index => $row ) {
727 if ( ! isset( $row['color'] )
728 || empty( $row['color'] )
729 || '#' === $row['color']
730 ) {
731 $rowset[ $row_index ]['color'] = '#F0F0F1';
732 }
733 }
734 }
735
736 return $rowset;
737 }
738
739 /**
740 * Init the dependencies.
741 */
742 public function init() {
743 do_action( 'alex_enable_module_upgrade', 'https://upstreamplugin.com/pricing/' );
744 }
745
746 /**
747 * Limit Up Stream User Access
748 *
749 * @return void
750 */
751 public function limit_up_stream_user_access() {
752 if ( empty( $_GET ) || ! is_admin() ) {
753 return;
754 }
755
756 $user = wp_get_current_user();
757 $user_is_up_stream_user = count(
758 array_intersect(
759 (array) $user->roles,
760 array( 'administrator', 'upstream_manager' )
761 )
762 ) === 0;
763
764 if ( $user_is_up_stream_user ) {
765 global $pagenow;
766
767 $should_redirect = false;
768 $get_data = isset( $_GET ) ? wp_unslash( $_GET ) : array();
769
770 // this is checked against a known list of post types later.
771 $post_type = isset( $get_data['post_type'] ) ? sanitize_text_field( $get_data['post_type'] ) : '';
772 $is_post_type_project = 'project' === $post_type;
773
774 if ( 'edit-tags.php' === $pagenow ) {
775 if ( isset( $get_data['taxonomy'] )
776 && 'project_category' === sanitize_text_field( $get_data['taxonomy'] )
777 && $is_post_type_project
778 ) {
779 $should_redirect = true;
780 }
781 } elseif ( 'post.php' === $pagenow
782 && $is_post_type_project
783 ) {
784 $project_members_list = (array) get_post_meta( (int) $get_data['post'], '_upstream_project_members', true );
785 // Since he's not and Administrator nor an UpStream Manager, we need to check if he's participating in the project.
786 if ( ! in_array( $user->ID, $project_members_list ) ) {
787 $should_redirect = true;
788 }
789 } elseif ( 'post-new.php' === $pagenow
790 && $is_post_type_project
791 ) {
792 $should_redirect = true;
793 } elseif ( 'edit.php' === $pagenow
794 && 'client' === $post_type
795 ) {
796 $should_redirect = true;
797 }
798
799 if ( $should_redirect ) {
800 // Redirect the user to the projects list page.
801 // $pagenow = 'edit.php';.
802 wp_redirect( admin_url( '/edit.php?post_type=project' ) );
803 exit;
804 }
805 }
806 }
807
808 /**
809 * Include any classes we need within admin.
810 */
811 public function includes() {
812 // option pages.
813 include_once 'class-upstream-admin-options.php';
814 include_once 'options/option-functions.php';
815
816 // metaboxes.
817 include_once 'class-upstream-admin-metaboxes.php';
818 include_once 'metaboxes/metabox-functions.php';
819
820 include_once 'up-enqueues.php';
821 include_once 'class-upstream-admin-projects-menu.php';
822 include_once 'class-upstream-admin-project-columns.php';
823 include_once 'class-upstream-admin-client-columns.php';
824 include_once 'class-upstream-admin-pointers.php';
825 }
826
827 /**
828 * Adds one or more classes to the body tag in the dashboard.
829 *
830 * @param String $classes Current body classes.
831 *
832 * @return String Altered body classes.
833 */
834 public function admin_body_class( $classes ) {
835 $screen = get_current_screen();
836
837 if ( in_array(
838 $screen->id,
839 array(
840 'client',
841 'edit-client',
842 'project',
843 'edit-project',
844 'edit-project_category',
845 'project_page_tasks',
846 'project_page_bugs',
847 'toplevel_page_upstream_general',
848 'upstream_page_upstream_bugs',
849 'upstream_page_upstream_tasks',
850 'upstream_page_upstream_milestones',
851 'upstream_page_upstream_clients',
852 'upstream_page_upstream_projects',
853 )
854 ) ) {
855 return "$classes upstream";
856 }
857
858 return $classes;
859 }
860
861 /**
862 * Only show current users media items
863 *
864 * @param mixed $query Query.
865 */
866 public function filter_user_attachments( $query = array() ) {
867 $user = wp_get_current_user();
868 $roles = upstream_media_unrestricted_roles();
869
870 // Get the user's role.
871 $match = array_intersect( $user->roles, $roles );
872
873 // If the user's has a role selected as unrestricted, we do not filter the attachments.
874 if ( ! empty( $match ) ) {
875 return $query;
876 }
877
878 // The user should only see its own attachments.
879 if ( is_object( $user ) && isset( $user->ID ) && ! empty( $user->ID ) ) {
880 $query['author'] = $user->ID;
881 }
882
883 return $query;
884 }
885
886 /**
887 * Override the media_comment_images option based on the current capabilities.
888 *
889 * @param string $test Test.
890 * @param mixed $default Default.
891 * @param mixed $instance Instance.
892 *
893 * @return array
894 */
895 public function filter_override_option_get_upstream_general( $test, $default, $instance ) {
896 // Identify roles that has the upstream_comment_images capability.
897 $roles = array_keys( get_editable_roles() );
898 $capable_roles = array();
899 foreach ( $roles as $role_id ) {
900 $role = get_role( $role_id );
901 if ( $role->has_cap( 'upstream_comment_images' ) ) {
902 $capable_roles[] = $role_id;
903 }
904 }
905
906 $options = get_option( 'upstream_general' );
907
908 $options['media_comment_images'] = $capable_roles;
909
910 return $options;
911 }
912 }
913
914 return new UpStream_Admin();
915