PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / trunk
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI vtrunk
8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 7.8.8 7.8.7 7.8.6 7.8.5 All 44 releases
gamipress / includes / functions / logs.php

logs.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI trunk, at includes/functions/logs.php

926 lines 29.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Logs Functions
4 *
5 * @package GamiPress\Logs_Functions
6 * @author GamiPress <contact@gamipress.com>, Ruben Garcia <rubengcdev@gmail.com>
7 * @since 1.0.0
8 */
9 // Exit if accessed directly
10 if( !defined( 'ABSPATH' ) ) exit;
11
12 /**
13 * Get an array of log types
14 *
15 * @since 1.0.0
16
17 * @return array The registered logs types
18 */
19 function gamipress_get_log_types() {
20
21 return apply_filters( 'gamipress_logs_types', array(
22 'event_trigger' => __( 'Event Trigger', 'gamipress' ),
23 'achievement_earn' => __( 'Achievement Earn', 'gamipress' ),
24 'achievement_award' => __( 'Achievement Award', 'gamipress' ),
25 'points_earn' => __( 'Points Earn', 'gamipress' ),
26 'points_deduct' => __( 'Points Deduction', 'gamipress' ),
27 'points_expend' => __( 'Points Expend', 'gamipress' ),
28 'points_award' => __( 'Points Award', 'gamipress' ),
29 'points_revoke' => __( 'Points Revoke', 'gamipress' ),
30 'rank_earn' => __( 'Rank Earn', 'gamipress' ),
31 'rank_award' => __( 'Rank Award', 'gamipress' ),
32 ) );
33
34 }
35
36 /**
37 * Get an array of log pattern tags
38 *
39 * @since 1.0.2
40 * @updated 1.3.7 Added the content parameter
41 * @updated 1.8.2 Added the {trigger_type_key} tag
42 *
43 * @param string $context
44 *
45 * @return array The registered log pattern tags
46 */
47 function gamipress_get_log_pattern_tags( $context = 'default' ) {
48
49 return apply_filters( 'gamipress_log_pattern_tags', array(
50 '{user}' => __( 'User assigned.', 'gamipress' ),
51 '{admin}' => __( 'Admin that awards.', 'gamipress' ),
52 '{achievement}' => __( 'Achievement user has earned.', 'gamipress' ),
53 '{achievement_type}' => __( 'Type of the achievement earned.', 'gamipress' ),
54 '{trigger_type}' => __( 'Event triggered label.', 'gamipress' ),
55 '{trigger_type_key}' => __( 'Event triggered internal key.', 'gamipress' ),
56 '{count}' => __( 'Times user triggered this event.', 'gamipress' ),
57 '{points}' => __( 'Points user has earned.', 'gamipress' ),
58 '{points_type}' => __( 'Type of the points earned.', 'gamipress' ),
59 '{total_points}' => __( 'Points user has earned until this log.', 'gamipress' ),
60 '{rank}' => __( 'Rank user has ranked.', 'gamipress' ),
61 '{rank_type}' => __( 'Rank type user has ranked.', 'gamipress' ),
62 '{site_title}' => __( 'Site name.', 'gamipress' ),
63 ), $context );
64
65 }
66
67 /**
68 * Get an array of log pattern tags based on custom context
69 *
70 * @since 1.3.7
71 *
72 * @param array $tags The registered log pattern tags
73 * @param string $context The context
74
75 * @return array Custom log pattern tags by context
76 */
77 function gamipress_get_log_pattern_tags_by_context( $tags, $context = 'default' ) {
78
79 switch( $context ) {
80 case 'deduct':
81 $tags['{points}'] = __( 'Points user has lost.', 'gamipress' );
82 $tags['{points_type}'] = __( 'Type of the points lost.', 'gamipress' );
83 break;
84 case 'expend':
85 $tags['{points}'] = __( 'Points user has expended.', 'gamipress' );
86 $tags['{points_type}'] = __( 'Type of the points expended.', 'gamipress' );
87 break;
88 }
89
90 return $tags;
91
92 }
93 add_filter( 'gamipress_log_pattern_tags', 'gamipress_get_log_pattern_tags_by_context', 10, 2 );
94
95 /**
96 * Get a string with the desired log pattern tags html markup
97 *
98 * @since 1.0.2
99 *
100 * @param array $specific_tags
101 * @param string $context
102 *
103 * @return string Log pattern tags html markup
104 */
105 function gamipress_get_log_pattern_tags_html( $specific_tags = array(), $context = 'default' ) {
106
107 $output = '<ul class="gamipress-log-pattern-tags-list">';
108
109 foreach( gamipress_get_log_pattern_tags( $context ) as $tag => $description ) {
110
111 if( ! empty( $specific_tags ) && ! in_array( $tag, $specific_tags ) ) {
112 continue;
113 }
114
115 $attr_id = 'tag-' . str_replace( array( '{', '}', '_' ), array( '', '', '-' ), $tag );
116
117 $output .= "<li id='{$attr_id}'><code>{$tag}</code> - {$description}</li>";
118 }
119
120 $output .= '</ul>';
121
122 return $output;
123
124 }
125
126 /**
127 * Helper function to easily query logs and centralize code of multiples log query functions
128 *
129 * @since 1.6.0
130 * @updated 1.6.9 Added 'where' and 'get_var' arguments, improvements on query args processing and support to where definition in format: array( 'key' =>'key', 'value' =>'value', 'compare' =>'compare' )
131 * @updated 1.7.6 Added support for array selects, to group_by parameter and the output parameter
132 *
133 * @param array $args
134 *
135 * @return mixed
136 */
137 function gamipress_query_logs( $args ) {
138
139 global $wpdb;
140
141 $logs = GamiPress()->db->logs;
142 $logs_meta = GamiPress()->db->logs_meta;
143
144 $args = wp_parse_args( $args, array(
145 'select' => 'l.id', // You can pass 'l.*', 'l.{field}', 'COUNT(*)' or an array as select
146 'where' => array(), // Supported formats: 'key' =>'value' | array( 'key'=>'key', 'value'=>'value', 'compare'=>'compare', 'type'=>'type' )
147 'date_query' => array(), // Supports before and after parameters
148 'user_id' => 0,
149 'group_by' => '',
150 'order_by' => 'l.date',
151 'order' => 'DESC',
152 'limit' => 0,
153 'since' => 0,
154 'get_var' => false, // Force the use of get_var() function
155 'output' => OBJECT, // Any of ARRAY_A | ARRAY_N | OBJECT | OBJECT_K constants.
156
157 // Deprecated
158 'meta' => array(),
159 ) );
160
161 // Backward compatibility
162 if( isset( $args['meta'] ) && count( $args['meta'] ) ) {
163 $args['where'] = array_merge( $args['where'], $args['meta'] );
164 }
165
166 $log_fields = array(
167 'log_id',
168 'title',
169 'type',
170 'trigger_type',
171 'access',
172 'user_id',
173 'date',
174 'points',
175 'points_type',
176 );
177
178 // Initialize query definitions
179 $select = array();
180 $joins = array();
181 $where = array();
182 $query_args = array();
183
184 // Select
185 if( is_array( $args['select'] ) ) {
186
187 foreach( $args['select'] as $key => $value ) {
188
189 if( isset( $value['field'] ) ) {
190 $field = $value['field'];
191 } else {
192 $field = $key;
193 }
194
195 if( in_array( $field, $log_fields ) ) {
196 $get_key = "l.{$field}";
197 } else {
198
199 $index = count( $joins );
200
201 $get_key = "lm{$index}.meta_value";
202 $joins[] = "INNER JOIN {$logs_meta} AS lm{$index} ON ( lm{$index}.log_id = l.log_id AND lm{$index}.meta_key = %s )";
203 $query_args[] = $field;
204 }
205
206 if ( isset( $value['function'] ) && $value['function'] ) {
207 $get = "{$value['function']}({$get_key})";
208 } else if ( isset( $value['cast'] ) && $value['cast'] ) {
209 $get = "CAST({$get_key} AS {$value['cast']})";
210 } else {
211 $get = "{$get_key}";
212 }
213
214 $select[] = "{$get} as `{$key}`";
215
216 }
217
218 $args['select'] = ( ! empty( $select ) ? implode( ', ', $select ) : '' );
219 }
220
221 // User ID
222 if( absint( $args['user_id'] ) !== 0 ) {
223
224 $where[] = "l.user_id = %s";
225
226 $query_args[] = $args['user_id'];
227
228 }
229
230 // Where
231
232 if( isset( $args['where'] ) && is_array( $args['where'] ) ) {
233
234 // Loop all log meta to build the where clause
235 foreach ( $args['where'] as $key => $value ) {
236
237 // Field key
238 if( is_array( $value ) && isset( $value['key'] ) ) {
239 $field = $value['key'];
240 } else {
241 $field = $key;
242 }
243
244 // Field value
245 if( is_array( $value ) && isset( $value['value'] ) ) {
246 $field_value = $value['value'];
247 } else {
248 $field_value = $value;
249 }
250
251 // Field compare
252 if( is_array( $field_value ) ) {
253 $default_compare = 'IN';
254 } else {
255 $default_compare = '=';
256 }
257
258 $compare = ( is_array( $value ) && isset( $value['compare'] ) ? $value['compare'] : $default_compare );
259
260 // Field type
261 $default_type = 'string';
262
263 $type = ( is_array( $value ) && isset( $value['type'] ) ? $value['type'] : $default_type );
264
265 // Parse common types to an unique one type
266 switch( $type ) {
267 case 'int':
268 case 'integer':
269 case 'number':
270 case 'numeric':
271 $type = 'integer';
272 break;
273 case 'text':
274 case 'string':
275 case 'char':
276 case 'varchar':
277 default:
278 $type = 'string';
279 break;
280 }
281
282 if( in_array( $field, $log_fields ) ) {
283
284 // Query log field
285
286 if( is_array( $field_value ) ) {
287
288 if( $type === 'integer' ) {
289 $field_value = implode( ", ", $field_value );
290 } else {
291 $field_value = "'" . implode( "', '", $field_value ) . "'";
292 }
293
294 $where[] = "l.{$field} {$compare} ({$field_value})";
295 } else {
296
297 if( $type === 'integer' ) {
298 $where[] = "l.{$field} {$compare} %d";
299 } else {
300 $where[] = "l.{$field} {$compare} %s";
301 }
302
303 $query_args[] = $field_value;
304 }
305
306 } else {
307
308 // Query log meta
309
310 $index = count( $joins );
311
312 $meta_key = '_gamipress_' . sanitize_key( $field );
313
314 // Setup query definitions
315 $joins[] = "LEFT JOIN {$logs_meta} AS lm{$index} ON ( l.log_id = lm{$index}.log_id AND lm{$index}.meta_key = '{$meta_key}' )";
316
317 // If meta value is an array then need to compare using IN operator
318 if( is_array( $field_value ) ) {
319
320 if( $type === 'integer' ) {
321 $field_value = implode( ", ", $field_value );
322 } else {
323 $field_value = "'" . implode( "', '", $field_value ) . "'";
324 }
325
326 $where[] = "lm{$index}.meta_value {$compare} ({$field_value})";
327
328 } else {
329 // Meta query in format: 'key' =>'value'
330 if( $type === 'integer' ) {
331 $where[] = "lm{$index}.meta_value {$compare} %d";
332 } else {
333 $where[] = "lm{$index}.meta_value {$compare} %s";
334 }
335
336 $query_args[] = $field_value;
337 }
338
339 }
340
341 }
342
343 }
344
345 // Date query before
346 if( isset( $args['date_query']['before'] ) && ! empty( $args['date_query']['before'] ) ) {
347 $where[] = "l.date <= %s";
348 $query_args[] = $args['date_query']['before'];
349 }
350
351 // Date query after
352 if( isset( $args['date_query']['after'] ) && ! empty( $args['date_query']['after'] ) ) {
353 $where[] = "l.date >= %s";
354 $query_args[] = $args['date_query']['after'];
355 }
356
357 // Since
358 if( absint( $args['since'] ) > 0 ) {
359 $date = date( 'Y-m-d H:i:s', $args['since'] );
360
361 $where[] = "l.date >= %s";
362 $query_args[] = $date;
363 }
364
365 // Group By
366 $group_by = '';
367
368 if( ! empty( $args['group_by'] ) ) {
369 $group_by = 'GROUP BY ' . $args['group_by'];
370 }
371
372 // Order By
373 $order_by = '';
374
375 if( ! empty( $args['order_by'] ) && ! empty( $args['order'] ) ) {
376 $order_by = 'ORDER BY ' . $args['order_by'] . ' ' . $args['order'];
377 }
378
379 // Turn arrays into strings
380 $select = $args['select'];
381 $joins = implode( ' ', $joins );
382 $where = ( ! empty( $where ) ? 'WHERE ( ' . implode( ' ) AND ( ', $where ) . ' ) ' : '' );
383 $limit = ( absint( $args['limit'] ) !== 0 ? 'LIMIT ' . absint( $args['limit'] ) : '' );
384
385 // Prepare the query SQL
386 $sql = $wpdb->prepare(
387 "SELECT {$select}
388 FROM {$logs} AS l
389 {$joins}
390 {$where}
391 {$group_by}
392 {$order_by}
393 {$limit}",
394 $query_args
395 );
396
397 if( strtoupper( $select ) === 'COUNT(*)' || $args['get_var'] ) {
398 // If is a count, ensure return an integer
399 $logs = absint( $wpdb->get_var( $sql ) );
400 } else {
401 $logs = $wpdb->get_results( $sql, $args['output'] );
402 }
403
404 return $logs;
405
406 }
407
408 /**
409 * Return user logs with the specified meta data
410 *
411 * @since 1.3.7
412 * @updated 1.3.9.6 Added $since parameter
413 * @updated 1.3.9.8 Improvements on since checks
414 * @updated 1.6.0 Code moved to gamipress_query_logs() function
415 *
416 * @param int $user_id
417 * @param array $where
418 * @param int $since
419 *
420 * @return array
421 */
422 function gamipress_get_user_logs( $user_id = 0, $where = array(), $since = 0 ) {
423
424 return gamipress_query_logs( array(
425 'select' => 'l.*',
426 'user_id' => $user_id,
427 'where' => $where,
428 'since' => $since
429 ) );
430
431 }
432
433 /**
434 * Return count of user logs with the specified meta data
435 *
436 * @since 1.1.8
437 * @updated 1.3.7 Added support for multiples types
438 * @updated 1.4.2 Added $since parameter
439 * @updated 1.6.0 Code moved to gamipress_query_logs() function
440 *
441 * @param int $user_id
442 * @param array $where
443 *
444 * @return int
445 */
446 function gamipress_get_user_log_count( $user_id = 0, $where = array(), $since = 0 ) {
447
448 return gamipress_query_logs( array(
449 'select' => 'COUNT(*)',
450 'user_id' => $user_id,
451 'where' => $where,
452 'since' => $since
453 ) );
454
455 }
456
457 /**
458 * Return the last user log with the specified meta data
459 *
460 * @since 1.4.2
461 *
462 * @param int $user_id
463 * @param array $where
464 *
465 * @return stdClass|false
466 */
467 function gamipress_get_user_last_log( $user_id = 0, $where = array() ) {
468
469 $user_logs = gamipress_query_logs( array(
470 'select' => 'l.*',
471 'user_id' => $user_id,
472 'where' => $where,
473 'limit' => 1
474 ) );
475
476 return ( is_array( $user_logs ) && isset( $user_logs[0] ) ? $user_logs[0] : false );
477
478 }
479
480 /**
481 * Posts a log entry when a user unlocks any achievement post
482 *
483 * @since 1.0.0
484 * @updated 1.2.8 Added $type parameter
485 * @updated 1.4.7 Added $trigger_type parameter
486 *
487 * @param string $type The log type
488 * @param int $user_id The user ID
489 * @param string $access Access to this log ( public|private )
490 * @param string $trigger_type Access to this log ( public|private )
491 * @param array $log_meta Log meta data
492 *
493 * @return int The log ID of the newly created log entry
494 */
495 function gamipress_insert_log( $type = '', $user_id = 0, $access = 'public', $trigger_type = '', $log_meta = array() ) {
496
497 global $wpdb;
498
499 // Backward compatibility for functions that called it by the old way
500 if( is_array( $trigger_type ) && empty( $log_meta ) ) {
501 $log_meta = $trigger_type;
502 $trigger_type = '';
503 }
504
505 // Trigger type is not a meta yet, so update it correctly
506 if( isset( $log_meta['trigger_type'] ) ) {
507 $trigger_type = $log_meta['trigger_type'];
508 unset( $log_meta['trigger_type'] );
509 }
510
511 // Setup table
512 $ct_table = ct_setup_table( 'gamipress_logs' );
513
514 // Post data
515 $log_data = array(
516 'title' => '',
517 'type' => $type,
518 'trigger_type' => $trigger_type,
519 'access' => $access,
520 'user_id' => $user_id === 0 ? get_current_user_id() : absint( $user_id ),
521 'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
522 );
523
524 $log_data['points'] = ( isset( $log_meta['points'] ) ) ? $log_meta['points'] : 0;
525 $log_data['points_type'] = ( isset( $log_meta['points_type'] ) ) ? $log_meta['points_type'] : '';
526
527 // Auto-generated post title
528 $log_data['title'] = gamipress_parse_log_pattern( $log_meta['pattern'], $log_data, $log_meta );
529
530 // Store log entry
531 $log_id = $ct_table->db->insert( $log_data );
532
533 // Store log meta data
534 if ( $log_id && ! empty( $log_meta ) ) {
535
536 $metas = array();
537
538 foreach ( (array) $log_meta as $key => $value ) {
539 // Sanitize vars
540 $meta_key = '_gamipress_' . sanitize_key( $key );
541 $meta_key = wp_unslash( $meta_key );
542 $meta_value = wp_unslash( $value );
543 $meta_value = esc_sql( $meta_value );
544 $meta_value = sanitize_meta( $meta_key, $meta_value, $ct_table->name );
545 $meta_value = maybe_serialize( $meta_value );
546
547 // Setup the insert value
548 $metas[] = $wpdb->prepare( '%d, %s, %s', array( $log_id, $meta_key, $meta_value ) );
549 }
550
551 $logs_meta = GamiPress()->db->logs_meta;
552 $metas = implode( '), (', $metas );
553
554 // Since the log is recently inserted, is faster to run a single query to insert all metas instead of insert them one-by-one
555 $wpdb->query( "INSERT INTO {$logs_meta} (log_id, meta_key, meta_value) VALUES ({$metas})" );
556
557 }
558
559 // Hook to add custom data
560 do_action( 'gamipress_insert_log', $log_id, $log_data, $log_meta, $user_id );
561
562 ct_reset_setup_table();
563
564 return $log_id;
565
566 }
567
568 /**
569 * Parse log pattern replacements
570 *
571 * @since 1.0.0
572 *
573 * @param string $log_pattern The pattern
574 * @param array $log_data Log post data
575 * @param array $log_meta Log meta data
576 *
577 * @return integer The post ID of the newly created log entry
578 */
579 function gamipress_parse_log_pattern( $log_pattern = '', $log_data = array(), $log_meta = array()) {
580
581 global $gamipress_pattern_replacements;
582
583 // Setup site pattern replacements
584 $gamipress_pattern_replacements['{site_title}'] = get_bloginfo( 'name' );
585
586 $user = get_userdata( $log_data['user_id'] );
587
588 // Setup user pattern replacements
589 $gamipress_pattern_replacements['{user_id}'] = ( $user ? $user->ID : '' );
590 $gamipress_pattern_replacements['{user}'] = ( $user ? $user->display_name : '' );
591
592 // TODO: Add more user tags
593
594 $gamipress_pattern_replacements['{trigger_type}'] = gamipress_get_activity_trigger_label( $log_data['trigger_type'] );
595 $gamipress_pattern_replacements['{trigger_type_key}'] = $log_data['trigger_type'];
596
597 foreach( $log_meta as $log_meta_key => $log_meta_value ) {
598
599 if( in_array( $log_meta_key, array( 'pattern', 'type' ) ) )
600 continue;
601
602 // Implode meta value if is an array of values
603 if( is_array( $log_meta_value ) )
604 $log_meta_value = implode( ', ', $log_meta_value );
605
606 $gamipress_pattern_replacements['{' . $log_meta_key . '}'] = $log_meta_value;
607 }
608
609 do_action( 'gamipress_before_parse_log_pattern', $log_data, $log_meta );
610
611 return str_replace( array_keys( $gamipress_pattern_replacements ), $gamipress_pattern_replacements, $log_pattern );
612
613 }
614
615 /**
616 * Log pattern replacements for achievements earn
617 *
618 * @since 1.0.0
619 *
620 * @uses global $gamipress_pattern_replacements
621 *
622 * @param array $log_data Log post data
623 * @param array $log_meta Log meta data
624 */
625 function gamipress_parse_achievement_log_pattern( $log_data, $log_meta ) {
626
627 // If log has assigned an achievement, then add achievement pattern replacements
628 if( isset( $log_meta['achievement_id'] ) ) {
629
630 global $gamipress_pattern_replacements;
631
632 // Achievement pattern replacements
633 $achievement = gamipress_get_post( $log_meta['achievement_id'] );
634 $achievement_types = gamipress_get_achievement_types();
635 $achievement_type = ( $achievement && isset( $achievement_types[$achievement->post_type]['singular_name'] ) ) ? $achievement_types[$achievement->post_type]['singular_name'] : '';
636
637 // {achievement} tag
638 $gamipress_pattern_replacements['{achievement}'] = $achievement->post_title;
639
640 // {achievement_type} tag
641 $gamipress_pattern_replacements['{achievement_type}'] = $achievement_type;
642
643 if( $log_data['type'] === 'achievement_award' ) {
644 $admin = get_userdata( $log_meta['admin_id'] );
645
646 // {admin_username} tag
647 $gamipress_pattern_replacements['{admin}'] = $admin->display_name;
648 }
649 }
650
651 }
652 add_action( 'gamipress_before_parse_log_pattern', 'gamipress_parse_achievement_log_pattern', 10, 2 );
653
654 /**
655 * Log pattern replacements for points earn/award
656 *
657 * @since 1.0.0
658 *
659 * @uses global $gamipress_pattern_replacements
660 *
661 * @param array $log_data Log post data
662 * @param array $log_meta Log meta data
663 */
664 function gamipress_parse_points_log_pattern( $log_data, $log_meta ) {
665
666 // If log is a points based entry, then add points pattern replacements
667 if( $log_data['type'] === 'points_award' || $log_data['type'] === 'points_revoke' || $log_data['type'] === 'points_earn' || $log_data['type'] === 'points_deduct' ) {
668
669 global $gamipress_pattern_replacements;
670
671 $points = absint( $log_data['points'] );
672 $points_type = $log_data['points_type'];
673
674 $points_types = gamipress_get_points_types();
675
676 // Default points label
677 $points_label = __( 'points', 'gamipress' );
678
679 if( isset( $points_types[$points_type] ) ) {
680 // Points type label
681 $points_label = strtolower( $points_types[$points_type]['plural_name'] );
682 }
683
684 // {points} tag, absint ensures a positive amount to build a pattern like "User expended 100 points" instead of "User expended -100 points"
685 $gamipress_pattern_replacements['{points}'] = gamipress_format_amount( $points, $points_type );
686
687 // {points_type} tag
688 $gamipress_pattern_replacements['{points_type}'] = $points_label;
689
690 if( $log_data['type'] === 'points_award' || $log_data['type'] === 'points_revoke' ) {
691 $admin = get_userdata( $log_meta['admin_id'] );
692
693 // {admin_username} tag
694 $gamipress_pattern_replacements['{admin}'] = $admin->display_name;
695 }
696
697 }
698
699 }
700 add_action( 'gamipress_before_parse_log_pattern', 'gamipress_parse_points_log_pattern', 10, 2 );
701
702 /**
703 * Log pattern replacements for rank earn/award
704 *
705 * @since 1.3.1
706 *
707 * @uses global $gamipress_pattern_replacements
708 *
709 * @param array $log_data Log post data
710 * @param array $log_meta Log meta data
711 */
712 function gamipress_parse_rank_log_pattern( $log_data, $log_meta ) {
713
714 // If log is a points based entry, then add points pattern replacements
715 if( $log_data['type'] === 'rank_award' || $log_data['type'] === 'rank_earn' ) {
716
717 global $gamipress_pattern_replacements;
718
719 $rank = gamipress_get_post( $log_meta['rank_id'] );
720
721 // {rank} and {tank_type} tags
722 $gamipress_pattern_replacements['{rank}'] = $rank ? $rank->post_title : '';
723 $gamipress_pattern_replacements['{rank_type}'] = $rank ? gamipress_get_rank_type_singular( $rank->post_type, true ) : '';
724
725 if( $log_data['type'] === 'rank_award' ) {
726 $admin = get_userdata( $log_meta['admin_id'] );
727
728 // {admin_username} tag
729 $gamipress_pattern_replacements['{admin}'] = $admin->display_name;
730 }
731
732 }
733
734 }
735 add_action( 'gamipress_before_parse_log_pattern', 'gamipress_parse_rank_log_pattern', 10, 2 );
736
737 /**
738 * Update the post title of a log entry.
739 *
740 * @since 1.0.0
741 *
742 * @param array $object_data An array with new object data.
743 * @param array $original_object_data An array with the original object data.
744 * @return array Updated post data.
745 */
746 function gamipress_maybe_apply_log_pattern( $object_data = array(), $original_object_data = array() ) {
747
748 global $ct_table;
749
750 // If not is our logs, return
751 if( $ct_table->name !== 'gamipress_logs' ) {
752 return $object_data;
753 }
754
755 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
756 return $object_data;
757 }
758
759 if ( isset( $original_object_data['log_id'] ) && $original_object_data['log_id'] !== 0 ) {
760
761 $log_id = $original_object_data['log_id'];
762
763 // Just update using pattern if title has been changed
764 if( empty( $object_data['title'] ) ) {
765 // Check pattern
766 if( isset( $_POST['_gamipress_pattern'] ) && ! empty( $_POST['_gamipress_pattern'] ) ) {
767 $pattern = sanitize_text_field( $_POST['_gamipress_pattern'] );
768 } else {
769 $pattern = ct_get_object_meta( $log_id, '_gamipress_pattern', true );
770 }
771
772 // Just parse pattern if not empty
773 if( ! empty( $pattern ) ) {
774 $object_data['title'] = gamipress_get_parsed_log( $log_id );
775 }
776 }
777 }
778
779 return $object_data;
780
781 }
782 add_filter( 'ct_insert_object_data' , 'gamipress_maybe_apply_log_pattern' , 99, 2 );
783
784
785 /**
786 * Get and apply the pattern of a log entry.
787 *
788 * @since 1.0.0
789 *
790 * @param integer $log_id The log's ID.
791 *
792 * @return string Parsed log pattern.
793 */
794 function gamipress_get_parsed_log( $log_id = null ) {
795
796 if( $log_id === null ) {
797 return '';
798 }
799
800 $prefix = '_gamipress_';
801
802 // Setup table
803 ct_setup_table( 'gamipress_logs' );
804
805 $log_data = ct_get_object( $log_id, ARRAY_A );
806
807 if( ! $log_data ) {
808 return '';
809 }
810
811 $log_meta = array(
812 'pattern' => ct_get_object_meta( $log_id, $prefix . 'pattern', true ),
813 );
814
815 $log_meta = apply_filters( 'gamipress_get_log_meta_data', $log_meta, $log_id, $log_data );
816
817 ct_reset_setup_table();
818
819 return gamipress_parse_log_pattern( $log_meta['pattern'], $log_data, $log_meta );
820
821 }
822
823 /**
824 * Get log meta data defaults from a log's object ID
825 *
826 * @param $log_meta
827 * @param $log_id
828 * @param $log_data
829 *
830 * @return mixed
831 */
832 function gamipress_get_log_meta_data_defaults( $log_meta, $log_id, $log_data ) {
833
834 $prefix = '_gamipress_';
835
836 $meta_keys = array();
837
838 if( $log_data['type'] === 'event_trigger' ) {
839 // Event trigger meta data
840 $meta_keys[] = 'count';
841 } else if( $log_data['type'] === 'achievement_earn' || $log_data['type'] === 'achievement_award' ) {
842 // Achievement earn meta data
843 $meta_keys[] = 'achievement_id';
844
845 if( $log_data['type'] === 'achievement_award' ) {
846 // Specific achievement award meta data
847 $meta_keys[] = 'admin_id';
848 }
849 } else if( $log_data['type'] === 'points_award' || $log_data['type'] === 'points_revoke' || $log_data['type'] === 'points_earn' || $log_data['type'] === 'points_deduct' ) {
850 // Points earn/deduct/award/revoke meta data
851 $meta_keys[] = 'points';
852 $meta_keys[] = 'points_type';
853 $meta_keys[] = 'total_points';
854
855 if( $log_data['type'] === 'points_award' || $log_data['type'] === 'points_revoke' ) {
856 // Specific points award meta data
857 $meta_keys[] = 'admin_id';
858 }
859 } else if( $log_data['type'] === 'rank_earn' || $log_data['type'] === 'rank_award' ) {
860 // Achievement earn meta data
861 $meta_keys[] = 'rank_id';
862
863 if( $log_data['type'] === 'rank_award' ) {
864 // Specific rank award meta data
865 $meta_keys[] = 'admin_id';
866 }
867 }
868
869 foreach( $meta_keys as $meta_key ) {
870 $log_meta[$meta_key] = ct_get_object_meta( $log_id, $prefix . $meta_key, true );
871 }
872
873 return $log_meta;
874
875 }
876 add_filter( 'gamipress_get_log_meta_data', 'gamipress_get_log_meta_data_defaults', 10, 3 );
877
878 /**
879 * Get the log object data
880 *
881 * @since 2.1.2
882 *
883 * @param int $log_id The log ID
884 * @param string $meta_key The meta key to retrieve. By default, returns
885 * data for all keys. Default empty.
886 * @param bool $single Optional. Whether to return a single value. Default false.
887 *
888 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true.
889 */
890 function gamipress_get_log_meta( $log_id, $meta_key = '', $single = false ) {
891
892 ct_setup_table( 'gamipress_logs' );
893
894 $meta_value = ct_get_object_meta( $log_id, $meta_key, $single );
895
896 ct_reset_setup_table();
897
898 return $meta_value;
899
900 }
901
902 /**
903 * Update the log object data
904 *
905 * @since 2.1.2
906 *
907 * @param int $log_id The log ID
908 * @param string $meta_key Metadata key.
909 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
910 * @param mixed $prev_value Optional. Previous value to check before removing.
911 * Default empty.
912 *
913 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
914 */
915 function gamipress_update_log_meta( $log_id, $meta_key, $meta_value, $prev_value = '' ) {
916
917 ct_setup_table( 'gamipress_logs' );
918
919 $meta_id = ct_update_object_meta( $log_id, $meta_key, $meta_value, $prev_value );
920
921 ct_reset_setup_table();
922
923 return $meta_id;
924
925 }
926