Inspect text), registered like Diagnostics. Removing it // from the Aiwend submenu instead made WordPress deny access to everyone. add_submenu_page('', __('Inspect knowledge', 'aiwend'), __('Inspect knowledge', 'aiwend'), Capabilities::MANAGE_KNOWLEDGE, self::SLUG, [$this, 'render']); }); // A page without a parent gets no document title or menu highlight; give it Knowledge's. add_filter('admin_title', fn(string $title): string => $this->current() ? __('Extracted knowledge', 'aiwend') . ' ' . $title : $title); add_filter('parent_file', fn($file) => $this->current() ? 'aiwend' : $file); add_filter('submenu_file', fn($file) => $this->current() ? 'aiwend-knowledge' : $file); } private function current(): bool { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only navigation or filter parameter; no state is changed return is_admin() && isset($_GET['page']) && $_GET['page'] === self::SLUG; } public function render(): void { if (!current_user_can(Capabilities::MANAGE_KNOWLEDGE)) { wp_die('Not authorized.', '', ['response' => 403]); } nocache_headers(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only navigation or filter parameter; no state is changed $page = max(1, min(10000, absint($_GET['paged'] ?? 1))); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only navigation or filter parameter; no state is changed $data = $this->plugin->sources()->inspect(get_current_blog_id(), absint($_GET['source'] ?? 0), $page); AdminView::open($this->plugin, 'aiwend-knowledge', __('Extracted knowledge', 'aiwend'), __('The text Aiwend found in this source and answers from.', 'aiwend')); echo '

← ' . esc_html__('Back to knowledge', 'aiwend') . '

'; if ($data === null) { echo '

' . esc_html__('Source unavailable. It may have been deleted.', 'aiwend') . '

'; AdminView::close(); return; } $source = $data['source']; $version = $data['version']; $state = AdminUi::sourceState($source); echo wp_kses('

' . esc_html($source['title']) . ' ' . AdminView::badge($state['label'], $state['tone']) . '

', AdminView::allowedHtml()); foreach ($this->explanations($source, $version) as [$tone, $text]) { echo '

' . esc_html($text) . '

'; } if ($version !== null) { /* translators: 1: index version number, 2: date and time of the last indexing, 3: number of chunks */ echo '

' . esc_html(sprintf(__('Index version %1$d · Last indexed %2$s · %3$d chunks', 'aiwend'), $version['version_no'], wp_date('Y-m-d H:i', (int) $version['updated_at']), $version['chunk_count'])) . '

'; echo '
' . esc_html__('Index details', 'aiwend') . '

' . esc_html($version['embedding_model'] . ' · ' . $version['dimension']) . '

'; } echo '

' . esc_html__('Review coverage and reading order, especially for tables, columns and scanned pages. Chunks may overlap.', 'aiwend') . '

'; foreach ($data['chunks'] as $chunk) { // Heading and the real location reference (e.g. a PDF page), as stored with the chunk. $where = array_values(array_unique(array_filter([(string) $chunk['heading'], (string) $chunk['anchor']], 'strlen'))); echo '

' . esc_html(implode(' · ', $where)) . '

' . esc_html($chunk['text']) . '

'; } if ($page > 1) { echo '

' . esc_html__('Previous page', 'aiwend') . '

'; } if ($data['has_more']) { echo '

' . esc_html__('Next page', 'aiwend') . '

'; } echo '
'; AdminView::close(); } /** * What the state means for the text shown. Only the last successful (published) index is ever * shown; a replacement still being built, or one that failed, never appears here as ready. * * @return list tone, text */ private function explanations(array $source, ?array $version): array { $out = []; $status = (string) $source['status']; if (in_array($status, ['queued', 'processing'], true)) { $out[] = ['info', $version === null ? __('This source is waiting to be indexed or is being indexed. Its text appears here when indexing completes.', 'aiwend') : __('A new index is being built. Until it completes, answers use the previous version shown below.', 'aiwend')]; } elseif ($status === 'failed' || $status === 'ocr_required') { $out[] = ['warn', $version === null ? __('Indexing did not succeed, so there is no text to show and this source is not used in answers.', 'aiwend') : __('The latest indexing did not succeed. Answers still use the previous version shown below.', 'aiwend')]; if ((string) ($source['error'] ?? '') !== '') { $out[] = ['warn', (string) $source['error']]; } } elseif ($status === 'ready') { if (str_starts_with((string) ($source['error'] ?? ''), 'Latest update failed')) { $out[] = ['warn', __('The latest update failed. Answers still use the version shown below.', 'aiwend') . ' ' . $source['error']]; } if ($version !== null && $source['origin'] === 'post') { $modified = (int) get_post_modified_time('U', true, (int) $source['origin_ref']); if ($modified > (int) $version['updated_at']) { $out[] = ['warn', __('Out of date: the page or post was edited after this index was built. Re-index it to use the current text.', 'aiwend')]; } } if ($source['visibility'] !== 'public') { $out[] = ['info', __('Indexed, but private: private sources are not used in answers in this build.', 'aiwend')]; } elseif ($out === []) { $out[] = ['info', __('Ready: this is the text answers are based on.', 'aiwend')]; } } return $out; } }