self::SCHEMA, 'generated_at' => time(), 'plugin' => array( 'core_version' => defined('AIEO_VERSION') ? (string) AIEO_VERSION : '', 'runtime_active' => defined('AIEO_RUNTIME_VERSION'), 'runtime_present' => class_exists('AIEO_Runtime_Presence') ? AIEO_Runtime_Presence::installed() : null, 'runtime_version' => class_exists('AIEO_Runtime_Presence') ? AIEO_Runtime_Presence::version() : '', 'runtime_state' => class_exists('AIEO_Runtime_Presence') ? AIEO_Runtime_Presence::state() : '', ), 'tier' => self::tier_block(), 'site' => array( 'is_ssl' => self::site_is_ssl(), 'wp_cron_disabled' => (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON), 'timezone' => wp_timezone_string(), ), 'features' => array( 'push' => self::push_block(), 'edge' => self::edge_block(), ), ); } public static function site_is_ssl() { return 'https' === strtolower((string) wp_parse_url(home_url('/'), PHP_URL_SCHEME)); } private static function tier_block() { $membership_pro = (get_option('aieo_user_membership') === 'Pro'); $rooster = (get_option('aieo_rooster_status') === 'connected'); return array( 'name' => ($membership_pro || $rooster) ? 'pro' : 'free', 'method' => $rooster ? 'hub' : ($membership_pro ? 'membership' : 'none'), ); } private static function push_block() { global $wpdb; $vapid = get_option('aieo_push_vapid', array()); $vpub = (is_array($vapid) && !empty($vapid['public_b64url'])) ? (string) $vapid['public_b64url'] : ''; $subs_t = $wpdb->prefix . 'aieo_push_subscriptions'; $schema = ((string) $wpdb->get_var("SHOW TABLES LIKE '{$subs_t}'") === $subs_t); $count = $schema ? (int) $wpdb->get_var("SELECT COUNT(*) FROM {$subs_t} WHERE status = 'active'") : 0; $engine = (get_option('aieo_push_engine_status', 'live') === 'paused') ? 'paused' : 'live'; $banner = get_option('aieo_push_banner_settings', array()); $banner_on = is_array($banner) && !empty($banner['banner_enabled']); $block = array( 'enabled' => (bool) $banner_on, 'ready' => (bool) (self::site_is_ssl() && $vpub !== '' && $schema && defined('AIEO_RUNTIME_VERSION')), 'tier_required' => 'pro', 'engine_status' => $engine, 'vapid_public_key' => $vpub, 'service_worker' => array('path' => '/aieo-push-sw.js', 'scope' => '/'), 'subscription_count' => $count, 'nginx_requirement' => array( 'location' => '/aieo-push-sw.js', 'block' => "location = /aieo-push-sw.js {\n try_files /nonexistent /index.php?aieo_push_sw=1;\n}", ), ); $block['hash'] = 'sha1:' . sha1(wp_json_encode($block)); return $block; } private static function edge_block() { $up_base = trailingslashit(wp_upload_dir()['basedir']); $edge_dir = $up_base . 'aieo-redirects/'; $settings = get_option('aieo_dmm_settings', array()); $seo_on = is_array($settings) && !empty($settings['seo']['enabled']); $ver_file = $edge_dir . 'version.txt'; $ver = is_readable($ver_file) ? trim((string) file_get_contents($ver_file)) : ''; if ($ver === '') { $ver = (string) get_option('aieo_seo_redirects_ver', '0'); } $counts = array(); foreach (array('301', '302', '307', '308', '410') as $code) { $counts[$code] = self::count_map_lines($edge_dir . $code . '.map'); } return array( 'enabled' => (bool) $seo_on, 'redirects_version' => $ver, 'redirect_counts' => $counts, 'sitemap_present' => is_readable($up_base . 'aieo-sitemaps/sitemap.xml'), ); } private static function count_map_lines($path) { if (!is_readable($path)) { return 0; } $fh = @fopen($path, 'r'); if (!$fh) { return 0; } $n = 0; while (($line = fgets($fh)) !== false) { $t = ltrim($line); if ($t === '' || $t[0] === '#') { continue; } $n++; } fclose($fh); return $n; } private static function write_atomic($path, $contents) { $tmp = $path . '.' . wp_generate_password(6, false, false) . '.tmp'; if (file_put_contents($tmp, $contents) === false) { return false; } if (!@rename($tmp, $path)) { @unlink($tmp); return false; } return true; } } if (!function_exists('aieo_panel_manifest_activate')) { function aieo_panel_manifest_activate() { add_option('aieo_push_engine_status', 'paused'); if (class_exists('AIEO_Panel_Manifest')) { AIEO_Panel_Manifest::write(); } } } if (defined('WP_CLI') && WP_CLI) { class AIEO_CLI_Push { public function prepare($args, $assoc_args) { $schema_php = AIEO_DIR . 'includes/dmm/sql/push-schema.php'; if (file_exists($schema_php)) { require_once $schema_php; } if (function_exists('aieo_push_install_schema')) { aieo_push_install_schema(); } $vpub = ''; if (class_exists('AIEO_Push_Sender') && method_exists('AIEO_Push_Sender', 'instance')) { $keys = AIEO_Push_Sender::instance()->get_keys(); if (is_array($keys) && !empty($keys['public_b64url'])) { $vpub = (string) $keys['public_b64url']; } } flush_rewrite_rules(false); if (class_exists('AIEO_Panel_Manifest')) { AIEO_Panel_Manifest::write(); } \WP_CLI::line(wp_json_encode(array( 'vapid_public_key' => $vpub, 'sw_path' => '/aieo-push-sw.js', 'scope' => '/', ))); } /** * @subcommand verify-readiness */ public function verify_readiness($args, $assoc_args) { global $wpdb; $subs_t = $wpdb->prefix . 'aieo_push_subscriptions'; $vapid = get_option('aieo_push_vapid', array()); \WP_CLI::line(wp_json_encode(array( 'php_openssl' => extension_loaded('openssl'), 'https' => AIEO_Panel_Manifest::site_is_ssl(), 'wp_cron' => !(defined('DISABLE_WP_CRON') && DISABLE_WP_CRON), 'schema' => ((string) $wpdb->get_var("SHOW TABLES LIKE '{$subs_t}'") === $subs_t), 'runtime' => defined('AIEO_RUNTIME_VERSION'), 'vapid' => (is_array($vapid) && !empty($vapid['public_b64url'])), ))); } public function status($args, $assoc_args) { global $wpdb; $subs_t = $wpdb->prefix . 'aieo_push_subscriptions'; $schema = ((string) $wpdb->get_var("SHOW TABLES LIKE '{$subs_t}'") === $subs_t); $count = $schema ? (int) $wpdb->get_var("SELECT COUNT(*) FROM {$subs_t} WHERE status = 'active'") : 0; $vapid = get_option('aieo_push_vapid', array()); $vpub = (is_array($vapid) && !empty($vapid['public_b64url'])) ? (string) $vapid['public_b64url'] : ''; $engine = (get_option('aieo_push_engine_status', 'live') === 'paused') ? 'paused' : 'live'; \WP_CLI::line(wp_json_encode(array( 'installed' => $schema, 'ready' => (bool) (AIEO_Panel_Manifest::site_is_ssl() && $vpub !== '' && $schema && defined('AIEO_RUNTIME_VERSION')), 'engine_status' => $engine, 'subscription_count' => $count, 'vapid_public_key' => $vpub, 'service_worker' => array('path' => '/aieo-push-sw.js', 'scope' => '/'), 'tier_required' => 'pro', ))); } /** * @subcommand set-engine */ public function set_engine($args, $assoc_args) { $state = isset($args[0]) ? strtolower((string) $args[0]) : ''; if (!in_array($state, array('live', 'paused'), true)) { \WP_CLI::line(wp_json_encode(array('ok' => false, 'error' => 'state must be "live" or "paused"'))); \WP_CLI::halt(1); } if (class_exists('AIEO_DMM_Web_Push') && method_exists('AIEO_DMM_Web_Push', 'set_engine_status')) { AIEO_DMM_Web_Push::set_engine_status($state); } else { update_option('aieo_push_engine_status', $state); } if (class_exists('AIEO_Panel_Manifest')) { AIEO_Panel_Manifest::write(); } \WP_CLI::line(wp_json_encode(array('ok' => true, 'engine_status' => $state))); } } \WP_CLI::add_command('aieo push', 'AIEO_CLI_Push'); }