'string', 'single' => true, 'default' => 'local_only', 'show_in_rest' => true, 'auth_callback' => $auth, 'sanitize_callback' => static function ( $value ) { $allowed = array( 'local_only', 'local_and_remote', 'remote_only' ); return in_array( $value, $allowed, true ) ? $value : 'local_only'; }, ) ); register_post_meta( 'post', '_lesending_remote_site_ids', array( 'type' => 'array', 'single' => true, 'default' => array(), 'show_in_rest' => array( 'schema' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ), ), ), 'auth_callback' => $auth, 'sanitize_callback' => static function ( $value ) { if ( ! is_array( $value ) ) { return array(); } return array_values( array_filter( array_map( 'sanitize_text_field', $value ) ) ); }, ) ); } public static function activate() { $defaults = array( 'enabled' => false, 'sync_media' => true, 'sites' => array(), ); if ( false === get_option( 'lesending_options' ) ) { add_option( 'lesending_options', $defaults, '', false ); } add_option( 'lesending_db_version', LESENDING_VERSION, '', false ); } public static function deactivate() { // 不删除数据;卸载由 uninstall.php 处理。 } /** * @return array{enabled:bool,sync_media:bool,sites:array>} */ public static function get_options() { $opt = get_option( 'lesending_options', array() ); if ( ! is_array( $opt ) ) { $opt = array(); } $opt = wp_parse_args( $opt, array( 'enabled' => false, 'sync_media' => true, 'sites' => array(), ) ); if ( ! is_array( $opt['sites'] ) ) { $opt['sites'] = array(); } return $opt; } /** * @param array $options 完整选项数组。 */ public static function update_options( $options ) { update_option( 'lesending_options', $options, false ); } /** * 是否开启远程发布功能。 */ public static function is_remote_enabled() { $o = self::get_options(); return ! empty( $o['enabled'] ); } /** * 是否将正文与特色图同步到远程媒体库。 */ public static function is_media_sync_enabled() { $o = self::get_options(); return ! empty( $o['sync_media'] ); } /** * 当前用户是否允许触发远程同步(使用已存储的远程凭据)。 * * @param int $post_id 文章 ID。 * @return bool */ public static function current_user_can_sync( $post_id ) { $post_id = (int) $post_id; $allowed = $post_id > 0 && current_user_can( 'edit_post', $post_id ) && current_user_can( 'publish_posts' ); /** * 过滤是否允许某用户触发远程同步。 * * @param bool $allowed 默认需具备 edit_post + publish_posts。 * @param int $post_id 文章 ID。 */ return (bool) apply_filters( 'lesending_current_user_can_sync', $allowed, $post_id ); } /** * 规范化远程站点列表(不解密密码,供编辑器列表用)。 * * @return array */ public static function get_public_site_list() { $sites = self::get_options()['sites']; $out = array(); foreach ( $sites as $row ) { if ( empty( $row['id'] ) ) { continue; } $auth = ( isset( $row['auth_mode'] ) && 'bridge' === $row['auth_mode'] ) ? 'bridge' : 'rest'; $url = isset( $row['url'] ) ? esc_url_raw( $row['url'] ) : ''; if ( $url === '' && 'bridge' === $auth && ! empty( $row['bridge_endpoint'] ) ) { $parts = wp_parse_url( $row['bridge_endpoint'] ); if ( ! empty( $parts['scheme'] ) && ! empty( $parts['host'] ) ) { $url = $parts['scheme'] . '://' . $parts['host']; if ( ! empty( $parts['port'] ) ) { $url .= ':' . $parts['port']; } } } $out[] = array( 'id' => (string) $row['id'], 'name' => isset( $row['name'] ) ? (string) $row['name'] : '', 'url' => $url, 'enabled' => ! empty( $row['enabled'] ), 'auth_mode' => $auth, ); } return $out; } /** * 按 ID 取站点(含解密后的应用密码)。 * * @param string $id 站点 ID。 * @return array|null */ public static function get_site_by_id( $id ) { foreach ( self::get_options()['sites'] as $row ) { if ( isset( $row['id'] ) && (string) $row['id'] === (string) $id ) { $row['auth_mode'] = ( isset( $row['auth_mode'] ) && 'bridge' === $row['auth_mode'] ) ? 'bridge' : 'rest'; $row['password_plain'] = ''; $row['bridge_secret_plain'] = ''; if ( ! empty( $row['app_password_enc'] ) ) { $row['password_plain'] = Lesending_Crypto::decrypt( $row['app_password_enc'] ); } if ( ! empty( $row['bridge_secret_enc'] ) ) { $row['bridge_secret_plain'] = Lesending_Crypto::decrypt( $row['bridge_secret_enc'] ); } return $row; } } return null; } }