get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE status = %s', Installer::table( 'log' ), 'success' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- stored once found. if ( $n > 0 ) { add_option( self::USED, 1, '', false ); return true; } return false; } /** * Print the checklist. * * @param int $apps Connected apps and tokens. * @param string $diag Connection check state: ok, warn, fail or none. * @param bool $brief Site brief written. * @param string $brief_url Site brief settings. * @param string $docs Docs link. * @param string $prompts Prompt library link. */ public static function render( int $apps, string $diag, bool $brief, string $brief_url, string $docs, string $prompts ): void { if ( ! current_user_can( 'manage_options' ) ) { return; } $state = (string) get_user_meta( get_current_user_id(), self::META, true ); if ( 'hidden' === $state ) { return; } $used = self::used(); $steps = array( array( $apps > 0, __( 'Connect an AI app', 'handymcp' ), __( 'Copy the server URL below, pick your app and follow its steps. Sign in and approve when your site asks.', 'handymcp' ), '' . esc_html__( 'Show the steps', 'handymcp' ) . '' ), array( 'ok' === $diag || 'warn' === $diag, __( 'Check the connection', 'handymcp' ), 'fail' === $diag ? __( 'The check found a problem. Open it to see what blocks AI apps and how to fix it.', 'handymcp' ) : __( 'HandyMCP tests HTTPS, sign-in and your host, and tells you exactly what to fix.', 'handymcp' ), '' . esc_html__( 'Go to the check', 'handymcp' ) . '' ), array( $brief, __( 'Write a site brief', 'handymcp' ), __( 'Optional. Your brand voice, words to avoid and house rules, followed by every AI app.', 'handymcp' ), '' . esc_html__( 'Write the brief', 'handymcp' ) . '' ), array( $used, __( 'Try a first prompt', 'handymcp' ), __( 'Paste one of these into your AI app. They only read or create drafts, so nothing live changes.', 'handymcp' ), '' ), ); $core = $steps[0][0] && $steps[1][0] && $steps[3][0]; $since = 0 === strpos( $state, 'done:' ) ? (int) substr( $state, 5 ) : 0; if ( $core && $since && time() - $since > DAY_IN_SECONDS ) { return; } $link = static function ( string $do ): string { return wp_nonce_url( add_query_arg( array( 'action' => 'handymcp_setup', 'do' => $do ), admin_url( 'admin-post.php' ) ), 'handymcp_setup' ); }; $problems = \HandyMCP\Auth\AppHealth::problems(); $waiting = $problems ? array() : \HandyMCP\Auth\AppHealth::waiting(); if ( $problems || $waiting ) { if ( $problems ) { $first = reset( $problems ); $text = \HandyMCP\Auth\AppHealth::message( (string) $first['name'], $first ); } else { $first = reset( $waiting ); $text = \HandyMCP\Auth\AppHealth::waiting_message( (string) $first['name'], (int) $first['time'] ); } echo '

' . esc_html__( 'An AI app needs to reconnect', 'handymcp' ) . '

' . esc_html( $text ) . '

'; return; } if ( $core ) { if ( ! $since ) { update_user_meta( get_current_user_id(), self::META, 'done:' . time() ); } echo '

' . esc_html__( 'You are all set', 'handymcp' ) . '

' . esc_html__( 'Your AI app is connected and working. Ask it for anything you would ask a WordPress developer.', 'handymcp' ) . ' ' . esc_html__( 'More prompt ideas', 'handymcp' ) . '

' . esc_html__( 'Hide', 'handymcp' ) . '
'; return; } $done = count( array_filter( array_column( $steps, 0 ) ) ); $out = '

' . esc_html__( 'Get started', 'handymcp' ) . '

' . esc_html( sprintf( /* translators: 1: done, 2: total */ __( '%1$d of %2$d done. Each step ticks itself off.', 'handymcp' ), $done, count( $steps ) ) ) . '

' . '
    '; foreach ( $steps as $i => $s ) { $out .= '
  1. ' . esc_html( $s[1] ) . '' . ( $s[0] ? ' ' . esc_html__( '(done)', 'handymcp' ) . '' : '' ) . '

    ' . esc_html( $s[2] ) . '

    '; if ( 3 === $i && ! $s[0] ) { $ideas = array( __( 'Tell me about this site: theme, plugins and the pages it has.', 'handymcp' ), __( 'Write a draft About page in the style of my home page.', 'handymcp' ), __( 'List the pages that are missing an SEO description.', 'handymcp' ), ); $out .= '
      '; foreach ( $ideas as $n => $idea ) { $out .= '
    • ' . esc_html( $idea ) . '
    • '; } $out .= '
    '; } $out .= '
    ' . ( ! $s[0] && '' !== $s[3] ? '
    ' . $s[3] . '
    ' : '' ) . '
  2. '; } $out .= '

' . esc_html__( 'Read the setup guide', 'handymcp' ) . '

'; echo wp_kses( $out, \HandyMCP\Support\Html::allowed() ); } public static function action(): void { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'Your account is not allowed to do this.', 'handymcp' ), 403 ); } check_admin_referer( 'handymcp_setup' ); if ( isset( $_GET['do'] ) && 'hide' === sanitize_key( wp_unslash( $_GET['do'] ) ) ) { update_user_meta( get_current_user_id(), self::META, 'hidden' ); } wp_safe_redirect( admin_url( 'admin.php?page=' . Admin::SLUG ) ); exit; } }