PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.5
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.5
8.0.5 8.0.4 8.0.3 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 All 47 releases
← All changes | includes/admin/tools/recount-activity.php +329 -0 7.9.0 → 8.0.5 View file →
@@ -1,0 +1,329 @@
1 +<?php
2 +/**
3 + * Recount Activity Tool
4 + *
5 + * @package GamiPress\Admin\Tools\Recount_Activity
6 + * @author GamiPress <[email protected]>, Ruben Garcia <[email protected]>
7 + * @since 1.1.8
8 + */
9 +// Exit if accessed directly
10 +if( !defined( 'ABSPATH' ) ) exit;
11 +
12 +/**
13 + * Register Recount Activity Tool meta boxes
14 + *
15 + * @since 1.1.8
16 + *
17 + * @param array $meta_boxes
18 + *
19 + * @return array
20 + */
21 +function gamipress_recount_activity_tool_meta_boxes( $meta_boxes ) {
22 +
23 + /**
24 + * Hook to add recountable activity triggers (login or daily visits are not recountable because they aren't stored in database)
25 + *
26 + * @since 1.1.8
27 + *
28 + * @param array $activity_triggers Activity triggers that can be recounted
29 + *
30 + * @return array
31 + */
32 + $recountable_activity_triggers = apply_filters( 'gamipress_recountable_activity_triggers',
33 + array(
34 + '' => __( 'Choose the activity to recount', 'gamipress' ),
35 + // WordPress
36 + __( 'WordPress', 'gamipress' ) => array(
37 + 'comments' => __( 'Recount comments', 'gamipress' ),
38 + 'published_content' => __( 'Recount content publishing', 'gamipress' ),
39 + ),
40 + )
41 + );
42 +
43 + $meta_boxes['recount-activity'] = array(
44 + 'title' => gamipress_dashicon( 'backup' ) . __( 'Recount Activity', 'gamipress' ),
45 + 'fields' => apply_filters( 'gamipress_recount_activity_tool_fields', array(
46 + 'recount_activity_desc' => array(
47 + 'content' => __( 'This tool will try to sync old activity with your already configured GamiPress install. GamiPress logs will be updated with all the activity stored in the database and the already configured points awards and deducts and achievements will be awarded or deducted too.', 'gamipress' )
48 + . '<br>' . __( '<strong>Note:</strong> Some activity may not be possible to recount (like user log ins or daily visits) because there are not registries stored in the database.', 'gamipress' )
49 + . '<br>' . __( '<strong>Important:</strong> If emails to notify users about new earnings are enabled is possible that users will receive a lot of emails so is recommendable to deactivate them temporally.', 'gamipress' ),
50 + 'type' => 'html',
51 + ),
52 + 'activity_to_recount' => array(
53 + 'name' => __( 'Activity to recount', 'gamipress' ),
54 + 'tooltip' => __( 'Choose the activity to recount.', 'gamipress' ),
55 + 'label_cb' => 'cmb_tooltip_label_cb',
56 + 'type' => 'advanced_select',
57 + 'options' => $recountable_activity_triggers,
58 + ),
59 + 'entries_per_loop' => array(
60 + 'name' => __( 'Entries per loop', 'gamipress' ),
61 + 'tooltip' => __( 'To prevent block your site, this tool performs the recount in small groups of entries. Set the number of entries to recount in each loop (by default, 100).', 'gamipress' ),
62 + 'label_cb' => 'cmb_tooltip_label_cb',
63 + 'desc' => __( '<strong>Note:</strong> If the recount process fails, try to reduce this setting to a lower number to 50, 20 or 10 entries per loop.', 'gamipress' ),
64 + 'type' => 'text',
65 + 'attributes' => array(
66 + 'type' => 'number',
67 + 'min' => '10',
68 + 'step' => '5'
69 + ),
70 + 'default' => '100'
71 + ),
72 + 'recount_activity' => array(
73 + 'label' => __( 'Recount Activity', 'gamipress' ),
74 + 'type' => 'button',
75 + 'button' => 'primary'
76 + ),
77 + ) )
78 + );
79 +
80 + return $meta_boxes;
81 +
82 +}
83 +add_filter( 'gamipress_tools_general_meta_boxes', 'gamipress_recount_activity_tool_meta_boxes' );
84 +
85 +/**
86 + * AJAX handler for the recount activity tool
87 + *
88 + * @since 1.1.8
89 + * @updated 1.4.2 Added the run again utility
90 + */
91 +function gamipress_ajax_recount_activity_tool() {
92 + // Security check, forces to die if not security passed
93 + check_ajax_referer( 'gamipress_admin', 'nonce' );
94 +
95 + // Check user capabilities
96 + if( ! current_user_can( gamipress_get_manager_capability() ) ) {
97 + wp_send_json_error( __( 'You are not allowed to perform this action.', 'gamipress' ) );
98 + }
99 +
100 + // Check parameters received
101 + if( ! isset( $_POST['activity'] ) || empty( $_POST['activity'] ) ) {
102 + wp_send_json_error( __( 'You need to choose an activity to recount.', 'gamipress' ) );
103 + }
104 +
105 + ignore_user_abort( true );
106 +
107 + if ( ! gamipress_is_function_disabled( 'set_time_limit' ) ) {
108 + set_time_limit( 0 );
109 + }
110 +
111 + // Setup a global var to make other functions meet that next awards comes from recount activity tool
112 + define( 'GAMIPRESS_DOING_ACTIVITY_RECOUNT', true );
113 +
114 + $response = array(
115 + 'success' => true,
116 + 'run_again' => false,
117 + 'message' => __( 'Activity recount process has been done successfully.', 'gamipress' ),
118 + 'log' => '',
119 + );
120 +
121 + $activity = sanitize_text_field( $_POST['activity'] );
122 + $loop = ( isset( $_POST['loop'] ) ? absint( $_POST['loop'] ) : 0 );
123 + $limit = ( isset( $_POST['limit'] ) ? absint( $_POST['limit'] ) : 100 );
124 + $offset = $limit * $loop;
125 +
126 + /**
127 + * Hook to process activity recount
128 + *
129 + * @since 1.1.8
130 + * @updated 1.4.2 Added $loop parameter
131 + * @updated 1.8.2 Added $limit and $offset parameters
132 + *
133 + * @param array $response Response to return. Response format: array(
134 + * success => true|false,
135 + * run_again => true|false,
136 + * message => string,
137 + * log => string,
138 + * )
139 + * @param int $loop Parameter to meet in which loop is the tool (just increased if run_again is set to true).
140 + * Important: First loop will be 0.
141 + *
142 + * @param int $limit Limit per loop, by default 100
143 + * @param int $offset Current offset
144 + */
145 + $response = apply_filters( "gamipress_activity_recount_$activity", $response, $loop, $limit, $offset );
146 +
147 + if( ! is_array( $response ) ) {
148 + wp_send_json_error( 'Activity recount process has failed!', 'gamipress' );
149 + }
150 +
151 + // Return the full response
152 + if( $response['run_again'] ) {
153 + wp_send_json_success( $response );
154 + }
155 +
156 + // Return the process response
157 + if( $response['success'] === true ) {
158 + wp_send_json_success( $response['message'] );
159 + } else {
160 + wp_send_json_error( $response['message'] );
161 + }
162 +
163 +}
164 +add_action( 'wp_ajax_gamipress_recount_activity_tool', 'gamipress_ajax_recount_activity_tool' );
165 +
166 +/**
167 + * Recount comments activity
168 + *
169 + * @since 1.1.8
170 + * @updated 1.4.2 Added $loop parameter
171 + *
172 + * @param array $response
173 + * @param int $loop
174 + * @param int $limit
175 + * @param int $offset
176 + *
177 + * @return array $response
178 + */
179 +function gamipress_activity_recount_comments( $response, $loop, $limit, $offset ) {
180 +
181 + global $wpdb;
182 +
183 + // Get all approved comments count
184 + $comments_count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->comments} WHERE comment_approved = '1'" ) );
185 +
186 + // On first loop send an informational text
187 + if( $loop === 0 && $comments_count > $limit ) {
188 + $response['run_again'] = true;
189 + $response['message'] = sprintf( __( '%d comments found, recounting...', 'gamipress' ), $comments_count );
190 + $response['log'] = sprintf( __( '%d comments found, recounting...', 'gamipress' ), $comments_count ) . "<br>\n";
191 +
192 + // Return early to inform
193 + return $response;
194 + }
195 +
196 + // Get all approved comments
197 + $comments = $wpdb->get_results( "SELECT * FROM {$wpdb->comments} WHERE comment_approved = '1' LIMIT {$offset}, {$limit}" );
198 +
199 + foreach( $comments as $comment ) {
200 +
201 + $comment_id = (int) $comment->comment_ID;
202 + $user_id = (int) $comment->user_id;
203 + $post_id = (int) $comment->comment_post_ID;
204 + $post_type = get_post_type( $post_id );
205 +
206 + // Skip wrong comments
207 + if( $comment_id === 0 ) continue;
208 +
209 + // Skip not user assigned comments
210 + if( $user_id === 0 ) continue;
211 +
212 + // Trigger comment actions to user
213 + do_action( 'gamipress_new_comment', $comment_id, $user_id, $post_id, $comment );
214 + do_action( 'gamipress_specific_new_comment', $comment_id, $user_id, $post_id, $comment );
215 + do_action( 'gamipress_new_comment_post_type', $comment_id, $user_id, $post_id, $post_type, $comment );
216 +
217 + $response['log'] .= sprintf( __( '[Comment on a post] Comment: %s User: %s Post: %s', 'gamipress' ),
218 + $comment_id,
219 + '<a href="' . get_edit_user_link( $user_id ) . '" target="_blank">' . $user_id . '</a>',
220 + '<a href="' . get_edit_post_link( $post_id ) . '" target="_blank">' . $post_id . '</a>'
221 + ) . "<br>\n";
222 +
223 + if( $post_id !== 0 ) {
224 +
225 + $post_author = absint( get_post_field( 'post_author', $post_id ) );
226 +
227 + // Trigger comment actions to author
228 + do_action( 'gamipress_user_post_comment', $comment_id, $post_author, $post_id, $comment );
229 + do_action( 'gamipress_user_specific_post_comment', $comment_id, $post_author, $post_id, $comment );
230 + do_action( 'gamipress_user_post_comment_post_type', $comment_id, $post_author, $post_id, $post_type, $comment );
231 +
232 + $response['log'] .= sprintf( __( '[Get a comment on a post] Comment: %s User: %s Post: %s', 'gamipress' ),
233 + $comment_id,
234 + '<a href="' . get_edit_user_link( $post_author ) . '" target="_blank">' . $post_author . '</a>',
235 + '<a href="' . get_edit_post_link( $post_id ) . '" target="_blank">' . $post_id . '</a>'
236 + ) . "<br>\n";
237 + }
238 + }
239 +
240 + $recounted_comments = $limit * ( $loop + 1 );
241 +
242 + // Check remaining comments
243 + if( $recounted_comments < $comments_count ) {
244 + $response['run_again'] = true;
245 + $response['message'] = sprintf( __( '%d remaining comments to finish recount', 'gamipress' ), ( $comments_count - $recounted_comments ) );
246 + }
247 +
248 + return $response;
249 +
250 +}
251 +add_filter( 'gamipress_activity_recount_comments', 'gamipress_activity_recount_comments', 10, 4 );
252 +
253 +/**
254 + * Recount published content
255 + *
256 + * @since 1.1.8
257 + * @updated 1.4.2 Added $loop parameter
258 + *
259 + * @param array $response
260 + * @param int $loop
261 + * @param int $limit
262 + * @param int $offset
263 + *
264 + * @return array $response
265 + */
266 +function gamipress_activity_recount_published_content( $response, $loop, $limit, $offset ) {
267 +
268 + global $wpdb;
269 +
270 + // Get all public post types which means they are visitable
271 + $public_post_types = get_post_types( array( 'public' => true ) );
272 +
273 + // Remove attachment from public post types
274 + if( isset( $public_post_types['attachment'] ) )
275 + unset( $public_post_types['attachment'] );
276 +
277 + // Get all published posts
278 + $posts_count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type IN ( '" . implode( "', '", $public_post_types ) . "' )" ) );
279 +
280 + // On first loop send an informational text
281 + if( $loop === 0 && $posts_count > $limit ) {
282 + $response['run_again'] = true;
283 + $response['message'] = sprintf( __( '%d posts found, recounting...', 'gamipress' ), $posts_count );
284 + $response['log'] = sprintf( __( '%d posts found, recounting...', 'gamipress' ), $posts_count ) . "<br>\n";
285 +
286 + // Return early to inform
287 + return $response;
288 + }
289 +
290 + // Get all published posts
291 + $posts = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} WHERE post_status = 'publish' AND post_type IN ( '" . implode( "', '", $public_post_types ) . "' ) LIMIT {$offset}, {$limit}" );
292 +
293 + foreach( $posts as $post ) {
294 + // Trigger content publishing action for each post
295 + gamipress_trigger_event( array(
296 + 'event' => "gamipress_publish_{$post->post_type}",
297 + 'post_id' => $post->ID,
298 + 'user_id' => $post->post_author,
299 + 'post' => $post,
300 + ) );
301 +
302 + // Trigger post type publishing actions
303 + gamipress_trigger_event( array(
304 + 'event' => 'gamipress_publish_post_type',
305 + 'post_id' => $post->ID,
306 + 'user_id' => $post->post_author,
307 + 'post_type' => $post->post_type,
308 + 'post' => $post,
309 + ) );
310 +
311 + $response['log'] .= sprintf( __( '[Publish a post] Post: %s User: %s Post Type: %s', 'gamipress' ),
312 + '<a href="' . get_edit_post_link( $post->ID ) . '" target="_blank">' . $post->ID . '</a>',
313 + '<a href="' . get_edit_user_link( $post->post_author ) . '" target="_blank">' . $post->post_author . '</a>',
314 + $post->post_type
315 + ) . "<br>\n";
316 + }
317 +
318 + $recounted_posts = $limit * ( $loop + 1 );
319 +
320 + // Check remaining posts
321 + if( $recounted_posts < $posts_count ) {
322 + $response['run_again'] = true;
323 + $response['message'] = sprintf( __( '%d remaining posts to finish recount', 'gamipress' ), ( $posts_count - $recounted_posts ) );
324 + }
325 +
326 + return $response;
327 +
328 +}
329 +add_filter( 'gamipress_activity_recount_published_content', 'gamipress_activity_recount_published_content', 10, 4 );