Plugin Directory

Changeset 3672480


Ignore:
Timestamp:
08/30/2026 11:51:52 AM (7 weeks ago)
Author:
sitehale
Message:

SiteHale 0.7.53

Location:
sitehale/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • sitehale/trunk/admin/class-sitehale-checkup.php

    r3655352 r3672480  
    334334                        'plain_permalinks' => ( '' === (string) get_option( 'permalink_structure' ) ),
    335335                        'seo_plugin'      => self::active_seo_plugin(),
     336                        'sitehale_seo'    => self::sitehale_renders(),
    336337                        'core_sitemaps'   => (bool) $sitemaps,
    337338                        // Block themes never declare title-tag support — core renders their
    … …  
    375376        }
    376377
     378        /**
     379         * Whether THIS plugin's SEO module is the one rendering here.
     380         *
     381         * ⚠️ Not "is SiteHale installed" — on this page it always is. The module
     382         * ships dormant, and stays dormant on a site it was never switched over
     383         * for: a wordpress.org install gets an admin-only plugin that renders
     384         * nothing on the front end. Installed and rendering are different facts
     385         * and only the second one belongs in a report about search results.
     386         *
     387         * Asking the renderer's own gate keeps one owner for that answer rather
     388         * than a second copy of it here — the gate is not a plugin census either
     389         * (it turns on the guard's "who is actually rendering" measurement), and a
     390         * reimplementation would drift from it in exactly the cases it exists for.
     391         *
     392         * The bug this fixes: the SEO card shipped in 0.6.0 knowing only the five
     393         * rivals above, so every client switched over to our own module read back
     394         * as "No SEO plugin detected" — and graded `warn` for it — while SiteHale
     395         * was writing its titles and descriptions.
     396         *
     397         * @return bool
     398         */
     399        public static function sitehale_renders() {
     400                return class_exists( 'SiteHale_SEO_Head' ) && SiteHale_SEO_Head::should_render();
     401        }
     402
    377403        public static function grade_seo( $data ) {
    378404                $status = 'ok';
    … …  
    388414                        $status = self::worst_of( $status, 'warn' );
    389415                }
    390                 if ( empty( $data['seo_plugin'] ) ) {
     416                // Who owns meta rendering, for the reader. Our own module answers this
     417                // first: when it renders, the guard is clear, so no rival is rendering
     418                // even on the clients that still carry one installed.
     419                $engine = ! empty( $data['sitehale_seo'] ) ? 'SiteHale' : (string) $data['seo_plugin'];
     420                if ( '' === $engine ) {
    391421                        $status = self::worst_of( $status, 'warn' );
    392422                }
    … …  
    396426
    397427                // Who serves the sitemap, and where. Every major SEO plugin replaces
    398                 // core's /wp-sitemap.xml with its own /sitemap.xml.
     428                // core's /wp-sitemap.xml with its own /sitemap.xml. ⚠️ Keyed on the
     429                // RIVAL, deliberately, not on $engine: our own module keeps core's
     430                // sitemap and filters it (SiteHale_SEO_Sitemap), so a switched-over
     431                // site serves /wp-sitemap.xml and reporting /sitemap.xml would send
     432                // the reader to a redirect at best.
    399433                $sitemap_url = '';
    400434                if ( ! empty( $data['seo_plugin'] ) ) {
    … …  
    411445                        'noindex'          => $noindex,
    412446                        'plain_permalinks' => ! empty( $data['plain_permalinks'] ),
    413                         'seo_plugin'       => (string) $data['seo_plugin'],
     447                        'seo_plugin'       => $engine,
    414448                        'sitemap_url'      => $sitemap_url,
    415449                        'title_tag'        => ! empty( $data['title_tag'] ),
    … …  
    745779        }
    746780
    747         protected static function card_close( $pitch ) {
    748                 if ( $pitch && ! SiteHale_Connect::is_connected() ) {
    749                         echo '<p style="margin:12px 0 0;padding-top:10px;border-top:1px solid #f0f0f1;color:#646970;font-size:12px;"><span class="dashicons dashicons-heart" style="font-size:14px;width:14px;height:14px;color:#2563EB;"></span> ' . esc_html( $pitch ) . '</p>';
     781        /**
     782         * Who ACTS on each card's findings, by plan. Not who reports them — this
     783         * page reports all of it to everyone, free included.
     784         *
     785         * 'fix'   SiteHale does the work. Nothing for the owner to do.
     786         * 'watch' SiteHale watches and alerts a human. The fix is still someone's,
     787         *         and saying otherwise on a client's own dashboard would be the
     788         *         false all-clear this plugin exists to prevent.
     789         *
     790         * `upsell` is the line a CARE client sees on a card only Managed acts on.
     791         * It is the one place a paying client is sold anything, and it is honest:
     792         * those two cards really are the Managed labor, not a feature gate.
     793         *
     794         * ⚠️ Environment EOL is deliberately absent. A PHP or database version
     795         * lives in the hosting account and no plan of ours changes it — see the
     796         * note the Updates card prints for itself.
     797         *
     798         * @return array
     799         */
     800        protected static function coverage() {
     801                return array(
     802                        'cron'    => array( 'care' => 'watch', 'managed' => 'watch' ),
     803                        'errors'  => array( 'care' => 'watch', 'managed' => 'watch' ),
     804                        'db'      => array(
     805                                'care'    => 'watch',
     806                                'managed' => 'fix',
     807                                'upsell'  => __( 'Managed adds database optimization and verified weekly backups, applied for you.', 'sitehale' ),
     808                        ),
     809                        'updates' => array(
     810                                'care'    => 'watch',
     811                                'managed' => 'fix',
     812                                'upsell'  => __( 'Managed applies these updates for you, staging-tested first when they are risky.', 'sitehale' ),
     813                        ),
     814                        'seo'     => array( 'care' => 'fix', 'managed' => 'fix' ),
     815                        'admins'  => array( 'care' => 'watch', 'managed' => 'watch' ),
     816                        'mail'    => array( 'care' => 'watch', 'managed' => 'watch' ),
     817                        'history' => array( 'care' => 'watch', 'managed' => 'watch' ),
     818                );
     819        }
     820
     821        /**
     822         * The footer line: on a free site the pitch, on a paying one the answer to
     823         * "so is somebody dealing with this?".
     824         *
     825         * ⚠️ Gated on the PLAN, never on the connection. Connecting is free and
     826         * provisions nothing, so a connected-but-unactivated site is not being
     827         * watched by anyone — it needs the pitch like any other free site. This
     828         * line used to check `SiteHale_Connect::is_connected()` and those sites
     829         * silently got no footer at all, which is the mistake
     830         * `SiteHale_Reports::active_plan()` documents in its own docblock.
     831         *
     832         * @param string $pitch Free-tier line for this card.
     833         * @param string $key   Coverage key, '' for a card nobody acts on.
     834         * @return string
     835         */
     836        protected static function coverage_line( $pitch, $key ) {
     837                $plan = class_exists( 'SiteHale_Reports' ) ? SiteHale_Reports::active_plan() : '';
     838                if ( '' === $plan ) {
     839                        return (string) $pitch;
     840                }
     841                $cov = self::coverage();
     842                if ( '' === $key || ! isset( $cov[ $key ][ $plan ] ) ) {
     843                        return '';
     844                }
     845                $label = class_exists( 'SiteHale_Health' ) ? SiteHale_Health::plan_label() : $plan;
     846
     847                // A Care client on a Managed-only card: tell them who acts, which is
     848                // nobody yet, rather than implying we already do.
     849                if ( 'care' === $plan && ! empty( $cov[ $key ]['upsell'] ) && 'fix' === $cov[ $key ]['managed'] ) {
     850                        /* translators: 1: what Managed adds, 2: the site's current plan */
     851                        return sprintf( __( '%1$s Your plan: %2$s.', 'sitehale' ), $cov[ $key ]['upsell'], $label );
     852                }
     853
     854                if ( 'fix' === $cov[ $key ][ $plan ] ) {
     855                        /* translators: %s: the site's plan */
     856                        return sprintf( __( 'SiteHale is handling this for you — nothing to do here. Your plan: %s.', 'sitehale' ), $label );
     857                }
     858                /* translators: %s: the site's plan */
     859                return sprintf( __( 'SiteHale is watching this and alerts a human if it changes. Your plan: %s.', 'sitehale' ), $label );
     860        }
     861
     862        protected static function card_close( $pitch, $key = '' ) {
     863                $line = self::coverage_line( $pitch, $key );
     864                if ( '' !== $line ) {
     865                        echo '<p style="margin:12px 0 0;padding-top:10px;border-top:1px solid #f0f0f1;color:#646970;font-size:12px;"><span class="dashicons dashicons-heart" style="font-size:14px;width:14px;height:14px;color:#2563EB;"></span> ' . esc_html( $line ) . '</p>';
    750866                }
    751867                echo '</div>';
    … …  
    877993                                );
    878994                        }
    879                         self::card_close( __( 'SiteHale watches cron health on your site every day, automatically — and alerts a human when it dies.', 'sitehale' ) );
     995                        self::card_close( __( 'SiteHale watches cron health on your site every day, automatically — and alerts a human when it dies.', 'sitehale' ), 'cron' );
    880996
    881997                        /* ---- PHP errors ---- */
    … …  
    9711087                                }
    9721088                        }
    973                         self::card_close( __( 'Fatal errors often never email anyone. SiteHale reads these logs weekly and reports the signatures that repeat.', 'sitehale' ) );
     1089                        self::card_close( __( 'Fatal errors often never email anyone. SiteHale reads these logs weekly and reports the signatures that repeat.', 'sitehale' ), 'errors' );
    9741090
    9751091                        /* ---- Database health ---- */
    … …  
    10061122                                )
    10071123                        );
    1008                         self::card_close( __( 'SiteHale runs this exact report monthly on every client site, plus weekly verified database backups.', 'sitehale' ) );
     1124                        self::card_close( __( 'SiteHale runs this exact report monthly on every client site, plus weekly verified database backups.', 'sitehale' ), 'db' );
    10091125
    10101126                        /* ---- Updates + environment EOL ---- */
    … …  
    10371153                                echo '<p style="font-weight:600;">' . esc_html( $row['label'] ) . '</p>';
    10381154                        }
     1155                        if ( $updates['eol'] && class_exists( 'SiteHale_Reports' ) && SiteHale_Reports::is_watched() ) {
     1156                                // ⚠️ Said out loud on purpose. Everything else on this card is
     1157                                // something a plan acts on, so silence here reads as "they have
     1158                                // it" — and a PHP or database version lives in the hosting
     1159                                // account, where no automation of ours reaches. g2computers has
     1160                                // sat on an EOL database for exactly this reason: it needs the
     1161                                // client and their host, not us.
     1162                                echo '<p style="color:#646970;font-size:13px;">' . esc_html__( 'PHP and database versions are set in your hosting account. SiteHale reports them, but changing one is a job for your host — ask them to move you to a supported version.', 'sitehale' ) . '</p>';
     1163                        }
    10391164                        if ( ! $updates['eol'] ) {
    10401165                                printf(
    … …  
    10501175                                );
    10511176                        }
    1052                         self::card_close( __( 'SiteHale tracks updates weekly and stages risky plugin updates on a copy of the site before they ever touch production.', 'sitehale' ) );
     1177                        self::card_close( __( 'SiteHale tracks updates weekly and stages risky plugin updates on a copy of the site before they ever touch production.', 'sitehale' ), 'updates' );
    10531178
    10541179                        /* ---- SEO basics (v0.6) ---- */
    … …  
    10921217                                echo '<p style="color:#646970;font-size:13px;">' . esc_html__( 'The site tagline is empty or still the WordPress default — on many themes it shows in the browser title and in search results.', 'sitehale' ) . '</p>';
    10931218                        }
    1094                         self::card_close( __( 'SiteHale runs full SEO audits monthly — titles, descriptions, keywords, broken links, and rankings from Google Search Console — and fixes what it finds.', 'sitehale' ) );
     1219                        self::card_close( __( 'SiteHale runs full SEO audits monthly — titles, descriptions, keywords, broken links, and rankings from Google Search Console — and fixes what it finds.', 'sitehale' ), 'seo' );
    10951220
    10961221                        /* ---- Administrators ---- */
    … …  
    11101235                        echo '</p>';
    11111236                        echo '<p>' . esc_html__( 'If any of these names surprises you, investigate now — a new administrator you did not create is the classic sign of a compromise.', 'sitehale' ) . '</p>';
    1112                         self::card_close( __( 'SiteHale keeps a baseline of this list and alerts the moment a new administrator appears.', 'sitehale' ) );
     1237                        self::card_close( __( 'SiteHale keeps a baseline of this list and alerts the moment a new administrator appears.', 'sitehale' ), 'admins' );
    11131238
    11141239                        /* ---- Mail test ---- */
    … …  
    11221247                        </form>
    11231248                        <?php
    1124                         self::card_close( __( 'SiteHale probes deliverability weekly and confirms actual arrival in a real inbox — not just that WordPress accepted the message.', 'sitehale' ) );
     1249                        self::card_close( __( 'SiteHale probes deliverability weekly and confirms actual arrival in a real inbox — not just that WordPress accepted the message.', 'sitehale' ), 'mail' );
    11251250
    11261251                        /* ---- Email this checkup (v0.4) ---- */
    … …  
    11781303                                </table>
    11791304                                <?php
    1180                                 self::card_close( __( 'SiteHale clients get this watching continuously — with a human on the alerts, not a table you have to remember to read.', 'sitehale' ) );
     1305                                self::card_close( __( 'SiteHale clients get this watching continuously — with a human on the alerts, not a table you have to remember to read.', 'sitehale' ), 'history' );
    11811306                        endif;
    11821307
  • sitehale/trunk/includes/class-sitehale-health.php

    r3655308 r3672480  
    280280        }
    281281
    282         protected static function plan_label() {
    283                 $plan = get_option( 'sitehale_plan', '' );
     282        /**
     283         * The site's plan, for a human.
     284         *
     285         * ⚠️ Derives from `SiteHale_Reports::active_plan()` rather than reading
     286         * the option itself. It used to carry its own copy of the two-signal rule
     287         * (option, else "a stored report proves Care"), which is the same
     288         * procedure written twice — and the Site Checkup footer now names this
     289         * plan to a client, so a label that drifted from the plan the rest of the
     290         * plugin acts on would be worse than a wrong word.
     291         *
     292         * Public because the Checkup prints it; behaviour is unchanged.
     293         *
     294         * @return string
     295         */
     296        public static function plan_label() {
     297                $plan = class_exists( 'SiteHale_Reports' ) ? SiteHale_Reports::active_plan() : '';
    284298                if ( 'managed' === $plan ) {
    285299                        return __( 'Managed', 'sitehale' );
    286300                }
    287                 if ( 'care' === $plan || ( class_exists( 'SiteHale_Reports' ) && SiteHale_Reports::index() ) ) {
     301                if ( 'care' === $plan ) {
    288302                        return __( 'Care', 'sitehale' );
    289303                }
  • sitehale/trunk/readme.txt

    r3670714 r3672480  
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 0.7.52
     7Stable tag: 0.7.53
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    130130== Upgrade Notice ==
    131131
     132= 0.7.53 =
     133Fixes Site Checkup reporting "No SEO plugin detected" on sites whose SEO is managed by SiteHale itself, and each section now says who acts on what it finds. Sites using another SEO plugin, or none, read exactly as before.
     134
    132135= 0.7.51 =
    133136Housekeeping only: no change to how the plugin behaves. Shops keep their review stars in search results when SiteHale manages their SEO, and a product with no reviews publishes no rating rather than a zero-star one.
    … …  
    172175
    173176== Changelog ==
     177
     178= 0.7.53 =
     179* Site Checkup now recognises SiteHale itself as the SEO plugin on a site whose SEO it manages. Sites switched over to SiteHale were told "No SEO plugin detected" — and had the SEO section marked as needing attention for it — while SiteHale was writing their titles and descriptions. Sites using another SEO plugin, or none, are unaffected and read exactly as before.
     180* Site Checkup now tells you who acts on each finding. On a Care or Managed site each section says whether SiteHale is handling it for you or watching it and alerting a human, so a section marked "Needs attention" no longer reads as a job waiting on you when it isn't. The status itself is unchanged — it still describes your site, not your plan.
     181* An end-of-life PHP or database version now says plainly that it is set in your hosting account and your host has to change it. No plan of ours can.
     182* Fixes the free-plan footer disappearing on a site that had connected to SiteHale but was never activated. Connecting is free and provisions nothing, so those sites are on the free plan and should read like it.
    174183
    175184= 0.7.52 =
  • sitehale/trunk/sitehale.php

    r3670714 r3672480  
    44 * Plugin URI:        https://sitehale.com/how-it-works/
    55 * Description:       Free Site Checkup (cron, PHP errors, database, updates, admins, SEO basics, disk, mail) plus the companion to the SiteHale managed care service. Sends nothing anywhere until you click Connect.
    6  * Version:           0.7.52
     6 * Version:           0.7.53
    77 * Requires at least: 5.7
    88 * Requires PHP:      7.4
    … …  
    3030}
    3131
    32 define( 'SITEHALE_VERSION', '0.7.52' );
     32define( 'SITEHALE_VERSION', '0.7.53' );
    3333define( 'SITEHALE_PLUGIN_FILE', __FILE__ );
    3434define( 'SITEHALE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
Note: See TracChangeset for help on using the changeset viewer.