Plugin Directory

Changeset 3442562


Ignore:
Timestamp:
01/19/2026 01:13:12 PM (2 months ago)
Author:
3task
Message:

Screenshots added and some fixes

Location:
linktrade-monitor
Files:
30 added
9 edited

Legend:

Unmodified
Added
Removed
  • linktrade-monitor/trunk/assets/css/admin.css

    r3441905 r3442562  
    11/**
    2  * Linktrade Monitor - Admin Styles v1.3
     2 * Linktrade Monitor - Admin Styles v1.4
    33 * Design: Clean Minimal + Modal
    44 */
     
    722722}
    723723
     724/* DR Comparison */
     725.dr-comparison {
     726    white-space: nowrap;
     727}
     728
     729.dr-vs {
     730    font-size: 0.65rem;
     731    color: #9ca3af;
     732    margin: 0 3px;
     733}
     734
     735.dr-badge.dr-mine {
     736    background: #fef3c7;
     737    color: #d97706;
     738}
     739
     740.dr-diff {
     741    font-size: 0.65rem;
     742    font-weight: 600;
     743    padding: 2px 5px;
     744    border-radius: 3px;
     745    margin-left: 6px;
     746}
     747
     748.dr-diff.dr-positive {
     749    background: #d1fae5;
     750    color: #047857;
     751}
     752
     753.dr-diff.dr-negative {
     754    background: #fee2e2;
     755    color: #dc2626;
     756}
     757
     758.dr-diff.dr-neutral {
     759    background: #f3f4f6;
     760    color: #6b7280;
     761}
     762
     763/* Form Grid (side by side fields) */
     764.form-row-grid {
     765    display: grid;
     766    grid-template-columns: 1fr 1fr;
     767    gap: 20px;
     768    margin-bottom: 12px;
     769}
     770
     771.form-row-grid .form-row {
     772    margin-bottom: 0;
     773}
     774
     775.form-row-grid .form-row label {
     776    display: block;
     777    font-weight: 500;
     778    margin-bottom: 6px;
     779    color: #374151;
     780    font-size: 0.9rem;
     781}
     782
     783.form-row-grid .form-row input {
     784    width: 100%;
     785    padding: 10px 14px;
     786    border: 1px solid #d1d5db;
     787    border-radius: 8px;
     788    font-size: 0.95rem;
     789}
     790
     791.form-row-grid + .description {
     792    margin-top: 4px;
     793    margin-bottom: 16px;
     794    font-size: 0.85rem;
     795    color: #6b7280;
     796}
     797
     798.linktrade-form .form-row .description {
     799    margin-top: 6px;
     800    font-size: 0.85rem;
     801    color: #6b7280;
     802}
     803
    724804/* Quality Badge */
    725805.quality-badge {
     
    14481528}
    14491529
     1530/* Expiration Badges */
     1531.date-start {
     1532    color: #6b7280;
     1533    font-size: 0.85rem;
     1534}
     1535
     1536.expiry-badge {
     1537    display: inline-block;
     1538    padding: 2px 8px;
     1539    border-radius: 4px;
     1540    font-size: 0.75rem;
     1541    font-weight: 600;
     1542}
     1543
     1544.expiry-badge.expired {
     1545    background: #fee2e2;
     1546    color: #dc2626;
     1547}
     1548
     1549.expiry-badge.expiring {
     1550    background: #fef3c7;
     1551    color: #d97706;
     1552}
     1553
    14501554/* Notice */
    14511555.linktrade-notice {
  • linktrade-monitor/trunk/assets/js/admin.js

    r3441905 r3442562  
    33 *
    44 * @package Linktrade_Monitor
    5  * @version 1.1.0
     5 * @version 1.1.2
    66 */
    77
     
    214214                        <input type="url" id="edit_backlink_target" name="backlink_target" value="${this.escapeHtml(link.backlink_target || '')}">
    215215                    </div>
     216                    <div class="form-row">
     217                        <label for="edit_backlink_anchor">Anchor Text</label>
     218                        <input type="text" id="edit_backlink_anchor" name="backlink_anchor" value="${this.escapeHtml(link.backlink_anchor || '')}">
     219                    </div>
    216220                </div>
    217221
     
    219223                    <h4>Additional Info</h4>
    220224                    <div class="form-row">
    221                         <label for="edit_domain_rating">Domain Rating (DR)</label>
    222                         <input type="number" id="edit_domain_rating" name="domain_rating" value="${link.domain_rating || ''}" min="0" max="100">
     225                        <label for="edit_start_date">Start Date</label>
     226                        <input type="date" id="edit_start_date" name="start_date" value="${link.start_date || ''}">
     227                    </div>
     228                    <div class="form-row">
     229                        <label for="edit_end_date">Expiration Date</label>
     230                        <input type="date" id="edit_end_date" name="end_date" value="${link.end_date || ''}">
     231                    </div>
     232                    <div class="form-row-grid">
     233                        <div class="form-row">
     234                            <label for="edit_domain_rating">Partner DR</label>
     235                            <input type="number" id="edit_domain_rating" name="domain_rating" value="${link.domain_rating || ''}" min="0" max="100">
     236                        </div>
     237                        <div class="form-row">
     238                            <label for="edit_my_domain_rating">My DR</label>
     239                            <input type="number" id="edit_my_domain_rating" name="my_domain_rating" value="${link.my_domain_rating || ''}" min="0" max="100">
     240                        </div>
    223241                    </div>
    224242                    <div class="form-row">
  • linktrade-monitor/trunk/includes/admin/class-admin.php

    r3441905 r3442562  
    195195            ),
    196196            'add'       => array(
    197                 'label' => __( '+ New', 'linktrade-monitor' ),
     197                'label' => __( 'New', 'linktrade-monitor' ),
    198198                'icon'  => 'dashicons-plus',
    199199            ),
     
    398398                    <th><?php esc_html_e( 'Category', 'linktrade-monitor' ); ?></th>
    399399                    <th><?php esc_html_e( 'Status', 'linktrade-monitor' ); ?></th>
     400                    <th><?php esc_html_e( 'Start / Expiration', 'linktrade-monitor' ); ?></th>
    400401                    <th><?php esc_html_e( 'DR', 'linktrade-monitor' ); ?></th>
    401402                    <th><?php esc_html_e( 'Last Check', 'linktrade-monitor' ); ?></th>
     
    406407                <?php if ( empty( $links ) ) : ?>
    407408                    <tr>
    408                         <td colspan="6" class="linktrade-empty">
     409                        <td colspan="7" class="linktrade-empty">
    409410                            <?php esc_html_e( 'No links found. Add your first link!', 'linktrade-monitor' ); ?>
    410411                        </td>
     
    424425                            <td>
    425426                                <?php echo wp_kses_post( $this->render_status_badge( $link ) ); ?>
     427                            </td>
     428                            <td>
     429                                <?php echo wp_kses_post( $this->render_date_info( $link ) ); ?>
    426430                            </td>
    427431                            <td>
     
    488492                        <th><?php esc_html_e( 'Their Link to You', 'linktrade-monitor' ); ?></th>
    489493                        <th><?php esc_html_e( 'Your Link to Them', 'linktrade-monitor' ); ?></th>
     494                        <th><?php esc_html_e( 'DR', 'linktrade-monitor' ); ?></th>
    490495                        <th><?php esc_html_e( 'Fairness', 'linktrade-monitor' ); ?></th>
    491496                    </tr>
     
    494499                    <?php if ( empty( $links ) ) : ?>
    495500                        <tr>
    496                             <td colspan="4" class="linktrade-empty"><?php esc_html_e( 'No link exchange partners found.', 'linktrade-monitor' ); ?></td>
     501                            <td colspan="5" class="linktrade-empty"><?php esc_html_e( 'No link exchange partners found.', 'linktrade-monitor' ); ?></td>
    497502                        </tr>
    498503                    <?php else : ?>
     
    505510                                $fairness_class = 'warning';
    506511                            }
     512                            // DR comparison (per link).
     513                            $partner_dr = (int) $link->domain_rating;
     514                            $my_dr = isset( $link->my_domain_rating ) ? (int) $link->my_domain_rating : 0;
     515                            $dr_diff = $partner_dr - $my_dr;
    507516                            ?>
    508517                            <tr data-id="<?php echo esc_attr( $link->id ); ?>" class="fairness-row fairness-<?php echo esc_attr( $fairness_class ); ?>">
    509518                                <td>
    510519                                    <strong><?php echo esc_html( $link->partner_name ); ?></strong>
    511                                     <?php if ( $link->domain_rating ) : ?>
    512                                         <span class="dr-badge">DR <?php echo esc_html( $link->domain_rating ); ?></span>
    513                                     <?php endif; ?>
    514520                                </td>
    515521                                <td>
     
    523529                                    <?php else : ?>
    524530                                        <span class="status unchecked"><?php esc_html_e( 'Not set', 'linktrade-monitor' ); ?></span>
     531                                    <?php endif; ?>
     532                                </td>
     533                                <td class="dr-comparison">
     534                                    <?php if ( $partner_dr > 0 && $my_dr > 0 ) : ?>
     535                                        <span class="dr-badge"><?php echo esc_html( $partner_dr ); ?></span>
     536                                        <span class="dr-vs">vs</span>
     537                                        <span class="dr-badge dr-mine"><?php echo esc_html( $my_dr ); ?></span>
     538                                        <?php if ( $dr_diff > 0 ) : ?>
     539                                            <span class="dr-diff dr-positive">+<?php echo esc_html( $dr_diff ); ?></span>
     540                                        <?php elseif ( $dr_diff < 0 ) : ?>
     541                                            <span class="dr-diff dr-negative"><?php echo esc_html( $dr_diff ); ?></span>
     542                                        <?php else : ?>
     543                                            <span class="dr-diff dr-neutral">=</span>
     544                                        <?php endif; ?>
     545                                    <?php elseif ( $partner_dr > 0 ) : ?>
     546                                        <span class="dr-badge"><?php echo esc_html( $partner_dr ); ?></span>
     547                                        <span class="dr-vs">vs</span>
     548                                        <span class="dr-badge dr-mine">?</span>
     549                                    <?php elseif ( $my_dr > 0 ) : ?>
     550                                        <span class="dr-badge">?</span>
     551                                        <span class="dr-vs">vs</span>
     552                                        <span class="dr-badge dr-mine"><?php echo esc_html( $my_dr ); ?></span>
     553                                    <?php else : ?>
     554                                        -
    525555                                    <?php endif; ?>
    526556                                </td>
     
    552582            <form id="linktrade-add-form" class="linktrade-form">
    553583                <div class="form-section">
     584                    <h4><?php esc_html_e( 'Start Date', 'linktrade-monitor' ); ?></h4>
     585                    <div class="form-row">
     586                        <label for="start_date"><?php esc_html_e( 'When was the link placed?', 'linktrade-monitor' ); ?></label>
     587                        <input type="date" id="start_date" name="start_date" value="<?php echo esc_attr( gmdate( 'Y-m-d' ) ); ?>">
     588                    </div>
     589                </div>
     590
     591                <div class="form-section">
    554592                    <h4><?php esc_html_e( 'Partner Information', 'linktrade-monitor' ); ?></h4>
    555593
     
    605643                        <input type="url" id="backlink_target" name="backlink_target" placeholder="https://partner-site.com/their-page">
    606644                    </div>
     645
     646                    <div class="form-row">
     647                        <label for="backlink_anchor"><?php esc_html_e( 'Anchor Text (your link)', 'linktrade-monitor' ); ?></label>
     648                        <input type="text" id="backlink_anchor" name="backlink_anchor" placeholder="<?php esc_attr_e( 'e.g. Partner Name', 'linktrade-monitor' ); ?>">
     649                    </div>
    607650                </div>
    608651
     
    611654
    612655                    <div class="form-row">
    613                         <label for="domain_rating"><?php esc_html_e( 'Domain Rating (DR)', 'linktrade-monitor' ); ?></label>
    614                         <input type="number" id="domain_rating" name="domain_rating" min="0" max="100">
    615                     </div>
     656                        <label for="end_date"><?php esc_html_e( 'Expiration Date', 'linktrade-monitor' ); ?></label>
     657                        <input type="date" id="end_date" name="end_date">
     658                        <p class="description"><?php esc_html_e( 'Only for time-limited agreements. Leave empty for permanent links.', 'linktrade-monitor' ); ?></p>
     659                    </div>
     660
     661                    <div class="form-row-grid">
     662                        <div class="form-row">
     663                            <label for="domain_rating"><?php esc_html_e( 'Partner DR', 'linktrade-monitor' ); ?></label>
     664                            <input type="number" id="domain_rating" name="domain_rating" min="0" max="100" placeholder="0-100">
     665                        </div>
     666                        <div class="form-row">
     667                            <label for="my_domain_rating"><?php esc_html_e( 'My DR', 'linktrade-monitor' ); ?></label>
     668                            <input type="number" id="my_domain_rating" name="my_domain_rating" min="0" max="100" placeholder="0-100">
     669                        </div>
     670                    </div>
     671                    <p class="description"><?php esc_html_e( 'Domain Rating for fairness comparison. Get DR from Ahrefs, Moz, or similar tools.', 'linktrade-monitor' ); ?></p>
    616672
    617673                    <div class="form-row">
     
    646702            $reminder_days = isset( $_POST['reminder_days'] ) ? absint( $_POST['reminder_days'] ) : 14;
    647703            $plugin_language = isset( $_POST['plugin_language'] ) ? sanitize_key( wp_unslash( $_POST['plugin_language'] ) ) : 'en';
    648             $credit_link_type = isset( $_POST['credit_link_type'] ) ? sanitize_key( wp_unslash( $_POST['credit_link_type'] ) ) : 'none';
    649704
    650705            update_option( 'linktrade_notification_email', $notification_email );
     
    809864
    810865    /**
     866     * Helper: Render date info (start date + expiration)
     867     *
     868     * @param object $link Link object.
     869     * @return string HTML date info.
     870     */
     871    private function render_date_info( $link ) {
     872        $output = '';
     873
     874        // Show start date.
     875        if ( ! empty( $link->start_date ) && '0000-00-00' !== $link->start_date ) {
     876            $start_formatted = wp_date( get_option( 'date_format' ), strtotime( $link->start_date ) );
     877            $output         .= '<span class="date-start">' . esc_html( $start_formatted ) . '</span>';
     878        } else {
     879            $output .= '<span class="date-start">-</span>';
     880        }
     881
     882        // Show expiration status if end_date is set.
     883        if ( ! empty( $link->end_date ) && '0000-00-00' !== $link->end_date ) {
     884            $end_timestamp     = strtotime( $link->end_date );
     885            $now               = current_time( 'timestamp' );
     886            $days_until_expiry = (int) ceil( ( $end_timestamp - $now ) / DAY_IN_SECONDS );
     887
     888            if ( $days_until_expiry < 0 ) {
     889                // Already expired.
     890                $output .= '<br><span class="expiry-badge expired">' . esc_html__( 'Expired', 'linktrade-monitor' ) . '</span>';
     891            } elseif ( $days_until_expiry <= 30 ) {
     892                // Expiring soon (within 30 days).
     893                $output .= '<br><span class="expiry-badge expiring">';
     894                /* translators: %d: number of days until expiration */
     895                $output .= sprintf( esc_html__( '%d days left', 'linktrade-monitor' ), $days_until_expiry );
     896                $output .= '</span>';
     897            } else {
     898                // Not expiring soon - show end date.
     899                $end_formatted = wp_date( get_option( 'date_format' ), $end_timestamp );
     900                $output       .= '<br><small>' . esc_html__( 'until', 'linktrade-monitor' ) . ' ' . esc_html( $end_formatted ) . '</small>';
     901            }
     902        }
     903
     904        return $output;
     905    }
     906
     907    /**
    811908     * Helper: Render backlink status badge
    812909     *
     
    863960            'backlink_target' => isset( $_POST['backlink_target'] ) ? esc_url_raw( wp_unslash( $_POST['backlink_target'] ) ) : '',
    864961            'backlink_anchor' => isset( $_POST['backlink_anchor'] ) ? sanitize_text_field( wp_unslash( $_POST['backlink_anchor'] ) ) : '',
    865             'domain_rating'   => isset( $_POST['domain_rating'] ) ? absint( $_POST['domain_rating'] ) : 0,
    866             'notes'           => isset( $_POST['notes'] ) ? sanitize_textarea_field( wp_unslash( $_POST['notes'] ) ) : '',
     962            'domain_rating'    => isset( $_POST['domain_rating'] ) ? absint( $_POST['domain_rating'] ) : 0,
     963            'my_domain_rating' => isset( $_POST['my_domain_rating'] ) ? absint( $_POST['my_domain_rating'] ) : 0,
     964            'notes'            => isset( $_POST['notes'] ) ? sanitize_textarea_field( wp_unslash( $_POST['notes'] ) ) : '',
     965            'start_date'      => isset( $_POST['start_date'] ) && ! empty( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : null,
     966            'end_date'        => isset( $_POST['end_date'] ) && ! empty( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : null,
    867967        );
    868968
     
    892992                $message .= ' ' . __( 'Link checked.', 'linktrade-monitor' );
    893993            }
     994
     995            // For exchanges, also check the backlink (your link to partner).
     996            if ( 'exchange' === $data['category'] && ! empty( $data['backlink_url'] ) && ! empty( $data['backlink_target'] ) ) {
     997                $backlink_result = $this->check_backlink( $id, $data['backlink_url'], $data['backlink_target'] );
     998                if ( $backlink_result ) {
     999                    $message .= ' ' . __( 'Backlink checked.', 'linktrade-monitor' );
     1000                }
     1001            }
     1002        }
     1003
     1004        // Recalculate fairness for exchange links when DR values change.
     1005        if ( 'exchange' === $data['category'] ) {
     1006            $this->recalculate_fairness( $id, $data['domain_rating'], $data['my_domain_rating'] );
    8941007        }
    8951008
     
    9461059
    9471060    /**
     1061     * Check the backlink (your link to partner) immediately.
     1062     *
     1063     * @param int    $link_id     The link ID.
     1064     * @param string $page_url    Your page URL where you placed the link.
     1065     * @param string $target_url  Partner's URL you link to.
     1066     * @return array|null Check result or null on failure.
     1067     */
     1068    private function check_backlink( $link_id, $page_url, $target_url ) {
     1069        require_once LINKTRADE_PLUGIN_DIR . 'includes/checker/class-link-checker.php';
     1070
     1071        $checker = new Linktrade_Link_Checker();
     1072        $result  = $checker->check( $page_url, $target_url );
     1073
     1074        if ( ! $result ) {
     1075            return null;
     1076        }
     1077
     1078        // Update backlink fields in database.
     1079        global $wpdb;
     1080        $table_name = $wpdb->prefix . 'linktrade_links';
     1081
     1082        $update_data = array(
     1083            'backlink_status'      => $result['status'],
     1084            'backlink_last_check'  => current_time( 'mysql' ),
     1085            'backlink_http_code'   => $result['http_code'],
     1086            'backlink_is_nofollow' => $result['is_nofollow'] ? 1 : 0,
     1087        );
     1088
     1089        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Update operation on custom table.
     1090        $wpdb->update( $table_name, $update_data, array( 'id' => $link_id ) );
     1091
     1092        return $result;
     1093    }
     1094
     1095    /**
     1096     * Recalculate fairness score for a link based on current status and DR values.
     1097     *
     1098     * @param int $link_id    The link ID.
     1099     * @param int $partner_dr Partner's Domain Rating.
     1100     * @param int $my_dr      My Domain Rating.
     1101     */
     1102    private function recalculate_fairness( $link_id, $partner_dr, $my_dr ) {
     1103        global $wpdb;
     1104        $table_name = $wpdb->prefix . 'linktrade_links';
     1105
     1106        // Get current link status.
     1107        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Query on custom table.
     1108        $link = $wpdb->get_row(
     1109            $wpdb->prepare(
     1110                'SELECT status, is_nofollow, backlink_status, backlink_is_nofollow FROM `' . esc_sql( $table_name ) . '` WHERE id = %d',
     1111                $link_id
     1112            )
     1113        );
     1114
     1115        if ( ! $link ) {
     1116            return;
     1117        }
     1118
     1119        // Calculate fairness with status and DR values.
     1120        $fairness = $this->calculate_fairness_score(
     1121            $link->status,
     1122            $link->backlink_status,
     1123            (bool) $link->is_nofollow,
     1124            (bool) $link->backlink_is_nofollow,
     1125            (int) $partner_dr,
     1126            (int) $my_dr
     1127        );
     1128
     1129        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Update operation on custom table.
     1130        $wpdb->update(
     1131            $table_name,
     1132            array( 'fairness_score' => $fairness ),
     1133            array( 'id' => $link_id ),
     1134            array( '%d' ),
     1135            array( '%d' )
     1136        );
     1137    }
     1138
     1139    /**
     1140     * Calculate fairness score.
     1141     *
     1142     * @param string $my_status      My link status (their link to me).
     1143     * @param string $their_status   Their link status (my link to them).
     1144     * @param bool   $my_nofollow    My incoming link nofollow.
     1145     * @param bool   $their_nofollow My outgoing link nofollow.
     1146     * @param int    $partner_dr     Partner's Domain Rating.
     1147     * @param int    $my_dr          My Domain Rating.
     1148     * @return int Fairness score (0-100).
     1149     */
     1150    private function calculate_fairness_score( $my_status, $their_status, $my_nofollow, $their_nofollow, $partner_dr = 0, $my_dr = 0 ) {
     1151        // Base fairness from link status.
     1152        if ( 'online' === $my_status && 'offline' === $their_status ) {
     1153            return 0; // Partner removed their link but I still link to them.
     1154        }
     1155        if ( 'offline' === $my_status && 'offline' === $their_status ) {
     1156            return 50; // Both links offline.
     1157        }
     1158
     1159        $base_score = 100;
     1160
     1161        // Nofollow penalty.
     1162        if ( ! $my_nofollow && $their_nofollow ) {
     1163            $base_score = 60; // I give dofollow, partner gives nofollow.
     1164        }
     1165
     1166        // DR comparison adjustment (only if both values are set).
     1167        if ( $partner_dr > 0 && $my_dr > 0 ) {
     1168            $dr_diff = $my_dr - $partner_dr;
     1169
     1170            // If my DR is higher, I'm giving more value than I receive.
     1171            if ( $dr_diff > 0 ) {
     1172                // Reduce fairness: -2 points per DR difference, max -40.
     1173                $dr_penalty = min( 40, $dr_diff * 2 );
     1174                $base_score = max( 0, $base_score - $dr_penalty );
     1175            }
     1176        }
     1177
     1178        return $base_score;
     1179    }
     1180
     1181    /**
    9481182     * AJAX: Delete link
    9491183     */
  • linktrade-monitor/trunk/includes/class-activator.php

    r3441905 r3442562  
    2222        // Check if this is a fresh install or upgrade
    2323        $current_version = get_option( 'linktrade_version', '0.0.0' );
    24        
     24
    2525        if ( version_compare( $current_version, LINKTRADE_VERSION, '<' ) ) {
    2626            self::create_tables();
    27         }
    28        
     27            self::run_migrations( $current_version );
     28        }
     29
    2930        self::set_default_options();
    3031        self::schedule_crons();
     
    9394            /* Partner metrics */
    9495            domain_rating TINYINT UNSIGNED DEFAULT 0,
     96            my_domain_rating TINYINT UNSIGNED DEFAULT 0,
    9597            domain_authority TINYINT UNSIGNED DEFAULT 0,
    9698            monthly_traffic INT UNSIGNED DEFAULT 0,
     
    190192    private static function set_default_options() {
    191193        $defaults = array(
    192             'linktrade_check_frequency'      => 'biweekly', // every 2 weeks
     194            'linktrade_check_frequency'      => 'monthly', // once a month
    193195            'linktrade_email_notifications'  => true,
    194196            'linktrade_notification_email'   => get_option( 'admin_email' ),
     
    209211
    210212    /**
    211      * Schedule cron jobs - Biweekly check (every 2 weeks)
     213     * Schedule cron jobs - Monthly check (once a month)
    212214     */
    213215    private static function schedule_crons() {
    214         // Biweekly link check (every 2 weeks)
     216        // Monthly link check (once a month)
    215217        if ( ! wp_next_scheduled( 'linktrade_check_links' ) ) {
    216             wp_schedule_event( time(), 'biweekly', 'linktrade_check_links' );
     218            wp_schedule_event( time(), 'monthly', 'linktrade_check_links' );
    217219        }
    218220
     
    222224        }
    223225    }
     226
     227    /**
     228     * Run database migrations for upgrades
     229     *
     230     * @param string $from_version Previous version.
     231     */
     232    private static function run_migrations( $from_version ) {
     233        global $wpdb;
     234        $table_name = $wpdb->prefix . 'linktrade_links';
     235
     236        // Migration for v1.1.1: Add my_domain_rating column
     237        if ( version_compare( $from_version, '1.1.1', '<' ) ) {
     238            // Check if column exists
     239            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- One-time migration check.
     240            $column_exists = $wpdb->get_results(
     241                $wpdb->prepare(
     242                    "SHOW COLUMNS FROM `{$table_name}` LIKE %s",
     243                    'my_domain_rating'
     244                )
     245            );
     246
     247            if ( empty( $column_exists ) ) {
     248                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- One-time migration.
     249                $wpdb->query( "ALTER TABLE `{$table_name}` ADD COLUMN `my_domain_rating` TINYINT UNSIGNED DEFAULT 0 AFTER `domain_rating`" );
     250            }
     251        }
     252    }
    224253}
  • linktrade-monitor/trunk/includes/class-linktrade.php

    r3441905 r3442562  
    115115                    $backlink_result['status'],
    116116                    $result['is_nofollow'],
    117                     $backlink_result['is_nofollow']
     117                    $backlink_result['is_nofollow'],
     118                    isset( $link->domain_rating ) ? (int) $link->domain_rating : 0,
     119                    isset( $link->my_domain_rating ) ? (int) $link->my_domain_rating : 0
    118120                );
    119121            }
     
    191193     * Calculate fairness score
    192194     *
    193      * @param string $my_status     My link status.
    194      * @param string $their_status  Their link status.
    195      * @param bool   $my_nofollow   My link nofollow.
    196      * @param bool   $their_nofollow Their link nofollow.
    197      * @return int Fairness score.
    198      */
    199     private function calculate_fairness( $my_status, $their_status, $my_nofollow, $their_nofollow ) {
     195     * @param string $my_status      My link status (their link to me).
     196     * @param string $their_status   Their link status (my link to them).
     197     * @param bool   $my_nofollow    My incoming link nofollow.
     198     * @param bool   $their_nofollow My outgoing link nofollow.
     199     * @param int    $partner_dr     Partner's Domain Rating.
     200     * @param int    $my_dr          My Domain Rating.
     201     * @return int Fairness score (0-100).
     202     */
     203    private function calculate_fairness( $my_status, $their_status, $my_nofollow, $their_nofollow, $partner_dr = 0, $my_dr = 0 ) {
     204        // Base fairness from link status.
    200205        if ( 'online' === $my_status && 'offline' === $their_status ) {
    201             return 0;
     206            return 0; // Partner removed their link but I still link to them.
    202207        }
    203208        if ( 'offline' === $my_status && 'offline' === $their_status ) {
    204             return 50;
    205         }
     209            return 50; // Both links offline.
     210        }
     211
     212        $base_score = 100;
     213
     214        // Nofollow penalty.
    206215        if ( ! $my_nofollow && $their_nofollow ) {
    207             return 60;
    208         }
    209         return 100;
     216            $base_score = 60; // I give dofollow, partner gives nofollow.
     217        }
     218
     219        // DR comparison adjustment (only if both values are set).
     220        if ( $partner_dr > 0 && $my_dr > 0 ) {
     221            $dr_diff = $my_dr - $partner_dr;
     222
     223            // If my DR is higher, I'm giving more value than I receive.
     224            if ( $dr_diff > 0 ) {
     225                // Reduce fairness: -2 points per DR difference, max -40.
     226                $dr_penalty = min( 40, $dr_diff * 2 );
     227                $base_score = max( 0, $base_score - $dr_penalty );
     228            }
     229        }
     230
     231        return $base_score;
    210232    }
    211233}
  • linktrade-monitor/trunk/languages/linktrade-monitor-de_DE.po

    r3441905 r3442562  
    66msgid ""
    77msgstr ""
    8 "Project-Id-Version: Linktrade Monitor 1.0.5\n"
     8"Project-Id-Version: Linktrade Monitor 1.1.1\n"
    99"Report-Msgid-Bugs-To: https://frank-stemmler.de\n"
    1010"POT-Creation-Date: 2025-01-11 12:00+0000\n"
     
    1717"Content-Transfer-Encoding: 8bit\n"
    1818"Plural-Forms: nplurals=2; plural=(n != 1);\n"
    19 "X-Generator: Claude Code\n"
     19"X-Generator: Poedit 3.4\n"
    2020
    2121# Plugin action links
     
    5757msgstr "Link geprüft."
    5858
     59msgid "Backlink checked."
     60msgstr "Backlink geprüft."
     61
    5962# Tabs
    6063msgid "Dashboard"
     
    6770msgstr "Fairness"
    6871
    69 msgid "+ New"
    70 msgstr "+ Neu"
     72msgid "New"
     73msgstr "Neu"
    7174
    7275# Dashboard
  • linktrade-monitor/trunk/languages/translations-de.php

    r3441905 r3442562  
    3030
    3131    // Check frequency
    32     'Every 2 Weeks' => 'Alle 2 Wochen',
     32    'Once a Month' => 'Einmal monatlich',
    3333    'Link checked.' => 'Link geprüft.',
     34    'Backlink checked.' => 'Backlink geprüft.',
    3435
    3536    // Tabs
     
    3738    'All Links' => 'Alle Links',
    3839    'Fairness' => 'Fairness',
    39     '+ New' => '+ Neu',
     40    'New' => 'Neu',
    4041
    4142    // Dashboard
     
    6566    'Category' => 'Kategorie',
    6667    'Status' => 'Status',
     68    'Start / Expiration' => 'Start / Ablauf',
    6769    'DR' => 'DR',
    6870    'Last Check' => 'Letzte Prüfung',
     
    8991    'Not set' => 'Nicht eingetragen',
    9092
     93    // Timing fields
     94    'Start Date' => 'Startdatum',
     95    'When was the link placed?' => 'Wann wurde der Link gesetzt?',
     96    'Expiration Date' => 'Ablaufdatum',
     97    'Only for time-limited agreements. Leave empty for permanent links.' => 'Nur für befristete Vereinbarungen. Bei permanenten Links leer lassen.',
     98    'Expired' => 'Abgelaufen',
     99    '%d days left' => 'Noch %d Tage',
     100    'until' => 'bis',
     101
    91102    // Add form
    92103    'Add New Link' => 'Neuen Link hinzufügen',
     
    101112    'Your page with link to partner' => 'Deine Seite mit Link zum Partner',
    102113    'Partner URL you link to' => 'Partner-URL die du verlinkst',
     114    'Anchor Text (your link)' => 'Ankertext (dein Link)',
     115    'e.g. Partner Name' => 'z.B. Partner-Name',
    103116    'Additional Info (optional)' => 'Zusätzliche Infos (optional)',
    104     'Domain Rating (DR)' => 'Domain Rating (DR)',
     117    'Partner DR' => 'Partner DR',
     118    'My DR' => 'Mein DR',
     119    'Domain Rating for fairness comparison. Get DR from Ahrefs, Moz, or similar tools.' => 'Domain Rating für Fairness-Vergleich. DR von Ahrefs, Moz oder ähnlichen Tools.',
    105120    'Notes' => 'Notizen',
    106121    'Save Link' => 'Link speichern',
  • linktrade-monitor/trunk/linktrade-monitor.php

    r3441905 r3442562  
    44 * Plugin URI: https://wordpress.org/plugins/linktrade-monitor/
    55 * Description: Backlink management and monitoring for WordPress. Track link exchanges, paid links, and free backlinks.
    6  * Version: 1.0.5
     6 * Version: 1.1.2
    77 * Author: 3task
    88 * Author URI: https://www.3task.de
     
    2222
    2323// Plugin constants.
    24 define( 'LINKTRADE_VERSION', '1.0.5' );
     24define( 'LINKTRADE_VERSION', '1.1.2' );
    2525define( 'LINKTRADE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    2626define( 'LINKTRADE_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
     
    4545}
    4646register_deactivation_hook( __FILE__, 'linktrade_deactivate' );
     47
     48/**
     49 * Check for plugin updates and run migrations if needed.
     50 */
     51function linktrade_check_version() {
     52    $current_version = get_option( 'linktrade_version', '0.0.0' );
     53
     54    if ( version_compare( $current_version, LINKTRADE_VERSION, '<' ) ) {
     55        require_once LINKTRADE_PLUGIN_DIR . 'includes/class-activator.php';
     56        Linktrade_Activator::activate();
     57    }
     58}
     59add_action( 'admin_init', 'linktrade_check_version' );
    4760
    4861/**
     
    141154 */
    142155function linktrade_add_cron_interval( $schedules ) {
    143     $schedules['biweekly'] = array(
    144         'interval' => 14 * DAY_IN_SECONDS,
    145         'display'  => esc_html__( 'Every 2 Weeks', 'linktrade-monitor' ),
     156    $schedules['monthly'] = array(
     157        'interval' => 30 * DAY_IN_SECONDS,
     158        'display'  => esc_html__( 'Once a Month', 'linktrade-monitor' ),
    146159    );
    147160    return $schedules;
  • linktrade-monitor/trunk/readme.txt

    r3441910 r3442562  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 1.0.5
     7Stable tag: 1.1.2
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    3131* **Three Link Categories** - Track exchanges, paid links, and free backlinks separately
    3232* **Instant Check on Add** - Every new link is verified immediately
    33 * **Automatic Checking** - Biweekly automated link verification (every 2 weeks)
     33* **Automatic Checking** - Monthly automated link verification (once a month)
     34* **Exchange Duration Tracking** - Track start dates and expiration for time-limited exchanges
    3435* **HTTP Status Monitoring** - Track 200, 301, 404, and other status codes
    3536* **nofollow/noindex Detection** - Get warned about link attribute changes
     
    5960| Partner Categories | **Yes** | No |
    6061
    61 = Need More Power? =
    62 
    63 [LinkTrade Monitor Pro](https://www.3task.de/linktrade-monitor-pro/) offers advanced automation features:
    64 
    65 * **Daily automated checks** instead of biweekly
    66 * **Bulk import/export** for large link portfolios
    67 * **Advanced email alerts** with detailed reports
    68 * **Priority support** from the development team
    69 
    70 [Learn more about Pro](https://www.3task.de/linktrade-monitor-pro/)
    71 
    7262== Installation ==
    7363
     
    8171= How often are links checked? =
    8272
    83 Links are checked instantly when you add them, plus automatic checks every 2 weeks.
     73Links are checked instantly when you add them, plus automatic checks once a month.
    8474
    8575= What does the Fairness Score mean? =
     
    110100Yes! Linktrade Monitor works alongside Yoast SEO, Rank Math, AIOSEO, and any other SEO plugin.
    111101
    112 = Is there a Pro version? =
    113 
    114 Yes! [LinkTrade Monitor Pro](https://www.3task.de/linktrade-monitor-pro/) adds automation features like daily checks, bulk operations, and advanced alerts. The free version is fully functional for manual link management.
    115 
    116102== Screenshots ==
    117103
     
    122108
    123109== Changelog ==
     110
     111= 1.1.2 =
     112* Fixed: Fairness Score now includes DR comparison in calculation
     113* Improved: Fairness is recalculated when DR values are changed
     114* New: Fairness reflects value imbalance when your DR is higher than partner's DR
     115
     116= 1.1.1 =
     117* New: Start date field moved to top of form for better workflow
     118* New: "My DR" field per link for accurate DR comparison across multiple projects
     119* New: DR comparison column in Fairness tab shows Partner DR vs My DR with difference indicator
     120* New: Backlink anchor text field for reciprocal links
     121* Improved: Form layout with side-by-side DR fields (Partner DR | My DR)
     122* Improved: Visual DR difference indicators (+green for benefit, -red for partner benefit)
     123
     124= 1.1.0 =
     125* New: Exchange start date tracking - know when each link exchange began
     126* New: Expiration date support for time-limited exchanges (e.g. 1 year agreements)
     127* New: Visual expiration indicators in link overview (expired, expiring soon)
     128* Improved: Link overview now shows start date and expiration status
    124129
    125130= 1.0.0 =
     
    136141== Upgrade Notice ==
    137142
     143= 1.1.2 =
     144Fairness Score now properly reflects DR imbalance. Update recommended for accurate fairness tracking.
     145
     146= 1.1.1 =
     147New: Track your own DR per link for accurate fairness comparison across multiple projects. Improved form workflow.
     148
     149= 1.1.0 =
     150New: Track exchange start dates and expiration for time-limited link agreements.
     151
    138152= 1.0.0 =
    139153First stable release. Start tracking your backlinks and link exchanges today!
Note: See TracChangeset for help on using the changeset viewer.