PluginProbe
Taskbuilder – Project Management & Task Management Tool With Kanban Board / 6.0.6
Taskbuilder – Project Management & Task Management Tool With Kanban Board v6.0.6
6.0.6 6.0.5 6.0.2 6.0.3 6.0.4 6.0.1 6.0.0 5.0.8 5.0.9 4.0.9 5.0.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 All 58 releases
← All changes | includes/admin/tasks/open_task/wppm_open_task.php +669 -177 5.0.36.0.6 View file →
@@ -3,10 +3,12 @@
3 3 exit; // Exit if accessed directly
4 4 }
5 5
6 6 global $current_user,$wpdb,$wppmfunction;
7 -$id = isset($_POST) && isset($_POST['id']) ? intval(sanitize_text_field($_POST['id'])) : "0";
7 +$id = isset($_POST) && isset($_POST['id']) ? intval(sanitize_text_field(wp_unslash($_POST['id']))) : "0";
8 +$page = isset($_POST) && isset($_POST['page']) ? sanitize_text_field(wp_unslash($_POST['page'])) : '';
8 9 $task_list_view = get_option('wppm_default_task_list_view');
10 +$project_id = isset($_POST) && isset($_POST['project_id']) ? intval(sanitize_text_field($_POST['project_id'])) : "0";
9 11 $wppm_default_task_date = get_option('wppm_default_task_date');
10 12 $wppm_task_time = get_option('wppm_task_time');
11 13 $appearance_settings = get_option("wppm-ap-individual-task");
12 14 $wppm_tinymce_visibility_open_task = get_option('wppm_tinymce_visibility_open_task');
@@ -19,11 +21,11 @@
19 21 $url_auth = false;
20 22 $auth_id = $wppmfunction->wppm_get_auth_code($id);
21 23 $auth_id = sanitize_text_field($auth_id);
22 24 // url authentication.
23 -$auth_code = isset( $_POST['auth-code'] ) ? sanitize_text_field( $_POST['auth-code'] ) : ''; // phpcs:ignore
25 +$auth_code = isset( $_POST['auth-code'] ) ? sanitize_text_field( wp_unslash($_POST['auth-code'] ) ) : ''; // phpcs:ignore
24 26 if ( ! $auth_code ) {
25 - $auth_code = isset( $_POST['auth_code'] ) ? sanitize_text_field( $_POST['auth_code'] ) : ''; // phpcs:ignore
27 + $auth_code = isset( $_POST['auth_code'] ) ? sanitize_text_field( wp_unslash($_POST['auth_code'] ) ) : ''; // phpcs:ignore
26 28 }
27 29
28 30 if ( $auth_code && $auth_id == $auth_code ) {
29 31 $url_auth = true;
@@ -28,37 +30,40 @@
28 30 if ( $auth_code && $auth_id == $auth_code ) {
29 31 $url_auth = true;
30 32 }
31 33 if (!(($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('view_task',$id)) || ($url_auth==true))) { ?>
32 - <div style="align-item:center;" ><h6><?php esc_attr_e( 'Unauthorized access!', 'taskbuilder' ); ?></h6></div>
34 + <div style="text-align:center;padding:20px 0;">
35 + <h6><?php esc_attr_e( 'Unauthorized access!', 'taskbuilder' ); ?></h6>
36 + <a href="<?php echo esc_url( admin_url('admin.php?page=wppm-tasks') ); ?>" class="btn btn-success btn-sm"><?php esc_html_e( 'Go to Task List', 'taskbuilder' ); ?></a>
37 + </div>
33 38 <?php
34 39 wp_die();
35 40 }
36 -$proj_id = isset($_POST) && isset($_POST['proj_id']) ? intval(sanitize_text_field($_POST['proj_id'])) : 0;
37 -$current_date = date('Y-m-d');
41 +$proj_id = isset($_POST) && isset($_POST['proj_id']) ? intval(sanitize_text_field(wp_unslash($_POST['proj_id']))) : 0;
42 +$current_date = wp_date('Y-m-d');
38 43 $wppm_current_user_capability = get_user_meta( $current_user->ID, 'wppm_capability', true );
39 -$cu_id = $current_user->ID;
44 +$cu_id = absint($current_user->ID);
40 45 if(!empty($id)){
41 - $task = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task where id='".esc_sql($id)."'");
46 + $task = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task where id=%d",$id));
42 47 $project_data = $wppmfunction->get_project($task->project);
43 - $task_comment = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id='".esc_sql($id)."' ORDER BY create_time DESC");
44 - $orderby_proj_sql = esc_sql(sanitize_sql_orderby( "create_time DESC" ));
45 - $task_comment = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id='".esc_sql($id)."' ORDER BY ". $orderby_proj_sql);
46 - $task_proj = isset($task->project) ? esc_sql($task->project) :"";
47 - $task_id = isset($task->id) ? esc_sql($task->id):"";
48 + $task_comment = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id=%d ORDER BY create_time DESC",$id));
49 + $orderby_proj_sql = (sanitize_sql_orderby( "create_time DESC" ));
50 + $task_comment = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id=%d ORDER BY ". $orderby_proj_sql,$id));
51 + $task_proj = isset($task->project) ? absint($task->project) :"";
52 + $task_id = isset($task->id) ? absint($task->id):"";
48 53 }
49 -$user_role = $wpdb->get_var( "SELECT role_id FROM {$wpdb->prefix}wppm_project_users where proj_id = '$task_proj' AND user_id = '$cu_id'");
54 +$user_role = $wpdb->get_var( $wpdb->prepare("SELECT role_id FROM {$wpdb->prefix}wppm_project_users where proj_id = %d AND user_id = %d",$task_proj,$cu_id));
50 55 if(!empty($task_proj)){
51 - $project_name = $wpdb->get_var( "SELECT project_name FROM {$wpdb->prefix}wppm_project where id= '$task_proj'");
56 + $project_name = $wpdb->get_var( $wpdb->prepare("SELECT project_name FROM {$wpdb->prefix}wppm_project where id= %d",$task_proj));
52 57 }
53 -$wppm_checklist=$wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist where task_id='$task_id'" );
58 +$wppm_checklist=$wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_checklist where task_id=%d",$task_id));
54 59 if(!empty($task->status)){
55 - $task_status_var = esc_sql($task->status);
56 - $task_status = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id='$task_status_var'");
60 + $task_status_var = absint($task->status);
61 + $task_status = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id=%d",$task_status_var));
57 62 }
58 63 if(!empty($task->priority)){
59 - $task_priority_var = esc_sql($task->priority);
60 - $task_priority = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id='$task_priority_var'");
64 + $task_priority_var = absint($task->priority);
65 + $task_priority = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id=%d",$task_priority_var));
61 66 }
62 67 if(!empty($task->users)){
63 68 $users = explode(",",$task->users);
64 69 }
@@ -63,9 +68,9 @@
63 68 $users = explode(",",$task->users);
64 69 }
65 70
66 71 if(!empty($task->description)){
67 - $task_description = stripslashes((htmlspecialchars_decode($task->description, ENT_QUOTES)));
72 + $task_description = !empty($task->description) ? wp_kses_post(wpautop($task->description)) : '';
68 73 }
69 74
70 75 if($wppm_task_time == 1){
71 76 $tsDate = new DateTime($task->start_date);
@@ -153,9 +158,9 @@
153 158 }
154 159 }
155 160 }
156 161 $flag = false;
157 -$wppm_task_fillter = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wppm_task where id='".esc_sql($id)."'");
162 +$wppm_task_fillter = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task where id=%d",$id));
158 163 if(!empty($wppm_task_fillter)){
159 164 foreach($wppm_task_fillter as $key_filter=>$val_filter){
160 165 $val_array = (array) $val_filter;
161 166 $tusers = $val_array['users'];
@@ -160,12 +165,12 @@
160 165 $val_array = (array) $val_filter;
161 166 $tusers = $val_array['users'];
162 167 $tusers_arr = explode(',',$tusers);
163 168 $tproject_id = $val_array['project'];
164 - $tproject_id = esc_sql($tproject_id);
169 + $tproject_id = absint($tproject_id);
165 170 if(!empty($tusers) && in_array($current_user->ID,$tusers_arr)){
166 - $project_user_role = $wpdb->get_var("SELECT role_id FROM {$wpdb->prefix}wppm_project_users WHERE proj_id = '$tproject_id' AND user_id = '$cu_id'");
167 - $project_users = $wpdb->get_var("SELECT users FROM {$wpdb->prefix}wppm_project WHERE id = '$tproject_id'");
171 + $project_user_role = $wpdb->get_var( $wpdb->prepare("SELECT role_id FROM {$wpdb->prefix}wppm_project_users WHERE proj_id = %d AND user_id = %d",$tproject_id,$cu_id));
172 + $project_users = $wpdb->get_var( $wpdb->prepare("SELECT users FROM {$wpdb->prefix}wppm_project WHERE id = %d",$tproject_id));
168 173 $project_users_arr = explode(',',(string)$project_users);
169 174 if((!empty($project_user_role)) && ($project_user_role == 1) && in_array($current_user->ID,$project_users_arr)){
170 175 $flag= true;
171 176 break;
@@ -172,9 +177,9 @@
172 177 }
173 178 }
174 179 }
175 180 }
176 -$project_creator = $wpdb->get_var("SELECT created_by FROM {$wpdb->prefix}wppm_project WHERE created_by = '$cu_id'");
181 +$project_creator = $wpdb->get_var( $wpdb->prepare("SELECT created_by FROM {$wpdb->prefix}wppm_project WHERE created_by = %d",$cu_id));
177 182 ?>
178 183 <form id="wppm_open_task" method="post">
179 184 <div id="wppm_alert_success" class="alert alert-success wppm_alert" style="display:none;" role="alert">
180 185 <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/success.svg'); ?>" alt="success"> <span class="wppm_alert_text"></span>
@@ -198,29 +203,40 @@
198 203 }else{
199 204 $archive_style= "display:none;";
200 205 }
201 206 if($proj_id==0) {
202 - ?> <span onclick="wppm_add_new_task(<?php echo esc_attr($proj_id) ?>)" class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" style="<?php echo $style?>" title="Create Task"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
207 + ?> <span onclick="wppm_add_new_task(<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)" class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" style="<?php echo esc_attr($style)?>" title="<?php esc_attr_e( 'Create Task', 'taskbuilder' ); ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
203 208 <?php }
204 209 else{ ?>
205 - <span class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" title="Create Task" onclick="wppm_create_project_task(<?php echo esc_attr($proj_id) ?>)" style="<?php echo $style ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
210 + <span class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" title="<?php esc_attr_e( '"Create Task', 'taskbuilder' ); ?>" onclick="wppm_create_project_task(<?php echo esc_attr($proj_id) ?>)" style="<?php echo esc_attr($style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
206 211 <?php } ?>
207 - <?php if($proj_id==0) {
208 - $task_list_function = ($task_list_view==1)?"wppm_get_task_list()":"wppm_view_task_search_filter()";
212 + <?php if($proj_id==0) {
213 + if (($project_id!=0)) {
214 + $task_list_function = "wppm_get_project_tasks_kanban_view( {$project_id})";
215 + }
216 + if (empty($project_id) && $task_list_view == 1) {
217 + $task_list_function = "wppm_get_task_list('', {$project_id})";
218 + }
219 + if(empty($task_list_view) && empty($project_id)) {
220 + $task_list_function = "wppm_view_task_search_filter('', '', {$project_id})";
221 + }
209 222 ?>
210 - <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="Task List" onclick="<?php echo $task_list_function ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
223 + <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="<?php esc_attr_e( 'Task List', 'taskbuilder' ); ?>"onclick="<?php echo esc_attr($task_list_function) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
211 224 <?php }
212 225 else{
213 226 ?>
214 - <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="Task List" onclick="wppm_get_project_tasks(<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
227 + <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="<?php esc_attr_e( 'Task List', 'taskbuilder' ); ?>" onclick="wppm_get_project_tasks(<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
215 228 <?php } ?>
216 - <?php $style = (($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('delete_task',$id)) || $wppm_current_user_capability == 'wppm_admin'|| $project_data['created_by']==$current_user->ID )? "display:inline":"display:none"; ?>
217 - <?php $clone_style = ((($current_user->ID && $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') || ($wppmfunction->has_permission('clone_task',$id)) || $project_data['created_by']==$current_user->ID ) && $task->is_archived!=1) ? "display:inline":"display:none"; ?>
229 + <?php $style = ((($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('delete_task',$id)) || $wppm_current_user_capability == 'wppm_admin'|| $project_data['created_by']==$current_user->ID ) && $user_role != 3) ? "display:inline":"display:none"; ?>
230 + <?php $clone_style = ((($current_user->ID && $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') || ($wppmfunction->has_permission('clone_task',$id)) || $project_data['created_by']==$current_user->ID ) && $task->is_archived!=1 && $user_role != 3) ? "display:inline":"display:none"; ?>
218 231 <?php $ar_css = ($task->is_archived==1) ? "display:none;" : "display:inline"; ?>
219 - <span class="wppm-delete_task_btn" id="wppm_delete_task_btn" title="Delete Task" onclick="wppm_get_delete_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)" style="<?php echo esc_attr($style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/bin.svg'); ?>" alt="delete"></span>
220 - <div class="wppm-clone_task_btn" id="wppm_clone_task_btn" title="Clone Task" onclick="wppm_clone_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id)?>)" style="<?php echo esc_attr($clone_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/duplicate.svg'); ?>" alt="clone"></div>
232 + <span class="wppm-dashboard-btn" id="wppm_dashboard_btn" title="<?php esc_attr_e( 'Dashboard', 'taskbuilder' ); ?>" onclick="wppm_get_project_tasks(<?php echo esc_attr($proj_id) ?>)">
233 + <a href="<?php echo esc_url(admin_url('admin.php?page=wppm-dashboard')); ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/dashboard-icon.svg'); ?>" alt="dashboard"></a>
234 + </span>
235 + <span class="wppm-delete_task_btn" id="wppm_delete_task_btn" title="Delete Task" onclick="wppm_get_delete_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)" style="<?php echo esc_attr($style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/bin.svg'); ?>" alt="delete"></span>
236 + <span class="wppm-clone_task_btn" id="wppm_clone_task_btn" title="Clone Task" onclick="wppm_clone_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id)?>,<?php echo esc_attr($project_id) ?>)" style="<?php echo esc_attr($clone_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/duplicate.svg'); ?>" alt="clone"></span>
221 237 <span class="wppm-print_task_btn" id="wppm_print_task_btn" title="Print Task" onclick="wppm_print_task(<?php echo esc_attr($id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/printer_menu.svg'); ?>" alt="print" style="<?php echo esc_attr($ar_css);?>"></span>
222 - <span class="wppm-archieve_task_btn" id="wppm_archieve_task_btn" title="<?php echo ($task->is_archived==1 ) ? 'Restore Task' : 'Archive Task'; ?>" onclick="wppm_archive_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($task->is_archived) ?>)" style="<?php echo esc_attr($archive_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/archive.svg'); ?>" alt="archive"></span>
238 + <span class="wppm-archieve_task_btn" id="wppm_archieve_task_btn" title="<?php echo ($task->is_archived==1 ) ? 'Restore Task' : 'Archive Task'; ?>" onclick="wppm_archive_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($task->is_archived) ?>,<?php echo esc_attr($project_id) ?>)" style="<?php echo esc_attr($archive_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/archive.svg'); ?>" alt="archive"></span>
223 239 <input type="hidden" name="wppm_archive_task_ajax_nonce" id="wppm_archive_task_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_archive_task_ajax_nonce' ) ); ?>">
224 240 <div class="menu" id="wppmprint_menu" onclick="event.stopPropagation();">
225 241 <a href="#" id="wppm_openPDF" onclick="wppm_open_pdf(<?php echo esc_attr($id) ?>)">🖨️ <?php echo esc_html_e('Open In Browser','taskbuilder');?></a>
226 242 <a href="#" id="wppm_downloadPDF" onclick="wppm_download_pdf(<?php echo esc_attr($id) ?>)">💾 <?php echo esc_html_e('Download PDF','taskbuilder');?></a>
@@ -225,9 +241,9 @@
225 241 <a href="#" id="wppm_openPDF" onclick="wppm_open_pdf(<?php echo esc_attr($id) ?>)">🖨️ <?php echo esc_html_e('Open In Browser','taskbuilder');?></a>
226 242 <a href="#" id="wppm_downloadPDF" onclick="wppm_download_pdf(<?php echo esc_attr($id) ?>)">💾 <?php echo esc_html_e('Download PDF','taskbuilder');?></a>
227 243 </div>
228 244 <?php do_action('wppm_individual_task_button',$id);?>
229 - </div>
245 + </div>
230 246 </div>
231 247 <div id="wppm_load_individual_task_container" class="row">
232 248 <div class="col-sm-8 wppm_body col-md-9">
233 249 <div class="wppm_task_details_container">
@@ -232,13 +248,28 @@
232 248 <div class="col-sm-8 wppm_body col-md-9">
233 249 <div class="wppm_task_details_container">
234 250 <div class="row">
235 251 <div class="col-sm-12">
236 - <span class="wppm_task_label"> <?php echo esc_html_e($task->task_name,'taskbuilder');
237 - if (($wppmfunction->has_permission('change_task_details',$id) || $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') && $task->is_archived!=1) { ?>
238 - <span id="wppm_individual_edit_task_subject" onclick="wppm_edit_task_details(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)" class="btn btn-sm wppm_action_btn" style="background-color:#FFFFFF !important;color:#000000 !important;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
252 + <span class="wppm_task_label"> <?php echo isset($task->task_name) ? esc_html($task->task_name ):"" ?>
253 + <?php if (($wppmfunction->has_permission('change_task_details',$id) || $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') && $task->is_archived!=1) { ?>
254 + <span id="wppm_individual_edit_task_subject" onclick="wppm_edit_task_details(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)" class="btn btn-sm wppm_action_btn" style="background-color:#FFFFFF !important;color:#000000 !important;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
239 255 <?php } ?>
240 256 </span>
257 + <?php if(!empty($task->parent_task_id)){
258 + $wppm_parent_task = $wpdb->get_row( $wpdb->prepare("SELECT id, task_name FROM {$wpdb->prefix}wppm_task where id=%d",absint($task->parent_task_id)));
259 + if(!empty($wppm_parent_task)){
260 + $wppm_can_convert_subtask = (($current_user->has_cap('manage_options') || $wppmfunction->has_permission('delete_task',$id)) && $task->is_archived!=1);
261 + ?>
262 + <div class="wppm_subtask_parent_link">
263 + <?php echo esc_html_e('Subtask of','taskbuilder');?>
264 + <a href="#" onclick="wppm_open_subtask(<?php echo esc_attr($wppm_parent_task->id) ?>,<?php echo esc_attr($proj_id) ?>);return false;"><?php echo esc_html($wppm_parent_task->task_name); ?></a>
265 + <?php if($wppm_can_convert_subtask){ ?>
266 + &nbsp;|&nbsp;<a href="#" onclick="wppm_convert_subtask_to_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>);return false;"><?php echo esc_html_e('Convert to Task','taskbuilder');?></a>
267 + <input type="hidden" name="wppm_convert_subtask_to_task_ajax_nonce" id="wppm_convert_subtask_to_task_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_convert_subtask_to_task' ) ); ?>">
268 + <?php } ?>
269 + </div>
270 + <?php }
271 + } ?>
241 272 </div>
242 273 </div>
243 274 <div class="row">
244 275 <div class="col-sm-3">
@@ -244,9 +275,9 @@
244 275 <div class="col-sm-3">
245 276 <span class="wppm_task_details_label"><?php echo esc_html_e('Project:','taskbuilder');?></span>
246 277 </div>
247 278 <div class="col-sm-9">
248 - <span class="wppm_task_details"><?php echo (isset($project_name))? esc_html_e($project_name,'taskbuilder'):"" ?></span>
279 + <span class="wppm_task_details"><?php echo (isset($project_name))? esc_html($project_name ):"" ?></span>
249 280 </div>
250 281 </div>
251 282 <div class="row">
252 283 <div class="col-sm-3">
@@ -307,9 +338,9 @@
307 338 <div class="col-sm-3">
308 339 <span class="wppm_task_details_label"><?php echo esc_html_e('Task Duration:','taskbuilder');?></span>
309 340 </div>
310 341 <div class="col-sm-9">
311 - <span class="wppm_task_details" id="wppm_edit_task_duration" style="<?php echo esc_attr($style); ?>"><?php echo (isset($wppm_task_duration))? esc_html($wppm_task_duration): "" ?></span>
342 + <span class="wppm_task_details" id="wppm_edit_task_duration" style="<?php echo esc_attr($style); ?>"><?php echo (isset($wppm_task_duration))? esc_html($wppm_task_duration ): "" ?></span>
312 343 </div>
313 344 </div> <?php
314 345 }?>
315 346 <div class="row">
@@ -316,9 +347,9 @@
316 347 <div class="col-sm-3">
317 348 <span class="wppm_task_details_label"><?php echo esc_html_e('Task Priority:','taskbuilder');?></span>
318 349 </div>
319 350 <div class="col-sm-9">
320 - <span class="wppm_task_details_priority"><span class="wppm_admin_label" style="background-color:<?php echo (isset($task_priority->bg_color))? esc_html($task_priority->bg_color):""?>;color:<?php echo (isset($task_priority->color))? esc_html($task_priority->color):""?>;"><?php echo (isset($task_priority->name)) ? esc_html_e($task_priority->name,'taskbuilder'):"" ?> </span></span>
351 + <span class="wppm_task_details_priority"><span class="wppm_admin_label" style="background-color:<?php echo (isset($task_priority->bg_color))? esc_html($task_priority->bg_color):""?>;color:<?php echo (isset($task_priority->color))? esc_html($task_priority->color):""?>;"><?php echo (isset($task_priority->name)) ? esc_html($task_priority->name):"" ?> </span></span>
321 352 </div>
322 353 </div>
323 354 <div class="row">
324 355 <div class="col-sm-3">
@@ -324,13 +355,173 @@
324 355 <div class="col-sm-3">
325 356 <span class="wppm_task_details_label"><?php echo esc_html_e('Description:','taskbuilder');?></span>
326 357 </div>
327 358 <div class="col-sm-9">
328 - <span class="wppm_task_description"><?php echo (isset($task_description))? wp_kses_post(wpautop($task_description)):"" ?></span>
359 + <span class="wppm_task_description"><?php echo (!empty($task_description))? wp_kses_post(wpautop($task_description)):"" ?></span>
329 360 </div>
330 361 </div>
331 362 <?php do_action('wppm_after_task_details_in_open_task',$task->id, $task->project);?>
332 363 </div>
364 + <?php if(empty($task->parent_task_id)){
365 + $wppm_subtasks = $wppmfunction->get_subtasks($task_id);
366 + $wppm_subtask_progress = $wppmfunction->get_subtask_progress($task_id);
367 + $wppm_default_task_status = get_option('wppm_default_task_status');
368 + $wppm_can_add_subtask = (($current_user->has_cap('manage_options') || $wppmfunction->has_permission('add_new_task',$task_id)) && $task->is_archived!=1 && $user_role != 3);
369 + ?>
370 + <div class="wppm_task_subtask_container" id="wppm_task_subtask_container">
371 + <div class="row">
372 + <div class="col-sm-8">
373 + <span class="wppm_checklist_label"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/task_list.svg'); ?>" alt="subtasks"><?php echo esc_html_e('Subtasks','taskbuilder');?></span>
374 + </div>
375 + </div>
376 + <?php if($wppm_subtask_progress['total'] > 0){
377 + $wppm_subtask_percent = round(($wppm_subtask_progress['completed'] / $wppm_subtask_progress['total']) * 100); ?>
378 + <div class="wppm_progress_bar_container row">
379 + <div class="col-sm-4">
380 + <span class="wppm_progressbar_label" id="wppm_subtask_progress_label"><?php echo esc_html($wppm_subtask_progress['completed'].'/'.$wppm_subtask_progress['total']); ?></span>
381 + </div>
382 + <div class="wppm_progress_bar col-sm-8">
383 + <div id="wppm_subtask_progressbar" class="wppm_checkprogress" role="progressbar" style="width: <?php echo esc_attr($wppm_subtask_percent); ?>%;background:#5ba4cf;" aria-valuemin="0" aria-valuemax="100"></div>
384 + </div>
385 + </div>
386 + <?php } ?>
387 + <input type="hidden" name="wppm_set_change_task_status_ajax_nonce" id="wppm_subtask_status_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_set_change_task_status' ) ); ?>">
388 + <input type="hidden" name="wppm_add_new_subtask_ajax_nonce" id="wppm_add_new_subtask_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_add_new_subtask' ) ); ?>">
389 + <input type="hidden" name="wppm_remove_subtask_ajax_nonce" id="wppm_remove_subtask_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_remove_subtask' ) ); ?>">
390 + <input type="hidden" name="wppm_convert_subtask_to_task_ajax_nonce" id="wppm_convert_subtask_to_task_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_convert_subtask_to_task' ) ); ?>">
391 + <ul id="wppm_subtask_items_container" class="wppm_checklist_items_container" style="list-style-type: none; padding-left:0px; margin-top:10px; margin-bottom:10px;">
392 + <?php if(!empty($wppm_subtasks)){
393 + foreach($wppm_subtasks as $subtask){
394 + $wppm_subtask_checked = ($subtask['status']==4) ? 'checked="checked"' : '';
395 + $wppm_subtask_users = !empty($subtask['users']) ? explode(",",$subtask['users']) : array();
396 + $wppm_subtask_can_change_status = ($current_user->has_cap('manage_options') || $wppmfunction->has_permission('change_status',$subtask['id'])) && $task->is_archived!=1;
397 + $wppm_subtask_can_delete = ($current_user->has_cap('manage_options') || $wppmfunction->has_permission('delete_task',$subtask['id'])) && $task->is_archived!=1;
398 + ?>
399 + <li id="wppm_subtask_<?php echo esc_attr($subtask['id']) ?>" class="row wppm_checklist_item" style="margin-bottom:10px;font: 15px 'Helvetica Neue',Helvetica,Arial,sans-serif;">
400 + <div class="col-sm-8">
401 + <input id="wppm_subtask_checkbox_<?php echo esc_attr($subtask['id']) ?>" type="checkbox" onchange="wppm_toggle_subtask_status(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($task_id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($wppm_default_task_status) ?>,this.checked)" <?php echo esc_attr($wppm_subtask_checked) ?> <?php echo $wppm_subtask_can_change_status ? '' : 'disabled'; ?> style="margin:5px;">
402 + <label style="padding-top: 5px;font-weight: normal;font: 13px 'Helvetica Neue',Helvetica,Arial,sans-serif;cursor:pointer;" onclick="wppm_open_subtask(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($proj_id) ?>)"><?php echo esc_html($subtask['task_name']); ?></label>
403 + </div>
404 + <div class="col-sm-4" style="text-align:right;">
405 + <?php $wppm_subtask_avatar_count = 0;
406 + $wppm_subtask_total_users = count( array_filter( $wppm_subtask_users ) );
407 + foreach($wppm_subtask_users as $wppm_subtask_user_id){
408 + if(!$wppm_subtask_user_id) continue;
409 + $wppm_subtask_avatar_count++;
410 + if($wppm_subtask_avatar_count > 3) break;
411 + $wppm_subtask_user_data = get_userdata($wppm_subtask_user_id);
412 + $wppm_subtask_user_name = !empty($wppm_subtask_user_data) ? $wppm_subtask_user_data->display_name : '';
413 + echo get_avatar($wppm_subtask_user_id, 20, "mysteryman", $wppm_subtask_user_name, array('extra_attr' => 'title="'.esc_attr($wppm_subtask_user_name).'"'));
414 + }
415 + $wppm_subtask_more_users = $wppm_subtask_total_users - 3;
416 + if ( $wppm_subtask_more_users > 0 ) {
417 + ?>
418 + <span class="wppm_subtask_more_users" title="<?php echo esc_attr( sprintf( _n( '%d more user assigned', '%d more users assigned', $wppm_subtask_more_users, 'taskbuilder' ), $wppm_subtask_more_users ) ); ?>">+<?php echo esc_html( $wppm_subtask_more_users ); ?></span>
419 + <?php
420 + } ?>
421 + <?php if($wppm_subtask_can_delete){ ?>
422 + <a href="#" title="<?php echo esc_attr__('Convert to Task','taskbuilder'); ?>" onclick="wppm_convert_subtask_to_task(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($task_id) ?>,<?php echo esc_attr($proj_id) ?>);return false;" style="font-size:11px;margin-right:8px;"><?php echo esc_html_e('Convert to Task','taskbuilder');?></a>
423 + <span onclick="wppm_delete_subtask(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($task_id) ?>,<?php echo esc_attr($proj_id) ?>)" style="cursor:pointer;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/trash.svg'); ?>" alt="delete"></span>
424 + <?php } ?>
425 + </div>
426 + </li>
427 + <?php
428 + }
429 + } ?>
430 + </ul>
431 + <?php if($wppm_can_add_subtask){
432 + $wppm_all_task_statuses = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wppm_task_statuses ORDER BY load_order ASC");
433 + ?>
434 + <div class="row">
435 + <div class="col-sm-12" style="padding-top:15px;">
436 + <a class="wppm_add_checklist" id="wppm_add_subtask_btn" onclick="wppm_show_add_subtask()"><?php echo esc_html_e('+ Add subtask','taskbuilder');?></a>
437 + </div>
438 + </div>
439 + <div class="row">
440 + <div class="col-sm-12" style="display:none;" id="wppm_add_subtask_label_container">
441 + <div class="row">
442 + <div class="wppm_task_frm_fields col-sm-6">
443 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Subtask Name','taskbuilder');?></b> <span style="color:#ff0000;">*</span></span><br>
444 + <input type="text" id="wppm_subtask_label" class="form-control" placeholder="<?php echo esc_attr__('Subtask name','taskbuilder') ?>" name="wppm_subtask_label">
445 + </div>
446 + <div class="wppm_task_frm_fields col-sm-6">
447 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Status','taskbuilder');?></b></span><br>
448 + <select id="wppm_subtask_status" name="wppm_subtask_status" class="form-control">
449 + <?php if(!empty($wppm_all_task_statuses)){
450 + foreach($wppm_all_task_statuses as $wppm_st){ ?>
451 + <option value="<?php echo esc_attr($wppm_st->id) ?>" <?php selected($wppm_st->id, $wppm_default_task_status); ?>><?php echo esc_html($wppm_st->name) ?></option>
452 + <?php }
453 + } ?>
454 + </select>
455 + </div>
456 + </div>
457 + <div class="row">
458 + <div class="wppm_task_frm_fields col-sm-6">
459 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Due date','taskbuilder');?></b></span><br>
460 + <input type="text" id="wppm_subtask_due_date" class="form-control" name="wppm_subtask_due_date" value="" autocomplete="off">
461 + </div>
462 + <div class="wppm_task_frm_fields col-sm-6">
463 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Assignee','taskbuilder');?></b></span><br>
464 + <input class="form-control wppm_subtask_assign_users ui-autocomplete-input" name="wppm_subtask_assign_users" type="text" autocomplete="off" placeholder="<?php echo esc_attr__('Search User...','taskbuilder');?>">
465 + </div>
466 + </div>
467 + <div class="row">
468 + <div class="col-sm-12">
469 + <ul class="wppm_subtask_filter_display_users_container" style="list-style:none;padding-left:0;"></ul>
470 + </div>
471 + </div>
472 + <div class="row">
473 + <div class="wppm_task_frm_fields col-sm-12">
474 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Description','taskbuilder');?></b></span><br>
475 + <textarea id="wppm_subtask_description" name="wppm_subtask_description" class="form-control" rows="3"></textarea>
476 + </div>
477 + </div>
478 + <div class="row" style="padding-top:10px;">
479 + <div class="col-sm-12">
480 + <input type="button" value="<?php echo esc_attr__('Add','taskbuilder') ?>" class="btn btn-success btn-sm" onclick="wppm_add_new_subtask(<?php echo esc_attr($task_id)?>,<?php echo esc_attr($proj_id) ?>)">
481 + <button type="button" class="wppm_reset_btn" onclick="wppm_hide_add_subtask()"><?php echo esc_html_e('Cancel','taskbuilder');?></button>
482 + </div>
483 + </div>
484 + </div>
485 + </div>
486 + <script type="text/javascript">
487 + jQuery(document).ready(function(){
488 + jQuery('#wppm_subtask_due_date').flatpickr({
489 + enableTime: true,
490 + dateFormat: "Y-m-d H:i"
491 + });
492 + jQuery('.wppm_subtask_assign_users').autocomplete({
493 + minLength: 1,
494 + appendTo: jQuery('.wppm_subtask_assign_users').parent(),
495 + source: function(request, response){
496 + jQuery.getJSON(wppm_admin.ajax_url, {
497 + action: 'wppm_filter_autocomplete',
498 + term: request.term,
499 + field: 'task_users_by_project_name',
500 + proj_id: <?php echo (int) $task->project; ?>
501 + }, function(data){ response(data); });
502 + },
503 + select: function(event, ui){
504 + if(!ui.item.user_id){ return false; }
505 + var html_str = '<li class="wppm_filter_display_element" style="list-style:none">'
506 + +'<div class="flex-container">'
507 + +'<div class="wppm_filter_display_text">'
508 + + ui.item.label
509 + + '<input type="hidden" name="wppm_subtask_user_names[]" value="'+ui.item.user_id+'">'
510 + +'</div>'
511 + +'<div class="wppm_filter_display_remove" onclick="wppm_remove_subtask_user(this);"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cross.svg'); ?>" alt="delete"></div>'
512 + +'</div>'
513 + +'</li>';
514 + jQuery('.wppm_subtask_filter_display_users_container').append(html_str);
515 + jQuery(this).val('');
516 + return false;
517 + }
518 + }).focus(function(){ jQuery(this).autocomplete("search", ""); });
519 + });
520 + </script>
521 + <?php } ?>
522 + </div>
523 + <?php } ?>
333 524 <div class="wppm_task_checklist_container" id="wppm_task_checklist_container">
334 525 <div id="wppm_checklist_container">
335 526 <?php
336 527 if(!empty($wppm_checklist)){
@@ -337,9 +528,9 @@
337 528 foreach( $wppm_checklist as $key=>$list){
338 529 ?>
339 530 <div class="row">
340 531 <div class="col-sm-8">
341 - <span class="wppm_checklist_label"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/checklist.svg'); ?>" alt="checklist"><?php echo esc_html_e($list->checklist_name,'taskbuilder');?></span>
532 + <span class="wppm_checklist_label"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/checklist.svg'); ?>" alt="checklist"><?php echo isset($list->checklist_name) ? esc_html($list->checklist_name):"" ?></span>
342 533 </div>
343 534 <?php
344 535 $check_style = (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('edit_checklist',$task->id)) && $task->is_archived!=1)? "display:inline":"display:none"; ?>
345 536 <?php $disabled = (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('delete_checklist',$task->id)|| ($wppmfunction->has_permission('add_checklist',0))) && $task->is_archived!=1)? "":"disabled"; ?>
@@ -358,10 +549,18 @@
358 549 <div id="CheckProgress_<?php echo esc_attr($list->id);?>" class="wppm_checkprogress" role="progressbar" style="width: 0%" aria-valuemin="0" aria-valuemax="100"></div>
359 550 </div>
360 551 </div>
361 552 <?php
362 - $list_id = esc_sql($list->id);
363 - $wppm_checklist_items = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist_items where checklist_id='$list_id' ORDER BY load_order ASC");
553 + $list_id = absint($list->id);
554 + $sql = $wpdb->prepare(
555 + "SELECT *
556 + FROM {$wpdb->prefix}wppm_checklist_items
557 + WHERE checklist_id = %d
558 + ORDER BY load_order ASC",
559 + $list_id
560 + );
561 + // Execute
562 + $wppm_checklist_items = $wpdb->get_results($sql);
364 563 ?>
365 564 <ul id="wppm_checklist_items_container_<?php echo esc_attr($list->id) ?>" class="wppm_checklist_items_container" style="list-style-type: none; padding-left:0px; margin-top:10px; margin-bottom:10px;">
366 565 <?php
367 566 if(!empty( $wppm_checklist_items)){
@@ -370,9 +569,9 @@
370 569 ?>
371 570 <li id="wppm_checklist_<?php echo esc_attr($val->id) ?>" data-id="<?php echo esc_attr($val->id); ?>" class="row wppm_checklist_item" style="margin-bottom:10px;font: 15px 'Helvetica Neue',Helvetica,Arial,sans-serif;">
372 571 <div class="col-sm-8" id="wppm_checklist_item_container_<?php echo esc_attr($val->id) ?>">
373 572 <span class="wppm_chk_items_drag">☰</span>
374 - <input id="wppm_checklist_item_<?php echo esc_attr($val->id) ?>" class="wppm_checklist_item_<?php echo esc_attr($val->checklist_id) ?>" onchange="wppm_checklist_progress(<?php echo esc_attr($val->checklist_id) ?>,<?php echo esc_attr($val->id) ?>,<?php echo esc_attr($task->id) ?>)" type="checkbox" name="wppm_checklist" <?php echo esc_attr($checked) ?> value="<?php echo esc_attr($val->id) ?>" <?php echo esc_attr($disabled) ?> style="margin:5px;"><label style="padding-top: 5px;font-weight: normal;font: 13px 'Helvetica Neue',Helvetica,Arial,sans-serif;"><?php echo esc_html_e($val->item_name,'taskbuilder') ?></label>
573 + <input id="wppm_checklist_item_<?php echo esc_attr($val->id) ?>" class="wppm_checklist_item_<?php echo esc_attr($val->checklist_id) ?>" onchange="wppm_checklist_progress(<?php echo esc_attr($val->checklist_id) ?>,<?php echo esc_attr($val->id) ?>,<?php echo esc_attr($task->id) ?>)" type="checkbox" name="wppm_checklist" <?php echo esc_attr($checked) ?> value="<?php echo esc_attr($val->id) ?>" <?php echo esc_attr($disabled) ?> style="margin:5px;"><label style="padding-top: 5px;font-weight: normal;font: 13px 'Helvetica Neue',Helvetica,Arial,sans-serif;"><?php echo isset($val->item_name) ? esc_html($val->item_name) : "" ?></label>
375 574 <input type="hidden" name="wppm_checklist_progress_ajax_nonce" id="wppm_checklist_progress_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_set_checklist_progress' ) ); ?>">
376 575 </div>
377 576 <?php if (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('delete_checklist',$task->id)) && $task->is_archived!=1) { ?>
378 577 <div class="col-sm-4" id="wppm_checklist_action_<?php echo esc_attr($val->id) ?>" style="text-align:right; display:none;cursor:pointer;">
@@ -413,28 +612,30 @@
413 612 <?php
414 613 }
415 614 } ?>
416 615 </div><?php
417 - if(($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')) && $task->is_archived!=1){ ?>
418 - <div id="wppm_add_checklist_container">
419 - <div class="row">
420 - <div class="col-sm-12">
421 - <span id="wppm_add_checklist" onclick="wppm_add_checklist()"> <?php echo esc_html_e('+Add a checklist','taskbuilder')?> </span>
616 + if($user_role != 3){
617 + if(($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')) && $task->is_archived!=1){ ?>
618 + <div id="wppm_add_checklist_container">
619 + <div class="row">
620 + <div class="col-sm-12">
621 + <span id="wppm_add_checklist" onclick="wppm_add_checklist()"> <?php echo esc_html_e('+Add a checklist','taskbuilder')?> </span>
622 + </div>
422 623 </div>
423 - </div>
424 - <div class="row" id="wppm_add_new_checklist" style="display:none;">
425 - <div class="col-sm-12">
426 - <input type="text" class="wppm_checklist_label" placeholder="<?php echo esc_attr__('Please insert checklist title','taskbuilder');?>" id="wppm_checklist_label" name="wppm_checklist_label">
427 - <input type="button" value="Add" id="wppm_checklist_btn" class="btn btn-success btn-sm" onclick="wppm_add_new_checklist(<?php echo esc_attr($id)?>,<?php echo esc_attr($proj_id) ?>)">
428 - <input type="hidden" name="wppm_checklist_ajax_nonce" id="wppm_checklist_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_add_new_checklist' ) ); ?>">
429 - <span onclick="wppm_remove_add_checklist()"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cross1.svg'); ?>"></span>
624 + <div class="row" id="wppm_add_new_checklist" style="display:none;">
625 + <div class="col-sm-12">
626 + <input type="text" class="wppm_checklist_label" placeholder="<?php echo esc_attr__('Please insert checklist title','taskbuilder');?>" id="wppm_checklist_label" name="wppm_checklist_label">
627 + <input type="button" value="Add" id="wppm_checklist_btn" class="btn btn-success btn-sm" onclick="wppm_add_new_checklist(<?php echo esc_attr($id)?>,<?php echo esc_attr($proj_id) ?>)">
628 + <input type="hidden" name="wppm_checklist_ajax_nonce" id="wppm_checklist_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_add_new_checklist' ) ); ?>">
629 + <span onclick="wppm_remove_add_checklist()"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cross1.svg'); ?>"></span>
630 + </div>
430 631 </div>
431 - </div>
432 - </br>
433 - </div><?php
434 - } ?>
632 + </br>
633 + </div><?php
634 + }
635 + }?>
435 636 </div>
436 - <div id="wppm_activity_container" style="<?php echo ($wppm_task_hide_comment_section==0) ? 'display:none;' : 'display:block;' ?>">
637 + <div id="wppm_activity_container" style="<?php echo ($wppm_task_hide_comment_section==0 || $user_role==3) ? 'display:none;' : 'display:block;' ?>">
437 638 <div class="row">
438 639 <div class="col-sm-12" style="margin-top:5px;">
439 640 <span class="wppm_task_discussion"><?php echo esc_html_e('Comment','taskbuilder')?></span><br>
440 641 </div>
@@ -462,18 +663,25 @@
462 663 <div class="wppm_attachment_container col-sm-12" style="display:none;">
463 664 </div>
464 665 </div>
465 666 </div>
466 - <div class="wppm_thread_container" style="<?php echo ($wppm_task_hide_comment_section==0) ? 'display:none;' : 'display:block;' ?>">
667 + <div class="wppm_thread_container" style="<?php echo ($wppm_task_hide_comment_section==0 || $user_role==3) ? 'display:none;' : 'display:block;' ?>">
467 668 <?php
468 669 if(!empty($task_comment)){
469 670 foreach($task_comment as $comment){
470 - $task_comment_meta = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_comment_meta where task_id='".esc_sql($id)."' AND comment_id='".esc_sql($comment->id)."'");
671 + $task_comment_meta = $wpdb->get_row( $wpdb->prepare(
672 + "SELECT *
673 + FROM {$wpdb->prefix}wppm_task_comment_meta
674 + WHERE task_id = %d
675 + AND comment_id = %d",
676 + absint($id),
677 + absint($comment->id)
678 + )
679 + );
471 680 $user = get_userdata( $comment->created_by );
472 - $comment_body = stripslashes((htmlspecialchars_decode($comment->body, ENT_QUOTES)));
473 - $comment_body = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $comment_body);
474 - $date = date("Y-m-d H:i:s" ,strtotime($comment->create_time));
475 - $thread_date = date("d F Y, h:i:s A" ,strtotime($date));
681 + $comment_body = (!empty($comment->body) ? ($comment->body) : '');
682 + $date = wp_date("Y-m-d H:i:s" ,strtotime($comment->create_time));
683 + $thread_date = wp_date("d F Y, h:i:s A" ,strtotime($date));
476 684 $attachment_ids = isset($comment->attachment_ids)? $comment->attachment_ids : '';
477 685 if($attachment_ids!=""){
478 686 $attachments = explode(",",$attachment_ids);
479 687 } else {
@@ -485,22 +693,30 @@
485 693 <?php echo (get_avatar($comment->created_by, 40));?>
486 694 </div>
487 695 <div class="wppm_thread_body">
488 696 <div class="wppm_thread_user_name">
489 - <strong style="color:<?php echo esc_attr($appearance_settings['comment-primary-color']);?>"><?php echo esc_html($user->display_name) ?></strong>
697 + <strong style="color:<?php echo esc_attr($appearance_settings['comment-primary-color']);?>"><?php echo isset($user->display_name) ? esc_html($user->display_name) : '' ?></strong>
490 698 <span><?php if(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_status')){
491 699 $comment_log_body = unserialize($comment->body);
492 700 $prev_status = $comment_log_body['prev_status'];
493 701 $new_status = $comment_log_body['new_status'];
494 702 if(isset($prev_status)){
495 - $prev_status = esc_sql($prev_status);
496 - $task_prev_status = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id='$prev_status'");
703 + $task_prev_status = $wpdb->get_row( $wpdb->prepare(
704 + "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id = %d",
705 + absint($prev_status)
706 + ));
497 707 }
498 708 if(isset($new_status)){
499 - $new_status = esc_sql($new_status);
500 - $task_new_status = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id='$new_status'");
709 + $task_new_status = $wpdb->get_row( $wpdb->prepare(
710 + "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id = %d",
711 + absint($new_status)
712 + ));
501 713 }
502 - esc_html_e("changed status from $task_prev_status->name to $task_new_status->name","taskbuilder");
714 + printf(
715 + esc_html__( 'Changed status from %1$s to %2$s', 'taskbuilder' ),
716 + esc_html( $task_prev_status->name ),
717 + esc_html( $task_new_status->name )
718 + );
503 719 } if(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_creator')){
504 720 $comment_log_body = unserialize($comment->body);
505 721 $prev_user = $comment_log_body['prev_user'];
506 722 $new_user = $comment_log_body['new_user'];
@@ -505,9 +721,13 @@
505 721 $prev_user = $comment_log_body['prev_user'];
506 722 $new_user = $comment_log_body['new_user'];
507 723 $prev_user_data = get_userdata($prev_user);
508 724 $new_user_data = get_userdata($new_user);
509 - esc_html_e("changed creator from $prev_user_data->display_name to $new_user_data->display_name","taskbuilder");
725 + printf(
726 + esc_html__( 'Changed creator from %1$s to %2$s', 'taskbuilder' ),
727 + esc_html( $prev_user_data->display_name ),
728 + esc_html( $new_user_data->display_name )
729 + );
510 730 }
511 731 if( !empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_assign_user')){
512 732 esc_html_e("changed the Assignee","taskbuilder");
513 733 }
@@ -515,21 +735,31 @@
515 735 $comment_log_body = unserialize($comment->body);
516 736 $prev_prio = $comment_log_body['prev_prio'];
517 737 $new_prio = $comment_log_body['new_prio'];
518 738 if(isset($prev_prio)){
519 - $prev_prio = esc_sql($prev_prio);
520 - $task_prev_prio = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id= '$prev_prio'");
739 + $prev_prio = absint($prev_prio);
740 + $task_prev_prio = $wpdb->get_row( $wpdb->prepare(
741 + "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id = %d",
742 + $prev_prio
743 + ));
521 744 }
522 745 if(isset($new_prio)){
523 - $new_prio = esc_sql($new_prio);
524 - $task_new_prio = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id= '$new_prio'");
746 + $new_prio = absint($new_prio);
747 + $task_new_prio = $wpdb->get_row( $wpdb->prepare(
748 + "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id = %d",
749 + $new_prio
750 + ));
525 751 }
526 752 $task_prev_prio_name = !empty($task_prev_prio) ? $task_prev_prio->name: "None";
527 753 $task_new_prio_name = !empty($task_new_prio) ? $task_new_prio->name: "None";
528 - esc_html_e("changed priority from $task_prev_prio_name to $task_new_prio_name","taskbuilder");
754 + printf(
755 + esc_html__( 'Changed priority from %1$s to %2$s', 'taskbuilder' ),
756 + esc_html( $task_prev_prio_name ),
757 + esc_html( $task_new_prio_name )
758 + );
529 759 }
530 760 ?>
531 - <small class="wppm_comment_date" style="color:<?php echo esc_attr($appearance_settings['comment-date-color']);?>"><i><?php echo esc_html($thread_date) ?></i></small>
761 + <small class="wppm_comment_date" style="color:<?php echo esc_attr($appearance_settings['comment-date-color']);?>"><i><?php echo isset($thread_date) ? esc_html($thread_date) : '' ?></i></small>
532 762 <div class="wppm_thread_action">
533 763 <?php if((((($current_user->has_cap('manage_options')) || ($wppmfunction->has_comment_permission('edit_task_comment',$id,$comment->id))) && ((empty($task_comment_meta->comment_type)) || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='comment')))) && ($task->is_archived!=1)){ ?>
534 764 <span title="Edit this thread" onclick="wppm_edit_thread(<?php echo esc_attr($comment->id)?>,<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit1.svg'); ?>" alt="edit"></span>
535 765 <span title="Delete this thread" onclick="wppm_delete_thread(<?php echo esc_attr($comment->id) ?>,<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/trash.svg'); ?>" alt="delete"></span>
@@ -537,11 +767,16 @@
537 767 </div>
538 768 </div>
539 769 <div class="wppm_thread_messege" style="color:<?php echo esc_attr($appearance_settings['comment-secondary-color']);?>">
540 770 <?php
541 - $allowedtags = array( 'br' => array(), 'abbr' => array('title' => array(),), 'p' => array(), 'strong' => array(), 'a' => array('href' => array(), 'title' => array(), 'target'=> array(), 'rel'=>array()),'em' =>array(),'span' =>array(), 'blockquote'=>array('cite' => array(),),'div' => array('class' => array(),'title' => array(),'style' => array(),),'ul'=>array(),'li'=>array(),'ol'=>array(),'img' => array( 'alt'=> array(),'class' => array(),'height' => array(),'src'=> array(),'width'=> array(),));
771 + $allowedtags = array( 'br' => array(), 'abbr' => array('title' => array(),), 'p' => array(), 'strong' => array(), 'a' => array('href' => array(), 'title' => array(), 'target'=> array(), 'rel'=>array()),'em' =>array(),'span' =>array('class' => true,
772 + 'data-user-id' => true,'data-username' => true,), 'blockquote'=>array('cite' => array(),),'div' => array('class' => array(),'title' => array(),'style' => array(),),'ul'=>array(),'li'=>array(),'ol'=>array(),'img' => array( 'alt'=> array(),'class' => array(),'height' => array(),'src'=> array(),'width'=> array(),));
542 773 if(!empty($comment_body) && ((empty($task_comment_meta->comment_type)) || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='comment') || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='delete_task_comment'))){
543 - echo wp_kses(wpautop($comment_body),$allowedtags) ;
774 + $comment_body = $wppmfunction->wppm_clean_mentions_html($comment_body);
775 + $comment_body = $wppmfunction->wppm_highlight_user_mentions($comment_body, $current_user->ID);
776 + //echo wp_kses(wpautop($comment_body),$allowedtags);
777 + //wp_kses($comment, $allowed_tags);
778 + echo wp_kses_post(($comment_body));
544 779 } elseif(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_status')){ ?>
545 780 <span class="wppm_admin_label" style="margin-right: 10px; background-color:<?php echo isset($task_prev_status->bg_color) ? esc_attr($task_prev_status->bg_color):""; ?>;color:<?php echo isset($task_prev_status->color) ? esc_attr($task_prev_status->color): "" ?>;"><?php echo isset($task_prev_status->name) ? esc_attr($task_prev_status->name) : "" ?></span> <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/arrow-right.svg'); ?>" alt="arrow_right"> <span class="wppm_admin_label" style="margin-left:10px; background-color:<?php echo isset($task_new_status->bg_color) ? esc_attr($task_new_status->bg_color):""; ?>;color:<?php echo isset($task_new_status->color) ? esc_attr($task_new_status->color): "" ?>;"><?php echo isset($task_new_status->name) ? esc_attr($task_new_status->name) : "" ?></span><?php
546 781 }elseif(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_creator')){ ?>
547 782 <span style="margin-right: 10px;"><?php echo isset($prev_user_data->display_name) ? esc_attr($prev_user_data->display_name) : "" ?></span> <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/arrow-right.svg'); ?>" alt="arrow_right"> <span style="margin-left:10px;"><?php echo isset($new_user_data->display_name) ? esc_attr($new_user_data->display_name) : "" ?></span><?php
@@ -590,10 +825,13 @@
590 825 <?php
591 826 if(!empty($attachments)){
592 827 foreach( $attachments as $attachment ):
593 828 $download_url = site_url('/').'?wppm_attachment='.$attachment.'&tid='.$id.'&tac='.$auth_id;
594 - $attachment = esc_sql($attachment);
595 - $attach = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_attachments where id='$attachment'");
829 + $attachment = absint($attachment);
830 + if (empty($attachment)) {
831 + continue; // or return, depending on the context
832 + }
833 + $attach = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_attachments where id=%d",$attachment));
596 834 $findStr = ".txt";
597 835 if(!empty( $attach)){
598 836 $attachment_name = preg_replace('/' . $findStr . '/', "", $attach->name, 1);
599 837 $attachment_name = sanitize_file_name($attachment_name);
@@ -604,9 +842,9 @@
604 842 <td>
605 843 <a class="wppm_attachment_link" href="<?php echo esc_url($download_url) ?>" target="_blank">
606 844 <span class="wppm_attachment_file_name" style="padding: 7px;"><?php echo isset($attach->file_name) ? esc_html($attach->file_name):"";?></span></a>
607 845 <?php if((($comment->created_by == $current_user->ID) || ($current_user->has_cap('manage_options')) || ($wppmfunction->has_comment_permission('edit_task_comment',$id,$comment->id))) && ($task->is_archived!=1)){ ?>
608 - <span class="wppm_thread_action_btn" onclick="wppm_thread_attachment_remove(this,<?php echo esc_attr($attach->id); ?>,<?php echo esc_attr($comment->id); ?>,<?php echo esc_attr($id); ?>,<?php echo esc_attr($proj_id);?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cancel.svg'); ?>" alt="cancel"></span>
846 + <span class="wppm_thread_action_btn" onclick="wppm_thread_attachment_remove(this,<?php echo !empty($attach->id) ? esc_attr($attach->id) : 0; ?>,<?php echo !empty($comment->id) ? esc_attr($comment->id) : 0; ?>,<?php echo !empty($id) ? esc_attr($id) : 0; ?>,<?php echo !empty($proj_id) ? esc_attr($proj_id) : 0;?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cancel.svg'); ?>" alt="cancel"></span>
609 847 <?php } ?>
610 848 </td>
611 849 </tr>
612 850 <input type="hidden" name="wppm_ajax_nonce" id="wppm_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_remove_thread_attachment' ) ); ?>">
@@ -627,12 +865,14 @@
627 865 <div class="row wppm_widget" id="wppm_status_widget">
628 866 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
629 867 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>"><?php echo esc_html_e('Status','taskbuilder')?></h4>
630 868 <?php
631 - if((($current_user->has_cap('manage_options') || $wppm_current_user_capability == ('wppm_admin') || ($flag==true) || ($wppmfunction->has_permission('change_task_status',$id))!="") && ($task->is_archived!=1))){
632 - ?>
633 - <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_status(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
634 - <?php
869 + if($user_role != 3){
870 + if((($current_user->has_cap('manage_options') || $wppm_current_user_capability == ('wppm_admin') || ($flag==true) || ($wppmfunction->has_permission('change_task_status',$id))!="") && ($task->is_archived!=1))){
871 + ?>
872 + <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_status(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
873 + <?php
874 + }
635 875 }
636 876 ?>
637 877 </div>
638 878 <hr class="widget_divider">
@@ -643,11 +883,13 @@
643 883 <div class="row wppm_widget" id="wppm_raisedby_widget">
644 884 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
645 885 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>">
646 886 <?php echo esc_html_e('Task Creator','taskbuilder')?></h4>
647 - <?php if ((($wppmfunction->has_permission('change_raised_by',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
648 - <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_creator(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
649 - <?php } ?>
887 + <?php if($user_role != 3){
888 + if ((($wppmfunction->has_permission('change_raised_by',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
889 + <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_creator(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
890 + <?php }
891 + }?>
650 892 </div>
651 893 <hr class="widget_divider"> <?php
652 894 if(isset($task->created_by)){
653 895 $user_info = get_userdata($task->created_by);
@@ -664,11 +906,14 @@
664 906 </div>
665 907 <div class="row wppm_widget" id="wppm_task_users_widget_container">
666 908 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
667 909 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>;"><?php echo esc_html_e('Users','taskbuilder')?></h4>
668 - <?php if ((($wppmfunction->has_permission('assign_task_users',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
669 - <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_users(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
670 - <?php } ?>
910 + <?php
911 + if($user_role != 3){
912 + if ((($wppmfunction->has_permission('assign_task_users',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
913 + <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_users(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
914 + <?php }
915 + }?>
671 916 </div>
672 917 <hr class="widget_divider">
673 918 <div class="wppm-widget-body" style="background-color:<?php echo esc_attr($appearance_settings['widget-body-bg-color'])?>">
674 919 <div id="wppm_task_users">
@@ -699,9 +944,9 @@
699 944 </div>
700 945 </div>
701 946 <?php do_action('wppm_after_task_widgets',$id,$task_id );?>
702 947 </div>
703 - <input type="hidden" id="wppm_nonce" value="<?php echo wp_create_nonce('wppm_upload_file')?>">
948 + <input type="hidden" id="wppm_nonce" value="<?php echo esc_attr(wp_create_nonce('wppm_upload_file'))?>">
704 949 <input type="file" id="wppm_attachment_upload" class="hidden" onchange="">
705 950 </div>
706 951 </form>
707 952 <style>
@@ -731,8 +976,11 @@
731 976 // Hide when clicking outside
732 977 document.addEventListener('click', () => {
733 978 box.style.display = 'none';
734 979 });
980 + jQuery('#wppm_task_comment').on('focus', function(){
981 + // showMentionList('');
982 + });
735 983 <?php
736 984 if ((($current_user->ID && $current_user->has_cap('manage_options')) || $wppmfunction->has_permission('change_task_details',$task->id))){ ?>
737 985 jQuery("#wppm_edit_tstart_date").flatpickr({
738 986 enableTime: true,
@@ -777,9 +1025,9 @@
777 1025 jQuery('#CheckProgress_'+<?php echo esc_attr($chklist->id);?>).css('width', progressWidth + '%');
778 1026 if(progressWidth>0){
779 1027 jQuery('#wppm_progressbar_label_'+<?php echo esc_attr($chklist->id);?>).text(progressWidth+'%');
780 1028 }
781 - <?php $wppm_checklist_items = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist_items where checklist_id=".$chklist->id);
1029 + <?php $wppm_checklist_items = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_checklist_items where checklist_id=%d",$chklist->id));
782 1030 foreach ($wppm_checklist_items as $chkitems) {
783 1031 ?> jQuery( '#wppm_checklist_'+<?php echo esc_attr($chkitems->id);?>).on("mouseover", function () {
784 1032 jQuery( '#wppm_checklist_action_'+<?php echo esc_attr($chkitems->id);?>).css("display","inline");
785 1033 jQuery( '#wppm_checklist_'+<?php echo esc_attr($chkitems->id);?>).css("background-color","#e7e8ea");
@@ -795,47 +1043,59 @@
795 1043 $italic = (isset($wppm_toolbar_actions['italic']) && $wppm_toolbar_actions['italic']==1)? 'italic' :"";
796 1044 $underline = (isset($wppm_toolbar_actions['underline']) && $wppm_toolbar_actions['underline']==1)?'underline' :"";
797 1045 $blockquote = (isset($wppm_toolbar_actions['blockquote']) && $wppm_toolbar_actions['blockquote']==1)? 'blockquote' :"";
798 1046 $align = (isset($wppm_toolbar_actions['align']) && $wppm_toolbar_actions['align']==1)? ' alignleft aligncenter alignright ' :"";
799 - $bullist = (isset($wppm_toolbar_actions['bullist']) && $wppm_toolbar_actions['bullist']==1)? $bullist = 'bullist' :"";
800 - $numlist = (isset($wppm_toolbar_actions['numlist']) && $wppm_toolbar_actions['numlist']==1)? $numlist = 'numlist' :"";
801 - $rtl = (isset($wppm_toolbar_actions['rtl']) && $wppm_toolbar_actions['rtl']==1)? $rtl = 'rtl' :"";
802 - $link = (isset($wppm_toolbar_actions['link']) && $wppm_toolbar_actions['link']==1)? $link = 'link' :"";
803 - $image = (isset($wppm_toolbar_actions['wppm_insert_editor_img']) && $wppm_toolbar_actions['wppm_insert_editor_img']==1)? $image = 'image' :"";
804 - $forecolor = (isset($wppm_toolbar_actions['forecolor']) && $wppm_toolbar_actions['forecolor']==1)? $forecolor = 'forecolor' :"";
805 - $backcolor = (isset($wppm_toolbar_actions['backcolor']) && $wppm_toolbar_actions['backcolor']==1)? $backcolor = 'backcolor' :"";
806 - $strikethrough = (isset($wppm_toolbar_actions['strikethrough']) && $wppm_toolbar_actions['strikethrough']==1)? $strikethrough = 'strikethrough' :"";
807 - if(($wppm_tinymce_visibility_open_task==1)){
808 - if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){
809 - ?>
810 - tinymce.remove();
811 - tinymce.init({
1047 + $bullist = (isset($wppm_toolbar_actions['bullist']) && $wppm_toolbar_actions['bullist']==1)? 'bullist' :"";
1048 + $numlist = (isset($wppm_toolbar_actions['numlist']) && $wppm_toolbar_actions['numlist']==1)? 'numlist' :"";
1049 + $rtl = (isset($wppm_toolbar_actions['rtl']) && $wppm_toolbar_actions['rtl']==1)? 'rtl' :"";
1050 + $link = (isset($wppm_toolbar_actions['link']) && $wppm_toolbar_actions['link']==1)? 'link' :"";
1051 + $image = (isset($wppm_toolbar_actions['wppm_insert_editor_img']) && $wppm_toolbar_actions['wppm_insert_editor_img']==1)? 'image' :"";
1052 + $forecolor = (isset($wppm_toolbar_actions['forecolor']) && $wppm_toolbar_actions['forecolor']==1)? 'forecolor' :"";
1053 + $backcolor = (isset($wppm_toolbar_actions['backcolor']) && $wppm_toolbar_actions['backcolor']==1)? 'backcolor' :"";
1054 + $strikethrough = (isset($wppm_toolbar_actions['strikethrough']) && $wppm_toolbar_actions['strikethrough']==1)? 'strikethrough' :"";
1055 + $toolbar = trim("$bold $italic $underline $blockquote | $align | $bullist $numlist | $rtl | $link $image | $forecolor $backcolor $strikethrough");
1056 + if(($wppm_tinymce_visibility_open_task==1)){ ?>
1057 + if((wppm_admin.rich_text_editor) && (wppm_admin.rich_text_editor.trim().length > 0) && (wppm_admin.rich_text_editor == 1)){
1058 + getMentionDropdown(editor);
1059 + tinymce.remove();
1060 + tinymce.init({
812 1061 selector:'#wppm_task_comment',
813 1062 body_id: 'wppm_task_comment',
814 - directionality : '<?php //echo 'rtl'; ?>',
815 1063 menubar: false,
816 1064 statusbar: false,
817 1065 height : '200',
818 1066 width : '100%',
819 - plugins: [
820 - 'lists link image directionality paste textcolor'
821 - ],
822 - image_advtab: true,
823 - toolbar: '<?php echo $bold ?> <?php echo $italic ?> <?php echo $underline ?> <?php echo $blockquote?> | <?php echo $align ?> | <?php echo $bullist ?> <?php echo $numlist ?> | <?php echo $rtl ?> | <?php echo $link ?> <?php echo $image ?> | <?php echo $forecolor?> <?php echo $backcolor?> <?php echo $strikethrough ?>',
824 - branding: false,
825 - autoresize_bottom_margin: 20,
826 - browser_spellcheck : true,
827 - relative_urls : false,
828 - remove_script_host : false,
829 - convert_urls : true,
830 - paste_as_text: true,
1067 + plugins: ['lists link image directionality paste textcolor'],
1068 + valid_elements: '*[*]',
1069 + extended_valid_elements: 'span[class|data-username|data-user-id|,p,br,strong,em,a[href|target]contenteditable]',
1070 + toolbar:'<?php echo esc_js($toolbar); ?>',
1071 + content_style: `
1072 + .wppm-mention{
1073 + display:inline-block;
1074 + background:linear-gradient(135deg,#eef2ff,#e0e7ff);
1075 + color:#5b21b6;
1076 + padding:2px 8px;
1077 + border-radius:16px;
1078 + font-weight:600;
1079 + border:1px solid #c7d2fe;
1080 + }
1081 +
1082 + .wppm-mention-me{
1083 + background:linear-gradient(135deg,#fef3c7,#fde68a);
1084 + color:#92400e;
1085 + border:1px solid #fbbf24;
1086 + font-weight:700;
1087 + }
1088 + `
831 1089 setup: function (editor) {
1090 + wppmmenwppmMentionSetup(editor)
1091 +
1092 + } // ✅ only ONE setup
1093 + });
1094 + jQuery('#wppm_comment_btn').show();
832 1095 }
833 - });
834 - jQuery('#wppm_comment_btn').show();
835 - <?php } ?>
836 - <?php } ?>
837 -});
1096 + <?php } ?>
1097 + });
838 1098
839 1099 jQuery(function(jQuery){
840 1100 // Checklist Sorting
841 1101 jQuery(".wppm_checklist_items_container").sortable({
@@ -887,54 +1147,64 @@
887 1147 <?php }?>
888 1148 }
889 1149
890 1150 function wppm_add_task_comment(){
891 - <?php
892 - if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){
893 - ?>
894 - tinymce.remove();
895 - tinymce.init({
896 - selector:'#wppm_task_comment',
897 - body_id: 'wppm_task_comment',
898 - directionality : '<?php //echo 'rtl'; ?>',
899 - menubar: false,
900 - statusbar: false,
901 - height : '200',
902 - width : '100%',
903 - plugins: [
904 - 'lists link image directionality paste textcolor'
905 - ],
906 - image_advtab: true,
907 - toolbar: '<?php echo $bold ?> <?php echo $italic ?> <?php echo $underline ?> <?php echo $blockquote?> | <?php echo $align ?> | <?php echo $bullist ?> <?php echo $numlist ?> | <?php echo $rtl ?> | <?php echo $link ?> <?php echo $image ?> | <?php echo $forecolor?> <?php echo $backcolor?> <?php echo $strikethrough ?>',
908 - branding: false,
909 - autoresize_bottom_margin: 20,
910 - browser_spellcheck : true,
911 - relative_urls : false,
912 - remove_script_host : false,
913 - convert_urls : true,
914 - paste_as_text: true,
915 - setup: function (editor) {
916 - }
917 - });
918 - <?php } else{ ?>
1151 + if((wppm_admin.rich_text_editor == 1)){
1152 + tinymce.remove();
1153 + tinymce.init({
1154 + selector:'#wppm_task_comment',
1155 + body_id: 'wppm_task_comment',
1156 + directionality : '<?php //echo 'rtl'; ?>',
1157 + menubar: false,
1158 + statusbar: false,
1159 + height : '200',
1160 + width : '100%',
1161 + plugins: [
1162 + 'lists link image directionality paste textcolor'
1163 + ],
1164 + image_advtab: true,
1165 + toolbar:'<?php echo esc_js( $toolbar ); ?>',
1166 + branding: false,
1167 + autoresize_bottom_margin: 20,
1168 + browser_spellcheck : true,
1169 + relative_urls : false,
1170 + remove_script_host : false,
1171 + convert_urls : true,
1172 + paste_as_text: true,
1173 + setup: function (editor) {
1174 + wppmMentionSetup(editor);
1175 + }
1176 + });
1177 + } else{
919 1178 jQuery('#wppm_task_comment').css("width", "100%");
920 1179 jQuery('#wppm_task_comment').css("height", "160px");
921 1180 jQuery('#wppm_task_comment').css("color", "#000");
922 - <?php }?>
1181 + }
923 1182 jQuery('#wppm_comment_btn').show();
924 1183 }
925 1184
926 -function wppm_submit_task_comment(id,proj_id){
1185 +function wppm_submit_task_comment(id, proj_id){
1186 + jQuery('#wppm_mention_list').remove();
927 1187 var dataform = new FormData(jQuery('#wppm_open_task')[0]);
928 1188 dataform.append('action','wppm_submit_task_comment');
929 - <?php
930 - if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){ ?>
931 - var comment_body = tinyMCE.get('wppm_task_comment').getContent().trim();
932 - <?php } else{ ?>
933 - var comment_body = jQuery("#wppm_task_comment").val();
934 - <?php }?>
935 - dataform.append('comment_body',comment_body);
936 - dataform.append('task_id',id);
1189 + let comment_body;
1190 + if(wppm_admin.rich_text_editor == 1){
1191 + const editor = tinyMCE.get('wppm_task_comment');
1192 + // Remove dropdown from TinyMCE iframe
1193 + const dropdown = editor.getDoc().getElementById('wppm_mention_list');
1194 + if (dropdown) {
1195 + dropdown.remove();
1196 + }
1197 + comment_body = editor.getContent().trim();
1198 + //comment_body = tinyMCE.get('wppm_task_comment').getContent().trim();
1199 + // remove mention dropdown if accidentally inserted
1200 + //comment_body = comment_body.replace(/<div[^>]*id="wppm_mention_list"[^>]*>.*?<\/div>/gi, '');
1201 + comment_body = comment_body.replace( /<div class="mention-item"[\s\S]*?<\/div>/g, '');
1202 + } else {
1203 + comment_body = jQuery("#wppm_task_comment").val();
1204 + }
1205 + dataform.append('comment_body', comment_body);
1206 + dataform.append('task_id', id);
937 1207 jQuery('#wppm_task_container').html(wppm_admin.loading_html);
938 1208 jQuery.ajax({
939 1209 url: wppm_admin.ajax_url,
940 1210 type: 'POST',
@@ -941,12 +1211,12 @@
941 1211 data: dataform,
942 1212 processData: false,
943 1213 contentType: false
944 1214 })
945 - .done(function (response_str) {
946 - if((proj_id!=0)||(proj_id!="")){
947 - wppm_open_project_tasks(id,proj_id);
948 - }else if((proj_id==0)||(proj_id=="")){
1215 + .done(function () {
1216 + if (proj_id != 0 && proj_id != "") {
1217 + wppm_open_project_tasks(id, proj_id);
1218 + } else {
949 1219 wppm_open_task(id);
950 1220 }
951 1221 });
952 1222 }
@@ -985,9 +1255,10 @@
985 1255 var file_extension = file_name_split[file_name_split.length-1];
986 1256 file_extension = file_extension.toLowerCase();
987 1257 if( (jQuery.inArray(file_extension,allowedExtension) > -1)){
988 1258 flag = true;
989 - alert("<?php _e('Attached file type not allowed!','taskbuilder')?>");
1259 + alert("<?php echo esc_js(__( 'Attached file type not allowed!', 'taskbuilder' ) ); ?>");
1260 +
990 1261 };
991 1262 <?php
992 1263 $max_upload = (int)(ini_get('upload_max_filesize')); ?>
993 1264 var current_filesize=file.size/1000000;
@@ -992,9 +1263,9 @@
992 1263 $max_upload = (int)(ini_get('upload_max_filesize')); ?>
993 1264 var current_filesize=file.size/1000000;
994 1265 if(current_filesize > <?php echo esc_attr($max_upload); ?>){
995 1266 flag = true;
996 - alert("<?php _e('File size exceed allowed limit!','taskbuilder')?>");
1267 + alert("<?php echo esc_js(__('File size exceed allowed limit!','taskbuilder')); ?>");
997 1268 }
998 1269 if (!flag){
999 1270 var html_str = '<div class="wppm_attachment">'+
1000 1271 '<div class="progress" style="float: none !important; width: unset !important;">'+
@@ -1041,6 +1312,227 @@
1041 1312 });
1042 1313 }
1043 1314 });
1044 1315 jQuery('#wppm_attachment_upload').trigger('click');
1316 +}
1317 +
1318 +function wppmMentionSetup(editor) {
1319 + let mentionIndex = -1;
1320 + editor.on('keyup', function (e) {
1321 + editor.lastMentionRange = editor.selection.getRng();
1322 + let rng = editor.selection.getRng();
1323 + let node = rng.startContainer;
1324 +
1325 + if (!node || node.nodeType !== 3) return;
1326 +
1327 + let text = node.textContent;
1328 + let cursorPos = rng.startOffset;
1329 + let textBeforeCursor = text.substring(0, cursorPos);
1330 +
1331 + let match = textBeforeCursor.match(/@(\w*)$/);
1332 + let dropdown = getMentionDropdown(editor);
1333 +
1334 + if (match) {
1335 + let query = match[1];
1336 + let rect = rng.getBoundingClientRect();
1337 + if (!rect || rect.top === 0) {
1338 + rect = editor.selection.getNode().getBoundingClientRect();
1339 + }
1340 + let top = rect.bottom + editor.getWin().scrollY;
1341 + let left = rect.left + editor.getWin().scrollX;
1342 + jQuery.post(wppm_admin.ajax_url, {
1343 + action: 'wppm_filter_autocomplete',
1344 + term: query,
1345 + field : 'task_user_name',
1346 + task_id:<?php echo esc_attr($task_id) ?>,
1347 + proj_id:<?php echo esc_attr($proj_id) ?>
1348 + }, function (res) {
1349 +
1350 + if (typeof res === "string") res = JSON.parse(res);
1351 + if (res.success) res = res.data;
1352 +
1353 + if (!Array.isArray(res)) return;
1354 +
1355 + dropdown.empty();
1356 + if( res.length === 0 ){
1357 + dropdown.hide();
1358 + return;
1359 + }else{
1360 + res.forEach(user => {
1361 + let item = jQuery('<div>')
1362 + .addClass('mention-item')
1363 + .attr('data-username', user.label)
1364 + .attr('data-user-id', user.user_id)
1365 + .text(user.label)
1366 + .css({
1367 + padding: '8px 12px',
1368 + cursor: 'pointer',
1369 + fontSize: '14px',
1370 + color: '#333',
1371 + background: '#fff',
1372 + borderBottom: '1px solid #eee'
1373 + });
1374 +
1375 + item.on('mouseenter', function () {
1376 + jQuery(this).css({
1377 + background: '#0073aa',
1378 + color: '#fff'
1379 + });
1380 + });
1381 + item.on('mouseleave', function () {
1382 + if (!jQuery(this).hasClass('active')) {
1383 + jQuery(this).css({
1384 + background: '#fff',
1385 + color: '#333'
1386 + });
1387 + }
1388 + });
1389 + dropdown.append(item);
1390 + });
1391 + let items = dropdown.find('.mention-item');
1392 + items.removeClass('active').css({
1393 + background: '#fff',
1394 + color: '#333'
1395 + });
1396 + items.eq(0)
1397 + .addClass('active')
1398 + .css({
1399 + background: '#0073aa',
1400 + color: '#fff'
1401 + });
1402 + mentionIndex = 0;
1403 + updateActiveItem(items.eq(0), mentionIndex);
1404 + dropdown.css({
1405 + position: 'absolute',
1406 + display: 'none',
1407 + background: '#fff',
1408 + border: '1px solid #ddd',
1409 + borderRadius: '6px',
1410 + padding: '5px 0',
1411 + minWidth: '180px',
1412 + maxHeight: '220px',
1413 + overflowY: 'auto',
1414 + boxShadow: '0 4px 10px rgba(0,0,0,.15)',
1415 + zIndex: 999999999999999
1416 + }).show();
1417 + }
1418 + });
1419 + } else {
1420 + dropdown.hide();
1421 + }
1422 + });
1423 + editor.on('keydown', function (e) {
1424 + let dropdown = getMentionDropdown(editor);
1425 + let items = dropdown.find('.mention-item');
1426 +
1427 + if (!dropdown.is(':visible') || !items.length) return;
1428 +
1429 + // DOWN
1430 + if (e.key === 'ArrowDown') {
1431 + e.preventDefault();
1432 + mentionIndex++;
1433 +
1434 + if (mentionIndex >= items.length) {
1435 + mentionIndex = 0;
1436 + }
1437 + updateActiveItem(items, mentionIndex);
1438 + items.removeClass('active').css({
1439 + background: '#fff',
1440 + color: '#333'
1441 + });
1442 +
1443 + items.eq(mentionIndex)
1444 + .addClass('active')
1445 + .css({
1446 + background: '#0073aa',
1447 + color: '#fff'
1448 + });
1449 + }
1450 +
1451 + // UP
1452 + if (e.key === 'ArrowUp') {
1453 + e.preventDefault();
1454 + mentionIndex--;
1455 + if (mentionIndex < 0) {
1456 + mentionIndex = items.length - 1;
1457 + }
1458 + updateActiveItem(items, mentionIndex);
1459 + items.removeClass('active').css({
1460 + background: '#fff',
1461 + color: '#333'
1462 + });
1463 +
1464 + items.eq(mentionIndex)
1465 + .addClass('active')
1466 + .css({
1467 + background: '#0073aa',
1468 + color: '#fff'
1469 + });
1470 + }
1471 + // ENTER
1472 + if (e.key === 'Enter') {
1473 + if (mentionIndex >= 0) {
1474 + e.preventDefault();
1475 + items.eq(mentionIndex).trigger('click');
1476 + }
1477 + }
1478 + // ESC
1479 + if (e.key === 'Escape') {
1480 + dropdown.hide();
1481 + mentionIndex = -1;
1482 + }
1483 + });
1484 + editor.on('click', function (e) {
1485 + let target = jQuery(e.target);
1486 + if (target.hasClass('mention-item')) {
1487 + let username = target.data('username');
1488 + let userId = target.data('user-id');
1489 +
1490 + editor.focus();
1491 +
1492 + let rng = editor.lastMentionRange || editor.selection.getRng();
1493 + editor.selection.setRng(rng);
1494 +
1495 + let node = rng.startContainer;
1496 + if (!node || node.nodeType !== 3) return;
1497 +
1498 + let text = node.textContent;
1499 + let cursorPos = rng.startOffset;
1500 +
1501 + let lastAtIndex = text.substring(0, cursorPos).lastIndexOf('@');
1502 +
1503 + if (lastAtIndex !== -1) {
1504 +
1505 + let range = editor.selection.getRng();
1506 + range.setStart(node, lastAtIndex);
1507 + range.setEnd(node, cursorPos);
1508 +
1509 + editor.selection.setRng(range);
1510 +
1511 + editor.selection.setContent(
1512 + '<span class="wppm-mention" contenteditable="false" data-username="' + username + '" data-user-id="' + userId + '">@' + username + '</span>&nbsp;'
1513 + );
1514 + }
1515 + getMentionDropdown(editor).hide();
1516 + }
1517 + });
1518 +
1519 + editor.on('blur', function () {
1520 + getMentionDropdown(editor).hide();
1521 + });
1522 +
1523 + editor.on('init', function () {
1524 + let body = editor.getBody();
1525 + if (!body) return;
1526 +
1527 + body.addEventListener('mousedown', function (e) {
1528 + if (e.target.classList.contains('mention-item')) {
1529 + e.preventDefault();
1530 + }
1531 + });
1532 + if (!editor.mentionDropdown) {
1533 + editor.mentionDropdown = jQuery('<div class="mention-dropdown"></div>');
1534 + jQuery('body').append(editor.mentionDropdown); // ✅ ONLY HERE
1535 + }
1536 + });
1045 1537 }
1046 1538 </script>