// phpcs:ignore Generic.Commenting.DocComment.MissingShort
/** @noinspection PhpIllegalPsrClassPathInspection */
namespace WPForms\Logger;
* Cache key name for total logs.
const CACHE_TOTAL_KEY = 'wpforms_logs_total';
* Get a not-limited total query.
* @since 1.9.0 Removed the argument.
public function __construct() {
$this->full_total = false;
$this->records_query = new RecordQuery();
$this->records = new Records();
public static function get_table_name(): string {
return $wpdb->prefix . 'wpforms_logs';
* Create table in the database.
public function create_table() {
$table = self::get_table_name();
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table (
id BIGINT(20) NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
message LONGTEXT NOT NULL,
types VARCHAR(255) NOT NULL,
create_at DATETIME NOT NULL,
* @param string $title Record title.
* @param string $message Record message.
* @param array|string $types Array, string, or string separated by comma types.
* @param int $form_id Record form ID.
* @param int $entry_id Record entry ID.
* @param int $user_id Record user ID.
public function add( $title, $message, $types, $form_id, $entry_id, $user_id ) {
Record::create( $title, $message, $types, $form_id, $entry_id, $user_id )
* @param int $limit Query limit of records.
* @param int $offset Offset of records.
* @param string $search Search.
* @param string $type Type of records.
public function records( $limit, $offset = 0, $search = '', $type = '' ) {
$data = $this->records_query->get( $limit, $offset, $search, $type );
$this->full_total = true;
$records = new Records();
// As we got raw data, we need to convert to Record.
foreach ( $data as $row ) {
$this->prepare_record( $row )
* @param int $id Record ID.
public function record( $id ) {
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
'SELECT * FROM ' . self::get_table_name() . ' WHERE id = %d', //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$item = $this->prepare_record( $item );
* Create record from DB row.
* @param object $row Row from DB.
private function prepare_record( $row ) {
absint( $row->entry_id ),
* Save records to the database.
// We can't use the empty function because it doesn't work with a Countable object.
if ( ! count( $this->records ) ) {
$sql = 'INSERT INTO ' . self::get_table_name() . ' ( `id`, `title`, `message`, `types`, `create_at`, `form_id`, `entry_id`, `user_id` ) VALUES ';
foreach ( $this->records as $record ) {
'( NULL, %s, %s, %s, %s, %d, %d, %d ),',
implode( ',', $record->get_types() ),
$record->get_date( 'sql' ),
$sql = rtrim( $sql, ',' );
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
//phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
wp_cache_delete( self::CACHE_TOTAL_KEY );
* Check if the database table exists.
public function table_exists() {
return DB::table_exists( self::get_table_name() );
* Get total count of logs.
public function get_total() {
$total = wp_cache_get( self::CACHE_TOTAL_KEY );
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared
$total = $this->full_total ? $wpdb->get_var( 'SELECT FOUND_ROWS()' ) : $wpdb->get_var( 'SELECT COUNT( ID ) FROM ' . self::get_table_name() );
//phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared
wp_cache_set( self::CACHE_TOTAL_KEY, $total, 'wpforms', DAY_IN_SECONDS );
* Clear all records in the Database.
public function clear_all() {
//phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$wpdb->query( 'TRUNCATE TABLE ' . self::get_table_name() );