--- a/link-whisper/core/Wpil/AI.php
+++ b/link-whisper/core/Wpil/AI.php
@@ -89,7 +89,14 @@
return array();
}*/
- return (is_array($content)) ? self::sendMultiRequest($args): self::sendRequest($args);
+ $response = null;
+ if(is_array($content)){
+ $response = self::sendMultiRequest($args);
+ }else{
+ $response = self::sendRequest($args);
+ }
+
+ return $response;
}
/**
@@ -251,12 +258,18 @@
}
// if this is the first go round
- if(self::$ai_service_connected && isset($_POST['start_time']) && empty($_POST['start_time'])){
- // do a credit check
- $credit = self::get_available_ai_credits(true);
- if($credit < 1){
- self::$insufficient_quota = true;
+ if(isset($_POST['start_time']) && empty($_POST['start_time'])){
+ // and we're connected to the ai service
+ if(self::$ai_service_connected){
+ // do a credit check
+ $credit = self::get_available_ai_credits(true);
+ if($credit < 1){
+ self::$insufficient_quota = true;
+ }
}
+
+ // clear the embedding id lock
+ self::set_last_embedding_id_lock();
}
if(in_array('create-post-embeddings', $selected_processes)){
@@ -433,6 +446,7 @@
public static function ajax_wpil_dismiss_api_key_decoding_error(){
update_option('wpil_open_ai_key_decoding_error', '0');
+ update_option('wpil_ai_token_decoding_error', '0'); // also update the Link Whisper AI since the user _should_ have updated the wp encryption tokens needed to run the system
}
public static function ajax_estimate_site_processing_cost(){
@@ -603,6 +617,12 @@
Wpil_Sitemap::save_sitemap($relatedness, 'ai_sitemap', 'AI Sitemap');
}
+ // if the embeddingsd are complete and no other factors concern us
+ if(self::has_completed_post_embedding_calculations()){
+ // clear the embedding lock
+ self::set_last_embedding_id_lock();
+ }
+
if(!Wpil_Base::overTimeLimit(5, 35)){
self::do_post_save_finishing();
@@ -4684,10 +4704,32 @@
global $wpdb;
$table = $wpdb->prefix . 'wpil_ai_embedding_data';
+ $index = self::get_last_embedding_id_lock();
+
+ if(!empty($index)){
+ return $index;
+ }
+
$index = $wpdb->get_var("SELECT `embed_index` FROM {$table} ORDER BY `embed_index` DESC LIMIT 1");
+
+ self::set_last_embedding_id_lock($index);
+
return (!empty($index)) ? (int)$index: 0;
}
+ private static function get_last_embedding_id_lock(){
+ $lock = get_transient('wpil_last_embedding_index_lock');
+ return (!empty($lock)) ? (int)$lock: 0;
+ }
+
+ private static function set_last_embedding_id_lock($id = null){
+ if(empty($id)){
+ delete_transient('wpil_last_embedding_index_lock');
+ }else{
+ set_transient('wpil_last_embedding_index_lock', (int)$id, DAY_IN_SECONDS);
+ }
+ }
+
/**
*
**/
--- a/link-whisper/core/Wpil/Base.php
+++ b/link-whisper/core/Wpil/Base.php
@@ -15,6 +15,7 @@
{
add_action('admin_init', [$this, 'init']);
add_action('admin_menu', [$this, 'addMenu']);
+ add_action('wp_dashboard_setup', [__CLASS__, 'register_link_health_widget']);
add_action('add_meta_boxes', [$this, 'addMetaBoxes']);
add_action('admin_enqueue_scripts', [$this, 'addScripts']);
add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_frontend_scripts'));
@@ -49,12 +50,8 @@
add_action('wp_ajax_wpil_get_dashboard_scan_loading_data', array('Wpil_Wizard', 'ajax_pull_loading_progress_for_dashboard'));
add_action('wp_ajax_wpil_wizard_set_completion_flag', array(__CLASS__, 'ajax_set_processing_complete_flag'));
add_action('wp_ajax_wpil_run_autolink_insert_search', array(__CLASS__, 'ajax_get_wizard_insert_count'));
- add_action('wp_ajax_wpil_load_tours', array('Wpil_Tour', 'ajax_load_tours'));
- add_action('wp_ajax_wpil_save_tour_progress', array('Wpil_Tour', 'ajax_save_tour_progress'));
- add_action('wp_ajax_wpil_mark_tour_shown', array('Wpil_Tour', 'ajax_mark_tour_shown'));
- add_action('wp_ajax_wpil_dismiss_tour_widget', array('Wpil_Tour', 'ajax_dismiss_tour_widget'));
- add_action('wp_ajax_wpil_load_popups', array('Wpil_Popup', 'ajax_load_popups'));
- add_action('wp_ajax_wpil_dismiss_popup', array('Wpil_Popup', 'ajax_dismiss_popup'));
+ add_action('wp_ajax_user_dismissed_ai_popup', array(__CLASS__, 'ajax_dismiss_ai_popup_banner'), 9);
+ add_action('wp_ajax_wpil_update_expanded_details_toggle', array(__CLASS__, 'ajax_update_expanded_details_toggle'), 9);
/*add_filter('the_content', array(__CLASS__, 'remove_link_whisper_attrs'));
add_filter('the_content', array(__CLASS__, 'add_link_attrs'));
add_filter('the_content', array(__CLASS__, 'add_link_icons'), 100, 1);*/
@@ -183,11 +180,26 @@
if(WPIL_STATUS_HAS_RUN_SCAN){
$page_title = __('Internal Links Report', 'wpil');
$menu_title = __('Reports', 'wpil');
- }else{
- $page_title = __('Internal Links Report', 'wpil');
- $menu_title = __('Complete Install', 'wpil');
+
+ self::$report_menu = add_submenu_page(
+ 'link_whisper',
+ $page_title,
+ $menu_title,
+ 'edit_posts',
+ 'link_whisper',
+ [Wpil_Report::class, 'init']
+ );
}
+ // hide the first item because that's just hte page title
+ add_action('admin_head', function() {
+ echo '<style>
+ #toplevel_page_link_whisper .wp-first-item{
+ display: none;
+ }
+ </style>';
+ });
+
$menu_list = array(
// 'link_whisper_dashboard', // we'll always have the main report page since we need to stick the reports to something
'link_whisper_target_keywords', //
@@ -201,7 +213,7 @@
self::$report_menu = add_submenu_page(
'link_whisper',
'Internal Links Report',
- 'Report',
+ 'Reports',
'edit_posts',
'link_whisper',
[Wpil_Report::class, 'init']
@@ -267,6 +279,270 @@
);
}
+ public static function register_link_health_widget(){
+ if( !defined('WPIL_STATUS_HAS_RUN_SCAN') || !WPIL_STATUS_HAS_RUN_SCAN
+ ){
+ // exist
+ return;
+ }
+ wp_add_dashboard_widget(
+ 'wpil_link_health_widget',
+ __('Link Whisper Site Health Report', 'wpil'),
+ [__CLASS__, 'render_link_health_widget']
+ );
+ }
+
+ public static function render_link_health_widget(){
+
+ $rows = self::get_dashboard_widget_rows();
+ $logo = plugin_dir_url(__DIR__).'../images/lw-icon.png'
+ ?>
+ <style>
+ #lw-digest-widget .lw-header { display:flex; gap:16px; align-items:flex-start; margin-bottom:14px; }
+ #lw-digest-widget .lw-logo { width:36px; height:36px; object-fit:contain; margin-top:2px; }
+ #lw-digest-widget .lw-title { margin:0 0 2px; font-size:18px; font-weight:600; }
+ #lw-digest-widget .lw-subtitle { margin:0; color:#6b7280; }
+ #lw-digest-widget .lw-site { margin:4px 0 0; color:#6b7280; }
+ #lw-digest-widget .lw-site a { text-decoration:none; }
+
+
+ #lw-digest-widget .lw-rows { list-style:none; margin:12px 0 0; padding:0; display:flex; flex-direction:column; gap:10px; }
+ #lw-digest-widget .lw-row { position:relative; border:1px solid #e5e7eb; background:#fff; border-radius:10px; padding:12px 88px 12px 14px; box-shadow:0 1px 0 rgba(16,24,40,.02); }
+ #lw-digest-widget .lw-row-main { display:flex; justify-content:space-between; gap:12px; }
+ #lw-digest-widget .lw-row-label { color:#374151; font-weight:600; }
+ #lw-digest-widget .lw-row-value { color:#111827; font-variant-numeric:tabular-nums; }
+ #lw-digest-widget .lw-row-note { font-size:12px; color:#6b7280; margin-top:6px; font-style:italic; }
+ #lw-digest-widget .lw-row-status { position:absolute; right:12px; top:50%; transform:translateY(-50%); }
+
+ #lw-digest-widget .lw-badge { display:inline-block; padding:4px 12px; border-radius:999px; font-size:12px; font-weight:700; line-height:1; }
+ #lw-digest-widget .lw-badge.is-great { background:#10b9811a; color:#047857; border:1px solid #10b98155; }
+ #lw-digest-widget .lw-badge.is-ok { background:#f59e0b1a; color:#92400e; border:1px solid #f59e0b55; }
+ #lw-digest-widget .lw-badge.is-fix { background:#ef44441a; color:#991b1b; border:1px solid #ef444455; }
+ #lw-digest-widget .lw-badge.is-info { background:#3b82f61a; color:#1e40af; border:1px solid #3b82f655; }
+
+ #lw-digest-widget .lw-delta { font-size:11px; opacity:.75; margin-left:6px; }
+
+ /* Responsive tweak for narrow admin widths */
+ @media (max-width: 782px) {
+ #lw-digest-widget .lw-row { padding-right:14px; }
+ #lw-digest-widget .lw-row-status { position:static; transform:none; margin-top:8px; }
+ }
+ </style>
+ <div id="lw-digest-widget" class="lw-digest">
+ <header class="lw-header">
+ <img class="lw-logo" src="<?php echo esc_url($logo); ?>" alt="Link Whisper" />
+ </header>
+
+
+ <ul class="lw-rows" role="list">
+ <?php foreach ($rows as $row): ?>
+ <li class="lw-row">
+ <div class="lw-row-main">
+ <div class="lw-row-label"><?php echo esc_html($row['label']); ?></div>
+ <div class="lw-row-value"><?php echo wp_kses_post($row['value']); ?></div>
+ </div>
+ <?php if (!empty($row['note'])): ?>
+ <div class="lw-row-note"><?php echo esc_html($row['note']); ?></div>
+ <?php endif; ?>
+ <div class="lw-row-status">
+ <?php echo self::status_badge($row['status'], $row['status_text'], $row['url']); ?>
+ </div>
+ </li>
+ <?php endforeach; ?>
+ </ul>
+ </div>
+ <?php
+ }
+
+ private static function get_dashboard_widget_rows(){
+ // get the datas!
+ // link density
+ $link_density = Wpil_Dashboard::get_percent_of_posts_hitting_link_targets();
+ $density_status = 'tag-positive';
+ $density_subtext = __('Great! The majority of your posts are linked enough.');
+ if(!empty($link_density['percent'])){
+ if($link_density['percent'] > 80){
+ $density_status = 'tag-positive';
+ $density_subtext = __('Great! The majority of your posts are linked enough.');
+ }elseif($link_density['percent'] > 60){
+ $density_status = 'tag-neutral';
+ $density_subtext = __('Most of the site's posts are linked enough.');
+ }else{
+ $density_status = 'tag-negative';
+ $density_subtext = __('Uh oh, the majority of the site's posts aren't linked enough.');
+ }
+ }
+
+ // broken links
+ $broken_link_count = Wpil_Dashboard::getBrokenLinksCount();
+ $broken_link_percentage = 0;
+ $broken_link_status = 'tag-positive';
+ $broken_link_subtext = __('Perfect! There aren't any broken links on the site.');
+ if(!empty($broken_link_count)){
+ $total_links = Wpil_Dashboard::getLinksCount();
+ if(!empty($total_links)){
+ $broken_link_percentage = round($broken_link_count / $total_links, 2) * 100;
+ }
+ }
+
+ if($broken_link_percentage == 0){
+ $broken_link_status = 'tag-positive';
+ $broken_link_subtext = __('Perfect! There aren't any broken links on the site.');
+ }elseif($broken_link_percentage < 5){
+ $broken_link_status = 'tag-positive';
+ $broken_link_subtext = __('Good! There are a relatively low number of broken links on the site.');
+ }elseif($broken_link_percentage < 10){
+ $broken_link_status = 'tag-neutral';
+ $broken_link_subtext = __('There are a number of broken links on the site that need fixing.');
+ }else{
+ $broken_link_status = 'tag-negative';
+ $broken_link_subtext = __('Houston, we have a problem. There are a lot of broken links on the site');
+ }
+
+ $posts_crawled = Wpil_Dashboard::getPostCount();
+ $posts_crawled_status = (empty($posts_crawled)) ? 'tag-negative': 'tag-positive';
+
+ $links_scanned = Wpil_Dashboard::getLinksCount();
+ $links_scanned_status = (empty($links_scanned)) ? 'tag-negative': 'tag-positive';
+
+ $links_inserted = Wpil_Dashboard::get_tracked_link_insert_count();
+ $links_inserted_status = ($links_inserted > 0) ? 'tag-positive': 'tag-neutral';
+
+ $orphaned_posts = Wpil_Dashboard::getOrphanedPostsCount();
+ if(!empty($orphaned_posts)){
+ $orphaned_posts_percentage = round($orphaned_posts/$posts_crawled, 2) * 100;
+ if($orphaned_posts_percentage == 0){
+ $orphaned_posts_status = 'tag-positive';
+ $orphaned_posts_subtext = esc_html__('Awesome! There are no orphaned posts on the site.', 'wpil');
+ }elseif($orphaned_posts_percentage < 5){
+ $orphaned_posts_status = 'tag-positive';
+ $orphaned_posts_subtext = esc_html__('Awesome! There are very few orphaned posts on the site.', 'wpil');
+ }elseif($orphaned_posts_percentage < 10){
+ $orphaned_posts_status = 'tag-neutral';
+ $orphaned_posts_subtext = esc_html__('There are a number of orphaned posts that need some links pointing to them.', 'wpil');
+ }else{
+ $orphaned_posts_status = 'tag-negative';
+ $orphaned_posts_subtext = esc_html__('Uh oh, looks like there are a lot of orphaned posts that need links!', 'wpil');
+ }
+ }else{
+ $orphaned_posts_status = 'tag-positive';
+ $orphaned_posts_subtext = esc_html__('Awesome! There are no orphaned posts on the site.', 'wpil');
+ }
+/*
+ $ai_active = Wpil_Settings::can_do_ai_powered_suggestions(); // if we have a API key and at least some of the embedding data processed
+ $link_relatedness = 0;
+ if($ai_active){
+ $link_relatedness = Wpil_Dashboard::get_related_link_percentage();
+ if($link_relatedness == 0){
+ $link_relatedness_status = 'tag-neutral';
+ $link_relatedness_subtext = esc_html__('Hmm, there's no data available. We might need to run a Link Scan.', 'wpil');
+ }elseif($link_relatedness > 79){
+ $link_relatedness_status = 'tag-positive';
+ $link_relatedness_subtext = esc_html__('Amazing! The majority of the site's links are going to highly related posts.', 'wpil');
+ }elseif($link_relatedness > 50){
+ $link_relatedness_status = 'tag-neutral';
+ $link_relatedness_subtext = esc_html__('Most of the site's links are pointing to topically related posts.', 'wpil');
+ }else{
+ $link_relatedness_status = 'tag-negative';
+ $link_relatedness_subtext = esc_html__('Uh oh, it looks like most of the site's links aren't going to related posts.', 'wpil');
+ }
+ }else{
+ $link_relatedness_status = 'tag-neutral';
+ $link_relatedness_subtext = esc_html__('Link Whisper's AI is not enabled, so we can't tell how many links are going to topically related posts.', 'wpil');
+ }
+*/
+ // link clicks
+ $click_stats = Wpil_Dashboard::get_click_traffic_stats();
+ $click_change_indicator = '(<span title="No change from previous 30 days">0%</span>)';
+ $click_change_subtext = esc_html__('The number of clicks has remained consistent over the past 30 days.', 'wpil');
+ $click_change_status = 'tag-neutral';
+ if($click_stats['percent_change'] > 0){
+ $click_change_status = 'tag-positive';
+ $click_change_indicator = '(<span class="tag-positive" title="Clicks have gone up over the past 30 days">+' . $click_stats['percent_change'] . '%</span>)';
+ $click_change_subtext = esc_html__('The number of clicks on the site has gone up over the past 30 days!', 'wpil');
+ }elseif($click_stats['percent_change'] < 0){
+ $click_change_status = 'tag-negative';
+ $click_change_indicator = '(<span class="tag-negative" title="Clicks have gone down over the past 30 days">-' . $click_stats['percent_change'] . '%</span>)';
+ $click_change_subtext = esc_html__('The number of clicks on the site have gone down over the past 30 days.', 'wpil');
+ }
+
+ return [
+ [
+ 'label' => __('Posts Crawled', 'wpil'),
+ 'value' => $posts_crawled,
+ 'note' => '',
+ 'status'=> $posts_crawled_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper')
+ ],
+ [
+ 'label' => __('Links Detected', 'wpil'),
+ 'value' => $links_scanned,
+ 'note' => '',
+ 'status'=> $links_scanned_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper&type=links')
+ ],
+ [
+ 'label' => __('Links Inserted', 'wpil'),
+ 'value' => $links_inserted,
+ 'note' => '',
+ 'status'=> $links_inserted_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper&type=links')
+ ],
+ [
+ 'label' => __('Link Coverage', 'wpil'),
+ 'value' => $link_density['percent'] . '%',
+ 'note' => '', //$density_subtext,
+ 'status'=> $density_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper&type=links&link_density=1')
+ ],
+ [
+ 'label' => __('Orphaned Posts', 'wpil'),
+ 'value' => $orphaned_posts,
+ 'note' => '', // $orphaned_posts_subtext,
+ 'status'=> $orphaned_posts_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper&type=links&orphaned=1')
+ ],
+ [
+ 'label' => __('Link Clicks Tracked', 'wpil'),
+ 'value' => $click_stats['clicks_30'],
+ 'note' => '', // $click_change_subtext,
+ 'status'=> $click_change_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper&type=clicks')
+ ],
+ [
+ 'label' => __('Broken Links Found', 'wpil'),
+ 'value' => $broken_link_count,
+ 'note' => '', // $broken_link_subtext,
+ 'status'=> $broken_link_status,
+ 'status_text' => '',
+ 'url' => admin_url('admin.php?page=link_whisper&type=error')
+ ],
+ ];
+ }
+
+ private static function status_badge($status, $text = '', $url = ''){
+ $map = [
+ 'tag-positive' => ['label' => (!empty($text) ? $text: __('Great', 'wpil')), 'class' => 'is-great'],
+ 'tag-neutral' => ['label' => (!empty($text) ? $text: __('OK', 'wpil')), 'class' => 'is-ok'],
+ 'tag-negative' => ['label' => (!empty($text) ? $text: __('Fix', 'wpil')), 'class' => 'is-fix'],
+ 'tag-info' => ['label' => (!empty($text) ? $text: __('Info', 'wpil')), 'class' => 'is-info'],
+ ];
+ $cfg = isset($map[$status]) ? $map[$status]: $map['tag-info'];
+ $label = esc_html($cfg['label']);
+ $cls = 'lw-badge ' . $cfg['class'];
+
+ if(!empty($url)){
+ return '<a class="'.$cls.'" href="'.esc_url($url).'" target="_blank">'.$label.'<span class="dashicons dashicons-external" style="position: relative;top: 1px;right: -1px;height: 5px;width: 5px;font-size: 12px;"></span></a>';
+ }
+ return '<span class="'.$cls.'">'.$label.'</span>';
+ }
+
/**
* Get post or term by ID from GET or POST request
*
@@ -600,8 +876,9 @@
$script_params['dismiss_tour_widget_nonce'] = wp_create_nonce('wpil_dismiss_tour_widget');
$script_params['popup_nonce'] = wp_create_nonce('wpil_load_popups');
$script_params['dismiss_popup_nonce'] = wp_create_nonce('wpil_dismiss_popup');
- $script_params['telemetry_active'] = 1; //Wpil_Settings::get_if_telemetry_active();
- $script_params['telemetry_nonce'] = wp_create_nonce(get_current_user_id() . 'wpil-telemetry-nonce');
+// $script_params['telemetry_active'] = 1; //Wpil_Settings::get_if_telemetry_active();
+// $script_params['telemetry_nonce'] = wp_create_nonce(get_current_user_id() . 'wpil-telemetry-nonce');
+// $script_params['tours_enabled'] = Wpil_Settings::get_tours_enabled();
$script_params['wpil_timepicker_format'] = Wpil_Toolbox::convert_date_format_for_js();
/*
@@ -752,45 +1029,6 @@
wp_register_script('wpil_help_overlay', WP_INTERNAL_LINKING_PLUGIN_URL.'js/wpil_help_overlay.js', array('jquery', 'wpil_base64', 'wpil_tippy', 'wpil_popper', 'wpil_helper'), $ver, true);
wp_enqueue_script('wpil_help_overlay');
-
- // Tour system assets
- $tours_css_path = 'css/wpil_tours.css';
- $tours_css_file = WP_INTERNAL_LINKING_PLUGIN_DIR . $tours_css_path;
- $tours_js_path = 'js/wpil_tours.js';
- $tours_js_file = WP_INTERNAL_LINKING_PLUGIN_DIR . $tours_js_path;
- if (file_exists($tours_css_file)) {
- wp_register_style('wpil_tours_style', WP_INTERNAL_LINKING_PLUGIN_URL . $tours_css_path, array(), filemtime($tours_css_file));
- wp_enqueue_style('wpil_tours_style');
- }
-
- if (file_exists($tours_js_file)) {
- wp_register_script('wpil_tours', WP_INTERNAL_LINKING_PLUGIN_URL . $tours_js_path, array('jquery', 'wpil_admin_script'), filemtime($tours_js_file), true);
- wp_enqueue_script('wpil_tours');
- }
-
- // Telemetry logging system
- $telemetry_js_path = 'js/wpil_telemetry.js';
- $telemetry_js_file = WP_INTERNAL_LINKING_PLUGIN_DIR . $telemetry_js_path;
- if (file_exists($telemetry_js_file)) {
- wp_register_script('wpil_telemetry', WP_INTERNAL_LINKING_PLUGIN_URL . $telemetry_js_path, array('jquery', 'wpil_admin_script'), filemtime($telemetry_js_file), true);
- wp_enqueue_script('wpil_telemetry');
- }
-
- // Enqueue popup assets
- $popups_css_path = 'css/wpil_popups.css';
- $popups_css_file = WP_INTERNAL_LINKING_PLUGIN_DIR . $popups_css_path;
- $popups_js_path = 'js/wpil_popups.js';
- $popups_js_file = WP_INTERNAL_LINKING_PLUGIN_DIR . $popups_js_path;
-
- if (file_exists($popups_css_file)) {
- wp_register_style('wpil_popups_style', WP_INTERNAL_LINKING_PLUGIN_URL . $popups_css_path, array(), filemtime($popups_css_file));
- wp_enqueue_style('wpil_popups_style');
- }
-
- if (file_exists($popups_js_file)) {
- wp_register_script('wpil_popups', WP_INTERNAL_LINKING_PLUGIN_URL . $popups_js_path, array('jquery', 'wpil_admin_script'), filemtime($popups_js_file), true);
- wp_enqueue_script('wpil_popups');
- }
}
/**
@@ -811,12 +1049,18 @@
}
}elseif(isset($_GET['page']) && $_GET['page'] === 'link_whisper'){
$page = 'dashboard';
+ }elseif(isset($_GET['page']) && $_GET['page'] === 'link_whisper_keywords'){
+ $page = 'autolinking';
+ }elseif(isset($_GET['page']) && $_GET['page'] === 'link_whisper_target_keywords'){
+ $page = 'target-keywords';
+ }elseif(isset($_GET['page']) && $_GET['page'] === 'link_whisper_url_changer'){
+ $page = 'url-changer';
+ }elseif(isset($_GET['page']) && $_GET['page'] === 'link_whisper_ai_subscription'){
+ $page = 'ai-subscription';
}elseif(!empty($current_page) && $current_page->base === 'post'){
$page = 'post-edit';
}elseif(!empty($current_page) && $current_page->base === 'term'){
$page = 'term-edit';
- }elseif(isset($_GET['page']) && $_GET['page'] === 'link_whisper_ai_subscription'){
- $page = 'ai-subscription';
}
return $page;
@@ -2750,4 +2994,17 @@
$link_count = $wpdb->get_col("SELECT COUNT(*) FROM {$table} WHERE `creation_time` > {$start_time}");
wp_send_json(array('data' => array('link_inserts' => $link_count, 'finished' => (!empty(get_transient('wpil_wizard_has_completed')) || empty(get_transient('wpil_doing_ajax_autolinks'))))));
}
+
+ /**
+ *
+ **/
+ public static function ajax_dismiss_ai_popup_banner(){
+ update_user_meta(get_current_user_id(), 'wpil_dismissed_ai_notice_banner', '1');
+ }
+
+ public static function ajax_update_expanded_details_toggle(){
+ $status = (!isset($_POST['status']) || empty($_POST['status'])) ? 0: 1;
+ update_option('wpil_show_expanded_suggestion_details', $status);
+ wp_send_json('updated details!');
+ }
}
--- a/link-whisper/core/Wpil/Model/Link.php
+++ b/link-whisper/core/Wpil/Model/Link.php
@@ -23,6 +23,7 @@
public $ai_relation_score = 0; // how related is the source post to the target post?
public $target_id = null;
public $target_type = null;
+ public $anchor_word_count = 0;
public function __construct($params = [])
{
@@ -32,6 +33,10 @@
$this->{$key} = $value;
}
}
+
+ if(empty($this->anchor_word_count) && !empty($this->anchor)){
+ $this->anchor_word_count = Wpil_Word::getWordCount($this->anchor);
+ }
}
function create_scroll_link_data(){
--- a/link-whisper/core/Wpil/Model/Post.php
+++ b/link-whisper/core/Wpil/Model/Post.php
@@ -474,11 +474,29 @@
$content .= $this->getMetaContent();
$this->editor = !empty($content) ? 'wordpress': null;
- if(class_exists('ThemifyBuilder_Data_Manager')){
+ // get the currently active theme
+ $theme = wp_get_theme();
+ $is_themify = false;
+ if(!empty($theme) && $theme->exists() &&
+ (false !== stripos($theme->name, 'Themify Ultra') ||
+ false !== stripos($theme->parent_theme, 'Themify Ultra'))
+ ){
+ $is_themify = true;
+ }
+
+ if(class_exists('ThemifyBuilder_Data_Manager') || $is_themify){
// if there's Themify static editor content in the post content
if(false !== strpos($content, 'themify_builder_static')){
// remove it
$content = mb_ereg_replace('<!--themify_builder_static-->[wW]*?<!--/themify_builder_static-->', '', $content);
+ $this->editor = 'themify';
+ }
+
+ // if there's themify builder content present
+ if(false !== strpos($content, 'themify_builder_content')){
+ // remove it too
+ $content = mb_ereg_replace('<!--themify_builder_content-->[wW]*?<!--/themify_builder_content-->', '', $content);
+ $this->editor = 'themify';
}
}
@@ -1202,6 +1220,7 @@
'ai_relation_score' => (isset($dat->ai_relation_score) && !empty($dat->ai_relation_score)) ? $dat->ai_relation_score: 0,
'target_id' => (isset($dat->target_id) && !empty($dat->target_id)) ? $dat->target_id: 0,
'target_id' => (isset($dat->target_type) && !empty($dat->target_type)) ? $dat->target_type: 0,
+ 'anchor_word_count' => (isset($dat->anchor_word_count) && !empty($dat->anchor_word_count)) ? $dat->anchor_word_count: 0,
]);
}else{
$meta['wpil_links_outbound_internal_count']++;
@@ -1219,6 +1238,7 @@
'ai_relation_score' => (isset($dat->ai_relation_score) && !empty($dat->ai_relation_score)) ? $dat->ai_relation_score: 0,
'target_id' => (isset($dat->target_id) && !empty($dat->target_id)) ? $dat->target_id: 0,
'target_id' => (isset($dat->target_type) && !empty($dat->target_type)) ? $dat->target_type: 0,
+ 'anchor_word_count' => (isset($dat->anchor_word_count) && !empty($dat->anchor_word_count)) ? $dat->anchor_word_count: 0,
]);
}
}else{
@@ -1236,6 +1256,7 @@
'link_context' => (isset($dat->link_context) && !empty($dat->link_context)) ? $dat->link_context: 0,
'target_id' => (isset($dat->target_id) && !empty($dat->target_id)) ? $dat->target_id: 0,
'target_id' => (isset($dat->target_type) && !empty($dat->target_type)) ? $dat->target_type: 0,
+ 'anchor_word_count' => (isset($dat->anchor_word_count) && !empty($dat->anchor_word_count)) ? $dat->anchor_word_count: 0,
]);
}
}
--- a/link-whisper/core/Wpil/Notification.php
+++ b/link-whisper/core/Wpil/Notification.php
@@ -20,7 +20,17 @@
// Build API URL
$api_url = self::BASE_API_URL . '/wp-json/lwnh/v1/notifications';
- $request_url = add_query_arg(['plugin_version' => WPIL_PLUGIN_VERSION_NUMBER, 'plugin_type' => 'free'], $api_url);
+ $query_args = [
+ 'plugin_version' => WPIL_PLUGIN_VERSION_NUMBER,
+ 'plugin_type' => 'free'
+ ];
+
+ // Add testing mode parameter if enabled
+ if (class_exists('Wpil_Settings') && Wpil_Settings::get_if_testing_mode_active()) {
+ $query_args['testing_mode'] = '1';
+ }
+
+ $request_url = add_query_arg($query_args, $api_url);
// Make the API request
$response = wp_remote_get($request_url, [
--- a/link-whisper/core/Wpil/Post.php
+++ b/link-whisper/core/Wpil/Post.php
@@ -10,6 +10,7 @@
'web-story'
);
public static $post_url_cache = array();
+ public static $editor_insert_log = array();
/**
* Register services
@@ -1085,7 +1086,7 @@
global $wpdb;
$post = null;
$link = trim($link);
- $link = Wpil_Link::get_url_redirection($link) ?: $link;
+ // $link = Wpil_Link::get_url_redirection($link) ?: $link; //todo: make work with
$starting_link = $link;
// check to see if we've already come across this link
--- a/link-whisper/core/Wpil/Report.php
+++ b/link-whisper/core/Wpil/Report.php
@@ -69,6 +69,7 @@
$page = isset($_REQUEST['page']) ? sanitize_text_field($_REQUEST['page']) : 'link_whisper';
$title = ''; // $title is title used in the link report
$report_description = '';
+ $sub_report = '';
if(isset($_GET['orphaned'])){
$title = __('Orphaned Posts Report', 'wpil');
}elseif(isset($_REQUEST['link_density'])){
@@ -78,6 +79,14 @@
<div style="font-size: 18px;">'. esc_html__('SEO best practices recommend posts have at least 1 Inbound Internal link, and 3 or more Outbound Internal links.', 'wpil') .'</div>'
. '<br>
<div style="font-size: 16px;">' . esc_html__('To help you meet these goals, this report will show you all the posts that could use some links, and give our recommendation on how many links to add!', 'wpil').'</div></div>';
+ }elseif(isset($_REQUEST['anchor_length'])){
+ $title = __('Anchor Length Report', 'wpil');
+ $report_description =
+ '<div style="float: left; background: #fff; padding: 10px; border-radius: 5px; border: 1px solid #cdcdcd; width:100%">
+ <div style="font-size: 18px;">'. esc_html__('SEO best practices recommend link anchor texts be between 3 and 7 words in length.', 'wpil') .'</div>'
+ . '<br>
+ <div style="font-size: 16px;">' . sprintf(esc_html__('To help you meet these goals, this report shows posts with out-of-guideline anchor text and %s where the percentage of compliant links is low.', 'wpil'), '<span style="background: #7645b1;border-radius: 10px;padding: 2px 6px;color: #fefefe;font-weight: bold;">highlights</span>').'</div></div>';
+ $sub_report = '<input id="wpil-report-sub-type" type="hidden" value="anchor_length">';
}elseif(isset($_REQUEST['link_relation'])){
$title = __('Link Quality Report', 'wpil');
$report_description =
@@ -1870,7 +1879,7 @@
* @param int $limit
* @return array
*/
- public static function getData($start = 0, $orderby = '', $order = 'DESC', $search='', $limit=20, $orphaned = false, $link_density_report = false)
+ public static function getData($start = 0, $orderby = '', $order = 'DESC', $search='', $limit=20, $orphaned = false, $link_density_report = false, $anchor_length_report = false)
{
global $wpdb;
$link_table = $wpdb->prefix . "wpil_report_links";
@@ -2089,6 +2098,11 @@
}
}
+ // if we're showing the anchor length report
+ if($anchor_length_report){
+ // TODO: think about filterign the results to only show posts and links hat are outside the anchor word guidelines
+ }
+
// hide ignored
$ignored_posts = Wpil_Query::get_all_report_ignored_post_ids('p', array('orphaned' => $orphaned, 'hide_noindex' => $hide_noindex));
$ignored_terms = '';
@@ -2343,6 +2357,7 @@
$show_click_traffic = !empty($options['show_click_traffic']) && $options['show_click_traffic'] != 'off';
$show_broken_link_type = !empty($options['show_broken_link_type']) && $options['show_broken_link_type'] != 'off';
$show_broken_link_discovered = !empty($options['show_broken_link_discovered']) && $options['show_broken_link_discovered'] != 'off';
+// $enable_tours = isset($options['enable_tours']) ? ($options['enable_tours'] != 'off') : Wpil_Settings::get_tours_enabled();
} else {
$show_categories = false;
$show_date = true;
@@ -2354,6 +2369,7 @@
$show_click_traffic = false;
$show_broken_link_type = false;
$show_broken_link_discovered = false;
+// $enable_tours = Wpil_Settings::get_tours_enabled();
}
//get apply button
@@ -2408,7 +2424,18 @@
if (!isset($_POST['report_options']['hide_noindex'])) {
$_POST['report_options']['hide_noindex'] = 'off';
}
+ if (!isset($_POST['report_options']['show_link_attrs'])) {
+ $_POST['report_options']['show_link_attrs'] = 'off';
+ }
+ if (!isset($_POST['report_options']['enable_tours'])) {
+ $_POST['report_options']['enable_tours'] = 'off';
+ }
$value = $_POST['report_options'];
+
+ // Also update the global setting for tours
+ if (isset($value['enable_tours'])) {
+ update_option('wpil_enable_tours', ($value['enable_tours'] != 'off') ? '1' : '0');
+ }
}
return $value;
@@ -2555,8 +2582,10 @@
$get_all_links = Wpil_Settings::showAllLinks();
$post_id = (int)$_POST['post_id'];
$post_type = ($_POST['post_type'] === 'post') ? 'post': 'term';
-
+ $show_fix_anchors = (isset($_POST['show_fix_anchor']) && !empty($_POST['show_fix_anchor'])) ? true: false;
$post = new Wpil_Model_Post($post_id, $post_type);
+ $phrases = ($show_fix_anchors) ? Wpil_Suggestion::get_post_paragraphs($post->getContent(false)): '';
+ $allow_multiple_links = !empty(get_user_meta(get_current_user_id(), 'wpil_allow_multiple_editor_links', true));
$activity_tooltip = __('Upgrade Link Whisper with AI and see how relevant your links really are.', 'wpil');
$ai_not_enabled = (!Wpil_Settings::has_ai_enabled()) ? '<div class="wpil-activity-upgrade-ai"><span>93%</span> <a href="'.admin_url('admin.php?page=link_whisper_ai_subscription').'" target="_blank" class="button-primary wpil-tippy-tooltipped" data-wpil-tooltip-theme="link-whisper-report-tippy" data-wpil-tooltip-interactive="1" data-wpil-tooltip-content="'.$activity_tooltip.'">Upgrade</a></div>': '';
@@ -2612,7 +2641,7 @@
}
$rep .= '</div>
</td>
- <td class="'.$related.'"><div style="margin: 3px 0;"> ' . ((empty($ai_not_enabled)) ? esc_html($link->get_ai_relation_percent()): $ai_not_enabled) . '</div></td>';
+ <td class="'.$related.'"><div style="margin: 3px 0;"> ' . ((empty($ai_not_enabled)) ? esc_html($link->get_ai_relation_percent()): $ai_not_enabled) . '</div></td>';
$rep .= ($get_all_links) ? '<td><div style="margin: 3px 0;">' . $link->location . '</div></td>' : '';
// $rep .= '<td class="wpil-status-icon-cell">' . self::get_dropdown_icons($link->post, $link, 'inbound-internal', true) . '</td>';
$rep .= '</tr>';
@@ -2631,10 +2660,15 @@
$header = array_merge($header, [
'<th>Target Post Title</th>',
'<th>Anchor Text</th>',
- '<th>URL</th>',
- '<th class="wpil-activity-panel-content-related '.$last_col.'">AI Content Relatedness</th>'
]);
+ if(!$show_fix_anchors){
+ $header = array_merge($header, [
+ '<th>URL</th>',
+ '<th class="wpil-activity-panel-content-related '.$last_col.'">AI Content Relatedness</th>'
+ ]);
+ }
+
if($get_all_links){
$header = array_merge($header, [
'<th class="wpil-activity-panel-link-location wpil-activity-last-col">Link Location</th>'
@@ -2645,8 +2679,19 @@
'<th class="wpil-link-status-icon-header wpil-activity-panel-fixed-th">Status</th>'
]);*/
+ if($show_fix_anchors){
+ $header = array_merge($header, [
+ //'<th>Primary Category</th>',
+ '<th class="wpil-activity-panel-anchor-words wpil-activity-last-col">Word Count</th>'
+ ]);
+ }
+
$links_data = $post->getOutboundInternalLinks();
foreach ($links_data as $link) {
+ if($show_fix_anchors && ($link->anchor_word_count > 2 && $link->anchor_word_count < 8)){
+ continue;
+ }
+
if (!Wpil_Filter::linksLocation() || $link->location == Wpil_Filter::linksLocation()) {
$target_post = (isset($link->target_id) && !empty($link->target_id)) ? new Wpil_Model_Post($link->target_id, $link->target_type): Wpil_Post::getPostByLink($link->url);
$edit_link = '';
@@ -2667,30 +2712,65 @@
$primary_category_note = '<td><div style="margin: 3px 0;">None</div></td>';
}*/
- $rep .= '<tr class="wpil-activity-panel-edit inactive">
+ $phrase_key = false;
+ $phrase_key_id = '';
+ if($show_fix_anchors){
+ $phrase_key = self::find_link_phrase_key($phrases, $link);
+ if(false !== $phrase_key){
+ $phrase_key_id = 'data-wpil-sentence-id="'.$phrase_key.'"';
+ }
+ }
+
+ $rep .= '<tr class="wpil-activity-panel-edit sentences inactive" '.$phrase_key_id.'>
<td class="wpil-activity-panel-checkbox"><input type="checkbox" class="wpil_link_select wpil_activity_select" data-link_id="' . $link->post->id . '" data-post_id="' . $post->id . '" data-post_type="' . $post->type . '" data-anchor="' . base64_encode($link->anchor) . '" data-url="' . base64_encode($link->url) . '" data-nonce="' . wp_create_nonce('wpil_report_edit_' . $link->post->id . '_nonce_' . $link->post->id) . '"></td>
<td class="wpil-activity-panel-post wpil-activity-panel-limited-text-cell"><div style="margin: 3px 0;"> ' . ((!empty($target_post)) ? esc_html($target_post->getTitle()): 'Unknown Post') . '</div></td>
- <td class="wpil-activity-panel-limited-text-cell">
- <div style="margin: 3px 0; display:flex">
+ <td class="'. (false !== $phrase_key ? '': 'wpil-activity-panel-limited-text-cell') .'">';
+ if(false !== $phrase_key && isset($phrases[$phrase_key])){
+ $phrase = $phrases[$phrase_key];
+ unset($phrases[$phrase_key]);
+ $phr = self::assemble_suggestion_item($phrase);
+ $rep .= '
+ <div style="display:none">'.$edit_link.'</div>
+ <div class="sentence top-level-sentence" data-id="'.esc_attr($post->id).'" data-type="'.esc_attr($post->type).'">
+ <div class="wpil_edit_sentence_form">
+ <textarea class="wpil_content">'.$phr->suggestions[0]->sentence_src_with_anchor.'</textarea>
+ <span class="button-primary">Save</span>
+ <span class="button-secondary">Cancel</span>
+ <span> <input type="checkbox" class="wpil-sentence-allow-multiple-links" data-nonce="'.wp_create_nonce(get_current_user_id() . 'allow_multiple_links_editor').'" '. (($allow_multiple_links) ? 'checked': '') .'>Allow multiple links in sentence</span>
+ </div>
+ <span class="wpil_sentence_with_anchor" data-li-id="0"><span class="wpil_sentence" title="'. esc_attr__('Double clicking a word will select it.', 'wpil') .'">' . $phr->suggestions[0]->sentence_with_anchor . '</span><span class="dashicons dashicons-image-rotate wpil-reload-sentence-with-anchor" title="'. esc_attr__('Click to undo changes', 'wpil') . '"></span></span>
+ <span class="wpil_edit_sentence link-form-button">| <a href="javascript:void(0)">Edit Sentence</a></span>
+ <input type="hidden" name="sentence" value="'.base64_encode($phr->sentence_src).'">
+ <input type="hidden" name="custom_sentence" value="">
+ <input type="hidden" name="original_sentence_with_anchor" value="'.base64_encode($phr->suggestions[0]->original_sentence_with_anchor).'">
+ <input type="hidden" class="wpil-activity-panel-url-edit wpil-report-edit-input" value="' . esc_attr($link->url) . '">
+ </div>';
+ }else{
+ $rep .= '<div style="margin: 3px 0; display:flex">
'.$edit_link.'
<div class="wpil-report-edit-display wpil-activity-panel-anchor-display"><div class="wpil-anchor-display-text">' . esc_html($link->anchor) . '</div> <a href="' . esc_url(add_query_arg(['wpil_admin_frontend' => '1', 'wpil_admin_frontend_data' => $link->create_scroll_link_data()], $post->getLinks()->view)) . '" target="_blank"><span class="dashicons dashicons-external" title="'.esc_attr__('View On Page','wpil').'" style="position: relative;top: 3px;"></span></a></div>';
- if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context)){
- $rep .= '<input class="wpil-activity-panel-anchor-edit wpil-report-edit-input" type="text" value="' . esc_attr($link->anchor) . '">';
- }
+ if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context)){
+ $rep .= '<input class="wpil-activity-panel-anchor-edit wpil-report-edit-input" type="text" value="' . esc_attr($link->anchor) . '">';
+ }
+ }
$rep .= '</div>
- </td>
- <td class="wpil-activity-panel-limited-text-cell">
- <div style="margin: 3px 0; display:flex">
- '.$edit_link.'
- <div href="' . esc_url($link->url) . '" target="_blank" class="wpil-report-edit-display wpil-activity-panel-url-display" style="text-decoration: underline">
- <div class="wpil-url-display-text">' . esc_html($link->url) . '</div>
- </div>';
- if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context)){
- $rep .= '<input class="wpil-activity-panel-url-edit wpil-report-edit-input" type="text" value="' . esc_attr($link->url) . '">';
+ </td>';
+ if($show_fix_anchors){
+ $rep .= '<td class="wpil-activity-panel-limited-text-cell wpil-activity-panel-word-count">' .$link->anchor_word_count. '</td>';
+ }else{
+ $rep .= '<td class="wpil-activity-panel-limited-text-cell">
+ <div style="margin: 3px 0; display:flex">
+ '.$edit_link.'
+ <div href="' . esc_url($link->url) . '" target="_blank" class="wpil-report-edit-display wpil-activity-panel-url-display" style="text-decoration: underline">
+ <div class="wpil-url-display-text">' . esc_html($link->url) . '</div>
+ </div>';
+ if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context) && !$show_fix_anchors){
+ $rep .= '<input class="wpil-activity-panel-url-edit wpil-report-edit-input" type="text" value="' . esc_attr($link->url) . '">';
+ }
+ $rep .= '</div>
+ </td>';
+ $rep .= '<td><div class="'.$related.'" style="margin: 3px 0;"><div class="content-relatedness-score">' . ((empty($ai_not_enabled)) ? esc_html($link->get_ai_relation_percent()): $ai_not_enabled) . '</div></div></td>';
}
- $rep .= '</div>
- </td>
- <td><div class="'.$related.'" style="margin: 3px 0;"><div class="content-relatedness-score">' . ((empty($ai_not_enabled)) ? esc_html($link->get_ai_relation_percent()): $ai_not_enabled) . '</div></div></td>';
$rep .= ($get_all_links) ? '<td><div style="margin: 3px 0;">' . $link->location . '</div></td>' : '';
// $rep .= $primary_category_note;
// $rep .= '<td class="wpil-status-icon-cell">' . self::get_dropdown_icons($post, $link, 'outbound-internal', true) . '</td>';
@@ -2702,48 +2782,118 @@
case 'outbound-external':
$header = array_merge($header, [
'<th>Anchor Text</th>',
- '<th>URL</th>',
]);
+ if(!$show_fix_anchors){
+ $header = array_merge($header, [
+ '<th>URL</th>'
+ ]);
+ }
+
if($get_all_links){
$header = array_merge($header, [
'<th class="wpil-activity-panel-link-location wpil-activity-last-col">Link Location</th>'
]);
}
+ if($show_fix_anchors){
+ $header = array_merge($header, [
+ //'<th>Primary Category</th>',
+ '<th class="wpil-activity-panel-anchor-words wpil-activity-last-col">Word Count</th>'
+ ]);
+ }
+
/*$header = array_merge($header, [
'<th class="wpil-link-status-icon-header wpil-activity-panel-fixed-th">Status</th>'
]);*/
$links_data = $post->getOutboundExternalLinks();
foreach ($links_data as $link) {
+ if($show_fix_anchors && ($link->anchor_word_count > 2 && $link->anchor_word_count < 8)){
+ continue;
+ }
+
if (!Wpil_Filter::linksLocation() || $link->location == Wpil_Filter::linksLocation()) {
- $edit_link = '';
+ $target_post = (isset($link->target_id) && !empty($link->target_id)) ? new Wpil_Model_Post($link->target_id, $link->target_type): Wpil_Post::getPostByLink($link->url);
+ $edit_link = ('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context)) ? '<span class="dashicons dashicons-edit wpil_activate_edit_link" title="' . esc_attr__('Edit Link', 'wpil') . '"></span>' : '';
+ $related = (!empty($link->get_ai_relation_percent(true)) && $link->get_ai_relation_percent(true) < 50) ? 'ai-not-related': '';
+
+ /*
+ $primary_category_note = '<td><div style="margin: 3px 0;">None assigned</div></td>';
+ if(!empty($link->post) && $link->post->type === 'post') {
+ // Get the main term
+ $primary_term = Wpil_Post::get_primary_term_for_main_taxonomy($link->post->id, $link->post->getRealType());
- $rep .= '<tr class="wpil-activity-panel-edit inactive">
- <td class="wpil-activity-panel-checkbox"><input type="checkbox" class="wpil_link_select wpil_activity_select" data-link_id="' . $post->id . '" data-post_id="' . $post->id . '" data-post_type="' . $post->type . '" data-anchor="' . base64_encode($link->anchor) . '" data-url="' . base64_encode($link->url) . '" data-nonce="' . wp_create_nonce('wpil_report_edit_' . $post->id . '_nonce_' . $post->id) . '"></td>
- <td class="wpil-activity-panel-limited-text-cell">
- <div style="margin: 3px 0; display:flex">
- '.$edit_link.'
- <div class="wpil-report-edit-display wpil-activity-panel-anchor-display"><div class="wpil-anchor-display-text">' . esc_html($link->anchor) . '</div> <a href="' . esc_url(add_query_arg(['wpil_admin_frontend' => '1', 'wpil_admin_frontend_data' => $link->create_scroll_link_data()], $post->getLinks()->view)) . '" target="_blank"><span class="dashicons dashicons-external" title="'.esc_attr__('View On Page','wpil').'" style="position: relative;top: 3px;"></span></a></div>';
- if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context)){
- $rep .= '<input class="wpil-activity-panel-anchor-edit wpil-report-edit-input" type="text" value="' . esc_attr($link->anchor) . '">';
+ if ($primary_term instanceof WP_Term) {
+ $primary_category_note = '<td><div style="margin: 3px 0;">' . esc_html($primary_term->name) . '</div></td>';
+ } else {
+ $primary_category_note = '<td><div style="margin: 3px 0;">None assigned</div></td>';
+ }
+ }elseif(!empty($link->post) && $link->post->type === 'term'){
+ $primary_category_note = '<td><div style="margin: 3px 0;">None</div></td>';
+ }*/
+
+ $phrase_key = false;
+ $phrase_key_id = '';
+ if($show_fix_anchors){
+ $phrase_key = self::find_link_phrase_key($phrases, $link);
+ if(false !== $phrase_key){
+ $phrase_key_id = 'data-wpil-sentence-id="'.$phrase_key.'"';
+ }
}
- $rep .= '</div>
- </td>
- <td class="wpil-activity-panel-limited-text-cell">
- <div style="margin: 3px 0; display:flex">
+
+ $rep .= '<tr class="wpil-activity-panel-edit sentences inactive" '.$phrase_key_id.'>
+ <td class="wpil-activity-panel-checkbox"><input type="checkbox" class="wpil_link_select wpil_activity_select" data-link_id="' . $link->post->id . '" data-post_id="' . $post->id . '" data-post_type="' . $post->type . '" data-anchor="' . base64_encode($link->anchor) . '" data-url="' . base64_encode($link->url) . '" data-nonce="' . wp_create_nonce('wpil_report_edit_' . $link->post->id . '_nonce_' . $link->post->id) . '"></td>
+ <td class="'. (false !== $phrase_key ? '': 'wpil-activity-panel-limited-text-cell') .'">';
+ if(false !== $phrase_key && isset($phrases[$phrase_key])){
+ $phrase = $phrases[$phrase_key];
+ unset($phrases[$phrase_key]);
+ $phr = self::assemble_suggestion_item($phrase);
+ $rep .= '
+ <div style="display:none">'.$edit_link.'</div>
+ <div class="sentence top-level-sentence" data-id="'.esc_attr($post->id).'" data-type="'.esc_attr($post->type).'">
+ <div class="wpil_edit_sentence_form">
+ <textarea class="wpil_content">'.$phr->suggestions[0]->sentence_src_with_anchor.'</textarea>
+ <span class="button-primary">Save</span>
+ <span class="button-secondary">Cancel</span>
+ <span> <input type="checkbox" class="wpil-sentence-allow-multiple-links" data-nonce="'.wp_create_nonce(get_current_user_id() . 'allow_multiple_links_editor').'" '. (($allow_multiple_links) ? 'checked': '') .'>Allow multiple links in sentence</span>
+ </div>
+ <span class="wpil_sentence_with_anchor" data-li-id="0"><span class="wpil_sentence" title="'. esc_attr__('Double clicking a word will select it.', 'wpil') .'">' . $phr->suggestions[0]->sentence_with_anchor . '</span><span class="dashicons dashicons-image-rotate wpil-reload-sentence-with-anchor" title="'. esc_attr__('Click to undo changes', 'wpil') . '"></span></span>
+ <span class="wpil_edit_sentence link-form-button">| <a href="javascript:void(0)">Edit Sentence</a></span>
+ <input type="hidden" name="sentence" value="'.base64_encode($phr->sentence_src).'">
+ <input type="hidden" name="custom_sentence" value="">
+ <input type="hidden" name="original_sentence_with_anchor" value="'.base64_encode($phr->suggestions[0]->original_sentence_with_anchor).'">
+ <input type="hidden" class="wpil-activity-panel-url-edit wpil-report-edit-input" value="' . esc_attr($link->url) . '">
+ </div>';
+ }else{
+ $rep .= '<div style="margin: 3px 0; display:flex">
'.$edit_link.'
- <div href="' . esc_url($link->url) . '" target="_blank" class="wpil-report-edit-display wpil-activity-panel-url-display" style="text-decoration: underline">
- <div class="wpil-url-display-text">' . esc_html($link->url) . '</div>
- </div>';
- if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_context)){
- $rep .= '<input class="wpil-activity-panel-url-edit wpil-report-edit-input" type="text" value="' . esc_attr($link->url) . '">';
- }
+ <div class="wpil-report-edit-display wpil-activity-panel-anchor-display"><div class="wpil-anchor-display-text">' . esc_html($link->anchor) . '</div> <a href="' . esc_url(add_query_arg(['wpil_admin_frontend' => '1', 'wpil_admin_frontend_data' => $link->create_scroll_link_data()], $post->getLinks()->view)) . '" target="_blank"><span class="dashicons dashicons-external" title="'.esc_attr__('View On Page','wpil').'" style="position: relative;top: 3px;"></span></a></div>';
+ if('related-post-link' !== Wpil_Toolbox::get_link_context($link->link_cont