get_col( $wpdb->prepare( "SELECT m.post_id FROM %i m INNER JOIN %i p ON p.ID = m.post_id AND p.post_status IN ( 'publish', 'private' ) WHERE m.meta_key = %s AND m.meta_value <> '' LIMIT %d", $wpdb->postmeta, $wpdb->posts, Repository::META_T0, self::MAX_PRODUCTS ) ); $service = new ReferenceService( new Repository(), new ReferenceCalculator() ); $cjeu = new CjeuMode( $service ); $counts = array( 'reduced' => 0, 'corrected' => 0, 'hidden' => 0, 'exempt' => 0, 'unknown' => 0, ); foreach ( (array) $ids as $id ) { $product = wc_get_product( (int) $id ); if ( ! $product || ! $product->is_on_sale( 'edit' ) ) { continue; } ++$counts['reduced']; if ( Perishable::applies( $product ) ) { ++$counts['exempt']; continue; } $decision = $cjeu->decide( $product ); $action = $decision['action']; if ( CjeuMode::ACTION_REPLACE === $action ) { // Only where the strike-through price really changes. if ( abs( (float) $decision['regular'] - (float) $product->get_regular_price( 'edit' ) ) > 0.005 ) { ++$counts['corrected']; } } elseif ( CjeuMode::ACTION_NO_REDUCTION === $action ) { ++$counts['hidden']; } elseif ( Reference::STATUS_NO_HISTORY === $service->get( $product )->status ) { ++$counts['unknown']; } } set_transient( self::TRANSIENT, $counts, 10 * MINUTE_IN_SECONDS ); return $counts; } /** * Points that need the shop owner, most urgent first. * * @return array */ public static function issues(): array { $settings = AdminPage::settings_url(); $issues = array(); if ( ! Settings::show_single() && ! Settings::show_loop() ) { $issues[] = self::issue( 'critical', __( 'The lowest price is not shown anywhere', 'strikewise' ), __( 'Customers do not see the price of the 30 days before a reduction.', 'strikewise' ), $settings, __( 'Turn on', 'strikewise' ) ); } elseif ( ! Settings::show_single() || ! Settings::show_loop() ) { $issues[] = self::issue( 'warning', __( 'The lowest price is only shown in part of the shop', 'strikewise' ), __( 'It belongs wherever a reduced price is shown.', 'strikewise' ), $settings, __( 'Turn on', 'strikewise' ) ); } if ( ! CjeuMode::is_enabled() ) { $issues[] = self::issue( 'warning', __( 'Strike-through prices are not corrected', 'strikewise' ), __( 'Since the CJEU ruling, a strike-through price must be the lowest price of the 30 days before.', 'strikewise' ), $settings, __( 'Turn on CJEU mode', 'strikewise' ) ); } $unknown = self::protection()['unknown']; if ( $unknown > 0 ) { $issues[] = self::issue( 'warning', /* translators: %d: number of products */ sprintf( _n( '%d reduction without an earlier price', '%d reductions without an earlier price', $unknown, 'strikewise' ), $unknown ), __( 'A strike-through price needs the earlier price. Enter it in the product or let Strikewise hide these reductions.', 'strikewise' ), $settings, __( 'Settings', 'strikewise' ) ); } if ( null === AdminPage::next_daily_run() ) { $issues[] = self::issue( 'warning', __( 'The daily sync is not running', 'strikewise' ), __( 'Deactivate and reactivate Strikewise.', 'strikewise' ), admin_url( 'plugins.php' ), __( 'Plugins', 'strikewise' ) ); } foreach ( array_merge( Compat::discount_plugins(), Compat::currency_plugins() ) as $name ) { $issues[] = self::issue( 'warning', /* translators: %s: plugin name */ sprintf( __( '%s: prices not visible to Strikewise', 'strikewise' ), $name ), __( 'Check the lowest price of reductions from this plugin yourself.', 'strikewise' ), '', '' ); } /** * Filters the points that need the shop owner (the premium scanner adds its findings). * * @param array $issues */ $issues = (array) apply_filters( 'strikewise_health_issues', $issues ); usort( $issues, static function ( $a, $b ) { return ( 'critical' === $b['tone'] ) <=> ( 'critical' === $a['tone'] ); } ); return $issues; } /** * @return array{tone:string,title:string,text:string,url:string,link:string} */ public static function issue( string $tone, string $title, string $text, string $url, string $link ): array { return array( 'tone' => $tone, 'title' => $title, 'text' => $text, 'url' => $url, 'link' => $link, ); } /** * Overall state: ok, warning or critical. * * @param array $issues */ public static function tone( array $issues ): string { if ( ! $issues ) { return 'ok'; } return in_array( 'critical', array_column( $issues, 'tone' ), true ) ? 'critical' : 'warning'; } /** * The headline of the status card. * * @param array $issues */ public static function headline( array $issues ): string { if ( ! $issues ) { return __( 'Your discounts are protected', 'strikewise' ); } /* translators: %d: number of points */ return sprintf( _n( '%d point needs your attention', '%d points need your attention', count( $issues ), 'strikewise' ), count( $issues ) ); } }