$now->format( 'Y-m-d' ), 'now' => $now->format( 'H:i' ), 'timezone' => wp_timezone_string(), 'currency' => get_woocommerce_currency(), 'currency_symbol' => html_entity_decode( get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8' ), 'price_decimals' => wc_get_price_decimals(), 'week_starts_on' => (int) get_option( 'start_of_week', 1 ), 'locale' => str_replace( '_', '-', get_user_locale() ), ); } /** * Order meta table and its order-id column, for whichever order storage is authoritative. * * @return array{table: string, id_column: string} */ public static function order_meta_table(): array { global $wpdb; if ( class_exists( OrderUtil::class ) && OrderUtil::custom_orders_table_usage_is_enabled() ) { return array( 'table' => $wpdb->prefix . 'wc_orders_meta', 'id_column' => 'order_id', ); } return array( 'table' => $wpdb->postmeta, 'id_column' => 'post_id', ); } /** * What Askshelf can read, with row counts, for the first-run checklist. * * @return array{items: list, import_pending: array{orders: int, customers: int}|null} */ public static function checklist(): array { global $wpdb; $stats = $wpdb->prefix . 'wc_order_stats'; // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Read-only counts on WooCommerce's Analytics tables. $orders = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE parent_id = 0', $stats ) ); $refunds = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE parent_id > 0', $stats ) ); $customers = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $wpdb->prefix . 'wc_customer_lookup' ) ); $meta = self::order_meta_table(); $first_attribute = $wpdb->get_var( $wpdb->prepare( 'SELECT MIN(s.date_created) FROM %i s INNER JOIN %i m ON m.%i = s.order_id AND m.meta_key = %s WHERE s.parent_id = 0', $stats, $meta['table'], $meta['id_column'], '_wc_order_attribution_source_type' ) ); // phpcs:enable $products = self::count_posts( 'product' ); $variations = self::count_posts( 'product_variation' ); $coupons = self::count_posts( 'shop_coupon' ); $attribution_detail = $first_attribute ? sprintf( /* translators: %s: a date such as "March 2024". */ __( 'since %s', 'askshelf' ), wp_date( 'F Y', (int) strtotime( (string) $first_attribute . ' ' . wp_timezone_string() ) ) ) : __( 'no attributed orders yet', 'askshelf' ); $items = array( array( 'key' => 'orders', 'label' => __( 'Orders', 'askshelf' ), /* translators: %s: number of rows. */ 'detail' => sprintf( _n( '%s row', '%s rows', $orders, 'askshelf' ), number_format_i18n( $orders ) ), 'count' => $orders, ), array( 'key' => 'refunds', 'label' => __( 'Refunds', 'askshelf' ), /* translators: %s: number of rows. */ 'detail' => sprintf( _n( '%s row', '%s rows', $refunds, 'askshelf' ), number_format_i18n( $refunds ) ), 'count' => $refunds, ), array( 'key' => 'products', 'label' => __( 'Products and variations', 'askshelf' ), 'detail' => number_format_i18n( $products + $variations ), 'count' => $products + $variations, ), array( 'key' => 'customers', 'label' => __( 'Customers', 'askshelf' ), /* translators: %s: number of customers. */ 'detail' => sprintf( __( '%s, counted only', 'askshelf' ), number_format_i18n( $customers ) ), 'count' => $customers, ), array( 'key' => 'coupons', 'label' => __( 'Coupons', 'askshelf' ), /* translators: %s: number of coupon codes. */ 'detail' => sprintf( _n( '%s code', '%s codes', $coupons, 'askshelf' ), number_format_i18n( $coupons ) ), 'count' => $coupons, ), array( 'key' => 'attribution', 'label' => __( 'Order attribution', 'askshelf' ), 'detail' => $attribution_detail, 'count' => null, ), ); return array( 'items' => $items, 'import_pending' => self::import_pending(), ); } /** * Orders and customers Analytics has not imported yet, or null if unknown. * * @return array{orders: int, customers: int}|null */ private static function import_pending(): ?array { try { $result = Analytics::get( '/reports/import/totals', array( 'skip_existing' => true ) ); } catch ( Throwable $e ) { return null; } $data = $result['data']; if ( ! is_array( $data ) ) { return null; } return array( 'orders' => (int) ( $data['orders'] ?? 0 ), 'customers' => (int) ( $data['customers'] ?? 0 ), ); } /** * Published or private posts of a type. * * @param string $type Post type. */ private static function count_posts( string $type ): int { $counts = wp_count_posts( $type ); return (int) ( $counts->publish ?? 0 ) + (int) ( $counts->private ?? 0 ); } }