File "ai_blog_api.php"

Full Path: /www/wwwroot/shphe-en.com/admin/ai_blog_api.php
File size: 17.62 KB
MIME-type: --
Charset: utf-8

<?php
// 获取绝对路径
$absPath = dirname( __DIR__ );
require_once( $absPath . '/wp-load.php' );
global $wpdb;

$type = $_GET['action'];

switch ( $type ) {
    /**
     * 接口:/admin/api.php?action=get_header_footer
     * 请求方式:GET
     */
    # 获取网站头部与底部
    case 'get_header_footer':   // 获取网站头部与底部

        ob_start();

        get_header();

        // 获取缓冲区的内容
        $header = ob_get_contents();

        // 清空缓冲区并关闭输出缓冲
        ob_end_clean();

        ob_start();

        get_footer();

        // 获取缓冲区的内容
        $footer = ob_get_contents();

        // 清空缓冲区并关闭输出缓冲
        ob_end_clean();
        $header = str_replace( 'ob_start_detected', '', $header );
        responseSuccess( compact( 'header', 'footer' ) );
        break;

    /**
     * 接口:/admin/api.php?action=static
     * 请求方式:POST
     * 请求格式:json
     * 参数说明:
     *  - content - 文件内容
     *  - filePath - 文件路径
     *  - action - 操作动作 html xml
     *  -- html 生成html文件
     *  -- xml  生成xml文件
     * 示例:{
     *  "content": "<!DOCTYPE html><html><head><title>这是页面标题  545 45</title></head><body><h1>页面内容</h1></body></html>",
     *  "filePath": "sfasf1555545461.xml",
     *  "action": "xml"
     *  }
     */
    # 生成静态
    case 'static':    // 获取内容  生成静态文件 数据格式 - json
        if ( isPost() ) {
            responseError( '请求方式错误~', 401 );
        }
        $res = getJsonRequest();
        // 文件内容
        $html = trim( $res['content'] );
        if ( empty( $html ) || strlen( $html ) <= 0 ) {
            responseError( '博客传输内容为空~', 401 );
        }
        // 文件名称
        $filePath = trim( $res['filePath'] );
        if ( empty( $filePath ) ) {
            responseError( '博客路径为空~', 401 );
        }
        // 操作动作
        $action = trim( $res['action'] );
        if ( empty( $action ) ) {
            responseError( '博客动作为空~', 401 );
        }
        $action = strtolower( $action );
        // 允许的类型
        $types = [ 'html', 'xml' ];
        if ( !in_array( $action, $types ) ) {
            responseError( '博客动作类型错误,仅支持html,xml~', 401 );
        }
        // 判断是正式站,还是测试站
        $bool = checkTestWeb( $absPath );
        // 如果是测试站,就保存到,/wp-content/cache/all 下
        if ( $bool ) {
            $path = $absPath . '/wp-content/cache/all';
        } else {
            // 如果是正式站,就保存到根目录
            $path = $absPath;
        }
        $originalFilePath = '';
        // 生成HTML
        if ( $action == 'html' ) {
            // 判断名称是否存在
            $originalFilePath = resetProductName( $filePath );
            if ( empty( $originalFilePath ) ) {
                responseError( '文件名称为空~', 401 );
            }
            $path     .= '/' . $originalFilePath;
            $filePath = $path . '/index.html';
        } elseif ( $action == 'xml' ) {     // 生成XML
            $originalFilePath = trim( current( explode( '.', $filePath ) ) ) . '.xml';
            $filePath         = $path . '/' . $originalFilePath;
            $filename         = 'sitemap.xml';
            $sitemap          = $path . '/' . $filename;
            editSitemap( $originalFilePath, $sitemap, $path );
        }
        // 创建文件夹
        $isCreated = createFolders( $path );
        if ( !$isCreated ) {
            responseError( '文件夹创建失败~', 401 );
        }
        // 将内容写入文件
        $result = file_put_contents( $filePath, $html );
        if ( $result !== false ) {
            responseSuccess( [ 'filePath' => $originalFilePath ], '文件保存成功~' );
        } else {
            responseError( '文件保存失败~', 401 );
        }
        break;

    /**
     * 接口:/admin/api.php?action=upload_file
     * 请求方式:POST
     * 请求格式:json
     * 参数说明:
     *  - fileData - 文件内容 base64
     *  - filename - 文件名称
     * 示例:{
     *  "fileData": "base64",
     *  "filename": "test.png"
     *  }
     */
    # 上传文件
    case 'upload_file':     // 上传文件到upload文件夹
        // // 读取文件内容
        // $fileContent = file_get_contents('https://q32.goodao.net/uploads/01.DC40-01A-300x149.jpg');

        // // 编码为base64
        // $base64Data = base64_encode($fileContent);
        // echo json_encode([
        //     'fileData' => $base64Data,
        //     'filename' => '01.DC40-01A-300x149.jpg'
        // ]);
        if ( isPost() ) {
            responseError( '请求方式错误~', 401 );
        }
        $res      = getJsonRequest();
        $fileData = trim( $res['fileData'] );
        if ( empty( $fileData ) ) {
            responseError( '文件内容为空~', 401 );
        }
        $filename = trim( $res['filename'] );
        if ( empty( $filename ) ) {
            responseError( '文件名称为空~', 401 );
        }
        // 解码Base64数据
        $fileData = base64_decode( $fileData );
        if ( $fileData === false ) {
            responseError( '文件内容解码失败~', 401 );
        }
        $uploadDir = $absPath . '/uploads/';

        // 确保目录存在
        createFolders( $uploadDir );

        $destination = $uploadDir . $filename;
        // 保存文件
        if ( file_put_contents( $destination, $fileData ) === false ) {
            responseError( '文件保存失败~', 401 );
        }
        responseSuccess( [ 'filePath' => $filename ], '文件保存成功~' );
        break;
    case 'file_exists':
        // 检查文件是否存在
        $path     = $absPath . '/wp-content/cache/all/';
        $filename = trim( $_REQUEST['filename'] );
        if ( empty( $filename ) ) {
            responseError( '文件名称不能为空~', 401 );
        }
        if ( !file_exists( $path . $filename ) ) {
            responseError( '文件不存在~', 401 );
        }
        responseSuccess( [], '文件存在~' );
        break;
    case 'del_sitemap';
        // 删除根目录sitemap.xml文件
        $bool = unlink( $absPath . '/sitemap.xml' );
        if ( empty( $bool ) ) {
            responseError( '删除sitemap文件失败~', 401 );
        }
        responseSuccess( [], '删除sitemap文件成功~' );
        break;
    default:
        responseError( '路由不存在~', 401 );
}


/**
 * 获取JSON请求数据
 * @return array
 */
function getJsonRequest ()
{
    return json_decode( file_get_contents( 'php://input' ), true );
}

/**
 * 判断是否是POST请求
 * @return bool
 */
function isPost ()
{
    return $_SERVER['REQUEST_METHOD'] !== 'POST';
}

/**
 * 将url添加到sitemap
 * @param string $sitemapPath sitemap文件的绝对路径
 * @param array $urlData 要添加的url
 * @return bool
 */
function addUrlToSitemapIfNotExists ( $sitemapPath, $urlData )
{
    // 默认值处理
    $defaults = [
        'loc'        => '',
        // 'lastmod'    => date( 'Y-m-d' ),
        'changefreq' => 'monthly',
        'priority'   => '0.5'
    ];

    $urlData = array_merge( $defaults, $urlData );

    if ( empty( $urlData['loc'] ) ) {
        return false;
    }

    // 检查URL是否已存在
    if ( isUrlInLargeSitemap( $sitemapPath, $urlData['loc'] ) ) {
        return false;
    }

    // 添加新URL
    if ( !file_exists( $sitemapPath ) ) {
        $xml = new SimpleXMLElement( '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>' );
    } else {
        $xml = simplexml_load_file( $sitemapPath );
        libxml_use_internal_errors( true );
        $xml = simplexml_load_file( $sitemapPath );
        if ( $xml == false ) {
            foreach ( libxml_get_errors() as $error ) {
                echo "XML 错误: {$error->message}\n";
            }
            libxml_clear_errors();
            $content = file_get_contents( $sitemapPath );
            $content = trim( $content );
            $content = preg_replace('/^\xEF\xBB\xBF/', '', $content); // 去除BOM
            if ( $content === false ) {
                die( "无法读取文件内容" );
            }
            $xml = simplexml_load_string( $content );
            if ( $xml === false ) {
                die( "无法解析 XML 内容" );
            }
        }
    }
    if ( $xml->sitemap ) {
        $urlNode = $xml->addChild( 'sitemap' );
    } else {
        $urlNode = $xml->addChild( 'url' );
    }
    $urlNode->addChild( 'loc', htmlspecialchars( $urlData['loc'] ) );
    if ( isset( $urlData['lastmod'] ) ) {
        $urlNode->addChild( 'lastmod', $urlData['lastmod'] );
    }
    if ( isset( $urlData['changefreq'] ) ) {
        $urlNode->addChild( 'changefreq', $urlData['changefreq'] );
    }
    if ( isset( $urlData['priority'] ) ) {
        $urlNode->addChild( 'priority', $urlData['priority'] );
    }

    // 格式化输出
    $dom                     = new DOMDocument( '1.0' );
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput       = true;
    $dom->loadXML( $xml->asXML() );

    return $dom->save( $sitemapPath ) != false;
}

/**
 * 检查sitemap中URL是否已存在 - 大文件优化版(逐行读取,内存友好)
 * @param string $sitemapPath sitemap文件的绝对路径
 * @param string $urlToCheck 要检查的url
 * @return bool
 */
function isUrlInLargeSitemap ( $sitemapPath, $urlToCheck )
{
    if ( !file_exists( $sitemapPath ) ) {
        return false;
    }

    $file       = fopen( $sitemapPath, 'r' );
    $buffer     = '';
    $urlToCheck = htmlspecialchars( $urlToCheck );

    while ( !feof( $file ) ) {
        $buffer .= fread( $file, 8192 );

        // 检查缓冲区中是否包含目标URL
        if ( strpos( $buffer, "<loc>$urlToCheck</loc>" ) !== false ) {
            fclose( $file );
            return true;
        }

        // 保留最后部分以避免截断匹配
        $buffer = substr( $buffer, -100 );
    }

    fclose( $file );
    return false;
}

/**
 * 检查sitemap中URL是否已存在
 * @param string $sitemapPath sitemap文件的绝对路径
 * @param string $urlToCheck 要检查的URL
 * @return bool
 */
function isUrlInSitemap ( $sitemapPath, $urlToCheck )
{
    if ( !file_exists( $sitemapPath ) ) {
        return false;
    }

    $xml = simplexml_load_file( $sitemapPath );
    if ( !$xml ) {
        return false;
    }

    foreach ( $xml->url as $url ) {
        if ( (string)$url->loc === $urlToCheck ) {
            return true;
        }
    }

    return false;
}

/**
 * 将urls添加到sitemap
 * @param array $urls 要添加的urls
 * @param string $sitemapPath sitemap文件的绝对路径
 * @return void
 */
function addUrlsToSitemap ( $urls, $sitemapPath = 'sitemap.xml' )
{
    if ( !file_exists( $sitemapPath ) ) {
        // 如果 sitemap 不存在,创建一个新的
        $xml = new SimpleXMLElement( '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>' );
    } else {
        // 加载现有 sitemap
        $xml = simplexml_load_file( $sitemapPath );
    }
    foreach ( $urls as $url ) {
        $urlNode = $xml->addChild( 'url' );
        // 判断是否存在
        if ( empty( $url['loc'] ) ) {
            continue;
        }
        $urlNode->addChild( 'loc', htmlspecialchars( $url['loc'] ) );
        $urlNode->addChild( 'lastmod', $url['lastmod'] ?: date( 'Y-m-d' ) );
        if ( isset( $url['changefreq'] ) ) {
            $urlNode->addChild( 'changefreq', $url['changefreq'] );
        }
        if ( isset( $url['priority'] ) ) {
            $urlNode->addChild( 'priority', $url['priority'] );
        }
    }

    // 保存修改
    return $xml->asXML( $sitemapPath );
}

/**
 * 编辑sitemap
 * @param string $url 要编辑的url
 * @param string $sitemapPath sitemap文件的绝对路径
 * @return bool
 */
function editSitemap ( $url, $sitemapPath, $path )
{
    $cdn_setting = get_option( "gd_cdn_setting" );
    $weburl      = $cdn_setting['weburl'];
    // 文件不存在则生成文件
    if ( !file_exists( $sitemapPath ) ) {
        $home_url        = home_url( '/' );
        $home_url_nohttp = str_replace( 'https:', '', str_replace( 'http:', '', $home_url ) );

        $weburl_nohttp = str_replace( 'https:', '', str_replace( 'http:', '', $weburl ) );
        $sitemap_index = request_get( $home_url . 'sitemap.xml' );
        if ( strpos( $sitemap_index, 'urlset xmlns=' ) !== false ) {
            createFolders( $path );
        }
        $sitemap_index_data = $sitemap_index;
        if ( !file_exists( $path . '/sitemap.xsl' ) ) {
            $data_xml_sytle_s = request_get( $home_url . 'wp-content/plugins/all-in-one-seo-pack/sitemap.xsl' );
            file_put_contents( $path . '/sitemap.xsl', $data_xml_sytle_s );
        }
        if ( !file_exists( $path . '/sitemap_translate.xsl' ) ) {
            $data_xml_sytle = request_get( $home_url . 'wp-content/plugins/prisna-wp-translate/styles/sitemap.xsl' );
            file_put_contents( $path . '/sitemap_translate.xsl', $data_xml_sytle );
        }

        $sitemap_index_data = str_replace( 'wp-content/plugins/all-in-one-seo-pack/sitemap.xsl', 'sitemap.xsl', $sitemap_index_data );
        $sitemap_index_data = str_replace( $home_url, $weburl, $sitemap_index_data );
        $sitemap_index_data = str_replace( $home_url_nohttp, $weburl_nohttp, $sitemap_index_data );
        $sitemapPath        = $path . '/sitemap.xml';
        file_put_contents( $path . '/sitemap.xml', $sitemap_index_data );
    }

    if ( empty( $url ) ) {
        return false;
    }

    // 使用示例
    return addUrlToSitemapIfNotExists( $sitemapPath, [
        'loc'        => $weburl . $url,
        'priority'   => '0.9',
        'changefreq' => 'weekly',
    ] );
}

/**
 * 重置产品名称
 * @param array $filePath
 * @return string
 */
function resetProductName ( $filePath = [] )
{
    // 重置文件路径
    $expFilePath = array_filter( explode( '/', $filePath ) );
    if ( empty( $expFilePath ) ) {
        return false;
    }
    global $wpdb;
    // 判断名称是否存在
    $slug = end( $expFilePath );
    $sql  = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}posts WHERE post_name = %s AND post_type LIKE 'blog'", $slug );
    $post = $wpdb->get_row( $sql );
    // 存在就重置名称
    if ( $post ) {
        $post_id     = 0; // 新文章设为0
        $post_type   = $post->post_type;
        $post_parent = 0;
        $unique_slug = wp_unique_post_slug( $slug, $post_id, $post->post_status, $post_type, $post_parent );
        array_pop( $expFilePath );
        $expFilePath[] = $unique_slug;
    }
    return implode( '/', $expFilePath );
}

/**
 * 获取网站内容
 * @param string $url
 * @return bool|string
 */
function request_get ( $url )
{
    $ch = curl_init( $url );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_HEADER, false );
    curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
    curl_setopt( $ch, CURLOPT_USERAGENT, 'Mozilla/5.0 ( Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ( KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246' );
    curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
    curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 50 );
    curl_setopt( $ch, CURLOPT_TIMEOUT, 50 );
    curl_setopt( $ch, CURLOPT_MAXREDIRS, 50 );
    curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
    curl_setopt( $ch, CURLOPT_SSLVERSION, 'all' );
    $content = curl_exec( $ch );
    curl_close( $ch );
    return $content;
}

/**
 * 判断是正式站,还是测试站
 * @param string $string
 * @return bool
 */
function checkTestWeb ( $string = '' )
{
    $absPath = $string ?: dirname( __DIR__ );
    // 判断是正式站,还是测试站
    $bool    = false;
    $verify1 = strstr( $absPath, 'goodao.net' );
    $verify2 = strstr( $absPath, 'quanqiusou.cn' );
    if ( $verify1 || $verify2 ) {
        $bool = true;
    }
    return $bool;
}

/**
 * 创建目录
 * @param string $dir
 * @return bool
 */
function createFolders ( $dir )
{
    header( "Content-type:text/html;charset=utf-8" );
    // 判断目录存在否,存在给出提示,不存在则创建目录
    if ( is_dir( $dir ) ) {
        return true;
    } else {
        // 第三个参数是“true”表示能创建多级目录,iconv防止中文目录乱码
        return mkdir( iconv( "UTF-8", "GBK", $dir ), 0777, true );
    }
}

/**
 * 将数组转换为json
 * @param $array
 * @return false|string
 */
function toolJsons ( $array = [] )
{
    return json_encode( $array, JSON_UNESCAPED_UNICODE );
}

/**
 * 成功
 * @param array|string $data
 * @param string $msg
 * @return void
 */
function responseSuccess ( $data = [], $msg = 'success' )
{
    if ( is_string( $data ) ) {
        $msg  = $data;
        $data = [];
    }
    echo toolJsons( [
        'code' => 200,
        'data' => $data,
        'msg'  => $msg
    ] );
    exit();
}

/**
 * 失败
 * @param string $msg
 * @param int $code
 * @return void
 */
function responseError ( $msg = '', $code = 500 )
{
    echo toolJsons( [
        'code' => $code,
        'msg'  => $msg
    ] );
    exit();
}