__( 'Post Order history', '3task-post-order' ), 'callback' => array( self::class, 'export_history' ), ); return $exporters;} ); add_filter( 'wp_privacy_personal_data_erasers', static function ( $erasers ) { $erasers['threepo'] = array( 'eraser_friendly_name' => __( 'Post Order history', '3task-post-order' ), 'callback' => array( self::class, 'erase_history' ), ); return $erasers;} ); add_action( 'rest_api_init', array( self::class, 'routes' ) ); register_deactivation_hook( THREEPO_FILE, array( self::class, 'deactivate' ) ); } public static function upgrade(): void { global $wpdb; if ( (int) get_option( 'threepo_schema', 0 ) < 5 ) { $lock = substr( Store::table( 'schema_lock' ), 0, 64 ); if ( (int) $wpdb->get_var( $wpdb->prepare( 'SELECT GET_LOCK(%s,0)', $lock ) ) === 1 ) { try { Store::install(); } finally { $wpdb->get_var( $wpdb->prepare( 'SELECT RELEASE_LOCK(%s)', $lock ) ); } } } if ( ! wp_next_scheduled( 'threepo_cleanup' ) ) { wp_schedule_event( time() + DAY_IN_SECONDS, 'daily', 'threepo_cleanup' ); } } public static function deactivate(): void { wp_clear_scheduled_hook( 'threepo_cleanup' ); } public static function cleanup(): void { global $wpdb; $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE created<%s', Store::table( 'history' ), gmdate( 'Y-m-d H:i:s', time() - 30 * DAY_IN_SECONDS ) ) ); $wpdb->query( $wpdb->prepare( 'DELETE s FROM %i s LEFT JOIN %i h ON h.context_id=s.context_id AND h.revision=s.revision WHERE h.id IS NULL', Store::table( 'snapshots' ), Store::table( 'history' ) ) ); } public static function routes(): void { register_rest_route( 'threepo/v1', '/settings', array( array( 'methods' => 'GET', 'permission_callback' => static function () { return current_user_can( 'manage_options' ); }, 'callback' => static function () { return array( 'delete_data' => (bool) get_option( 'threepo_delete_data', false ), 'conflicts' => Importer::conflicts(), ); }, ), array( 'methods' => 'POST', 'permission_callback' => static function () { return current_user_can( 'manage_options' ); }, 'callback' => static function ( $r ) { $body = Api::body( $r, array( 'delete_data' ) ); if ( is_wp_error( $body ) ) { return $body; } update_option( 'threepo_delete_data', (bool) $r['delete_data'], false ); return array( 'delete_data' => (bool) get_option( 'threepo_delete_data', false ) ); }, 'args' => array( 'delete_data' => array( 'type' => 'boolean', 'required' => true, ), ), ), ) ); add_filter( 'rest_pre_dispatch', static function ( $result, $server, $request ) { if ( strpos( strtolower( $request->get_route() ), '/threepo/v1/' ) === 0 && strlen( (string) $request->get_body() ) > 65536 ) { return rest_convert_error_to_response( Store::error( 'size', __( 'The request is too large.', '3task-post-order' ), 413 ) ); } return $result; }, 1, 3 ); } /** @return array */ public static function export_history( string $email, int $page = 1 ): array { global $wpdb; $user = get_user_by( 'email', $email ); if ( ! $user ) { return array( 'data' => array(), 'done' => true, ); } $rows = $wpdb->get_results( $wpdb->prepare( 'SELECT id,context_id,action,created FROM %i WHERE actor=%d ORDER BY id LIMIT 100 OFFSET %d', Store::table( 'history' ), $user->ID, ( max( 1, $page ) - 1 ) * 100 ), ARRAY_A ); $data = array(); foreach ( $rows as $row ) { $data[] = array( 'group_id' => 'threepo-history', 'group_label' => __( 'Post Order history', '3task-post-order' ), 'item_id' => 'threepo-' . $row['id'], 'data' => array( array( 'name' => __( 'Context', '3task-post-order' ), 'value' => (string) $row['context_id'], ), array( 'name' => __( 'Action', '3task-post-order' ), 'value' => $row['action'], ), array( 'name' => __( 'Date (UTC)', '3task-post-order' ), 'value' => $row['created'], ), ), ); } return array( 'data' => $data, 'done' => count( $rows ) < 100, ); } /** @return array */ public static function erase_history( string $email ): array { global $wpdb; $user = get_user_by( 'email', $email ); $removed = false; if ( $user ) { $result = $wpdb->update( Store::table( 'history' ), array( 'actor' => 0, 'fingerprint' => hash( 'sha256', wp_generate_uuid4() ), ), array( 'actor' => $user->ID ) ); if ( false === $result ) { return array( 'items_removed' => false, 'items_retained' => true, 'messages' => array( __( 'History could not be anonymized. Please retry.', '3task-post-order' ) ), 'done' => false, ); } $removed = $result > 0; } return array( 'items_removed' => $removed, 'items_retained' => false, 'messages' => array(), 'done' => true, ); } }