dvadf
File manager - Edit - /home/centroca/public_html/Db.zip
Back
PK �D0]gE@n, n, Analytics/DB.phpnu �[��� <?php namespace WPForms\Db\Analytics; use DateTimeImmutable; use RuntimeException; use WPForms\Helpers\DB as HelpersDB; /** * Analytics DB operations. * * Writes raw snapshot headers and serves as the Lite query base for the * Forms Overview columns. Extended by WPForms\Pro\Db\Analytics\DB which adds * field-level writes and all Pro read queries. * * @since 2.0.0 */ class DB { /** * Per-request cache for the tables_exist() check. * * @since 2.0.0 * * @var bool|null */ private static $tables_exist; /** * Magic period_date value marking the lifetime sentinel row. * * Used in the analytics_forms and analytics_fields aggregate tables. * Real date far in the past (year 1000) so it's invisible to all realistic * date-range queries while remaining compatible with MySQL 5.7+ default * sql_mode (which rejects '0000-00-00'). * * @since 2.0.0 */ public const LIFETIME_SENTINEL_DATE = '1000-01-01'; /** * Get the full wp_wpforms_analytics_snapshots table name. * * @since 2.0.0 * * @return string Prefixed table name. */ public static function snapshots_table(): string { global $wpdb; return $wpdb->prefix . 'wpforms_analytics_snapshots'; } /** * Get the full wp_wpforms_analytics_forms table name. * * @since 2.0.0 * * @return string Prefixed table name. */ public static function forms_table(): string { global $wpdb; return $wpdb->prefix . 'wpforms_analytics_forms'; } /** * Whether all analytics tables required by the current tier exist. * * Checks the two Lite tables unconditionally, plus the two Pro-only * tables when Pro is active. Cached per request. * * @since 2.0.0 * * @return bool */ public static function tables_exist(): bool { if ( self::$tables_exist !== null ) { return self::$tables_exist; } global $wpdb; if ( ! $wpdb ) { return false; } $exists = HelpersDB::table_exists( self::snapshots_table() ) && HelpersDB::table_exists( self::forms_table() ); if ( $exists && wpforms()->is_pro() ) { $exists = HelpersDB::table_exists( $wpdb->prefix . 'wpforms_analytics_snapshot_fields' ) && HelpersDB::table_exists( $wpdb->prefix . 'wpforms_analytics_fields' ); } self::$tables_exist = $exists; return self::$tables_exist; } /** * Insert a snapshot header into wp_wpforms_analytics_snapshots. * * @since 2.0.0 * * @param array $data Snapshot header data. Required keys: form_id, session_id, * trigger_type, form_visible, payload, occurred_at. * Optional: page_number, processed (defaults 0). * * @return int|false Inserted row ID on success, false on failure. */ public function save( array $data ) { global $wpdb; $defaults = [ 'page_number' => null, 'processed' => 0, ]; $row = array_merge( $defaults, $data ); $formats = [ '%d', // form_id. '%s', // session_id. '%d', // trigger_type. '%d', // page_number (nullable — wpdb treats as int). '%d', // form_visible. '%s', // payload. '%s', // occurred_at. '%d', // processed. ]; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $result = $wpdb->insert( self::snapshots_table(), [ 'form_id' => (int) $row['form_id'], 'session_id' => (string) $row['session_id'], 'trigger_type' => (int) $row['trigger_type'], 'page_number' => isset( $row['page_number'] ) ? (int) $row['page_number'] : null, 'form_visible' => (int) $row['form_visible'], 'payload' => (string) $row['payload'], 'occurred_at' => (string) $row['occurred_at'], 'processed' => (int) $row['processed'], ], $formats ); if ( $result === false ) { return false; } return (int) $wpdb->insert_id; } /** * Upsert a daily form-level aggregate row. * * Uses INSERT ... ON DUPLICATE KEY UPDATE so repeat calls accumulate * delta values. Called by the nightly aggregation task. * * @since 2.0.0 * * @param int $form_id Form ID. * @param string $period_date Aggregation date (Y-m-d). * @param array $deltas Keys: views, unique_sessions, submissions. Missing keys default to 0. * * @return void * * @throws RuntimeException When the upsert fails, so the surrounding aggregation transaction rolls back. */ public function upsert_form_aggregate( int $form_id, string $period_date, array $deltas ): void { global $wpdb; $table = self::forms_table(); $views = (int) ( $deltas['views'] ?? 0 ); $unique_sessions = (int) ( $deltas['unique_sessions'] ?? 0 ); $submissions = (int) ( $deltas['submissions'] ?? 0 ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $result = $wpdb->query( $wpdb->prepare( "INSERT INTO {$table} (form_id, period_date, views, unique_sessions, submissions) VALUES (%d, %s, %d, %d, %d) ON DUPLICATE KEY UPDATE views = views + VALUES(views), unique_sessions = unique_sessions + VALUES(unique_sessions), submissions = submissions + VALUES(submissions)", $form_id, $period_date, $views, $unique_sessions, $submissions ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared if ( $result === false ) { wpforms_log( 'Analytics DB: upsert_form_aggregate failed', [ 'table' => $table, 'form_id' => $form_id, 'period_date' => $period_date, 'last_error' => $wpdb->last_error, ], [ 'type' => [ 'error' ], 'force' => true, ] ); // Abort the aggregation transaction: committing the marked-processed // snapshots while this additive delta was dropped would lose the delta // permanently. Throwing routes through aggregate_in_transaction()'s // catch, which rolls back so the snapshots are retried next run. // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message routed to the error log, not HTML output. throw new RuntimeException( 'Analytics aggregation: upsert_form_aggregate failed. ' . $wpdb->last_error ); } } /** * Upsert the lifetime sentinel row for a form. * * Convenience wrapper — period_date is always LIFETIME_SENTINEL_DATE. * * @since 2.0.0 * * @param int $form_id Form ID. * @param array $deltas Delta values (see upsert_form_aggregate). * * @return void */ public function upsert_form_sentinel( int $form_id, array $deltas ): void { $this->upsert_form_aggregate( $form_id, self::LIFETIME_SENTINEL_DATE, $deltas ); } /** * Get lifetime overview stats for the given forms. * * Hybrid query: merges the lifetime sentinel row (fast PK lookup) with * today's unprocessed snapshots (live count since the last nightly * aggregation). Returns correct numbers on brand-new installs too. * * @since 2.0.0 * * @param array $form_ids Form IDs to fetch stats for. * * @return array Map of form_id => [ 'views' => int, 'submissions' => int ]. */ public function get_overview_stats( array $form_ids ): array { if ( empty( $form_ids ) ) { return []; } global $wpdb; $form_ids = array_values( array_filter( array_map( 'absint', $form_ids ) ) ); if ( empty( $form_ids ) ) { return []; } $placeholders = implode( ',', array_fill( 0, count( $form_ids ), '%d' ) ); $forms_table = self::forms_table(); $snaps_table = self::snapshots_table(); [ $today_start, $tomorrow_start ] = $this->today_boundaries(); // Layer 1: lifetime sentinel rows (PK lookup). // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $sentinel_rows = $wpdb->get_results( $wpdb->prepare( "SELECT form_id, views, submissions FROM {$forms_table} WHERE form_id IN ({$placeholders}) AND period_date = %s", array_merge( $form_ids, [ self::LIFETIME_SENTINEL_DATE ] ) ), ARRAY_A ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared // Layer 2: today's unprocessed snapshots (index-friendly range filter). // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber $today_rows = $wpdb->get_results( $wpdb->prepare( "SELECT form_id, COUNT(DISTINCT session_id) AS views, COUNT(DISTINCT CASE WHEN trigger_type = 2 THEN session_id END) AS submissions FROM {$snaps_table} WHERE form_id IN ({$placeholders}) AND processed = 0 AND form_visible = 1 AND occurred_at >= %s AND occurred_at < %s GROUP BY form_id", array_merge( $form_ids, [ $today_start, $tomorrow_start ] ) ), ARRAY_A ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber return $this->merge_overview_layers( $sentinel_rows, $today_rows, $form_ids ); } /** * Compute today's window boundaries in site timezone as DATETIME strings. * * @since 2.0.0 * * @return array Tuple [ today_start, tomorrow_start ] in 'Y-m-d H:i:s' form. */ public function today_boundaries(): array { $tz = wp_timezone(); $today = new DateTimeImmutable( 'today', $tz ); $tomorrow = $today->modify( '+1 day' ); $today_start = $today->format( 'Y-m-d H:i:s' ); $tomorrow_start = $tomorrow->format( 'Y-m-d H:i:s' ); return [ $today_start, $tomorrow_start ]; } /** * Merge sentinel + today DB rows into a form_id-keyed map. * * @since 2.0.0 * * @param array $sentinel_rows Rows from layer 1. * @param array $today_rows Rows from layer 2. * @param array $form_ids Form IDs requested. * * @return array Map of form_id => stats. */ protected function merge_overview_layers( array $sentinel_rows, array $today_rows, array $form_ids ): array { $by_form = []; foreach ( $form_ids as $form_id ) { $by_form[ $form_id ] = [ 'views' => 0, 'submissions' => 0, ]; } $by_form = $this->accumulate_overview_rows( $by_form, $sentinel_rows ); return $this->accumulate_overview_rows( $by_form, $today_rows ); } /** * Add one query layer's rows into the form-keyed accumulator. * * Both overview layers (lifetime sentinel + today) share the same shape and * column set, so they accumulate through this single routine. * * @since 2.0.0 * * @param array $by_form Accumulator keyed by form_id. * @param array $rows Rows from one query layer. * * @return array The accumulator with $rows added. */ private function accumulate_overview_rows( array $by_form, array $rows ): array { foreach ( $rows as $row ) { $id = (int) $row['form_id']; $by_form[ $id ]['views'] += (int) $row['views']; $by_form[ $id ]['submissions'] += (int) $row['submissions']; } return $by_form; } } PK �D0]��Y� � Analytics/Forms.phpnu �[��� <?php namespace WPForms\Db\Analytics; use WPForms_DB; /** * Custom-tables handler for the analytics forms aggregate table. * * Owns the schema for wp_wpforms_analytics_forms and registers it with the * self-healing custom-tables registry. Read/write access lives in * WPForms\Db\Analytics\DB. The table uses a composite primary key * (form_id, period_date); the inherited scalar-PK CRUD is never used here. * * @since 2.0.0 */ class Forms extends WPForms_DB { /** * Primary class constructor. * * @since 2.0.0 */ public function __construct() { parent::__construct(); $this->table_name = self::get_table_name(); $this->primary_key = 'form_id'; $this->type = 'analytics_forms'; } /** * Get the table name. * * @since 2.0.0 * * @return string */ public static function get_table_name(): string { return DB::forms_table(); } /** * Create the table. * * @since 2.0.0 */ public function create_table(): void { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $query = "CREATE TABLE $this->table_name ( form_id BIGINT(20) UNSIGNED NOT NULL, period_date DATE NOT NULL, views INT(10) UNSIGNED NOT NULL DEFAULT 0, unique_sessions INT(10) UNSIGNED NOT NULL DEFAULT 0, submissions INT(10) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (form_id, period_date) ) {$charset_collate};"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $query ); } } PK �D0]<�u4] ] Analytics/Snapshots.phpnu �[��� <?php namespace WPForms\Db\Analytics; use WPForms_DB; /** * Custom-tables handler for the analytics snapshots table. * * Owns the schema for wp_wpforms_analytics_snapshots and registers it with the * self-healing custom-tables registry (WPForms_Lite::CUSTOM_TABLES) so it is * created on install and recreated by the Settings self-heal / recreate-tables * tool. Read/write access lives in WPForms\Db\Analytics\DB. * * @since 2.0.0 */ class Snapshots extends WPForms_DB { /** * Primary class constructor. * * @since 2.0.0 */ public function __construct() { parent::__construct(); $this->table_name = self::get_table_name(); $this->primary_key = 'id'; $this->type = 'analytics_snapshots'; } /** * Get the table name. * * @since 2.0.0 * * @return string */ public static function get_table_name(): string { return DB::snapshots_table(); } /** * Create the table. * * @since 2.0.0 */ public function create_table(): void { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $query = "CREATE TABLE $this->table_name ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, form_id BIGINT(20) UNSIGNED NOT NULL, session_id VARCHAR(64) NOT NULL, trigger_type TINYINT(3) UNSIGNED NOT NULL, page_number TINYINT(3) UNSIGNED NULL DEFAULT NULL, form_visible TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, payload LONGTEXT NOT NULL, occurred_at DATETIME NOT NULL, processed TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY idx_unprocessed (processed, occurred_at), KEY idx_session (session_id, form_id, trigger_type), KEY idx_form_date (form_id, processed, form_visible, occurred_at) ) {$charset_collate};"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $query ); } } PK �D0]��dN�4 �4 Payments/Payment.phpnu �[��� <?php namespace WPForms\Db\Payments; use WPForms_DB; /** * Class for the Payments database table. * * @since 1.8.2 */ class Payment extends WPForms_DB { /** * Primary class constructor. * * @since 1.8.2 */ public function __construct() { parent::__construct(); $this->table_name = self::get_table_name(); $this->primary_key = 'id'; $this->type = 'payment'; } /** * Get the table name. * * @since 1.8.2 * * @return string */ public static function get_table_name() { global $wpdb; return $wpdb->prefix . 'wpforms_payments'; } /** * Get table columns. * * @since 1.8.2 * * @return array */ public function get_columns() { return [ 'id' => '%d', 'form_id' => '%d', 'status' => '%s', 'subtotal_amount' => '%f', 'discount_amount' => '%f', 'total_amount' => '%f', 'currency' => '%s', 'entry_id' => '%d', 'gateway' => '%s', 'type' => '%s', 'mode' => '%s', 'transaction_id' => '%s', 'customer_id' => '%s', 'subscription_id' => '%s', 'subscription_status' => '%s', 'title' => '%s', 'date_created_gmt' => '%s', 'date_updated_gmt' => '%s', 'is_published' => '%d', ]; } /** * Default column values. * * @since 1.8.2 * * @return array */ public function get_column_defaults() { $date = gmdate( 'Y-m-d H:i:s' ); return [ 'form_id' => 0, 'status' => '', 'subtotal_amount' => 0, 'discount_amount' => 0, 'total_amount' => 0, 'currency' => '', 'entry_id' => 0, 'gateway' => '', 'type' => '', 'mode' => '', 'transaction_id' => '', 'customer_id' => '', 'subscription_id' => '', 'subscription_status' => '', 'title' => '', 'date_created_gmt' => $date, 'date_updated_gmt' => $date, 'is_published' => 1, ]; } /** * Insert a new payment into the database. * * @since 1.8.2 * * @param array $data Column data. * @param string $type Optional. Data type context. * * @return int ID for the newly inserted payment. Zero otherwise. */ public function add( $data, $type = '' ) { // Return early if the status is not allowed. // TODO: consider validating other properties as well or get rid of it. if ( isset( $data['status'] ) && ! ValueValidator::is_valid( $data['status'], 'status' ) ) { return 0; } // Use database type identifier if a context is empty. $type = empty( $type ) ? $this->type : $type; return parent::add( $data, $type ); } /** * Retrieve a payment from the database based on a given payment ID. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $args Additional arguments. * * @return object|null */ public function get( $payment_id, $args = [] ) { if ( ! $this->current_user_can( $payment_id, $args ) && wpforms()->obj( 'access' )->init_allowed() ) { return null; } $payment = parent::get( $payment_id ); return $payment ? $this->cast_amounts_to_float( $payment ) : null; } /** * Retrieve a row based on column value. * * @since 1.8.7 * * @param string $column Column name. * @param int|string $value Column value. * * @return object|null Database query result, object or null on failure. */ public function get_by( $column, $value ) { $payment = parent::get_by( $column, $value ); return $payment ? $this->cast_amounts_to_float( $payment ) : null; } /** * Cast amounts to float in the given payment data object. * * @since 1.8.7 * * @param object $payment Payment ID. * * @return object */ private function cast_amounts_to_float( $payment ) { if ( empty( $payment ) || ! is_object( $payment ) ) { return $payment; } // Amounts is stored in DB as decimal(26,8), but appear here as strings. // Therefore, they should be cast to float to avoid further multi-time currency conversion. $payment->subtotal_amount = $payment->subtotal_amount ? (float) $payment->subtotal_amount : 0; $payment->discount_amount = $payment->discount_amount ? (float) $payment->discount_amount : 0; $payment->total_amount = $payment->total_amount ? (float) $payment->total_amount : 0; return $payment; } /** * Update an existing payment in the database. * * @since 1.8.2 * * @param string $payment_id Payment ID. * @param array $data Array of columns and associated data to update. * @param string $where Column to match against in the WHERE clause. If empty, $primary_key will be used. * @param string $type Data type context. * @param array $args Additional arguments. * * @return bool */ public function update( $payment_id, $data = [], $where = '', $type = '', $args = [] ) { if ( ! $this->current_user_can( $payment_id, $args ) ) { return false; } // TODO: consider validating other properties as well or get rid of it. if ( isset( $data['status'] ) && ! ValueValidator::is_valid( $data['status'], 'status' ) ) { return false; } // Use database type identifier if a context is empty. $type = empty( $type ) ? $this->type : $type; return parent::update( $payment_id, $data, $where, $type ); } /** * Delete a payment from the database, also removes payment meta. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $args Additional arguments. * * @return bool False if the payment and meta could not be deleted, true otherwise. */ public function delete( $payment_id = 0, $args = [] ): bool { if ( ! $this->current_user_can( $payment_id, $args ) ) { return false; } $is_payment_deleted = parent::delete( $payment_id ); $is_meta_deleted = wpforms()->obj( 'payment_meta' )->delete_by( 'payment_id', $payment_id ); return $is_payment_deleted && $is_meta_deleted; } /** * Retrieve a list of payments. * * @since 1.8.2 * * @param array $args Arguments. * * @return array */ public function get_payments( $args = [] ) { global $wpdb; $args = $this->sanitize_get_payments_args( $args ); if ( ! $this->current_user_can( 0, $args ) ) { return []; } // Prepare query. $query[] = "SELECT p.* FROM {$this->table_name} as p"; /** * Filter the query for get_payments method before the WHERE clause. * * @since 1.8.2 * * @param string $where Before the WHERE clause in DB query. * @param array $args Query arguments. * * @return string */ $query[] = apply_filters( 'wpforms_db_payments_payment_get_payments_query_before_where', '', $args ); $query[] = 'WHERE 1=1'; $query[] = $this->add_columns_where_conditions( $args ); $query[] = $this->add_secondary_where_conditions( $args ); /** * Extend the query for the get_payments method after the WHERE clause. * * This hook provides the flexibility to modify the SQL query by appending custom conditions * right after the WHERE clause. * * @since 1.8.4 * * @param string $where After the WHERE clause in the database query. * @param array $args Query arguments. * * @return string */ $query[] = apply_filters( 'wpforms_db_payments_payment_get_payments_query_after_where', '', $args ); // Order. $query[] = sprintf( 'ORDER BY %s', sanitize_sql_orderby( "{$args['orderby']} {$args['order']}" ) ); // Limit. $query[] = $wpdb->prepare( 'LIMIT %d, %d', $args['offset'], $args['number'] ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared $result = $wpdb->get_results( implode( ' ', $query ), ARRAY_A ); // Get results. return ! $result ? [] : $result; } /** * Create the table. * * @since 1.8.2 */ public function create_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); /** * To avoid any possible issues during migration from entries to payments' table, * all data types are preserved. * * Note: there must be two spaces between the words PRIMARY KEY and the definition of primary key. * * @link https://codex.wordpress.org/Creating_Tables_with_Plugins#Creating_or_Updating_the_Table */ $query = "CREATE TABLE $this->table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, form_id bigint(20) NOT NULL, status varchar(10) NOT NULL DEFAULT '', subtotal_amount decimal(26,8) NOT NULL DEFAULT 0, discount_amount decimal(26,8) NOT NULL DEFAULT 0, total_amount decimal(26,8) NOT NULL DEFAULT 0, currency varchar(3) NOT NULL DEFAULT '', entry_id bigint(20) NOT NULL DEFAULT 0, gateway varchar(20) NOT NULL DEFAULT '', type varchar(12) NOT NULL DEFAULT '', mode varchar(4) NOT NULL DEFAULT '', transaction_id varchar(40) NOT NULL DEFAULT '', customer_id varchar(40) NOT NULL DEFAULT '', subscription_id varchar(40) NOT NULL DEFAULT '', subscription_status varchar(10) NOT NULL DEFAULT '', title varchar(255) NOT NULL DEFAULT '', date_created_gmt datetime NOT NULL, date_updated_gmt datetime NOT NULL, is_published tinyint(1) NOT NULL DEFAULT 1, PRIMARY KEY (id), KEY form_id (form_id), KEY status (status(8)), KEY total_amount (total_amount), KEY type (type(8)), KEY transaction_id (transaction_id(32)), KEY customer_id (customer_id(32)), KEY subscription_id (subscription_id(32)), KEY subscription_status (subscription_status(8)), KEY title (title(64)) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $query ); } /** * Check if the current user has capabilities to manage payments. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $args Additional arguments. * * @return bool * @noinspection IfReturnReturnSimplificationInspection */ private function current_user_can( $payment_id, $args = [] ) { $manage_cap = wpforms_get_capability_manage_options(); if ( ! isset( $args['cap'] ) ) { $args['cap'] = $manage_cap; } if ( ! empty( $args['cap'] ) && ! wpforms_current_user_can( $args['cap'], $payment_id ) ) { return false; } return true; } /** * Construct where clauses for selected columns. * * @since 1.8.4 * * @param array $args Query arguments. * * @return string */ public function add_columns_where_conditions( $args = [] ) { // Allowed columns for filtering. $allowed_cols = [ 'form_id', 'entry_id', 'status', 'subscription_status', 'type', 'gateway', ]; $where = ''; // Determine if this is a table query. $is_table_query = ! empty( $args['table_query'] ); $keys_to_validate = [ 'status', 'subscription_status', 'type', 'gateway' ]; foreach ( $args as $key => $value ) { if ( empty( $value ) || ! in_array( $key, $allowed_cols, true ) ) { continue; } // Explode values if needed. $values = explode( '|', $value ); // Run some keys through the "ValueValidator" class to make sure they are valid. if ( in_array( $key, $keys_to_validate, true ) ) { $values = array_filter( $values, static function ( $v ) use ( $key ) { return ValueValidator::is_valid( $v, $key ); } ); } // Skip if no valid values found. if ( empty( $values ) ) { continue; } // Merge "Partially Refunded" status with "Refunded" status. if ( $is_table_query && $key === 'status' && in_array( 'refunded', $values, true ) ) { $values[] = 'partrefund'; } $placeholders = wpforms_wpdb_prepare_in( $values ); // Prepare and add to WHERE clause. $where .= " AND {$key} IN ({$placeholders})"; } return $where; } /** * Construct secondary where clauses. * * @since 1.8.2 * * @param array $args Query arguments. * * @return string */ public function add_secondary_where_conditions( $args = [] ) { global $wpdb; /** * Filter arguments needed for all query. * * @since 1.8.2 * * @param array $args Query arguments. */ $args = (array) apply_filters( 'wpforms_db_payments_payment_add_secondary_where_conditions_args', $args ); $args = wp_parse_args( (array) $args, [ 'currency' => wpforms_get_currency(), 'mode' => 'live', 'is_published' => 1, ] ); $where = ''; // If it's a valid mode, add it to a WHERE clause. if ( ValueValidator::is_valid( $args['mode'], 'mode' ) ) { $where .= $wpdb->prepare( ' AND mode = %s', $args['mode'] ); } $where .= $wpdb->prepare( ' AND currency = %s', $args['currency'] ); $where .= $wpdb->prepare( ' AND is_published = %d', $args['is_published'] ); return $where; } /** * Sanitize query arguments for get_payments() method. * * @since 1.8.2 * * @param array $args Query arguments. * * @return array */ private function sanitize_get_payments_args( $args ) { $defaults = [ 'number' => 20, 'offset' => 0, 'orderby' => 'id', 'order' => 'DESC', ]; $args = wp_parse_args( (array) $args, $defaults ); // Sanitize. $args['number'] = absint( $args['number'] ); $args['offset'] = absint( $args['offset'] ); if ( $args['number'] === 0 ) { $args['number'] = $defaults['number']; } return $args; } } PK �D0]D f�_. _. Payments/Queries.phpnu �[��� <?php namespace WPForms\Db\Payments; /** * Class for the Payments database queries. * * @since 1.8.2 */ class Queries extends Payment { /** * Check if given payment table column has different values. * * @since 1.8.2 * * @param string $column Column name. * * @return bool */ public function has_different_values( $column ) { global $wpdb; $subquery[] = "SELECT $column FROM $this->table_name WHERE 1=1"; $subquery[] = $this->add_secondary_where_conditions(); $subquery[] = 'LIMIT 1'; $subquery = implode( ' ', $subquery ); $query[] = "SELECT $column FROM $this->table_name WHERE 1=1"; $query[] = $this->add_secondary_where_conditions(); $query[] = "AND $column != ( $subquery )"; $query[] = 'LIMIT 1'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared $result = $wpdb->get_var( implode( ' ', $query ) ); return ! empty( $result ); } /** * Check if there is a subscription payment. * * @since 1.8.2 * * @return bool */ public function has_subscription() { return $this->if_exists( [ 'type' => implode( '|', array_keys( ValueValidator::get_allowed_subscription_types() ) ), ] ); } /** * Retrieve the number of all payments. * * @since 1.8.2 * * @param array $args Redefine query parameters by providing own arguments. * * @return int Number of payments or count of payments. */ public function count_all( $args = [] ) { // Retrieve the global database instance. global $wpdb; $query[] = 'SELECT SUM(count) AS total_count FROM ('; $query[] = "SELECT COUNT(*) AS count FROM {$this->table_name} as p"; /** * Add parts to the query for count_all method before the WHERE clause. * * @since 1.8.2 * * @param string $where Before the WHERE clause in DB query. * @param array $args Query arguments. * * @return string */ $query[] = apply_filters( 'wpforms_db_payments_queries_count_all_query_before_where', '', $args ); $query[] = 'WHERE 1=1'; $query[] = $this->add_columns_where_conditions( $args ); $query[] = $this->add_secondary_where_conditions( $args ); /** * Append custom query parts after the WHERE clause for the count_all method. * * This hook allows external code to extend the SQL query by adding custom conditions * immediately after the WHERE clause. * * @since 1.8.4 * * @param string $where After the WHERE clause in the database query. * @param array $args Query arguments. * * @return string */ $query[] = apply_filters( 'wpforms_db_payments_queries_count_all_query_after_where', '', $args ); // Close the subquery. $query[] = ') AS counts;'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared return (int) $wpdb->get_var( implode( ' ', $query ) ); } /** * Whether at least one payment exists with the given arguments. * * @since 1.8.4 * * @param array $args Optionally, you can redefine query parameters by providing custom arguments. * * @return bool False if no results found. */ public function if_exists( $args = [] ) { // Retrieve the global database instance. global $wpdb; $query[] = "SELECT 1 FROM {$this->table_name}"; /** * Add parts to the query for if_exists method before the WHERE clause. * * @since 1.8.4 * * @param string $where Before the WHERE clause in DB query. * @param array $args Query arguments. * * @return string */ $query[] = apply_filters( 'wpforms_db_payments_queries_count_if_exists_before_where', '', $args ); $query[] = 'WHERE 1=1'; $query[] = $this->add_columns_where_conditions( $args ); $query[] = $this->add_secondary_where_conditions( $args ); /** * Append custom query parts after the WHERE clause for the if_exists method. * * This hook allows external code to extend the SQL query by adding custom conditions * immediately after the WHERE clause. * * @since 1.8.4 * * @param string $where After the WHERE clause in the database query. * @param array $args Query arguments. * * @return string */ $query[] = apply_filters( 'wpforms_db_payments_queries_count_if_exists_after_where', '', $args ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared return (bool) $wpdb->get_var( implode( ' ', $query ) ); } /** * Get next payment. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $args Where conditions. * * @return object|null Object from DB values or null. */ public function get_next( $payment_id, $args = [] ) { global $wpdb; if ( empty( $payment_id ) ) { return null; } $query[] = "SELECT * FROM {$this->table_name}"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $query[] = $wpdb->prepare( "WHERE $this->primary_key > %d", $payment_id ); $query[] = $this->add_secondary_where_conditions( $args ); $query[] = "ORDER BY $this->primary_key LIMIT 1"; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_row( implode( ' ', $query ) ); } /** * Get previous payment. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $args Where conditions. * * @return object|null Object from DB values or null. */ public function get_prev( $payment_id, $args = [] ) { global $wpdb; if ( empty( $payment_id ) ) { return null; } $query[] = "SELECT * FROM $this->table_name"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $query[] = $wpdb->prepare( "WHERE $this->primary_key < %d", $payment_id ); $query[] = $this->add_secondary_where_conditions( $args ); $query[] = "ORDER BY $this->primary_key DESC LIMIT 1"; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_row( implode( ' ', $query ) ); } /** * Get previous payments count. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $args Where conditions. * * @return int */ public function get_prev_count( $payment_id, $args = [] ) { global $wpdb; if ( empty( $payment_id ) ) { return 0; } $query[] = "SELECT COUNT( $this->primary_key ) FROM $this->table_name"; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $query[] = $wpdb->prepare( "WHERE $this->primary_key < %d", $payment_id ); $query[] = $this->add_secondary_where_conditions( $args ); $query[] = "ORDER BY $this->primary_key ASC"; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return (int) $wpdb->get_var( implode( ' ', $query ) ); } /** * Get subscription payment history for the given subscription ID. * This function returns an array of subscription payment object and renewal payments associated with the subscription. * * @global wpdb $wpdb Instantiation of the wpdb class. * * @since 1.8.4 * * @param string $subscription_id Subscription ID. * @param string $currency Currency that the payment was made in. * * @return array Array of payment objects. */ public function get_subscription_payment_history( $subscription_id, $currency = '' ) { $subscription = null; $renewals = []; // Bail early if the subscription ID is empty. if ( empty( $subscription_id ) ) { return [ $subscription, $renewals ]; } // Get the currency, if not provided. if ( empty( $currency ) ) { $currency = wpforms_get_currency(); } // Get the database instance. global $wpdb; // Get the general where clause. $where_clause = $this->add_secondary_where_conditions( [ 'currency' => $currency ] ); // Construct the query using a prepared statement. // Execute the query and fetch the results. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE subscription_id = %s AND (type = 'subscription' OR type = 'renewal') {$where_clause} ORDER BY type ASC, date_created_gmt DESC", $subscription_id ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared // Search for the subscription object in the "$results" array. foreach ( $results as $key => $result ) { if ( $result->type === 'subscription' ) { $subscription = $result; unset( $results[ $key ] ); break; // Exit the loop after finding the subscription object. } } // Assign the remaining results to renewals. $renewals = $results; return [ $subscription, $renewals ]; } /** * Determine if given subscription has a renewal payment. * * @global wpdb $wpdb Instantiation of the wpdb class. * * @since 1.8.4 * * @param string $subscription_id Subscription ID. * * @return bool True if the subscription has a renewal payment, false otherwise. */ public function if_subscription_has_renewal( $subscription_id ) { // Bail early if the subscription ID is empty. if ( empty( $subscription_id ) ) { return false; } // Get the database instance. global $wpdb; $query[] = "SELECT 1 FROM {$this->table_name} AS s"; $query[] = 'WHERE s.subscription_id = %s'; $query[] = "AND s.type = 'subscription'"; $query[] = 'AND EXISTS('; $query[] = "SELECT 1 FROM {$this->table_name} AS r"; $query[] = 'WHERE s.subscription_id = r.subscription_id'; $query[] = "AND r.type = 'renewal'"; $query[] = ')'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare return (bool) $wpdb->get_var( $wpdb->prepare( implode( ' ', $query ), $subscription_id ) ); } /** * Get subscription payment for given subscription ID. * * @since 1.8.4 * * @param string $subscription_id Subscription ID. * * @return object|null */ public function get_subscription( $subscription_id ) { global $wpdb; $query[] = "SELECT * FROM {$this->table_name}"; $query[] = "WHERE subscription_id = %s AND type = 'subscription'"; $query[] = 'ORDER BY id DESC LIMIT 1'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare return $wpdb->get_row( $wpdb->prepare( implode( ' ', $query ), $subscription_id ) ); } /** * Get renewal payment for given invoice ID. * * @since 1.8.4 * * @param string $invoice_id Invoice ID. * * @return object|null */ public function get_renewal_by_invoice_id( $invoice_id ) { global $wpdb; $meta_table_name = wpforms()->obj( 'payment_meta' )->table_name; $query[] = "SELECT p.* FROM {$this->table_name} as p"; $query[] = "INNER JOIN {$meta_table_name} as pm ON p.id = pm.payment_id"; $query[] = "WHERE pm.meta_key = 'invoice_id' AND pm.meta_value = %s"; $query[] = 'ORDER BY p.id DESC LIMIT 1'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare return $wpdb->get_row( $wpdb->prepare( implode( ' ', $query ), $invoice_id ) ); } } PK �D0]|��k� � Payments/ValueValidator.phpnu �[��� <?php namespace WPForms\Db\Payments; /** * ValueValidator class. * * This class is used to validate values for the Payments DB table. * * @since 1.8.2 */ class ValueValidator { /** * Check if value is valid for the given column. * * @since 1.8.2 * * @param string $value Value to check if is valid. * @param string $column Database column name. * * @return bool */ public static function is_valid( $value, $column ) { $method = 'get_allowed_' . self::get_plural_column_name( $column ); if ( ! method_exists( __CLASS__, $method ) ) { return false; } return isset( self::$method()[ $value ] ); } /** * Get allowed modes. * * @since 1.8.2 * * @return array */ private static function get_allowed_modes() { return [ 'live' => esc_html__( 'Live', 'wpforms-lite' ), 'test' => esc_html__( 'Test', 'wpforms-lite' ), ]; } /** * Get allowed gateways. * * @since 1.8.2 * * @return array */ public static function get_allowed_gateways() { /** * Filter allowed gateways. * * @since 1.8.2 * * @param array $gateways Array of allowed gateways. */ return (array) apply_filters( 'wpforms_db_payments_value_validator_get_allowed_gateways', [ 'paypal_standard' => esc_html__( 'PayPal Standard', 'wpforms-lite' ), 'paypal_commerce' => esc_html__( 'PayPal Commerce', 'wpforms-lite' ), 'stripe' => esc_html__( 'Stripe', 'wpforms-lite' ), 'square' => esc_html__( 'Square', 'wpforms-lite' ), 'authorize_net' => esc_html__( 'Authorize.net', 'wpforms-lite' ), ] ); } /** * Get allowed statuses. * * @since 1.8.2 * * @return array */ public static function get_allowed_statuses() { return array_merge( self::get_allowed_one_time_statuses(), self::get_allowed_subscription_statuses() ); } /** * Get allowed one-time payment statuses. * * @since 1.8.4 * * @return array */ public static function get_allowed_one_time_statuses() { return [ 'processed' => __( 'Processed', 'wpforms-lite' ), 'completed' => __( 'Completed', 'wpforms-lite' ), 'pending' => __( 'Pending', 'wpforms-lite' ), 'failed' => __( 'Failed', 'wpforms-lite' ), 'refunded' => __( 'Refunded', 'wpforms-lite' ), 'partrefund' => __( 'Partially Refunded', 'wpforms-lite' ), ]; } /** * Get allowed subscription statuses. * * @since 1.8.2 * * @return array */ public static function get_allowed_subscription_statuses() { return [ 'active' => __( 'Active', 'wpforms-lite' ), 'cancelled' => __( 'Cancelled', 'wpforms-lite' ), 'not-synced' => __( 'Not Synced', 'wpforms-lite' ), 'failed' => __( 'Failed', 'wpforms-lite' ), 'pending' => __( 'Pending', 'wpforms-lite' ), 'completed' => __( 'Completed', 'wpforms-lite' ), ]; } /** * Get allowed types. * * @since 1.8.2 * * @return array */ public static function get_allowed_types() { return array_merge( [ 'one-time' => __( 'One-Time', 'wpforms-lite' ), ], self::get_allowed_subscription_types() ); } /** * Get allowed subscription types. * * @since 1.8.2 * * @return array */ public static function get_allowed_subscription_types() { return [ 'subscription' => __( 'Subscription', 'wpforms-lite' ), 'renewal' => __( 'Renewal', 'wpforms-lite' ), ]; } /** * Get allowed subscription intervals. * The measurement of time between billing occurrences for an automated recurring billing subscription. * * @since 1.8.2 * * @return array */ public static function get_allowed_subscription_intervals() { return [ 'daily' => esc_html__( 'day', 'wpforms-lite' ), 'weekly' => esc_html__( 'week', 'wpforms-lite' ), 'monthly' => esc_html__( 'month', 'wpforms-lite' ), 'quarterly' => esc_html__( 'quarter', 'wpforms-lite' ), 'semiyearly' => esc_html__( 'semi-year', 'wpforms-lite' ), 'yearly' => esc_html__( 'year', 'wpforms-lite' ), ]; } /** * Map singular to plural column names. * * @since 1.8.2 * * @param string $column Column name. * * @return string */ private static function get_plural_column_name( $column ) { $map = [ 'mode' => 'modes', 'gateway' => 'gateways', 'status' => 'statuses', 'type' => 'types', 'subscription_type' => 'subscription_types', 'subscription_status' => 'subscription_statuses', ]; return isset( $map[ $column ] ) ? $map[ $column ] : $column; } } PK �D0]�豔0 �0 Payments/Meta.phpnu �[��� <?php namespace WPForms\Db\Payments; use WPForms_DB; /** * Class for the Payment Meta database table. * * @since 1.8.2 */ class Meta extends WPForms_DB { /** * Primary class constructor. * * @since 1.8.2 */ public function __construct() { parent::__construct(); $this->table_name = self::get_table_name(); $this->primary_key = 'id'; $this->type = 'payment_meta'; } /** * Get the table name. * * @since 1.8.2 * * @return string */ public static function get_table_name() { global $wpdb; return $wpdb->prefix . 'wpforms_payment_meta'; } /** * Get table columns. * * @since 1.8.2 * * @return array */ public function get_columns() { return [ 'id' => '%d', 'payment_id' => '%d', 'meta_key' => '%s', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => '%s', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ]; } /** * Default column values. * * @since 1.8.2 * * @return array */ public function get_column_defaults() { return [ 'payment_id' => 0, 'meta_key' => '', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => '', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ]; } /** * Create the table. * * @since 1.8.2 */ public function create_table() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $max_index_length = self::MAX_INDEX_LENGTH; /** * Note: there must be two spaces between the words PRIMARY KEY and the definition of primary key. * * @link https://codex.wordpress.org/Creating_Tables_with_Plugins#Creating_or_Updating_the_Table */ $query = "CREATE TABLE $this->table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, payment_id bigint(20) NOT NULL, meta_key varchar(255), meta_value longtext, PRIMARY KEY (id), KEY payment_id (payment_id), KEY meta_key (meta_key($max_index_length)), KEY meta_value (meta_value($max_index_length)) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $query ); } /** * Insert payment meta's. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param array $meta Payment meta to be inserted. */ public function bulk_add( $payment_id, $meta ) { global $wpdb; $values = []; foreach ( $meta as $meta_key => $meta_value ) { // Empty strings are skipped. if ( $meta_value === '' ) { continue; } $values[] = $wpdb->prepare( '( %d, %s, %s )', $payment_id, $meta_key, maybe_serialize( $meta_value ) ); } if ( ! $values ) { return; } $values = implode( ', ', $values ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query( "INSERT INTO $this->table_name ( payment_id, meta_key, meta_value ) VALUES $values" ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching } /** * Update or add payment meta. * * If the meta key already exists for given payment id, update the meta value. Otherwise, add the meta key and value. * * @since 1.8.4 * * @param int $payment_id Payment ID. * @param string $meta_key Payment meta key. * @param mixed $meta_value Payment meta value. * * @return bool */ public function update_or_add( $payment_id, $meta_key, $meta_value ) { // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value $row = $this->get_last_by( $meta_key, $payment_id ); if ( $row ) { return $this->update( $row->id, [ 'meta_value' => maybe_serialize( $meta_value ) ], '', $this->type ); } return (bool) $this->add( [ 'payment_id' => $payment_id, 'meta_key' => $meta_key, 'meta_value' => maybe_serialize( $meta_value ), ], $this->type ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value } /** * Add payment log. * * @since 1.8.4 * * @param int $payment_id Payment ID. * @param string $content Log content. * * @return bool */ public function add_log( $payment_id, $content ) { return (bool) $this->add( [ 'payment_id' => $payment_id, 'meta_key' => 'log', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => wp_json_encode( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value [ 'value' => wp_kses_post( $content ), 'date' => gmdate( 'Y-m-d H:i:s' ), ] ), ], $this->type ); } /** * Get single payment meta. * * @since 1.8.2 * * @param int $payment_id Payment ID. * @param string|null $meta_key Payment meta to be retrieved. * * @return mixed Meta value. */ public function get_single( $payment_id, $meta_key ) { global $wpdb; // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching $meta_value = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM $this->table_name WHERE payment_id = %d AND meta_key = %s ORDER BY id DESC LIMIT 1", $payment_id, $meta_key ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return maybe_unserialize( $meta_value ); } /** * Get all payment meta. * * @since 1.8.2 * * @param int $payment_id Payment ID. * * @return array|null */ public function get_all( $payment_id ) { global $wpdb; // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value as value FROM $this->table_name WHERE payment_id = %d ORDER BY id DESC", $payment_id ), OBJECT_K ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching } /** * Retrieve all rows based on meta_key value. * * @since 1.8.2 * * @param string $meta_key Meta key value. * @param int $payment_id Payment ID. * * @return object|null */ public function get_all_by( $meta_key, $payment_id ) { global $wpdb; if ( empty( $meta_key ) ) { return null; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_results( $wpdb->prepare( "SELECT meta_value as value FROM $this->table_name WHERE payment_id = %d AND meta_key = %s ORDER BY id DESC", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $payment_id, $meta_key ), ARRAY_A ); } /** * Check if there are valid entries with a specific meta key. * * @since 1.8.4 * * @param string $meta_key The meta key to check. * * @return bool */ public function is_valid_meta_by_meta_key( $meta_key ) { // Check if the meta key is empty and return false. if ( empty( $meta_key ) ) { return false; } // Retrieve the global database instance. global $wpdb; $payment_handler = wpforms()->obj( 'payment' ); $payment_table_name = $payment_handler->table_name; $secondary_where_clause = $payment_handler->add_secondary_where_conditions(); // Prepare and execute the SQL query to check if there are valid entries with the given meta key. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching return (bool) $wpdb->get_var( $wpdb->prepare( "SELECT 1 FROM {$this->table_name} AS pm WHERE meta_key = %s AND meta_value IS NOT NULL AND EXISTS (SELECT 1 FROM {$payment_table_name} AS p WHERE p.id = pm.payment_id {$secondary_where_clause}) LIMIT 1", $meta_key ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching } /** * Check if the given meta key and value exist in the payment meta table. * * @since 1.8.4 * * @param string $meta_key Meta key value. * @param string $meta_value Meta value. * * @return bool */ public function is_valid_meta( $meta_key, $meta_value ) { // Check if the meta key or value is empty and return false. if ( empty( $meta_key ) || empty( $meta_value ) ) { return false; } // Retrieve the global database instance. global $wpdb; // Prepare and execute the SQL query to check if the given meta key and value exist in the payment meta table. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared return (bool) $wpdb->get_var( $wpdb->prepare( "SELECT EXISTS( SELECT 1 FROM {$this->table_name} WHERE meta_key = %s AND meta_value = %s )", $meta_key, $meta_value ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared } /** * Retrieve payment meta data by given meta key and value. * * @since 1.8.4 * * @param string $meta_key Meta key value. * @param string $meta_value Meta value. * * @return array */ public function get_all_by_meta( $meta_key, $meta_value ) { // Check if the meta key or value is empty and return null. if ( empty( $meta_key ) || empty( $meta_value ) ) { return []; } // Retrieve the global database instance. global $wpdb; // Prepare and execute the SQL query to retrieve payment meta data based on the given meta key and value. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared return $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value AS value FROM {$this->table_name} WHERE payment_id = ( SELECT payment_id FROM {$this->table_name} WHERE meta_key = %s AND meta_value = %s LIMIT 1 )", $meta_key, $meta_value ), OBJECT_K ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared } /** * Get row from the payment meta table for given payment id and meta key. * * @since 1.8.4 * * @param string $meta_key Meta key value. * @param int $payment_id Payment ID. * * @return object|null */ public function get_last_by( $meta_key, $payment_id ) { global $wpdb; // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $this->table_name WHERE payment_id = %d AND meta_key = %s ORDER BY id DESC LIMIT 1", $payment_id, $meta_key ) ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.SlowDBQuery.slow_db_query_meta_key } /** * Get Payment ID by meta key and value. * * @since 1.10.2 * * @param string $meta_key Meta key value. * @param string $meta_value Meta value. * * @return int */ public function get_payment_id_by_meta( string $meta_key, string $meta_value ): int { // Check if the meta key or value are empty. if ( empty( $meta_key ) || empty( $meta_value ) ) { return 0; } global $wpdb; return (int) $wpdb->get_var( $wpdb->prepare( "SELECT payment_id FROM {$this->table_name} WHERE meta_key = %s AND meta_value = %s LIMIT 1", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $meta_key, $meta_value ) ); } } PK �D0]�侟 � Payments/UpdateHelpers.phpnu �[��� <?php namespace WPForms\Db\Payments; /** * Payment values update helpers class. * * @since 1.8.4 */ class UpdateHelpers { /** * Refund payment in database. * * @since 1.8.4 * * @param Payment $payment_db Payment DB object. * @param int $refunded_amount Refunded amount with cent separated. * @param string $log Log message. * * @return bool */ public static function refund_payment( $payment_db, $refunded_amount, $log = '' ) { $status = $refunded_amount < $payment_db->total_amount ? 'partrefund' : 'refunded'; if ( ! wpforms()->obj( 'payment' )->update( $payment_db->id, [ 'status' => $status ] ) ) { return false; } if ( ! wpforms()->obj( 'payment_meta' )->update_or_add( $payment_db->id, 'refunded_amount', $refunded_amount ) ) { return false; } if ( $log ) { wpforms()->obj( 'payment_meta' )->add_log( $payment_db->id, $log ); } return true; } /** * Cancel subscription in database. * * @since 1.8.4 * * @param int $payment_id Payment ID. * @param string $log Log message. * * @return bool */ public static function cancel_subscription( $payment_id, $log = '' ) { if ( ! wpforms()->obj( 'payment' )->update( $payment_id, [ 'subscription_status' => 'cancelled' ] ) ) { return false; } if ( $log ) { wpforms()->obj( 'payment_meta' )->add_log( $payment_id, $log ); } return true; } } PK �D0]gE@n, n, Analytics/DB.phpnu �[��� PK �D0]��Y� � �, Analytics/Forms.phpnu �[��� PK �D0]<�u4] ] �2 Analytics/Snapshots.phpnu �[��� PK �D0]��dN�4 �4 �: Payments/Payment.phpnu �[��� PK �D0]D f�_. _. [o Payments/Queries.phpnu �[��� PK �D0]|��k� � �� Payments/ValueValidator.phpnu �[��� PK �D0]�豔0 �0 � Payments/Meta.phpnu �[��� PK �D0]�侟 � �� Payments/UpdateHelpers.phpnu �[��� PK � ��
dvadf
dvadf
| ver. 1.4 |
Github
|
.
| PHP 8.2.33 | Generation time: 0.01 |
proxy
|
phpinfo
|
Settings