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/wppm_tasks_list.php +685 -132 5.0.36.0.6 View file →
@@ -3,17 +3,54 @@
3 3 exit; // Exit if accessed directly
4 4 }
5 5 global $current_user,$wpdb,$wppmfunction;
6 6 $task_per_page = 20;
7 -$page_no = isset($_POST['page_no']) ? intval(sanitize_text_field($_POST['page_no'])): '0';
8 -$search_tag = isset($_POST['task_search']) ? sanitize_text_field($_POST['task_search']) : '';
9 -$order = isset($_POST['order']) ? sanitize_text_field($_POST['order']) :"ASC";
10 -$sort_by = isset($_POST['sort_by']) ? sanitize_text_field($_POST['sort_by']):"task_name";
11 -$filter_by = isset($_POST['wppm_task_filter']) ? sanitize_text_field($_POST['wppm_task_filter']) : "all";
12 -$proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field($_POST['wppm_proj_filter']) : "0";
13 -$proj_attr = isset($_POST['wppm_project_attr']) ? sanitize_text_field($_POST['wppm_project_attr']):"";
14 -$public_projects = isset($_POST['public_projects']) ? sanitize_text_field($_POST['public_projects']):"0";
15 -$page = isset($_POST['page']) ? sanitize_text_field($_POST['page']):"";
7 +$page_no = isset($_POST['page_no']) ? intval(sanitize_text_field(wp_unslash($_POST['page_no']))) : '0';
8 +$project_id = isset($_POST['project_id']) ? intval(sanitize_text_field(wp_unslash($_POST['project_id']))) : "0";
9 +$search_tag = isset($_POST['task_search']) ? sanitize_text_field(wp_unslash($_POST['task_search'])) : '';
10 +$order = isset($_POST['order']) ? sanitize_text_field(wp_unslash($_POST['order'])) :"ASC";
11 +$sort_by = isset($_POST['sort_by']) ? sanitize_text_field(wp_unslash($_POST['sort_by'])):"task_name";
12 +$filter_by = isset($_POST['wppm_task_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_task_filter'])) : "all";
13 +if (isset($_POST['filters'])) {
14 + if (is_string($_POST['filters'])) {
15 + $advanced_filter = json_decode( stripslashes( sanitize_text_field( wp_unslash($_POST['filters']))),true );
16 + } elseif (is_array($_POST['filters'])) {
17 + $raw_filters = wp_unslash($_POST['filters']);
18 + $advanced_filter = [
19 + 'created_by' => array_map('absint', (array) ($raw_filters['created_by'] ?? [])),
20 + 'assigned' => array_map('absint', (array) ($raw_filters['assigned'] ?? [])),
21 + 'priority' => array_map('absint', (array) ($raw_filters['priority'] ?? [])),
22 + 'start_date' => sanitize_text_field($raw_filters['start_date'] ?? ''),
23 + 'end_date' => sanitize_text_field($raw_filters['end_date'] ?? ''),
24 + ];
25 + } else {
26 + $advanced_filter = [];
27 + }
28 +}else{
29 + $advanced_filter = [];
30 +}
31 +///$advanced_filter = isset($_POST['filters']) ? (($_POST['filters'])) : "array()";
32 +$proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_proj_filter'])) : "0";
33 +$proj_attr = isset($_POST['wppm_project_attr']) ? sanitize_text_field(wp_unslash($_POST['wppm_project_attr'])):"";
34 +$public_projects = isset($_POST['public_projects']) ? sanitize_text_field(wp_unslash($_POST['public_projects'])):"0";
35 +$tb_start_date = isset($_POST['tb_start_date']) ? sanitize_text_field($_POST['tb_start_date']) : '';
36 +$tb_end_date = isset($_POST['tb_end_date']) ? sanitize_text_field($_POST['tb_end_date']) : '';
37 +$tb_created_by = isset($_POST['tb_created_by']) ? sanitize_text_field($_POST['tb_created_by']) : '';
38 +$page = isset($_POST['page']) ? sanitize_text_field(wp_unslash($_POST['page'])):"";
39 +$priorities = $wpdb->get_results("SELECT id, name FROM {$wpdb->prefix}wppm_task_priorities ORDER BY id ASC ");
40 +$users = get_users(array(
41 + 'orderby' => 'display_name',
42 + 'order' => 'ASC'
43 +));
44 +$assigned_users = $wpdb->get_col( " SELECT DISTINCT users FROM {$wpdb->prefix}wppm_task WHERE users != ''");
45 +$all_assigned = [];
46 +foreach ($assigned_users as $row) {
47 + $ids = explode(',', $row);
48 + foreach ($ids as $id) {
49 + $all_assigned[] = trim($id);
50 + }
51 +}
52 +$all_assigned = array_unique($all_assigned);
16 53 $wppm_current_user_capability = get_user_meta( $current_user->ID, 'wppm_capability', true );
17 54 $wppm_create_tasks_coworkers_permission = get_option('wppm_allow_coworkers_create_task');
18 55 $orderby_proj_sql = esc_sql(sanitize_sql_orderby( "project_name" ));
19 56 $wppm_date_setting = get_option('wppm_date_setting');
@@ -26,44 +63,84 @@
26 63 $wppm_hide_task_statuses_from_frontend = '';
27 64 }
28 65 $proj_attr = esc_sql($proj_attr);
29 66 $is_frontend = 0;
30 -if(!empty($proj_attr )){
31 - $wppm_proj_attr = ' AND (proj.project_name = "'.$proj_attr.'")';
32 -}else{
33 - $wppm_proj_attr = '';
67 +if ( ! empty( $proj_attr ) ) {
68 + $wppm_proj_attr = $wpdb->prepare(
69 + ' AND (proj.project_name = %s)',
70 + $proj_attr
71 + );
72 +} else {
73 + $wppm_proj_attr = '';
34 74 }
35 -$current_date = date('Y-m-d');
75 +$current_date = wp_date('Y-m-d');
36 76 $current_date = esc_sql($current_date );
37 77 $cu_id = esc_sql($current_user->ID);
38 -$archived_where = "";
39 -if ( isset($page) && $page === 'wppm-archived-tasks' ) {
40 - $archived_where = " AND is_archived = 1";
78 +$archived_where = '';
79 +if ( isset( $page ) && $page === 'wppm-archived-tasks' ) {
80 + $archived_where = ' AND Task.is_archived = 1';
81 +} elseif ( isset( $page ) && $page === 'wppm-tasks' ) {
82 + $archived_where = ' AND Task.is_archived = 0';
41 83 }
42 -if( isset($page) && $page === 'wppm-tasks'){
43 - $archived_where = " AND is_archived = 0";
44 -}
45 84 $wppm_task_time = get_option('wppm_task_time');
46 -$query = ("SELECT proj.*
47 - FROM {$wpdb->prefix}wppm_project AS proj
48 - Left join {$wpdb->prefix}wppm_project_meta proj_meta ON proj.id = proj_meta.project_id");
49 -if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
50 - if(!empty($proj_attr )){
51 - $where = " where project_name = '".$proj_attr."' Group by proj.id ORDER BY ".$orderby_proj_sql;
52 - }else{
53 - if(!empty($public_projects)){
54 - $where = " where proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1 Group by proj.id ORDER BY ".$orderby_proj_sql;
55 - }else{
56 - $where = " Group by proj.id ORDER BY ".$orderby_proj_sql;
85 +$query = "SELECT proj.*
86 +FROM {$wpdb->prefix}wppm_project AS proj
87 +LEFT JOIN {$wpdb->prefix}wppm_project_meta AS proj_meta ON proj.id = proj_meta.project_id";
88 +if ( $current_user->has_cap( 'manage_options' ) || $wppm_current_user_capability === 'wppm_admin' ) {
89 + if ( ! empty( $proj_attr ) ) {
90 + $where = $wpdb->prepare(
91 + " WHERE proj.project_name = %s
92 + GROUP BY proj.id
93 + ORDER BY $orderby_proj_sql",
94 + $proj_attr
95 + );
96 + } else {
97 + if ( ! empty( $public_projects ) ) {
98 + $where = $wpdb->prepare(
99 + " WHERE proj_meta.meta_key = %s
100 + AND proj_meta.meta_value = %d
101 + GROUP BY proj.id
102 + ORDER BY $orderby_proj_sql",
103 + 'public_project',
104 + 1
105 + );
106 + } else {
107 + $where = " GROUP BY proj.id ORDER BY $orderby_proj_sql";
108 + }
57 109 }
58 - }
59 -}else{
60 - if(!empty($public_projects)){
61 - $where = " where (proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) $wppm_proj_attr Group by proj.id ORDER BY $orderby_proj_sql";
62 - }
63 - else{
64 - $where = " where ((FIND_IN_SET('$current_user->ID',proj.users)) OR (proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR ( proj.created_by='$cu_id')) $wppm_proj_attr Group by proj.id ORDER BY $orderby_proj_sql";
65 - }
110 +} else {
111 + if ( ! empty( $public_projects ) ) {
112 + $where = $wpdb->prepare(
113 + " WHERE (
114 + proj_meta.meta_key = %s
115 + AND proj_meta.meta_value = %d
116 + )
117 + $wppm_proj_attr
118 + GROUP BY proj.id
119 + ORDER BY $orderby_proj_sql",
120 + 'public_project',
121 + 1
122 + );
123 +
124 + } else {
125 + $where = $wpdb->prepare(
126 + " WHERE (
127 + FIND_IN_SET(%d, proj.users)
128 + OR (
129 + proj_meta.meta_key = %s
130 + AND proj_meta.meta_value = %d
131 + )
132 + OR proj.created_by = %d
133 + )
134 + $wppm_proj_attr
135 + GROUP BY proj.id
136 + ORDER BY $orderby_proj_sql",
137 + $current_user->ID,
138 + 'public_project',
139 + 1,
140 + $cu_id
141 + );
142 + }
66 143 }
67 144 $where = apply_filters('wppm_project_filter_in_task_list_where',$where);
68 145 $query.= $where;
69 146 $projects = $wpdb->get_results($query);
@@ -75,8 +152,20 @@
75 152 'filter'=>$filter_by,
76 153 'proj_filter' =>$proj_filter
77 154 );
78 155 $tl_filters = isset( $_COOKIE['wppm_filters'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wppm_filters'] ) ) : $filters;
156 +$tl_advanced_filters = [];
157 +if ( !empty($_COOKIE['tb_list_filters']) ) {
158 + $tl_advanced_filters = json_decode(
159 + stripslashes($_COOKIE['tb_list_filters']),
160 + true
161 + );
162 + if ( ! is_array($tl_advanced_filters) ) {
163 + $tl_advanced_filters = [];
164 + }
165 +}
166 +//$tl_advanced_filters = isset( $_COOKIE['wppm_advanced_filters'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wppm_advanced_filters'] ) ) : $tl_advanced_filters;
167 +
79 168 if(!is_array($tl_filters)){
80 169 $tl_filters = json_decode($tl_filters);
81 170 $tl_filters_arr = (array) $tl_filters;
82 171 } else{
@@ -82,13 +171,13 @@
82 171 } else{
83 172 $tl_filters_arr = $filters;
84 173 }
85 174 $wppm_tl_filter = "1=1";
86 -$order = isset($_POST['order']) ? sanitize_text_field($_POST['order']) :$tl_filters_arr['order'];
87 -$sort_by = isset($_POST['sort_by']) ? sanitize_text_field($_POST['sort_by']):$tl_filters_arr['sort_by'];
88 -$search_tag = isset($_POST['task_search']) ? sanitize_text_field($_POST['task_search']) : $tl_filters_arr['search'];
89 -$filter_by = isset($_POST['wppm_task_filter']) ? sanitize_text_field($_POST['wppm_task_filter']) : $tl_filters_arr['filter'];
90 -$proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field($_POST['wppm_proj_filter']) : $tl_filters_arr['proj_filter'];
175 +$order = isset($_POST['order']) ? sanitize_text_field(wp_unslash($_POST['order'])) :$tl_filters_arr['order'];
176 +$sort_by = isset($_POST['sort_by']) ? sanitize_text_field(wp_unslash($_POST['sort_by'])):$tl_filters_arr['sort_by'];
177 +$search_tag = isset($_POST['task_search']) ? sanitize_text_field(wp_unslash($_POST['task_search'])) : $tl_filters_arr['search'];
178 +$filter_by = isset($_POST['wppm_task_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_task_filter'])) : $tl_filters_arr['filter'];
179 +$proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_proj_filter'])) : $tl_filters_arr['proj_filter'];
91 180 $proj_filter = esc_sql($proj_filter);
92 181 if($sort_by == ""){
93 182 $sort_by = 'task_name';
94 183 }
@@ -99,9 +188,9 @@
99 188 'filter'=>$filter_by,
100 189 'proj_filter'=>$proj_filter
101 190 );
102 191 setcookie('wppm_filters',wp_json_encode( $filters ),time() + 3600);
103 -
192 +//setcookie('wppm_advanced_filters',wp_json_encode( $tl_advanced_filters ),time() + 3600);
104 193 // Allowed sort columns
105 194 $allowed_sort_by = [
106 195 'project' => 'proj.project_name',
107 196 'status' => 'task_statuses.name',
@@ -112,15 +201,14 @@
112 201 ];
113 202
114 203 // Resolve sort_by safely
115 204 $sort_key = isset($_POST['sort_by'])
116 - ? sanitize_text_field($_POST['sort_by'])
205 + ? sanitize_text_field(wp_unslash($_POST['sort_by']))
117 206 : ($tl_filters_arr['sort_by'] ?? 'task_name');
118 207
119 -$sort_by = $allowed_sort_by[$sort_key] ?? 'task_name';
120 -
208 +$sort_by = $allowed_sort_by[$sort_key] ?? 'Task.task_name';
121 209 // Resolve order safely
122 -$order = (isset($_POST['order']) && strtoupper($_POST['order']) === 'ASC')
210 +$order = (isset($_POST['order']) && strtoupper(wp_unslash($_POST['order'])) === 'ASC')
123 211 ? 'ASC'
124 212 : 'DESC';
125 213
126 214 if($filter_by=='all'){
@@ -143,22 +231,103 @@
143 231 }elseif($filter_by == 'mine'){
144 232 $wppm_tl_filter = "(FIND_IN_SET('$current_user->ID',Task.users)>0)";
145 233 }elseif($filter_by == 'archived'){
146 234 $wppm_tl_filter = "Task.is_archived = 1";
235 +} elseif($filter_by == 'today'){
236 + $wppm_tl_filter = "DATE(Task.end_date) = CURDATE()";
237 +}elseif($filter_by == 'upcoming'){
238 + $wppm_tl_filter = "DATE(Task.end_date) BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY) AND Task.status != 4 AND Task.active = 1 AND Task.is_archived = 0";
239 +}elseif ($filter_by == 'mytasks') {
240 + $wppm_tl_filter = "(
241 + FIND_IN_SET('$current_user->ID', Task.users)
242 + OR Task.created_by = '$current_user->ID'
243 + )
244 + AND Task.status != 4
245 + AND Task.active = 1
246 + AND Task.is_archived = 0";
247 +
147 248 }
148 249
149 -if(!empty($wppm_hide_task_statuses_from_frontend) && is_array($wppm_hide_task_statuses_from_frontend) && ((isset($_POST['is_frontend'])) && (sanitize_text_field($_POST['is_frontend'])==1))){
250 +if(!empty($tl_advanced_filters['created_by'])){
251 + $created_by_ids = array_map('intval', $tl_advanced_filters['created_by']);
252 + $wppm_tl_filter .= " AND Task.created_by IN (" . implode(',', $created_by_ids) . ")";
253 +}
254 +if(!empty($tl_advanced_filters['assigned'])){
255 + $assigned_ids = array_map('intval', $tl_advanced_filters['assigned']);
256 + $assigned_sql = [];
257 + foreach ($assigned_ids as $id) {
258 + $assigned_sql[] = "FIND_IN_SET('$id', Task.users)";
259 + }
260 + $wppm_tl_filter .= " AND (" . implode(' OR ', $assigned_sql) . ")";
261 +}
262 +if(!empty($tl_advanced_filters['priority'])){
263 + $priority = array_map('intval', $tl_advanced_filters['priority']);
264 + $wppm_tl_filter .= " AND Task.priority IN (" . implode(',', $priority) . ")";
265 +}
266 +if(!empty($tl_advanced_filters['start_date'])){
267 + $start_date = sanitize_text_field($tl_advanced_filters['start_date']);
268 + $wppm_tl_filter .= $wpdb->prepare(" AND (CAST(Task.start_date AS DATE)) >= %s", $start_date);
269 +}
270 +if(!empty($tl_advanced_filters['end_date'])){
271 + $end_date = sanitize_text_field($tl_advanced_filters['end_date']);
272 + $wppm_tl_filter .= $wpdb->prepare(" AND (CAST(Task.end_date AS DATE)) <= %s", $end_date);
273 +}
274 +
275 +$advanced_conditions = [];
276 +// Created By
277 +if (!empty($advanced_filter['created_by'])) {
278 + $created_by_ids = array_map('intval', $advanced_filter['created_by']);
279 + $advanced_conditions[] = "Task.created_by IN (" . implode(',', $created_by_ids) . ")";
280 +}
281 +// Assigned Users
282 +if (!empty($advanced_filter['assigned'])) {
283 + $assigned_ids = array_map('intval', $advanced_filter['assigned']);
284 + $assigned_sql = [];
285 + foreach ($assigned_ids as $id) {
286 + $assigned_sql[] = "FIND_IN_SET('$id', Task.users)";
287 + }
288 + $advanced_conditions[] = "(" . implode(' OR ', $assigned_sql) . ")";
289 +}
290 +// Priority
291 +if (!empty($advanced_filter['priority'])) {
292 + $priority = array_map('intval', $advanced_filter['priority']);
293 + $advanced_conditions[] = "Task.priority IN (" . implode(',', $priority) . ")";
294 +}
295 +// Start Date
296 +if (!empty($advanced_filter['start_date'])) {
297 + $start_date = sanitize_text_field($advanced_filter['start_date']);
298 + $advanced_conditions[] = $wpdb->prepare("(CAST(Task.start_date AS DATE)) >= %s", $start_date);
299 +}
300 +// End Date
301 +if (!empty($advanced_filter['end_date'])) {
302 + $end_date = sanitize_text_field($advanced_filter['end_date']);
303 + $advanced_conditions[] = $wpdb->prepare("(CAST(Task.end_date AS DATE)) <= %s", $end_date);
304 +}
305 +if (!empty($advanced_conditions)) {
306 + $wppm_tl_filter .= " AND " . implode(" AND ", $advanced_conditions);
307 +}
308 +// Subtasks are shown only within their parent task, never as their own row in the task list.
309 +$wppm_tl_filter .= " AND (Task.parent_task_id = 0 OR Task.parent_task_id IS NULL)";
310 +//setcookie('wppm_advanced_filters',wp_json_encode( $advanced_filter ),time() + 3600);
311 +if(!empty($wppm_hide_task_statuses_from_frontend) && is_array($wppm_hide_task_statuses_from_frontend) && ((isset($_POST['is_frontend'])) && (sanitize_text_field(wp_unslash($_POST['is_frontend']))==1))){
150 312 foreach($wppm_hide_task_statuses_from_frontend as $status){
151 313 $wppm_tl_filter .= " AND Task.status != '$status'";
152 314 }
153 315 }
154 -if($proj_filter!=0){
155 - $wppm_task_by_proj_filter = "Task.project = '$proj_filter'";
156 -}else{
157 - $wppm_task_by_proj_filter ="1=1";
316 +if ( $proj_filter != 0 || $project_id != 0 ) {
317 + if ( $project_id != 0 ) {
318 + $proj_filter = $project_id;
319 + }
320 + $proj_filter = absint( $proj_filter );
321 + $wppm_task_by_proj_filter = $wpdb->prepare(
322 + "Task.project = %d",
323 + $proj_filter
324 + );
325 +} else {
326 + $wppm_task_by_proj_filter = "1=1";
158 327 }
159 328 $wppm_default_task_date = get_option('wppm_default_task_date');
160 -$search_tag_text = '%'.$wpdb->esc_like($search_tag).'%';
329 +$search_tag_text = "";
161 330 if(!empty($search_tag)){
162 331 $search_tag_text = '%'.$wpdb->esc_like($search_tag).'%';
163 332 $query = ("SELECT Task.*
164 333 FROM {$wpdb->prefix}wppm_task AS Task
@@ -165,9 +334,9 @@
165 334 Left join {$wpdb->prefix}wppm_project proj ON Task.project = proj.id
166 335 Left join {$wpdb->prefix}wppm_task_statuses task_statuses ON Task.status = task_statuses.id
167 336 Left join {$wpdb->prefix}wppm_task_priorities task_priorities ON Task.priority = task_priorities.id
168 337 Left join {$wpdb->prefix}wppm_project_users proj_users ON Task.project = proj_users.proj_id
169 - Left join {$wpdb->base_prefix}users user ON (FIND_IN_SET(user.id,Task.users)>0) AND user.display_name LIKE '$search_tag_text'
338 + Left join {$wpdb->base_prefix}users user ON (FIND_IN_SET(user.ID,Task.users)>0)
170 339 Left join {$wpdb->prefix}wppm_project_meta proj_meta ON Task.project = proj_meta.project_id");
171 340 }
172 341 else{
173 342 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
@@ -198,31 +367,207 @@
198 367 $no_of_rows = ( "SELECT count(*) FROM ($query");
199 368 if(!empty($search_tag )){
200 369 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
201 370 if(!empty($public_projects)){
202 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text') $wppm_proj_attr ";
371 + //$where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text') $wppm_proj_attr ";
372 + $where = $wpdb->prepare( " WHERE (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter
373 + AND (
374 + Task.task_name LIKE %s
375 + OR proj.project_name LIKE %s
376 + OR task_statuses.name LIKE %s
377 + OR task_priorities.name LIKE %s
378 + OR user.display_name LIKE %s
379 + ) $wppm_proj_attr",
380 + $search_tag_text,
381 + $search_tag_text,
382 + $search_tag_text,
383 + $search_tag_text,
384 + $search_tag_text
385 + );
203 386 }else{
204 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text') $wppm_proj_attr ";
387 + $where = $wpdb->prepare(
388 + " WHERE $wppm_tl_filter
389 + AND $wppm_task_by_proj_filter
390 + AND (
391 + Task.task_name LIKE %s
392 + OR proj.project_name LIKE %s
393 + OR task_statuses.name LIKE %s
394 + OR task_priorities.name LIKE %s
395 + OR user.display_name LIKE %s
396 + )
397 + $wppm_proj_attr",
398 + $search_tag_text,
399 + $search_tag_text,
400 + $search_tag_text,
401 + $search_tag_text,
402 + $search_tag_text
403 + );
205 404 }
206 405 } else{
207 406 if(!empty($public_projects)){
208 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter AND (((FIND_IN_SET('$current_user->ID',Task.users)>0) OR (Task.created_by= '$cu_id') OR (proj_users.user_id = '$cu_id' AND proj_users.role_id = 1 AND (FIND_IN_SET('$current_user->ID',proj.users)>0)) OR (Task.project = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR (proj.created_by='$cu_id' AND (FIND_IN_SET('$current_user->ID',proj.users)>0))) AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text')) $wppm_proj_attr";
209 - }else{
210 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter AND (((FIND_IN_SET('$current_user->ID',Task.users)>0) OR (Task.created_by= '$cu_id') OR (proj_users.user_id = '$cu_id' AND proj_users.role_id = 1 AND (FIND_IN_SET('$current_user->ID',proj.users)>0)) OR (Task.project = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR (proj.created_by='$cu_id' AND (FIND_IN_SET('$current_user->ID',proj.users)>0))) AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text')) $wppm_proj_attr";
407 + $where = $wpdb->prepare(
408 + " WHERE
409 + (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND (proj.is_archived = 0)
410 + AND $wppm_tl_filter
411 + AND $wppm_task_by_proj_filter
412 + AND (
413 + (
414 + FIND_IN_SET(%d, Task.users) > 0
415 + OR Task.created_by = %d
416 + OR (
417 + proj_users.user_id = %d
418 + AND proj_users.role_id = 1
419 + AND FIND_IN_SET(%d, proj.users) > 0
420 + )
421 + OR (
422 + Task.project = proj_meta.project_id
423 + AND proj_meta.meta_key='public_project'
424 + AND proj_meta.meta_value=1
425 + )
426 + OR (
427 + proj.created_by = %d
428 + AND FIND_IN_SET(%d, proj.users) > 0
429 + )
430 + )
431 + AND (
432 + Task.task_name LIKE %s
433 + OR proj.project_name LIKE %s
434 + OR task_statuses.name LIKE %s
435 + OR task_priorities.name LIKE %s
436 + OR user.display_name LIKE %s
437 + )
438 + )
439 + $wppm_proj_attr",
440 + $current_user->ID,
441 + $cu_id,
442 + $cu_id,
443 + $current_user->ID,
444 + $cu_id,
445 + $current_user->ID,
446 + $search_tag_text,
447 + $search_tag_text,
448 + $search_tag_text,
449 + $search_tag_text,
450 + $search_tag_text
451 + );
452 + }else{
453 + $where = $wpdb->prepare(
454 + " WHERE
455 + (proj.is_archived = 0)
456 + AND $wppm_tl_filter
457 + AND $wppm_task_by_proj_filter
458 + AND (
459 + (
460 + FIND_IN_SET(%d, Task.users) > 0
461 + OR Task.created_by = %d
462 + OR (
463 + proj_users.user_id = %d
464 + AND proj_users.role_id = 1
465 + AND FIND_IN_SET(%d, proj.users) > 0
466 + )
467 + OR (
468 + Task.project = proj_meta.project_id
469 + AND proj_meta.meta_key='public_project'
470 + AND proj_meta.meta_value=1
471 + )
472 + OR (
473 + proj.created_by = %d
474 + AND FIND_IN_SET(%d, proj.users) > 0
475 + )
476 + )
477 + AND (
478 + Task.task_name LIKE %s
479 + OR proj.project_name LIKE %s
480 + OR task_statuses.name LIKE %s
481 + OR task_priorities.name LIKE %s
482 + OR user.display_name LIKE %s
483 + )
484 + )
485 + $wppm_proj_attr",
486 + $current_user->ID,
487 + $cu_id,
488 + $cu_id,
489 + $current_user->ID,
490 + $cu_id,
491 + $current_user->ID,
492 + $search_tag_text,
493 + $search_tag_text,
494 + $search_tag_text,
495 + $search_tag_text,
496 + $search_tag_text
497 + );
211 498 }
212 499 }
213 500 }else{
214 501 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
215 502 if(!empty($public_projects)){
216 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
503 + $where = $wpdb->prepare(
504 + " WHERE
505 + (proj_meta.meta_key = %s AND proj_meta.meta_value = %d)
506 + AND (proj.is_archived = 0)
507 + AND $wppm_tl_filter
508 + AND $wppm_task_by_proj_filter
509 + $wppm_proj_attr",
510 + 'public_project',
511 + 1
512 + );
217 513 }else{
218 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
514 + $where = " where (proj.is_archived = 0) AND $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
219 515 }
220 516 } else{
221 517 if(!empty($public_projects)){
222 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
518 + $where = $wpdb->prepare(
519 + " WHERE
520 + (
521 + proj_meta.meta_key = %s
522 + AND proj_meta.meta_value = %d
523 + )
524 + AND (proj.is_archived = 0)
525 + AND $wppm_tl_filter
526 + AND $wppm_task_by_proj_filter
527 + $wppm_proj_attr",
528 + 'public_project',
529 + 1
530 + );
223 531 }else{
224 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter AND ((FIND_IN_SET('$current_user->ID',Task.users)>0) OR (Task.created_by= '$cu_id') OR (proj_users.user_id = '$cu_id' AND proj_users.role_id = 1 AND (FIND_IN_SET('$current_user->ID',proj.users)>0)) OR (Task.project = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR (proj.created_by='$cu_id' AND (FIND_IN_SET('$current_user->ID',proj.users)>0))) $wppm_proj_attr";
532 + $where = $wpdb->prepare(
533 + " WHERE
534 + (proj.is_archived = 0)
535 + AND $wppm_tl_filter
536 + AND $wppm_task_by_proj_filter
537 + AND (
538 + (
539 + FIND_IN_SET(%d, Task.users) > 0
540 + )
541 + OR (
542 + Task.created_by = %d
543 + )
544 + OR (
545 + proj_users.user_id = %d
546 + AND proj_users.role_id = %d
547 + AND FIND_IN_SET(%d, proj.users) > 0
548 + )
549 + OR (
550 + Task.project = proj_meta.project_id
551 + AND proj_meta.meta_key = %s
552 + AND proj_meta.meta_value = %d
553 + )
554 + OR (
555 + proj.created_by = %d
556 + AND FIND_IN_SET(%d, proj.users) > 0
557 + )
558 + )
559 + $wppm_proj_attr",
560 + $current_user->ID,
561 + $cu_id,
562 + $cu_id,
563 + 1,
564 + $current_user->ID,
565 + 'public_project',
566 + 1,
567 + $cu_id,
568 + $current_user->ID
569 + );
225 570 }
226 571 }
227 572 }
228 573 $query = apply_filters('wppm_task_list_list_view_query',$query,$search_tag_text);
@@ -242,9 +587,9 @@
242 587 $task_id_array = array();
243 588 $query = $query.$limit;
244 589 $wppm_task_fillter = $wpdb->get_results($query);
245 590 $flag = false;
246 -$project_creator = $wpdb->get_var("SELECT created_by FROM {$wpdb->prefix}wppm_project WHERE created_by = '$cu_id'");
591 +$project_creator = $wpdb->get_var($wpdb->prepare("SELECT created_by FROM {$wpdb->prefix}wppm_project WHERE created_by = %d",$cu_id));
247 592 if(!empty($wppm_task_fillter)){
248 593 foreach($wppm_task_fillter as $key_filter=>$val_filter){
249 594 $val_array = (array) $val_filter;
250 595 $tusers = $val_array['users'];
@@ -250,10 +595,10 @@
250 595 $tusers = $val_array['users'];
251 596 $tusers_arr = explode(',',$tusers);
252 597 $tproject_id = esc_sql($val_array['project']);
253 598 if(!empty($tusers) && in_array($current_user->ID,$tusers_arr)){
254 - $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'");
255 - $project_users = $wpdb->get_var("SELECT users FROM {$wpdb->prefix}wppm_project WHERE id = '$tproject_id'");
599 + $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));
600 + $project_users = $wpdb->get_var($wpdb->prepare("SELECT users FROM {$wpdb->prefix}wppm_project WHERE id = %d",$tproject_id));
256 601 $project_users_arr = explode(',',(string)$project_users);
257 602 if(((!empty($project_user_role)) && ($project_user_role == 1) && in_array($current_user->ID,$project_users_arr))){
258 603 $flag= true;
259 604 break;
@@ -296,12 +641,19 @@
296 641 <div class="row">
297 642 <div class="col-sm-12" id="wppm_heading_inline">
298 643 <span class="wppm-heading-inline"><?php echo (isset($page) && $page === 'wppm-archived-tasks' ) ? esc_html_e('Archived Tasks','taskbuilder'): esc_html_e('Tasks','taskbuilder');?> </span>
299 644 <span class="wppm-add-new-btn btn-primary" id="wppm_add_new_task_btn_tl" style="background-color:<?php echo esc_attr($appearance_settings['list-header-button-background-color'])?>;color:<?php echo esc_attr($appearance_settings['list-header-button-text-color'])?>;<?php echo esc_attr($style)?>;" onclick="wppm_add_new_task()"><img class="wppm_add_new_task_img" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus_icon.svg'); ?>" alt="add_icon"><?php echo esc_html_e('Add New','taskbuilder');?></span>
645 + <!-- Dashboard Button -->
646 + <a class="wppm-add-new-btn btn-primary" style="background-color:<?php echo esc_attr($appearance_settings['list-header-button-background-color'])?>;color:<?php echo esc_attr($appearance_settings['list-header-button-text-color'])?>;<?php echo esc_attr($style)?>;" href="<?php echo esc_url( admin_url('admin.php?page=wppm-dashboard') ); ?>"
647 + style="margin-right:10px;" title="<?php echo esc_attr_e('Go to Dashboard','taskbuilder'); ?>">
648 + <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/dashboard.svg'); ?>" alt="dashboard_icon">
649 + <?php esc_html_e('Dashboard','taskbuilder'); ?>
650 + </a>
651 + </span>
300 652 </div>
301 653 </div>
302 - <div style="display:flex;justify-content:space-between;margin-top:20px;flex-wrap: wrap;">
303 - <div style="display:flex;flex-wrap: wrap;min-width: 0; max-width: 100%; ">
654 + <div>
655 + <div style="display:flex;flex-wrap: wrap;min-width: 0; max-width: 100%;margin-top: 20px;">
304 656 <div id="wppm_task_filter_container">
305 657 <div class="wppm-bulk-actions"style="margin-left: -14px !important;">
306 658 <button
307 659 id="wppm-task-bulk-actions-btn"
@@ -325,12 +677,12 @@
325 677 <div class="wppm-filter-item">
326 678 <label for="wppm_task_filter" style="margin-left:20px;"> <?php echo esc_html_e('Filter','taskbuilder');?></label>
327 679 <select id="wppm_task_filter" name="wppm_task_filter" onchange="wppm_apply_task_filter('<?php echo esc_attr($page); ?>')" style="margin-left:20px;">
328 680 <option value="all"<?php echo ($filter_by == "all")? 'selected':""?>><?php echo esc_html_e('All','taskbuilder');?></option>
329 - <option value="1" style="<?php echo esc_attr($todo_status_style); ?>" <?php echo ($filter_by == "1")? 'selected':""?>><?php echo esc_html_e($todo_status_name,'taskbuilder');?></option>
330 - <option value="2" style="<?php echo esc_attr($inp_status_style); ?>" <?php echo ($filter_by == "2")? 'selected':""?>><?php echo esc_html_e($inp_status_name,'taskbuilder');?></option>
331 - <option value="3" style="<?php echo esc_attr($hold_status_style); ?>" <?php echo ($filter_by == "3")? 'selected':""?>><?php echo esc_html_e($hold_status_name,'taskbuilder');?></option>
332 - <option value="4" style="<?php echo esc_attr($completed_status_style); ?>" <?php echo ($filter_by == "4")? 'selected':""?>><?php echo esc_html_e($completed_status_name,'taskbuilder');?></option>
681 + <option value="1" style="<?php echo esc_attr($todo_status_style); ?>" <?php echo ($filter_by == "1")? 'selected':""?>><?php echo esc_html($todo_status_name);?></option>
682 + <option value="2" style="<?php echo esc_attr($inp_status_style); ?>" <?php echo ($filter_by == "2")? 'selected':""?>><?php echo esc_html($inp_status_name);?></option>
683 + <option value="3" style="<?php echo esc_attr($hold_status_style); ?>" <?php echo ($filter_by == "3")? 'selected':""?>><?php echo esc_html($hold_status_name);?></option>
684 + <option value="4" style="<?php echo esc_attr($completed_status_style); ?>" <?php echo ($filter_by == "4")? 'selected':""?>><?php echo esc_html($completed_status_name);?></option>
333 685 <option value="mine" <?php echo ($filter_by == "mine")? 'selected':""?>><?php echo esc_html_e('Mine','taskbuilder');?></option>
334 686 <option value="unassigned" <?php echo ($filter_by == "unassigned")? 'selected':""?>><?php echo esc_html_e('Unassigned','taskbuilder');?></option>
335 687 <option value="overdue" <?php echo ($filter_by == "overdue")? 'selected':""?>><?php echo esc_html_e('Overdue','taskbuilder');?></option>
336 688 <option value="archived" style="<?php echo esc_attr($arch_filter_style); ?>" <?php echo ($filter_by == "archived")? 'selected':""?>><?php echo esc_html_e('Archived','taskbuilder');?></option>
@@ -337,22 +689,89 @@
337 689 </select>
338 690 </div>
339 691 </div>
340 692 </div>
341 - <div class="wppm-filter-item wppm_project_autocomplete_container" style="margin: 0 0 0 28px;">
342 - <label for="wppm_task_list_proj_filter">
343 - <?php echo esc_html_e('Project','taskbuilder');?>
344 - </label><br>
345 - <select searchable="search here" onchange="wppm_tasks_by_select_project('<?php echo esc_attr($page); ?>')" class="form-control" size="40" name="wppm_task_list_proj_filter" id="wppm_task_list_proj_filter" data-width="100%" style="width: 100%!important;">
346 - <option value="0" <?php echo ($proj_filter == 0)? 'selected':""?>><?php echo esc_html_e('All','taskbuilder');?></option>
693 + <div class="wppm-filter-item wppm_project_autocomplete_container" style="margin: 0 0 0 20px;">
694 + <label for="wppm_task_list_proj_filter">
695 + <?php echo esc_html_e('Project','taskbuilder');?>
696 + </label><br>
697 + <select searchable="search here" onchange="wppm_tasks_by_select_project('<?php echo esc_attr($page); ?>')" class="form-control" size="40" name="wppm_task_list_proj_filter" id="wppm_task_list_proj_filter" data-width="100%" style="width: 100%!important;">
698 + <option value="0" <?php echo ($proj_filter == 0)? 'selected':""?>><?php echo esc_html_e('All','taskbuilder');?></option>
699 + <?php
700 + if(!empty($projects)){
701 + foreach($projects as $proj) {
702 + ?><option value="<?php echo esc_attr($proj->id)?>" <?php echo ($proj_filter == $proj->id)? 'selected':""?>><?php echo esc_html($proj->project_name,'taskbuilder');?></option>
703 + <?php }
704 + } ?>
705 + </select>
706 + </div>
707 + <!-- FILTER BUTTON -->
708 + <div class="tb-filters" class="wppm-filter-item" style="display:flex;margin-left: 4px;">
709 + <div class="tb-filter-bar">
710 + <span id="tb-advanced-toggle" class="tb-btn" style="margin-top:0px!important;">
711 + <?php echo esc_html_e('⚙️ Filters', 'taskbuilder'); ?>
712 + </span>
713 +
714 + <!-- ACTIVE FILTER CHIPS -->
715 + <div id="tb-active-filters" class="tb-chips"></div>
716 +
717 + <!-- POPOVER -->
718 + <div id="tb-advanced-panel" class="tb-popover">
719 + <div class="tb-mobile-header">
720 + <span><?php echo esc_html_e('Filters', 'taskbuilder'); ?></span>
721 + <button type="button" id="tb-close-filters">✕</button>
722 + </div>
723 + <div class="tb-arrow"></div>
724 +
725 + <div class="tb-section">
726 + <h4> <?php echo esc_html_e('Created By', 'taskbuilder'); ?></h4>
727 + <select id="tb-created-by" class="form-control" multiple>
347 728 <?php
348 - if(!empty($projects)){
349 - foreach($projects as $proj) {
350 - ?>
351 - <option value="<?php echo esc_attr($proj->id)?>" <?php echo ($proj_filter == $proj->id)? 'selected':""?>><?php echo esc_html_e($proj->project_name,'taskbuilder');?></option>
352 - <?php }
353 - } ?>
729 + if(!empty($users)){
730 + foreach($users as $user): ?>
731 + <option value="<?php echo esc_attr($user->ID); ?>"><?php echo esc_html($user->display_name); ?></option>
732 + <?php endforeach; ?>
733 + <?php } ?>
734 + </select>
735 + <h4> <?php echo esc_html_e('Assigned To', 'taskbuilder'); ?></h4>
736 + <select id="tb-assigned" multiple>
737 + <?php
738 + if(!empty($all_assigned)){
739 + foreach($all_assigned as $uid){
740 + $user = get_userdata($uid);
741 + if($user){ ?>
742 + <option value="<?php echo esc_attr($uid); ?>">
743 + <?php echo esc_html($user->display_name); ?>
744 + </option>
745 + <?php }
746 + }
747 + }
748 + ?>
354 749 </select>
750 + </div>
751 + <div class="tb-section">
752 + <h4> <?php echo esc_html_e('Priority', 'taskbuilder'); ?></h4>
753 + <select id="tb-priority" class="form-control" multiple>
754 + <?php if(!empty($priorities)) {
755 + foreach($priorities as $priority){ ?>
756 + <option value="<?php echo esc_attr($priority->id); ?>">
757 + <?php echo esc_html($priority->name); ?>
758 + </option>
759 + <?php } } ?>
760 + </select>
761 + </div>
762 + <div class="tb-section">
763 + <h4> <?php echo esc_html_e('Date', 'taskbuilder'); ?></h4>
764 + <input type="date" class="form-control" id="tb-start-date">
765 + <input type="date" class="form-control"id="tb-end-date">
766 + </div>
767 + <div id="tb-filter-actions">
768 + <button class="wppm-submit-btn" id="tb-apply-filter" type="button"> <?php echo esc_html_e('Apply', 'taskbuilder'); ?></button>
769 + <button class="wppm_reset_btn" id="tb-reset-filter" type="button"> <?php echo esc_html_e('Reset', 'taskbuilder'); ?></button>
770 + </div>
771 + </div>
772 + </div>
773 + <div id="tb-backdrop"></div>
355 774 </div>
356 775 <div class="wppm_display_submit" style="margin: 0 0 -5px 10px;">
357 776 <div class="wppm-filter-actions">
358 777 <span class="wppm-link" onclick="wppm_tl_reset_filter('<?php echo esc_attr($page); ?>')"> <?php echo esc_html_e('Reset','taskbuilder');?></span>
@@ -357,19 +776,19 @@
357 776 <div class="wppm-filter-actions">
358 777 <span class="wppm-link" onclick="wppm_tl_reset_filter('<?php echo esc_attr($page); ?>')"> <?php echo esc_html_e('Reset','taskbuilder');?></span>
359 778 </div>
360 779 </div>
361 - </div>
362 - <div id="wppm_task_search" style="display:flex;justify-content:flex-end;">
363 - <img width="25px" height="15" class="wppm_task_search_filter_img" style="position: relative;top: 10px;left: 30px;" height="15px" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/search.svg'); ?>" alt="search">
364 - <input type="search" id="wppm_task_search_filter" style="margin-right:10px;" name="wppm_task_search_filter" class="form-control form-control-sm" aria-controls="selection-datatable" placeholder="<?php echo esc_attr__('Search','taskbuilder');?>" value="<?php echo (!empty($search_tag)) ? esc_attr($search_tag) : "" ?>">
780 + <div id="wppm_task_search" style="display:flex;justify-content:flex-end;margin-left: auto;">
781 + <img width="25px" height="15" class="wppm_task_search_filter_img" style="position: relative;top: 10px;left: 30px;" height="15px" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/search.svg'); ?>" alt="search">
782 + <input type="search" id="wppm_task_search_filter" style="margin-right:10px;" name="wppm_task_search_filter" class="form-control form-control-sm" aria-controls="selection-datatable" placeholder="<?php echo esc_attr__('Search','taskbuilder');?>" value="<?php echo (!empty($search_tag)) ? esc_attr($search_tag) : "" ?>">
365 783 </div>
366 784 </div>
367 785 </div>
368 - <div style="display:flex;justify-content:flex-end;margin-right: 10px;">
369 - <span id="wppm_grid_view_btn" onclick="wppm_view_task_search_filter(<?php echo esc_attr($page_no)?>,'<?php echo esc_attr($page)?>')"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/grid_view.svg'); ?>" alt="grid_view"><span><?php echo esc_html_e('Grid view','taskbuilder');?></span></span>
370 - </div>
371 786 </div>
787 + <div style="display:flex;justify-content:flex-end;margin-right: 10px;">
788 + <span id="wppm_grid_view_btn" onclick="wppm_view_task_search_filter('<?php echo esc_attr($page_no)?>','<?php echo esc_attr($page)?>','<?php echo esc_attr($project_id)?>')"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/grid_view.svg'); ?>" alt="grid_view"><span><?php echo esc_html_e('Grid view','taskbuilder');?></span></span>
789 + </div>
790 + </div>
372 791 <script>
373 792 jQuery('#wppm-more-actions-btn, #wppm-task-bulk-actions-btn').gpopover({width: 200});
374 793 </script>
375 794 <div id="wppm_task_table_container" class="wppm_task_table_container table-responsive" style="padding: 0 15px 15px 15px;">
@@ -434,37 +853,60 @@
434 853 </thead>
435 854 <tbody>
436 855 <?php
437 856 $task_index = 0;
857 + $statuses = $wpdb->get_results(
858 + "SELECT * FROM {$wpdb->prefix}wppm_task_statuses",
859 + OBJECT_K
860 + );
861 +
862 + $priorities = $wpdb->get_results(
863 + "SELECT * FROM {$wpdb->prefix}wppm_task_priorities",
864 + OBJECT_K
865 + );
866 + $projects = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_project", OBJECT_K) ;
867 + $task_ids = wp_list_pluck($wppm_task_fillter, 'id');
868 + $checklist_counts = [];
869 + if (!empty($task_ids)) {
870 + $task_ids_sql = implode(',', array_map('absint', $task_ids));
871 + $checklist_results = $wpdb->get_results(" SELECT checklist.task_id,
872 + COUNT(Items.id) AS total_items,
873 + SUM(CASE WHEN Items.checked = 1 THEN 1 ELSE 0 END) AS checked_items
874 + FROM {$wpdb->prefix}wppm_checklist_items AS Items
875 + LEFT JOIN {$wpdb->prefix}wppm_checklist AS checklist
876 + ON Items.checklist_id = checklist.id
877 + WHERE checklist.task_id IN ($task_ids_sql)
878 + GROUP BY checklist.task_id"
879 + );
880 + foreach ($checklist_results as $row) {
881 + $checklist_counts[$row->task_id] = [
882 + 'total' => (int) $row->total_items,
883 + 'checked' => (int) $row->checked_items,
884 + ];
885 + }
886 + }
438 887 if(!empty($wppm_task_fillter)){
439 888 foreach($wppm_task_fillter as $task) {
440 - $task_id = esc_sql($task->id);
889 + $task_id = absint($task->id);
441 890 $wppm_task_duration = $wppmfunction->wppm_get_duration($task->start_date,$task->end_date);
442 - $checklists = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist where task_id = '$task_id'" );
891 + $checklists = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_checklist where task_id = %d",$task_id) );
443 892 if(!empty($task)){
444 893 $taskdata = $wppmfunction->get_task($task->id);
445 894 $project_data = $wppmfunction->get_project($task->project);
446 895 $task_index++;
447 - $total=$wpdb->get_var("SELECT COUNT(Items.id) AS check_id
448 - FROM {$wpdb->prefix}wppm_checklist_items AS Items
449 - Left join {$wpdb->prefix}wppm_checklist checklist ON Items.checklist_id = checklist.id
450 - WHERE checklist.task_id = '$task_id'");
451 - $total_checked_items=$wpdb->get_var("SELECT COUNT(Items.id) AS check_id
452 - FROM {$wpdb->prefix}wppm_checklist_items AS Items
453 - Left join {$wpdb->prefix}wppm_checklist checklist ON Items.checklist_id = checklist.id
454 - WHERE checklist.task_id = '$task_id' AND Items.checked=1");
455 -
896 + $total = $checklist_counts[$task_id]['total'] ?? 0;
897 + $total_checked_items = $checklist_counts[$task_id]['checked'] ?? 0;
456 898 if(isset($task->status)){
457 - $tstatus = esc_sql($task->status);
458 - $status = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id = '$tstatus'" );
899 + $tstatus = absint($task->status);
900 + $status = $statuses[$task->status] ?? null;
459 901 }
460 902 if(!empty($task->priority)){
461 - $tpriority = esc_sql($task->priority);
462 - $priority = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id ='$tpriority' " );
903 + $tpriority = absint($task->priority);
904 + $priority = $priorities[$task->priority] ?? null;
463 905 }
464 906 if(isset($task->project)){
465 - $tproj = esc_sql($task->project);
466 - $project = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_project where id = '$tproj'" );
907 + $tproj = absint($task->project);
908 + $project = $projects[$task->project] ?? null;
467 909 }
468 910 if($wppm_task_time == 1){
469 911 $tsDate = new DateTime($task->start_date);
470 912 $teDate = new DateTime($task->end_date);
@@ -499,9 +941,8 @@
499 941 $task_end_date = $teDate->format($wppm_date_setting);
500 942 }else{
501 943 $task_end_date = isset($task->end_date) ? $task->end_date: "" ;
502 944 }
503 -
504 945 }
505 946 } elseif($wppm_task_time == 0){
506 947 $tsDate = new DateTime($task->start_date);
507 948 $teDate = new DateTime($task->end_date);
@@ -553,9 +994,9 @@
553 994 }
554 995 }
555 996 $url = $wppmfunction->get_task_url( $task->id, $is_frontend );
556 997 ?>
557 - <tr onclick= "if(link)wppm_tl_handle_click(event, <?php echo esc_attr($task->id) ?>, '<?php echo esc_url( $url ); ?>')" >
998 + <tr onclick= "if(link)wppm_tl_handle_click(event, <?php echo esc_attr($task->id) ?>, '<?php echo esc_url( $url ); ?>',<?php echo esc_attr($project_id) ?>)" >
558 999 <td class="bulk-selector" onmouseover="link=false;" onmouseout="link=true;">
559 1000 <div class="wppm-pl-item-selector">
560 1001 <div class="checkbox-container">
561 1002 <input id="wppm_bulk_select_<?php echo esc_attr($task->id) ?>" class="wppm-task-bulk-select" type="checkbox" onchange="wppm_bulk_task_item_select_change();" value="<?php echo esc_attr( $task->id ); ?>"/>
@@ -563,39 +1004,43 @@
563 1004 </div>
564 1005 </div>
565 1006 </td>
566 1007 <td onmouseover="link=true;">
567 - <?php echo esc_html_e($task->task_name,'taskbuilder') ?>
1008 + <?php echo esc_html($task->task_name) ?>
1009 + <?php $wppm_row_subtask_progress = $wppmfunction->get_subtask_progress($task->id);
1010 + if($wppm_row_subtask_progress['total'] > 0){ ?>
1011 + <span class="wppm_subtask_badge" title="<?php esc_attr_e('Subtasks','taskbuilder'); ?>"><?php echo esc_html($wppm_row_subtask_progress['completed'].'/'.$wppm_row_subtask_progress['total']); ?></span>
1012 + <?php } ?>
568 1013 </td>
569 1014 <td onmouseover="link=true;">
570 1015 <?php if(!empty($project->project_name)){
571 - echo esc_html_e($project->project_name,'taskbuilder');
1016 + echo esc_html($project->project_name);
572 1017 }
573 1018 ?>
574 1019 </td>
575 1020 <td onmouseover="link=true;">
576 1021 <?php if(!empty($task->status)){ ?>
577 - <span class="wppm_td_task_status" style="background-color:<?php echo (isset($status->bg_color))? esc_attr($status->bg_color):"";?>; color: <?php echo (isset($status->color))? esc_attr($status->color):""; ?>"><?php echo (isset($status->name))? esc_html_e($status->name,'taskbuilder'):"" ?></span>
1022 + <span class="wppm_td_task_status" style="background-color:<?php echo (isset($status->bg_color))? esc_attr($status->bg_color):"";?>; color: <?php echo (isset($status->color))? esc_attr($status->color):""; ?>"><?php echo (isset($status->name))? esc_html($status->name):"" ?></span>
578 1023 <?php } ?>
579 1024 </td>
580 1025 <td onmouseover="link=true;">
581 1026 <?php if(!empty($task->priority)){ ?>
582 - <span class ="wppm_td_task_priority" style="background-color:<?php echo (isset($priority->bg_color))? esc_attr($priority->bg_color):"" ;?>; color: <?php echo (isset($priority->color))? esc_attr($priority->color):""; ?>"><?php echo (isset($priority->name))? esc_html_e($priority->name,'taskbuilder'):"" ?></span>
1027 + <span class ="wppm_td_task_priority" style="background-color:<?php echo (isset($priority->bg_color))? esc_attr($priority->bg_color):"" ;?>; color: <?php echo (isset($priority->color))? esc_attr($priority->color):""; ?>"><?php echo (isset($priority->name))? esc_html($priority->name):"" ?></span>
583 1028 <?php } ?>
584 1029 </td>
585 1030 <?php if($wppm_default_task_date == 1 && $wppm_deafault_time_duration_task==0) { ?>
586 1031 <td onmouseover="link=true;">
587 1032 <?php if(!empty($task_start_date)){ ?>
588 - <?php echo esc_html_e($task_start_date,'taskbuilder');
1033 + <?php echo esc_html($task_start_date);
589 1034 } ?>
590 1035 </td>
591 - <td onmouseover="link=true;">
592 - <?php if(!empty($task_end_date) && ($task->status!=4 && $task_end_date < $current_date && $task_end_date != '0000-00-00 00:00:00' && $task_end_date != '00-00-0000 00:00:00' && $task_end_date != '00-00-0000' && $task_end_date != '0000-00-00')){
1036 + <td onmouseover="link=true;"><?php
1037 + if(!empty($task_end_date) && ($task->status!=4 && $task_end_date < $current_date && $task_end_date != '0000-00-00 00:00:00' && $task_end_date != '00-00-0000 00:00:00' && $task_end_date != '00-00-0000' && $task_end_date != '0000-00-00')){
593 1038 $style = "color:#FF0000";
594 1039 } else{
595 1040 $style = "color:#2C3E50";
596 1041 }?>
597 - <span style="<?php echo esc_attr($style); ?>"><?php echo esc_html_e($task_end_date,'taskbuilder');?></span>
1042 + <span style="<?php echo esc_attr($style); ?>"><?php echo esc_html($task_end_date);?></span>
598 1043 </td>
599 1044 <?php } ?>
600 1045 <?php if($wppm_deafault_time_duration_task==1){ ?>
601 1046 <?php
@@ -658,13 +1103,13 @@
658 1103 ?>
659 1104 </tbody>
660 1105 </table>
661 1106 <script>
662 - function wppm_tl_handle_click(event, id, url) {
1107 + function wppm_tl_handle_click(event, id, url,project_id) {
663 1108 if ( ( event.ctrlKey || event.metaKey ) && url ) {
664 1109 window.open(url, '_blank');
665 1110 } else {
666 - wppm_open_task(id);
1111 + wppm_open_task(id,project_id);
667 1112 }
668 1113 }
669 1114 </script>
670 1115 <?php
@@ -676,9 +1121,9 @@
676 1121 $next_class=($total_pages==$current_page)?'disabled':'';
677 1122 ?>
678 1123 <div class="row" style="background-color:#ffffff;">
679 1124 <div class="col-sm-12">
680 - <div class="wppm_task_result" style="<?php echo esc_attr($total_pages==0)? '':'display: none;';?>"><?php _e('Your search request returned no results.','taskbuilder');?></div>
1125 + <div class="wppm_task_result" style="<?php echo esc_attr($total_pages==0)? '':'display: none;';?>"><?php esc_html_e('Your search request returned no results.','taskbuilder');?></div>
681 1126 <hr style="<?php echo esc_attr($total_pages==0)? '':'display: none;';?>">
682 1127 </div>
683 1128 <div>
684 1129 </div>
@@ -728,8 +1173,14 @@
728 1173 .select2-container {
729 1174 max-width: 150px !important;
730 1175 min-width: 150px !important;
731 1176 }
1177 +
1178 + .select2-selection--multiple {
1179 + max-width: 290px !important;
1180 + min-width: 290px !important;
1181 + }
1182 +
732 1183 #wppm_task_filter{
733 1184 min-height: 30px !important;
734 1185 max-height: 35px !important;
735 1186 }
@@ -751,16 +1202,90 @@
751 1202 background-color:<?php echo esc_attr($appearance_settings['list-header-button-hover-color'])?>!important;
752 1203 }
753 1204 </style>
754 1205 <script type="text/javascript">
755 - var link = true;
756 - jQuery( document ).ready( function( jQuery ) {
757 - jQuery("input[name='wppm_task_search_filter']").keypress(function(e) {
758 - //Enter key
759 - if (e.which == 13) {
760 - wppm_task_search_filter('<?php echo esc_attr($page); ?>');
761 - }
762 - });
1206 + var link = true;
1207 + window.listFilters = window.listFilters || {
1208 + created_by: [],
1209 + assigned: [],
1210 + priority: [],
1211 + start_date: "",
1212 + end_date: ""
1213 + };
1214 +
1215 + var listFilters = window.listFilters;
1216 + jQuery( document ).ready( function( jQuery ) {
1217 + // SET VALUES AFTER INIT
1218 + let createdBy = <?php echo wp_json_encode(array_map('strval', $advanced_filter['created_by'] ?? [])); ?>;
1219 +
1220 + let assigned = <?php echo wp_json_encode(array_map('strval', $advanced_filter['assigned'] ?? [])); ?>;
1221 +
1222 + let priority = <?php echo wp_json_encode(array_map('strval', $advanced_filter['priority'] ?? [])); ?>;
1223 + jQuery('#tb-created-by').val(createdBy).trigger('change');
1224 + jQuery('#tb-assigned').val(assigned).trigger('change');
1225 + jQuery('#tb-priority').val(priority).trigger('change');
1226 + jQuery('#tb-start-date').val('<?php echo esc_attr($advanced_filter['start_date'] ?? ''); ?>');
1227 + jQuery('#tb-end-date').val('<?php echo esc_attr($advanced_filter['end_date'] ?? ''); ?>');
1228 + jQuery(document).off("click", "#tb-apply-filter").on("click", "#tb-apply-filter", function (e) {
1229 + e.preventDefault();
1230 + listFilters.created_by = jQuery("#tb-created-by").val() || [];
1231 + listFilters.assigned = jQuery("#tb-assigned").val() || [];
1232 + listFilters.priority = jQuery("#tb-priority").val() || [];
1233 + listFilters.start_date = jQuery("#tb-start-date").val() || "";
1234 + listFilters.end_date = jQuery("#tb-end-date").val() || "";
1235 + listFilters.id = "<?php echo esc_attr($project_id); ?>";
1236 + renderActiveFilters(listFilters);
1237 + setListFilterCookie(listFilters);
1238 + triggerFilter(1, listFilters,'list');
1239 + });
1240 + jQuery(document).on("click", ".tb-remove", function () {
1241 + let key = jQuery(this).attr("data-key");
1242 + let value = jQuery(this).attr("data-value");
1243 + // DATE REMOVE
1244 + if (key === "date") {
1245 + listFilters.start_date = "";
1246 + listFilters.end_date = "";
1247 + jQuery("#tb-start-date").val("");
1248 + jQuery("#tb-end-date").val("");
1249 + } else {
1250 + listFilters[key] = (listFilters[key] || [])
1251 + .map(String)
1252 + .filter(v => v !== String(value));
1253 + jQuery(`#tb-${key}`).val(listFilters[key]).trigger("change");
1254 + }
1255 + // REMOVE CHIP UI
1256 + jQuery(this).closest(".tb-chip").remove();
1257 + syncUIWithFilters(listFilters);
1258 + // save cookie
1259 + setListFilterCookie(listFilters);
1260 + // reload data
1261 + triggerFilter(1,listFilters,'list');
1262 + });
1263 + jQuery(document)
1264 + .off("click", "#tb-reset-filter").on("click", "#tb-reset-filter", function () {
1265 + resetFilters('list');
1266 + });
1267 + let saved = getListFilterCookie();
1268 + if (saved && typeof saved === "object") {
1269 + window.listFilters = {
1270 + created_by: saved.created_by || [],
1271 + assigned: saved.assigned || [],
1272 + priority: saved.priority || [],
1273 + start_date: saved.start_date || "",
1274 + end_date: saved.end_date || ""
1275 + };
1276 + listFilters = window.listFilters;
1277 + }
1278 + setTimeout(function () {
1279 + syncUIWithFilters(listFilters);
1280 + renderActiveFilters(listFilters);
1281 + }, 100);
1282 + jQuery("input[name='wppm_task_search_filter']").keypress(function(e) {
1283 + //Enter key
1284 + if (e.which == 13) {
1285 + wppm_task_search_filter('<?php echo esc_attr($page); ?>');
1286 + }
1287 + });
763 1288 jQuery("#wppm_task_name_th").hover(function(){
764 1289 jQuery('#wppm_chevron_sort_up_task_name_img').show();
765 1290 jQuery('#wppm_chevron_sort_down_task_name_img').hide();
766 1291 });
@@ -791,8 +1316,14 @@
791 1316
792 1317 })
793 1318 jQuery('#wppm_task_list_proj_filter').select2({ dropdownAutoWidth: true, width: 'auto' });
794 1319 jQuery('#wppm_task_list_proj_filter').val(<?php echo esc_attr($proj_filter) ?>);
1320 + jQuery('#tb-created-by').select2({ dropdownAutoWidth: true, width: '100%'});
1321 + jQuery('#tb-created-by').val(<?php echo wp_json_encode($advanced_filter['created_by'] ?? []); ?>).trigger('change');
1322 + jQuery('#tb-assigned').select2({ dropdownAutoWidth: true, width: '100%' });
1323 + jQuery('#tb-assigned').val(<?php echo wp_json_encode($advanced_filter['assigned'] ?? []); ?>).trigger('change');
1324 + jQuery('#tb-priority').select2({dropdownAutoWidth: true, width: '100%'});
1325 + jQuery('#tb-priority').val(<?php echo wp_json_encode($advanced_filter['priority'] ?? []); ?>).trigger('change');
795 1326 /**
796 1327 * Bulk item selector change
797 1328 */
798 1329 function wppm_bulk_task_item_select_change() {
@@ -805,5 +1336,27 @@
805 1336 jQuery("#wppm-task-bulk-actions-btn").hide();
806 1337 jQuery(".wppm-bulk-selector").prop("checked", false);
807 1338 }
808 1339 }
809 -</script>
1340 + jQuery(document).off("click", "#tb-advanced-toggle").on("click", "#tb-advanced-toggle", function (e) {
1341 + e.stopPropagation();
1342 + jQuery("#tb-advanced-panel").toggleClass("tb-open");
1343 + });
1344 +
1345 + /* Close on backdrop click */
1346 + jQuery(document).on("click", "#tb-backdrop", function () {
1347 + jQuery("#tb-advanced-panel").removeClass("tb-open");
1348 + jQuery(this).removeClass("active");
1349 + });
1350 +
1351 + /* Close on outside (desktop only) */
1352 + jQuery(document).on("click", function (e) {
1353 + if (window.innerWidth > 768) {
1354 + if (!jQuery(e.target).closest("#tb-advanced-panel, #tb-advanced-toggle").length) {
1355 + jQuery("#tb-advanced-panel").removeClass("tb-open");
1356 + }
1357 + }
1358 + });jQuery(document).on("click", "#tb-close-filters", function () {
1359 + jQuery("#tb-advanced-panel").removeClass("tb-open");
1360 + jQuery("#tb-backdrop").removeClass("active");
1361 + });
1362 +</script>