KOKINIO - MANAGER
Edit File: hustle-entry-model.php
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName /** * Hustle_Entry_Model * * @package Hustle */ /** * Entry model. * Base model for all entries. * * @since 4.0 */ class Hustle_Entry_Model { /** * Entry id * * @var int */ public $entry_id = 0; /** * Entry type * * @var string */ public $entry_type; /** * Module id * * @var int */ public $module_id; /** * Date created in sql format 0000-00-00 00:00:00 * * @var string */ public $date_created_sql; /** * Date created in sql format D M Y * * @var string */ public $date_created; /** * Time created in sql format D M Y @ H:i A * * @var string */ public $time_created; /** * Meta data * * @var array */ public $meta_data = array(); /** * The table name * * @var string */ protected $table_name; /** * The table meta name * * @var string */ protected $table_meta_name; /** * Hold information about connected addons * * @var array */ private static $connected_addons = array(); /** * Subscribed emails * * @var type array */ private static $subscribed_emails = array(); /** * Initialize the Model * * @since 4.0 * @param int $entry_id Entry id. */ public function __construct( $entry_id = null ) { $this->table_name = Hustle_Db::entries_table(); $this->table_meta_name = Hustle_Db::entries_meta_table(); if ( is_numeric( $entry_id ) && $entry_id > 0 ) { $this->get( $entry_id ); } } /** * Load an entry by its id. * After load, set entry to cache. * * @since 4.0 * * @param int $entry_id Entry id. * @return bool|mixed */ public function get( $entry_id ) { global $wpdb; $cache_key = get_class( $this ); $entry_object_cache = wp_cache_get( $entry_id, $cache_key ); if ( $entry_object_cache ) { $this->entry_id = $entry_object_cache->entry_id; $this->entry_type = $entry_object_cache->entry_type; $this->module_id = $entry_object_cache->module_id; $this->date_created_sql = $entry_object_cache->date_created_sql; $this->date_created = $entry_object_cache->date_created; $this->time_created = $entry_object_cache->time_created; $this->meta_data = $entry_object_cache->meta_data; return $entry_object_cache; } else { $sql = "SELECT `entry_type`, `module_id`, `date_created` FROM {$this->table_name} WHERE `entry_id` = %d"; $entry = $wpdb->get_row( $wpdb->prepare( $sql, $entry_id ) );// phpcs:ignore if ( $entry ) { $this->entry_id = $entry_id; $this->entry_type = $entry->entry_type; $this->module_id = $entry->module_id; $this->date_created_sql = $entry->date_created; $this->date_created = date_i18n( 'j M Y', strtotime( $entry->date_created ) ); $this->time_created = date_i18n( 'j M Y @ H:i A', strtotime( $entry->date_created ) ); $this->load_meta(); // TODO: check if the cache behaves properly when the module's form fields are updated. wp_cache_set( $entry_id, $this, $cache_key ); } } } /** * Set entry fields. * * @since 4.0 * * @param array $meta_array Array of data to be saved. * * @type key - string the meta key * @type value - string the meta value * } * @param string $date_created Created date, default null will be completed. * * @return bool */ public function set_fields( $meta_array, $date_created = null ) { global $wpdb; if ( $meta_array && ! is_array( $meta_array ) && ! empty( $meta_array ) ) { return false; } // Set the meta_data values even though entry_id is null for object reference for its usage in the future. // entry_id has null value is the outcome of failed to save or local list is disabled. if ( ! $this->entry_id ) { foreach ( $meta_array as $meta ) { if ( isset( $meta['name'] ) && isset( $meta['value'] ) ) { $key = $meta['name']; $value = $meta['value']; $key = wp_unslash( $key ); $value = wp_unslash( $value ); $this->meta_data[ $key ] = array( 'id' => $key, 'value' => $value, ); } } return false; } if ( empty( $date_created ) ) { $date_created = Hustle_Time_Helper::get_current_date(); } // clear cache first. $cache_key = get_class( $this ); wp_cache_delete( $this->entry_id, $cache_key ); foreach ( $meta_array as $meta ) { if ( isset( $meta['name'] ) && isset( $meta['value'] ) ) { $key = $meta['name']; $value = $meta['value']; $key = wp_unslash( $key ); $value = wp_unslash( $value ); $value = maybe_serialize( $value ); $meta_id = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $this->table_meta_name, array( 'entry_id' => $this->entry_id, 'meta_key' => $key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => $value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value 'date_created' => $date_created, ) ); // Set meta data for later usage. if ( $meta_id ) { $this->meta_data[ $key ] = array( 'id' => $meta_id, 'value' => is_array( $value ) ? array_map( 'maybe_unserialize', $value ) : maybe_unserialize( $value ), ); } } } return true; } /** * Load all meta data for entry * * @since 4.0 * * @param object|bool $db - the WP_Db object. */ public function load_meta( $db = false ) { if ( ! $db ) { global $wpdb; $db = $wpdb; } $this->meta_data = array(); $sql = "SELECT `meta_id`, `meta_key`, `meta_value` FROM {$this->table_meta_name} WHERE `entry_id` = %d"; $results = $db->get_results( $db->prepare( $sql, $this->entry_id ) ); foreach ( $results as $result ) { $key = $result->meta_key; $this->meta_data[ $key ] = array( 'id' => $result->meta_id, 'value' => is_array( $result->meta_value ) ? array_map( 'maybe_unserialize', $result->meta_value ) : maybe_unserialize( $result->meta_value ), ); } } /** * Get Meta * * @since 4.0 * * @param string $meta_key - the meta key. * @param bool|object $default_value - the default value. * * @return bool|string */ public function get_meta( $meta_key, $default_value = false ) { if ( ! empty( $this->meta_data ) && isset( $this->meta_data[ $meta_key ] ) ) { return $this->meta_data[ $meta_key ]['value']; } return $default_value; } /** * Update Meta * * @since 4.0.2 * * @param string $meta_id Meta id. * @param string $meta_key - the meta key. * @param bool|object $default_value - the default value. * @param string $date_updated Date updated. * @param string $date_created Date created. */ public function update_meta( $meta_id, $meta_key, $default_value = false, $date_updated = '', $date_created = '' ) { global $wpdb; $updated_meta = array( 'entry_id' => $this->entry_id, 'meta_key' => $meta_key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => $default_value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ); if ( ! empty( $date_updated ) ) { $updated_meta['date_updated'] = $date_updated; } if ( ! empty( $date_created ) ) { $updated_meta['date_created'] = $date_created; } $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $this->table_meta_name, $updated_meta, array( 'meta_id' => $meta_id, ) ); $cache_key = get_class( $this ); wp_cache_delete( $this->entry_id, $cache_key ); $this->get( $this->entry_id ); } /** * Save entry * * @since 4.0 * * @param string $date_created Created date, default null will be completed. * * @return bool */ public function save( $date_created = null ) { global $wpdb; if ( empty( $date_created ) ) { $date_created = Hustle_Time_Helper::get_current_date(); } $result = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $this->table_name, array( 'entry_type' => $this->entry_type, 'module_id' => $this->module_id, 'date_created' => $date_created, ) ); if ( ! $result ) { return false; } wp_cache_delete( $this->module_id, 'hustle_total_entries' ); wp_cache_delete( $this->module_id, 'hustle_subscribed_emails' ); wp_cache_delete( 'all_module_types', 'hustle_total_entries' ); wp_cache_delete( $this->entry_type . '_module_type', 'hustle_total_entries' ); $this->entry_id = (int) $wpdb->insert_id; return true; } /** * Custom Query entries * * @since 4.0 * * @param array $args Args. * @param int $count pass by reference for get count. * * @return array Hustle_Entry_Model[] */ public static function query_entries( $args, &$count ) { global $wpdb; /** * $args * [ * module_id => X, * date_created=> array(), * search = '', * min_id => * max_id => * orderby => 'x', * order => 'DESC', * per_page => '10' * offset => 0 * ] */ if ( ! isset( $args['per_page'] ) ) { $args['per_page'] = 10; } if ( ! isset( $args['offset'] ) ) { $args['offset'] = 0; } if ( ! isset( $args['order'] ) ) { $args['order'] = 'DESC'; } $entries_table_name = Hustle_Db::entries_table(); $entries_meta_table_name = Hustle_Db::entries_meta_table(); $entries = array(); // Building where. $where = 'WHERE 1=1'; // exclude Addon meta. $where .= $wpdb->prepare( ' AND metas.meta_key NOT LIKE %s', $wpdb->esc_like( 'hustle_provider_' ) . '%' ); if ( isset( $args['module_id'] ) ) { $where .= $wpdb->prepare( ' AND entries.module_id = %d', $args['module_id'] ); } if ( isset( $args['date_created'] ) ) { $date_created = $args['date_created']; if ( is_array( $date_created ) && isset( $date_created[0] ) && isset( $date_created[1] ) ) { $date_created[1] = $date_created[1] . ' 23:59:00'; $where .= $wpdb->prepare( ' AND ( entries.date_created >= %s AND entries.date_created <= %s )', $date_created[0], $date_created[1] ); } } if ( isset( $args['search_email'] ) ) { $where .= $wpdb->prepare( ' AND metas.meta_value LIKE %s', '%' . $wpdb->esc_like( $args['search_email'] ) . '%' ); } // group. $group_by = 'GROUP BY entries.entry_id'; $group_by = apply_filters( 'hustle_query_entries_group_by', $group_by, $args ); // order by. $order_by = 'ORDER BY entries.entry_id'; if ( isset( $args['order_by'] ) ) { $order_by = 'ORDER BY ' . $args['order_by']; // unesacaped. } $order_by = apply_filters( 'hustle_query_entries_order_by', $order_by, $args ); // order (DESC/ASC). $order = $args['order']; $order = apply_filters( 'hustle_query_entries_order', $order, $args ); // limit. $limit = $wpdb->prepare( 'LIMIT %d, %d', $args['offset'], $args['per_page'] ); $limit = apply_filters( 'hustle_query_entries_limit', $limit, $args ); // sql count. $sql_count = "SELECT count(DISTINCT entries.entry_id) as total_entries FROM {$entries_table_name} AS entries INNER JOIN {$entries_meta_table_name} AS metas ON (entries.entry_id = metas.entry_id) {$where} "; $sql_count = apply_filters( 'hustle_query_entries_sql_count', $sql_count, $args ); $count = intval( $wpdb->get_var( $sql_count ) );// phpcs:ignore if ( $count > 0 ) { // sql. $sql = "SELECT entries.entry_id AS entry_id FROM {$entries_table_name} AS entries INNER JOIN {$entries_meta_table_name} AS metas ON (entries.entry_id = metas.entry_id) {$where} {$group_by} {$order_by} {$order} {$limit} "; $sql = apply_filters( 'hustle_query_entries_sql', $sql, $args ); $results = $wpdb->get_results( $sql );// phpcs:ignore foreach ( $results as $result ) { $entries[] = new Hustle_Entry_Model( $result->entry_id ); } } return $entries; } /** * Count entries by module * * @since 4.0 * * @param int $module_id Module ID. * @param object|bool $db - the WP_Db object. * @return int - total entries */ public static function count_entries( $module_id, $db = false ) { if ( ! $db ) { global $wpdb; $db = $wpdb; } $cache_key = 'hustle_total_entries'; $entries_cache = wp_cache_get( $module_id, $cache_key ); if ( $entries_cache ) { return $entries_cache; } else { $table_name = Hustle_Db::entries_table(); $sql = "SELECT count(`entry_id`) FROM {$table_name} WHERE `module_id` = %d"; $entries = $db->get_var( $db->prepare( $sql, $module_id ) ); if ( $entries ) { wp_cache_set( $module_id, $entries, $cache_key ); return $entries; } } return 0; } /** * Get global count entries * * @since 4.0 * * @return int - total entries */ public static function global_count_entries() { global $wpdb; $cache_group = 'hustle_total_entries'; $cache_key = 'global_count'; $entries_cache = wp_cache_get( $cache_key, $cache_group ); if ( $entries_cache ) { $global_count = $entries_cache; } else { $table_name = Hustle_Db::entries_table(); $global_count = (int) $wpdb->get_var( "SELECT count(`entry_id`) FROM {$table_name}" );// phpcs:ignore wp_cache_set( $cache_key, $global_count, $cache_group ); } return $global_count; } /** * Ignored fields * Fields not saved nor shown in submissions or export. * * @since 4.0 * * @return array */ public static function ignored_fields() { return apply_filters( 'hustle_entry_ignored_fields', array( 'recaptcha', 'turnstile', 'submit' ) ); } /** * Get all entries from a module. * * @since 4.0.1 * * @param int $module_id Module ID. * @return Hustle_Entry_Model[] */ public static function get_entries( $module_id ) { global $wpdb; $entries = array(); $table_name = Hustle_Db::entries_table(); $sql = "SELECT `entry_id` FROM {$table_name} WHERE `module_id` = %d ORDER BY `entry_id` DESC"; $results = $wpdb->get_results( $wpdb->prepare( $sql, $module_id ) );// phpcs:ignore if ( ! empty( $results ) ) { foreach ( $results as $result ) { $entries[] = new Hustle_Entry_Model( $result->entry_id ); } } return $entries; } /** * Delete entries by a string of comma separated entres ids * * @since 4.0 * * @param int $module_id Module ID. * @param array $entries Entries. * @param object|bool $db - the WP_Db object. * * @return bool */ public static function delete_by_entries( $module_id, $entries, $db = false ) { if ( ! $db ) { global $wpdb; $db = $wpdb; } if ( empty( $entries ) ) { return false; } $table_name = Hustle_Db::entries_table(); $table_meta_name = Hustle_Db::entries_meta_table(); $module_id = (int) $module_id; $prepared_placeholders = implode( ', ', array_fill( 0, count( $entries ), '%s' ) ); /** * Fires just before an entry getting deleted * * @since 4.0 */ do_action_ref_array( 'hustle_before_delete_entries', array( $module_id, $entries ) ); $sql = $db->prepare( "DELETE FROM {$table_meta_name} WHERE `entry_id` IN ($prepared_placeholders)", $entries ); $db->query( $sql ); $sql = $db->prepare( "DELETE FROM {$table_name} WHERE `entry_id` IN ($prepared_placeholders)", $entries ); $db->query( $sql ); wp_cache_delete( $module_id, 'hustle_total_entries' ); wp_cache_delete( $module_id, 'hustle_subscribed_emails' ); wp_cache_delete( 'all_module_types', 'hustle_total_entries' ); $module_type = Hustle_Model::get_module_type_by_module_id( $module_id ); if ( ! is_wp_error( $module_type ) ) { wp_cache_delete( $module_type . '_module_type', 'hustle_total_entries' ); } } /** * Delete by entry. * * @since 4.0 * * @param int $module_id Module ID. * @param int $entry_id Entry id. * @param object|bool $db - the WP_Db object. */ public static function delete_by_entry( $module_id, $entry_id, $db = false ) { if ( ! $db ) { global $wpdb; $db = $wpdb; } $table_name = Hustle_Db::entries_table(); $table_meta_name = Hustle_Db::entries_meta_table(); $cache_key = __CLASS__; $module_id = (int) $module_id; $entry_id = (int) $entry_id; $entry_model = new Hustle_Entry_Model( $entry_id ); $sql = "DELETE FROM {$table_meta_name} WHERE `entry_id` = %d"; $db->query( $db->prepare( $sql, $entry_id ) ); $sql = "DELETE FROM {$table_name} WHERE `entry_id` = %d"; $db->query( $db->prepare( $sql, $entry_id ) ); wp_cache_delete( $entry_id, $cache_key ); wp_cache_delete( $module_id, 'hustle_total_entries' ); wp_cache_delete( $module_id, 'hustle_subscribed_emails' ); wp_cache_delete( 'all_module_types', 'hustle_total_entries' ); wp_cache_delete( $entry_model->entry_type . '_module_type', 'hustle_total_entries' ); } /** * Delete entries * * @global object $wpdb * @param int $module_id Module ID. */ public static function delete_entries( $module_id ) { global $wpdb; $entires_table = Hustle_Db::entries_table(); $entires_meta_table = Hustle_Db::entries_meta_table(); $entires = $wpdb->get_col( $wpdb->prepare( "SELECT `entry_id` FROM {$entires_table} WHERE `module_id` = %d", $module_id ) ); // phpcs:ignore if ( $entires ) { // delete entries meta data. $wpdb->query( "DELETE FROM {$entires_meta_table} WHERE `entry_id` IN ('" . implode( "','", $entires ) . "')" ); // phpcs:ignore // delete entries data. $wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $entires_table, array( 'module_id' => $module_id, ), array( '%d', ) ); wp_cache_delete( $module_id, 'hustle_total_entries' ); wp_cache_delete( $module_id, 'hustle_subscribed_emails' ); wp_cache_delete( 'all_module_types', 'hustle_total_entries' ); $available_entry_types = self::available_entry_types(); foreach ( $available_entry_types as $type ) { wp_cache_delete( $type . '_module_type', 'hustle_total_entries' ); } $cache_key = __CLASS__; foreach ( $entires as $entry_id ) { wp_cache_delete( $entry_id, $cache_key ); } } } /** * Convert meta value to string. * Useful for displaying metadata without PHP warnings on conversion. * * @since 4.0 * * @param string $field_type Field type. * @param string $meta_value Meta value. * @param bool $allow_html Allow HTML. * @param int $truncate truncate returned string (usefull if display container is limited). * * @return string */ public static function meta_value_to_string( $field_type, $meta_value, $allow_html = false, $truncate = PHP_INT_MAX ) { switch ( $field_type ) { case 'email': if ( ! empty( $meta_value ) ) { $string_value = $meta_value; // truncate. if ( $allow_html ) { // make link. $email = $string_value; // truncate. if ( strlen( $email ) > $truncate ) { $email = substr( $email, 0, $truncate ) . '...'; } $string_value = '<a href="' . esc_url( 'mailto:' . $email ) . '" target="_blank" title="' . esc_attr__( 'Send Email', 'hustle' ) . '">' . esc_html( $email ) . '</a>'; } elseif ( strlen( $string_value ) > $truncate ) { // truncate url. $string_value = substr( $string_value, 0, $truncate ) . '...'; } } else { $string_value = ''; } break; case 'url': if ( ! empty( $meta_value ) ) { $string_value = $meta_value; // truncate. if ( $allow_html ) { // make link. $website = $string_value; // truncate. if ( strlen( $website ) > $truncate ) { $website = substr( $website, 0, $truncate ) . '...'; } $string_value = '<a href="' . esc_url( $website ) . '" target="_blank" title="' . esc_attr__( 'View Website', 'hustle' ) . '">' . esc_html( $website ) . '</a>'; } elseif ( strlen( $string_value ) > $truncate ) { // truncate url. $string_value = substr( $string_value, 0, $truncate ) . '...'; } } else { $string_value = ''; } break; default: // base flattener // implode on array. if ( is_array( $meta_value ) ) { $string_value = implode( ', ', $meta_value ); } else { // or juggling to string. $string_value = (string) $meta_value; } // truncate. if ( strlen( $string_value ) > $truncate ) { $string_value = substr( $string_value, 0, $truncate ) . '...'; } break; } return $string_value; } /** * Get the stored number of entries. * * @since 4.0 * @return int */ public static function get_total_entries_count() { global $wpdb; $table_name = Hustle_Db::entries_table(); $sql = "SELECT COUNT(`entry_id`) FROM {$table_name}"; return $wpdb->get_var( $sql );// phpcs:ignore } /** * Available entry types * * @return array */ private static function available_entry_types() { $available_entry_types = array( 'popup', 'slidein', 'embedded', 'all', ); return $available_entry_types; } /** * Get latest entry * * @since 4.0 * * @param string $entry_type Entry type. * @return Hustle_Entry_Model|null */ public static function get_latest_entry( $entry_type = 'popup' ) { $available_entry_types = self::available_entry_types(); if ( ! in_array( $entry_type, $available_entry_types, true ) ) { return null; } global $wpdb; $entry = null; $table_name = Hustle_Db::entries_table(); if ( 'all' !== $entry_type ) { $sql = "SELECT `entry_id` FROM {$table_name} WHERE `entry_type` = %s ORDER BY `date_created` DESC"; $sql = $wpdb->prepare( $sql, $entry_type );// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared } else { $sql = "SELECT `entry_id` FROM {$table_name} ORDER BY `date_created` DESC"; } $entry_id = $wpdb->get_var( $sql );// phpcs:ignore if ( ! empty( $entry_id ) ) { $entry = new Hustle_Entry_Model( $entry_id ); } return $entry; } /** * Get Latest Entry by module_id * * @since 4.0 * * @param int $module_id Module ID. * @return Hustle_Entry_Model|null */ public static function get_latest_entry_by_module_id( $module_id ) { global $wpdb; $entry = null; $table_name = Hustle_Db::entries_table(); $sql = "SELECT `entry_id` FROM {$table_name} WHERE `module_id` = %d ORDER BY `date_created` DESC"; $entry_id = $wpdb->get_var( $wpdb->prepare( $sql, $module_id ) );// phpcs:ignore if ( ! empty( $entry_id ) ) { $entry = new Hustle_Entry_Model( $entry_id ); } return $entry; } /** * Get entries newer than $date_created * Previously get_newer_entry_ids * * @since 4.0 * * @param string $entry_type Entry type. * @param string $date_created Date created. * * @return array */ public static function count_newer_entries_by_module_type( $entry_type, $date_created ) { global $wpdb; $entry_table_name = Hustle_Db::entries_table(); $sql = "SELECT count(`entry_id`) FROM {$entry_table_name} WHERE `entry_type` = %s AND `date_created` > %s"; $entries = $wpdb->get_var( $wpdb->prepare( $sql, $entry_type, $date_created ) );// phpcs:ignore return $entries; } /** * Get subscribed emails * * @global object $wpdb WPDB. * @param type $module_id Module ID. * @return array */ public static function get_subscribed_emails( $module_id ) { if ( isset( self::$subscribed_emails[ $module_id ] ) ) { return self::$subscribed_emails[ $module_id ]; } $cache_group = 'hustle_subscribed_emails'; $emails = wp_cache_get( $module_id, $cache_group ); if ( false === $emails ) { global $wpdb; $entries_table = Hustle_Db::entries_table(); $entries_meta_table = Hustle_Db::entries_meta_table(); $query = "SELECT DISTINCT e.entry_id as id, m.meta_value as val FROM {$entries_table} e INNER JOIN {$entries_meta_table} m ON e.entry_id = m.entry_id AND e.module_id = %d AND m.meta_key = 'email'"; $query = $wpdb->prepare( $query, $module_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $result = $wpdb->get_results( $query ); // phpcs:ignore $emails = wp_list_pluck( $result, 'val', 'id' ); wp_cache_set( $module_id, $emails, $cache_group ); } self::$subscribed_emails[ $module_id ] = $emails; return $emails; } /** * Check if there's a subscription with this email in this module. * * @since 4.0 * * @param int $module_id Module ID. * @param string $email Email. * @return bool */ public static function is_email_subscribed_to_module_id( $module_id, $email ) { $emails = self::get_subscribed_emails( $module_id ); $is_subscribed = in_array( $email, $emails, true ); return apply_filters( 'hustle_is_email_in_module_local_list', $is_subscribed, $module_id, $email ); } /** * Get entry_id by email. * * @since 4.0 * * @param int $module_id Module ID. * @param string $email Email. * @return int */ public static function get_email_subscribed_to_module_id( $module_id, $email ) { $emails = self::get_subscribed_emails( $module_id ); $id = array_search( $email, $emails, true ); $entry_id = apply_filters( 'hustle_email_entry_id_in_module_local_list', $id ); return $entry_id; } /** * Returns an array with the IDs of the modules to which the given email is subscribed to the local list. * * @since 4.0.0 * * @param string $email Email. * @return array */ public function get_modules_id_by_email_in_local_list( $email ) { global $wpdb; $cache_key = get_class( $this ); $id = wp_cache_get( 'local_' . $email, $cache_key ); if ( empty( $id ) ) { $query = $wpdb->prepare( 'SELECT DISTINCT `module_id` FROM ' . Hustle_Db::entries_table() . ' e INNER JOIN ' . Hustle_Db::entries_meta_table() . " m ON e.entry_id = m.entry_id AND m.meta_key = 'email' AND m.meta_value = %s", // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $email ); $id = $wpdb->get_col( $query );// phpcs:ignore wp_cache_set( 'local_' . $email, $id, $cache_key ); } return $id; } /** * Does the actual email unsubscription. * * @since 4.0.0 * @param string $email Email to be unsubscribed. * @param string $nonce Nonce associated with the email for the unsubscription. * @return boolean */ public function unsubscribe_email( $email, $nonce ) { $data = get_option( Hustle_Module_Model::KEY_UNSUBSCRIBE_NONCES, false ); if ( ! $data ) { return false; } if ( ! isset( $data[ $email ] ) || ! isset( $data[ $email ]['nonce'] ) || ! isset( $data[ $email ]['lists_id'] ) ) { return false; } $email_data = $data[ $email ]; if ( ! hash_equals( (string) $email_data['nonce'], $nonce ) ) { return false; } // Nonce expired. Remove it. Currently giving 1 day of life span. if ( ( time() - (int) $email_data['date_created'] ) > DAY_IN_SECONDS ) { unset( $data[ $email ] ); update_option( Hustle_Module_Model::KEY_UNSUBSCRIBE_NONCES, $data ); return false; } // Proceed to unsubscribe. foreach ( $email_data['lists_id'] as $id ) { $unsubscribed = $this->remove_local_subscription_by_email_and_module_id( $email, $id ); } // Clear cache after unsubscription. $cache_key = get_class( $this ); $id = wp_cache_delete( 'local_' . $email, $cache_key ); // The email was unsubscribed and the nonce was used. Remove it from the saved list. unset( $data[ $email ] ); update_option( Hustle_Module_Model::KEY_UNSUBSCRIBE_NONCES, $data ); return true; } /** * Removes the given email from the local list of the given module id. * * @since 4.0.0 * * @param string $email Email. * @param int $module_id Module ID. * @return array */ public function remove_local_subscription_by_email_and_module_id( $email, $module_id ) { $cache_group = 'hustle_entries'; $cache_key = $module_id . $email; $entries = wp_cache_get( $cache_key, $cache_group ); if ( false === $entries ) { global $wpdb; $query = sprintf( 'SELECT DISTINCT e.`entry_id` FROM %s e INNER JOIN %s m ON e.`entry_id` = m.`entry_id` AND m.`meta_key` = \'email\' AND m.`meta_value` = %%s WHERE e.`module_id` = %%d', Hustle_Db::entries_table(), Hustle_Db::entries_meta_table() ); $query = $wpdb->prepare( $query, $email, $module_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $entries = $wpdb->get_col( $query ); // phpcs:ignore wp_cache_set( $cache_key, $entries, $cache_group ); } if ( empty( $entries ) ) { return; } $unsubscribe_from_3rd_party_lists = apply_filters( 'hustle_unsubscribe_from_3rd_party_lists', true, $module_id ); if ( $unsubscribe_from_3rd_party_lists ) { $this->unsubscribe_from_3rd_party_lists( $module_id, $email, $entries ); } self::delete_by_entries( $module_id, $entries ); wp_cache_delete( $cache_key, $cache_group ); } /** * Unsubscribe from all subscribed integration lists * * @param string $module_id Module ID. * @param string $email Email. * @param array $entries Array of submission IDs. */ private function unsubscribe_from_3rd_party_lists( $module_id, $email, $entries ) { global $wpdb; foreach ( $entries as $entry_id ) { // phpcs:ignore $integrations = $wpdb->get_var( $wpdb->prepare( 'SELECT `meta_value` FROM ' . esc_sql( $this->table_meta_name ) . " WHERE `entry_id` = %d AND `meta_key` = 'active_integrations'", $entry_id ) ); if ( is_wp_error( $integrations ) ) { continue; } $integrations = maybe_unserialize( $integrations ); if ( ! $integrations || ! is_array( $integrations ) ) { continue; } // Submitted Integrations for this email. $slugs = array_keys( $integrations ); // Active Integrations for the module. $connected_addons = Hustle_Provider_Utils::get_addons_instance_connected_with_module( $module_id ); foreach ( $connected_addons as $connected_addon ) { $slug = $connected_addon->get_slug(); try { if ( ! in_array( $slug, $slugs, true ) ) { continue; } $form_hooks = $connected_addon->get_addon_form_hooks( $module_id ); if ( $form_hooks instanceof Hustle_Provider_Form_Hooks_Abstract && method_exists( $form_hooks, 'unsubscribe' ) ) { $form_hooks->unsubscribe( $email ); } } catch ( Exception $e ) { Opt_In_Utils::maybe_log( $slug, 'failed to unsubscribe', $e->getMessage() ); } } } } /** * Get entries older than $date_created * * @since 4.0.2 * * @param string $date_created Date created. * * @return array */ public static function get_older_entry_ids( $date_created ) { global $wpdb; $entries_table = Hustle_Db::entries_table(); $query = "SELECT e.entry_id AS entry_id FROM {$entries_table} e WHERE e.date_created < %s"; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $query = $wpdb->prepare( $query, $date_created ); // phpcs:ignore return $wpdb->get_col( $query ); } /** * Get entries by email * * @since 4.0.2 * @param string $email Email. * * @return array */ public static function get_entries_by_email( $email ) { global $wpdb; $meta_table = Hustle_Db::entries_meta_table(); $query = "SELECT m.entry_id AS entry_id FROM {$meta_table} m WHERE (m.meta_key LIKE %s) AND m.meta_value = %s GROUP BY m.entry_id"; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $query = $wpdb->prepare( $query, 'email', $email ); // phpcs:ignore return $wpdb->get_col( $query ); } /** * Delete all IP * * @since 4.0.0 */ public function delete_all_ips() { global $wpdb; $wpdb->delete( $this->table_meta_name, array( 'meta_key' => 'hustle_ip' ) );// phpcs:ignore } /** * Delete selected IPs * * @since 4.0.0 * * @param array $ips Array of IPs to remove. */ public function delete_selected_ips( $ips ) { if ( empty( $ips ) || ! is_array( $ips ) ) { return; } global $wpdb; $in = array(); $ranges = array(); foreach ( $ips as $one ) { if ( is_array( $one ) ) { $ranges[] = sprintf( '( INET_ATON( `meta_value` ) BETWEEN %d AND %d )', $one[0], $one[1] ); } else { $in[] = $one; } } $query = sprintf( 'DELETE FROM `%s` WHERE `meta_key` = \'hustle_ip\' AND ( ', Hustle_Db::entries_meta_table() ); if ( ! empty( $in ) ) { $formatted_in_array = array_map( function ( $a ) { return sprintf( '\'%s\'', $a ); }, $in ); $query .= sprintf( '`meta_value` IN ( %s ) ', implode( ', ', $formatted_in_array ) ); if ( ! empty( $ranges ) ) { $query .= 'OR '; } } if ( ! empty( $ranges ) ) { $query .= implode( ' OR ', $ranges ); } $query .= ' )'; $wpdb->query( $query );// phpcs:ignore } }