PluginProbe
Code Engine – PHP Snippets, AI Functions & Automation for WordPress / 0.4.3
Code Engine – PHP Snippets, AI Functions & Automation for WordPress v0.4.3
0.5.7 0.5.6 0.5.5 0.5.4 0.5.3 0.5.2 0.5.1 0.5.0 0.4.9 0.4.8 0.4.7 0.4.6 trunk 0.0.1 0.0.2 0.2.8 0.2.9 0.3.0 0.3.1 0.3.2 0.3.3 0.3.4 0.3.5 0.3.6 0.3.7 All 33 releases
← All changes | common/admin.php +9 -275 0.5.20.4.3 View file →
@@ -3,10 +3,10 @@
3 3 if ( !class_exists( 'MeowKit_MWCODE_Admin' ) ) {
4 4
5 5 class MeowKit_MWCODE_Admin {
6 6 public static $loaded = false;
7 - public static $version = '5.0';
8 - public static $admin_version = '5.0';
7 + public static $version = '4.0';
8 + public static $admin_version = '4.0';
9 9 public static $network_license_modal_added = false;
10 10 public static $network_license_plugins = [];
11 11
12 12 /**
@@ -157,13 +157,8 @@
157 157 if ( $page === 'meowapps-main-menu' ) {
158 158 add_filter( 'admin_footer_text', [ $this, 'admin_footer_text' ], 100000, 1 );
159 159 }
160 160
161 - // Promote AI Engine on the WordPress 7 Connectors page when AI Engine
162 - // itself isn't installed. When AI Engine is active, its own banner
163 - // takes over — so this path only runs on "bare" Meow Apps installs.
164 - add_action( 'admin_footer', [ $this, 'maybe_render_wpai_promo' ] );
165 -
166 161 MeowKit_MWCODE_Admin::$loaded = true;
167 162 }
168 163
169 164 // PER-INSTANCE SETUP: Run for each plugin that uses this library
@@ -434,18 +429,14 @@
434 429 add_settings_field( 'meowapps_hide_ads', 'Meow Apps Menu', [ $this, 'meowapps_hide_dashboard_callback' ], 'general' );
435 430 return;
436 431 }
437 432
438 - // Create standard menu if it does not already exist.
439 - // The cat logo is injected as an <img> inside the menu title (rather than passed as
440 - // the $icon_url argument) so the original SVG fills are preserved — passing it via
441 - // $icon_url makes WordPress add the .svg class and the admin color scheme strips
442 - // the colors to a single fill.
433 + // Create standard menu if it does not already exist
443 434 global $submenu;
444 435 if ( !isset( $submenu[ 'meowapps-main-menu' ] ) ) {
445 436 add_menu_page(
446 437 'Meow Apps',
447 - '<img alt="Meow Apps" class="meowapps-menu-icon" src="' . MeowKit_MWCODE_Admin::$logo . '" />Meow Apps',
438 + '<img alt="Meow Apps" style="width: 21px; margin-left: -28px; position: absolute; margin-top: 2px;" src="' . MeowKit_MWCODE_Admin::$logo . '" />Meow Apps',
448 439 'manage_options',
449 440 'meowapps-main-menu',
450 441 [ $this, 'admin_meow_apps' ],
451 442 '',
@@ -460,84 +451,15 @@
460 451 [ $this, 'admin_meow_apps' ]
461 452 );
462 453 }
463 454
464 - // Position the cat icon so it sits in the standard icon column in both the
465 - // expanded and the collapsed (folded) sidebar.
466 - //
467 - // The image lives inside the .wp-menu-name title (where the original code
468 - // put it) so the <img> renders with its native SVG fills. When the sidebar
469 - // is collapsed, WP hides .wp-menu-name (and everything inside it), so a
470 - // small JS snippet below clones the same <img> into the .wp-menu-image
471 - // slot — which WP keeps visible in both states. We use a real <img>
472 - // (not a background-image) on purpose: at small sizes WP's admin renders
473 - // background-image SVGs noticeably lighter than the equivalent <img>,
474 - // and we want the colored cat in both states.
475 - //
476 - // The !important rules also override an older "display: none" style that
477 - // previous-generation Meow Apps common copies inject for .wp-menu-image;
478 - // if any of them load first, ours still wins.
455 + // Add CSS to hide the default icon
479 456 add_action( 'admin_head', function () {
480 457 echo '<style>
481 - #toplevel_page_meowapps-main-menu .meowapps-menu-icon {
482 - width: 20px;
483 - height: auto;
484 - position: absolute;
485 - margin-left: -28px;
486 - margin-top: 3px;
487 - }
488 - #toplevel_page_meowapps-main-menu .wp-menu-image {
489 - display: block !important;
490 - position: relative;
491 - }
492 - #toplevel_page_meowapps-main-menu .wp-menu-image::before {
493 - display: none !important;
494 - }
495 - #toplevel_page_meowapps-main-menu .wp-menu-image .meowapps-menu-icon-folded {
496 - display: none;
497 - position: absolute;
498 - top: 50%;
499 - left: 50%;
500 - transform: translate(-50%, calc(-50% - 3px));
501 - width: 20px;
502 - height: auto;
503 - }
504 - body.folded #toplevel_page_meowapps-main-menu .wp-menu-image .meowapps-menu-icon-folded {
505 - display: block;
506 - }
507 - body.folded #toplevel_page_meowapps-main-menu .meowapps-menu-icon {
508 - display: none;
509 - }
510 - @media only screen and (max-width: 960px) {
511 - body.auto-fold #toplevel_page_meowapps-main-menu .wp-menu-image .meowapps-menu-icon-folded {
512 - display: block;
513 - }
514 - body.auto-fold #toplevel_page_meowapps-main-menu .meowapps-menu-icon {
515 - display: none;
516 - }
517 - }
518 - </style>';
519 - }, 999 );
520 -
521 - // Inject a clone of the in-title cat icon into the .wp-menu-image slot.
522 - // CSS above shows it only when the sidebar is folded; in the normal
523 - // expanded state the .wp-menu-name <img> stays the visible icon.
524 - add_action( 'admin_footer', function () {
525 - ?>
526 - <script>
527 - ( function () {
528 - var li = document.getElementById( 'toplevel_page_meowapps-main-menu' );
529 - if ( !li ) { return; }
530 - var src = li.querySelector( '.meowapps-menu-icon' );
531 - var slot = li.querySelector( '.wp-menu-image' );
532 - if ( !src || !slot || slot.querySelector( '.meowapps-menu-icon-folded' ) ) { return; }
533 - var clone = src.cloneNode();
534 - clone.className = 'meowapps-menu-icon-folded';
535 - clone.removeAttribute( 'style' );
536 - slot.appendChild( clone );
537 - } )();
538 - </script>
539 - <?php
458 + #toplevel_page_meowapps-main-menu .wp-menu-image {
459 + display: none;
460 + }
461 + </style>';
540 462 } );
541 463 }
542 464
543 465 public function meowapps_hide_dashboard_callback() {
@@ -581,195 +503,7 @@
581 503 __( 'Thanks for using <a href="https://meowapps.com">Meow Apps</a>! This is the Meow Admin %1$s <br /><i>Loaded from %2$s </i>', $this->domain ),
582 504 MeowKit_MWCODE_Admin::$version,
583 505 __FILE__
584 506 );
585 - }
586 -
587 - /**
588 - * Renders a promo banner on WordPress 7's Connectors page when AI Engine
589 - * isn't installed. Kept self-contained so the common library stays simple:
590 - * no new file, no REST endpoint, dismissal persists in localStorage.
591 - */
592 - public function maybe_render_wpai_promo() {
593 - // WordPress 7+ only.
594 - if ( ! class_exists( 'WP_Connector_Registry' ) ) {
595 - return;
596 - }
597 - // If AI Engine is installed, its own Connectors banner takes over.
598 - if ( class_exists( 'Meow_MWAI_Core' ) ) {
599 - return;
600 - }
601 - // Another Meow Apps plugin's common copy may have rendered already.
602 - if ( defined( 'MEOWAPPS_WPAI_PROMO_RENDERED' ) ) {
603 - return;
604 - }
605 - // Gate on the Connectors screen. The hook suffix differs between the
606 - // direct file (`options-connectors.php`) and the menu-page variant.
607 - $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
608 - $id = $screen ? $screen->id : ( isset( $GLOBALS['hook_suffix'] ) ? $GLOBALS['hook_suffix'] : '' );
609 - $targets = array( 'options-connectors', 'options-connectors.php', 'settings_page_options-connectors-wp-admin' );
610 - if ( ! in_array( $id, $targets, true ) ) {
611 - return;
612 - }
613 - define( 'MEOWAPPS_WPAI_PROMO_RENDERED', true );
614 -
615 - // Install button → WordPress's own plugin-install search page, pre-
616 - // filtered for AI Engine. One click from there to install. This is the
617 - // most reliable path: no custom nonces, native progress UI, native
618 - // filesystem credential prompt if needed.
619 - $can_install = current_user_can( 'install_plugins' );
620 - $install_url = $can_install
621 - ? self_admin_url( 'plugin-install.php?tab=search&type=term&s=AI+Engine' )
622 - : 'https://wordpress.org/plugins/ai-engine/';
623 - $wporg_url = 'https://wordpress.org/plugins/ai-engine/';
624 - $learn_url = 'https://meowapps.com/wordpress-7-ai-engine-gateway/';
625 -
626 - // Title is split so "AI Engine" can carry an anchor to wp.org. Keeping
627 - // the pieces as data (not one HTML string) avoids escaping surprises and
628 - // keeps the translation unit stable.
629 - $payload = array(
630 - 'titleBefore' => __( 'Highly recommended: Let ', 'meowapps' ),
631 - 'titleLink' => __( 'AI Engine', 'meowapps' ),
632 - 'titleAfter' => __( ' handle your connections.', 'meowapps' ),
633 - 'sub' => __( 'One plugin for every provider. Keep your AI setup clean and consistent: monitor your API costs in one place, log every single request, and avoid the mess of juggling separate plugins for each AI model.', 'meowapps' ),
634 - 'install' => __( 'Install AI Engine', 'meowapps' ),
635 - 'learn' => __( 'Learn more', 'meowapps' ),
636 - 'dismiss' => __( 'Dismiss', 'meowapps' ),
637 - 'installUrl' => $install_url,
638 - 'wporgUrl' => $wporg_url,
639 - 'learnUrl' => $learn_url,
640 - );
641 - ?>
642 - <style>
643 - .meowapps-wpai-promo {
644 - margin: 0 0 16px; padding: 14px 18px;
645 - display: flex; align-items: flex-start; gap: 14px;
646 - background: #f0f4ff; border: 1px solid #d6deff; border-radius: 4px;
647 - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
648 - font-size: 13px; line-height: 1.45; color: #1e1e1e;
649 - }
650 - .meowapps-wpai-promo-icon {
651 - width: 32px; height: 32px; border-radius: 50%;
652 - background: #2f5fff; color: #fff;
653 - display: flex; align-items: center; justify-content: center;
654 - flex-shrink: 0;
655 - margin-top: 1px;
656 - }
657 - .meowapps-wpai-promo-icon svg { width: 18px; height: 18px; display: block; }
658 - .meowapps-wpai-promo-body {
659 - flex: 1; min-width: 0;
660 - display: flex; flex-direction: column; gap: 10px;
661 - }
662 - .meowapps-wpai-promo-text strong { font-weight: 700; display: block; margin-bottom: 3px; }
663 - .meowapps-wpai-promo-text span { color: #50575e; }
664 - .meowapps-wpai-promo-titlelink {
665 - color: #2f5fff; text-decoration: none; border-bottom: 1px dashed #2f5fff;
666 - }
667 - .meowapps-wpai-promo-titlelink:hover { color: #2448cc; border-bottom-color: #2448cc; }
668 - .meowapps-wpai-promo-actions {
669 - display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
670 - }
671 - .meowapps-wpai-promo-btn {
672 - appearance: none; border: 1px solid transparent; border-radius: 4px;
673 - padding: 7px 16px; font: inherit; font-size: 12.5px; font-weight: 600;
674 - cursor: pointer; text-decoration: none;
675 - transition: background 0.12s ease, border-color 0.12s ease;
676 - }
677 - .meowapps-wpai-promo-btn-primary { background: #2f5fff; color: #fff; }
678 - .meowapps-wpai-promo-btn-primary:hover { background: #2448cc; color: #fff; }
679 - .meowapps-wpai-promo-btn-secondary { background: #7c3aed; color: #fff; }
680 - .meowapps-wpai-promo-btn-secondary:hover { background: #6527c9; color: #fff; }
681 - .meowapps-wpai-promo-btn-dismiss {
682 - margin-left: auto;
683 - background: transparent; color: #6b7280;
684 - font-weight: 500; padding: 7px 10px;
685 - }
686 - .meowapps-wpai-promo-btn-dismiss:hover { color: #1e1e1e; background: rgba(0,0,0,0.04); }
687 - </style>
688 - <script>
689 - (function () {
690 - var D = <?php echo wp_json_encode( $payload ); ?>;
691 - try { if (localStorage.getItem('meowapps-wpai-promo-dismissed') === '1') return; } catch (e) {}
692 -
693 - function build() {
694 - var host = document.createElement('div');
695 - host.className = 'meowapps-wpai-promo';
696 - host.setAttribute('role', 'status');
697 - var iconSvg = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>';
698 - host.innerHTML = [
699 - '<span class="meowapps-wpai-promo-icon">', iconSvg, '</span>',
700 - '<div class="meowapps-wpai-promo-body">',
701 - '<div class="meowapps-wpai-promo-text">',
702 - '<strong></strong> <span class="meowapps-wpai-promo-sub"></span>',
703 - '</div>',
704 - '<div class="meowapps-wpai-promo-actions"></div>',
705 - '</div>'
706 - ].join('');
707 - // Title carries an anchor on "AI Engine" → wp.org plugin page.
708 - var strong = host.querySelector('strong');
709 - strong.appendChild(document.createTextNode(D.titleBefore));
710 - var tLink = document.createElement('a');
711 - tLink.href = D.wporgUrl;
712 - tLink.target = '_blank';
713 - tLink.rel = 'noopener noreferrer';
714 - tLink.className = 'meowapps-wpai-promo-titlelink';
715 - tLink.textContent = D.titleLink;
716 - strong.appendChild(tLink);
717 - strong.appendChild(document.createTextNode(D.titleAfter));
718 - host.querySelector('.meowapps-wpai-promo-sub').textContent = D.sub;
719 - var actions = host.querySelector('.meowapps-wpai-promo-actions');
720 -
721 - function link(label, cls, href, newTab) {
722 - var a = document.createElement('a');
723 - a.className = 'meowapps-wpai-promo-btn ' + cls;
724 - a.textContent = label;
725 - a.href = href;
726 - if (newTab) { a.target = '_blank'; a.rel = 'noopener noreferrer'; }
727 - actions.appendChild(a);
728 - return a;
729 - }
730 -
731 - // Install → WordPress's plugin-install search page, pre-filtered.
732 - // User lands on a familiar screen with AI Engine as the top hit and
733 - // can install with the native WordPress UX.
734 - link(D.install, 'meowapps-wpai-promo-btn-primary', D.installUrl, false);
735 - link(D.learn, 'meowapps-wpai-promo-btn-secondary', D.learnUrl, true);
736 -
737 - var d = document.createElement('button');
738 - d.type = 'button';
739 - d.className = 'meowapps-wpai-promo-btn meowapps-wpai-promo-btn-dismiss';
740 - d.textContent = D.dismiss;
741 - d.addEventListener('click', function () {
742 - try { localStorage.setItem('meowapps-wpai-promo-dismissed', '1'); } catch (e) {}
743 - if (host.parentNode) host.parentNode.removeChild(host);
744 - });
745 - actions.appendChild(d);
746 - return host;
747 - }
748 -
749 - function ensure() {
750 - if (document.querySelector('.meowapps-wpai-promo')) return;
751 - var page = document.querySelector('.connectors-page');
752 - if (page) { page.insertBefore(build(), page.firstChild); return; }
753 - var header = document.querySelector('.boot-layout__stage header');
754 - if (header && header.parentNode) {
755 - header.parentNode.insertBefore(build(), header.nextSibling);
756 - }
757 - }
758 -
759 - var tries = 0;
760 - var iv = setInterval(function () {
761 - ensure();
762 - if (document.querySelector('.meowapps-wpai-promo') || ++tries > 40) clearInterval(iv);
763 - }, 120);
764 -
765 - var app = document.getElementById('options-connectors-wp-admin-app')
766 - || document.getElementById('options-connectors-app');
767 - if (app && 'MutationObserver' in window) {
768 - new MutationObserver(ensure).observe(app, { childList: true, subtree: true });
769 - }
770 - })();
771 - </script>
772 - <?php
773 507 }
774 508 }
775 509 }