StaticHtmlRepository.php 12.7 KB
<?php
/**
 * Created by PhpStorm.
 * User: zhl
 * Date: 2023/8/31
 * Time: 14:54
 */

namespace App\Repositories;

use App\Helper\Translate;
use App\Models\CustomModule\CustomModule;
use App\Models\CustomModule\CustomModuleCategory;
use App\Models\Module\Module;
use App\Models\Module\ModuleCategory;
use App\Models\RouteMap\RouteMap;
use App\Models\WebSetting\Translate as WebTranslate;

/**
 * Class StaticHtmlRepository
 * @package App\Repositories
 */
class StaticHtmlRepository
{

    /**
     * 通过域名和路由 获取主语种HTML
     * @param string $domain
     * @param string $route
     * @return string
     */
    public function getMainHtml($domain, $route)
    {
        $html = '';
        return $html;
    }

    /**
     * 5.0生成路径
     */
    public function getProjectRoutePath5($project,$route,$page): string
    {
        $routerMap = RouteMap::where("project_id",$project->id)->where("route",$route)->where("path","")->first();
        if (empty($routerMap)){
            $routerMap = RouteMap::where("project_id",$project->id)->where("route",$route)->first();
        }
        if (!empty($routerMap)){
            if ($routerMap->source == "news"){
                $route =  "news/".$route;
            }elseif($routerMap->source == "blog" || $routerMap->source == "blogs"){
                $route = "blogs/".$route;
            }elseif ($routerMap->source == "news_category"){
                if ($route == "news"){
                    $route = $page == null || $page == 1 ? $route : $route . "/page";
                }else{
                    $route = $page == null || $page == 1 ? "news_catalog/".$route : "news_catalog/".$route."/page";
                }
            }elseif ($routerMap->source == "blog_category"){
                if ($route == "blog"){
                    $route = $page == null || $page == 1 ? $route : $route."/page";
                }else{
                    $route = $page == null || $page == 1 ? "blog_catalog/".$route : "blog_catalog/".$route."/page";
                }
            }elseif ($routerMap->source == "product_category"){
                $route = $page == null || $page == 1 ? $route : $route."/page";
            }elseif ($routerMap->source == "module_category"){
                $moduleCategory = CustomModuleCategory::getModuleCategoryAndExtendById($project->id,$routerMap->source_id);
                if (!empty($moduleCategory->getExtend->route)){
                    if ($moduleCategory->getExtend->route == $route){
                        $route = $moduleCategory->route;
                    }else{
                        $route = $moduleCategory->getExtend->route."_catalog/".$moduleCategory->route."/page";
                    }
                }else{
                    $route = $moduleCategory->route."/page";
                }
            }elseif ($routerMap->source == "module"){
                $modules = CustomModule::where("project_id",$project->id)->where("id",$routerMap->source_id)->where("status",0)->first();
                $moduleCategoryInfo = CustomModule::getModuleCategory($project->id,$modules);
                if (isset($moduleCategoryInfo->getExtend->route) && !empty($moduleCategoryInfo->getExtend->route)){
                    $route = $moduleCategoryInfo->route."/".$modules->route;
                }
            }else{
                $route = $route == "index" ? "/" : $route;
            }
        }else{
            if ($route == "products"){
                if ($page == null || $page == 1){
                }else{
                    $route = $route."/page";
                }
            }elseif ($route == "news"){
            }elseif ($route == "blog"){
                $route = $page == null || $page == 1 ? "blog_catalog/".$route : "blog_catalog/".$route."/page";
            }else{
                $route = $route == "index" ? "/" : $route;
            }
        }
        return $route;
    }

    /**
     * 6.0生成路径
     */
    public function getProjectRoutePath6($project,$route): string
    {
        $routerMap = RouteMap::where("project_id",$project->id)->where("route",$route)->first();
        if (!empty($routerMap)){
            if ($routerMap->source == "news"){
                $route =  "news/".$route;
            }elseif($routerMap->source == "blog"){
                $route = "blogs/".$route;
            }elseif($routerMap->source == "module"){
                $modules = CustomModule::where("project_id",$project->id)->where("id",$routerMap->source_id)->where("status",0)->first();
                $moduleCategoryInfo = CustomModule::getModuleCategory($project->id,$modules);
                if (isset($moduleCategoryInfo->route) && !empty($moduleCategoryInfo->route)){
                    $route = $moduleCategoryInfo->route."/".$route;
                }
            }else{
                $route = $route == "index" ? "/" : $route;
            }
        }else{
            $route = $route == "index" ? "/" : $route;
        }
        return $route;
    }

    public function compactUrl($project,$route,$page): string
    {
        //是否是5.0升级项目
        if (isset($project->update_info["is_update"]) && $project->update_info["is_update"] == 1){
            //5.0生成路径
            $path = $this->getProjectRoutePath5($project,$route,$page);
        }else{
            //6.0生成路径
            $path = $this->getProjectRoutePath6($project,$route);
        }
        return $path;
    }


    /**
     * 通过域名和路由以及目标语种 获取小语种HTML
     * @param string $domain
     * @param string $route
     * @param string $tl
     * @return string
     */
    public function getOtherLangHtml($domain, $route, $tl)
    {
        $path = '通过域名和路由获取主语种静态文件路径';
        if (is_file($path)) {
            $main_html = file_get_contents($path);
        } else {
            $main_html = $this->getMainHtml($domain, $route);
        }
        $html = '通过主语种HTML生成小语种HTML 并处理小语种特有的内容';
        return $html;
    }

    /**
     * 获取翻译后的HTML
     * TODO HTML转dom, 提取需要渲染的词, 翻译关键词, 根据节点还原关键词, 清除dom, 返回HTML
     * @param string $html  原HTML
     * @param string $tl    目标语种
     * @param string $sl    原语种
     * @return mixed
     */
    public function getTranHtml($project,string $html, string $tl,$route,$page, string $sl = 'auto')
    {
        $dom = str_get_html($html);
//        file_put_contents(public_path("aaa.html"), $html);
        if (is_bool($dom)){
            return  $html;
        }
        $texts = $dom->find("text");

        $description = $dom->find("meta[name=description]",0);
        $keywords = $dom->find("meta[name=keywords]",0);
        // 组装需要翻译的内容 HTML内文案、meta description、meta keywords
        $need_tran = [];
        //处理图片alt
        $images = $dom->find("img");
        foreach ($images as $img){
            $alt = $img->alt;
            if($alt){
                $need_tran[] = $alt;
            }
        }
        //处理a标签title
        $aTitles = $dom->find("a");
        foreach ($aTitles as $aTitle){
            $title = $aTitle->title;
            if($title){
                $need_tran[] = $title;
            }
        }
        foreach ($texts as $k=>$text) {
            $tag= $text->parent()->tag;
            if (in_array($tag, ['script', 'style', 'root']))
                continue;

            $string = trim($text->text());
            if (empty($string))
                continue;

            $country_class = '';
            if (method_exists($text->parent()->parent(),"find") && $text->parent()->parent()->find("b")) {
                $country_class = $text->parent()->parent()->find("b",0)->class;
            }
            if(FALSE !== strpos($country_class, 'country-flag'))
                continue;
            $need_tran[] = htmlspecialchars_decode(html_entity_decode($string));
        }
        if (isset($description->attr['content'])){
            $need_tran[] = $description->attr['content'];
        }
        if (isset($keywords->attr['content'])){
            $need_tran[] = $keywords->attr['content'];
        }

        // 翻译内容字符串, 最多翻译三次, 超过三次没有结果, 返回原文
        $tran_string = [];
        if ($need_tran) {
            $i = 0;
            $tl_tran = $tl == "zh-ct" ? "zh-TW" : $tl;
            TranslateArray:
            $tran_result = Translate::translate($need_tran, $tl_tran, $sl);
            if (!isset($tran_result[0]) || empty($tran_result[0]['code'] || $tran_result[0]['code'] != 200)) {
                if ($i >= 3)
                    return $html;
                $i++;
                goto TranslateArray;
            }

            $tran_string = $tran_result[0]['texts'];
        }

        //组装路由
        $page = $page == null || $page == 1 ? "" : "/".$page;
        $route = $this->compactUrl($project,$route,$page);
        $url = $route.$page;
        //图片翻译校对数据
        $webImageTranslate = WebTranslate::where("alias",$tl)->where("url",$url)->where("type",WebTranslate::$imageType)->first();
        $webImageAllTranslate = WebTranslate::where("alias",$tl)->where("url","All")->where("type",WebTranslate::$imageType)->first();
        $imageAllData = !empty($webImageAllTranslate) ?  json_decode($webImageAllTranslate->data,true) : [];
        $imageSelfData = !empty($webImageTranslate) ? json_decode($webImageTranslate->data,true) : [];
        $imageData = array_merge($imageAllData,$imageSelfData);
        //文本翻译校对数据
        $webTextTranslate = WebTranslate::where("alias",$tl)->where("url",$url)->where("type",WebTranslate::$textType)->first();
        $webTextAllTranslate = WebTranslate::where("alias",$tl)->where("url","All")->where("type",WebTranslate::$textType)->first();
        $textAllData = !empty($webTextAllTranslate) ? json_decode($webTextAllTranslate->data,true) : [];
        $textSelfData = !empty($webTextTranslate) ? json_decode($webTextTranslate->data,true) : [];
        $textData = array_merge($textSelfData, $textAllData);
        // 图片按照节点还原
        $tmp = [];
        foreach ($images as $img){
            $alt = $img->alt;
            if($alt){
                $tmp[] = $alt;
                $key = count($tmp) - 1;
                if (!empty($imageData) && isset($imageData[$alt])){
                    $img->attr['alt'] = $imageData[$alt];
                }else{
                    $img->attr['alt'] = $tran_string[$key];
                }
            }
        }

        foreach ($aTitles as $aTitle){
            $title = $aTitle->title;
            if($title){
                $tmp[] = $title;
                $key = count($tmp) - 1;
                if (!empty($textData) && isset($textData[$title])){
                    $aTitle->attr['title'] = $textData[$title];
                }else{
                    $aTitle->attr['title'] = $tran_string[$key];
                }
            }
        }

        foreach ($texts as $text) {
            $tag= $text->parent()->tag;
            if (in_array($tag, ['script', 'style', 'root']))
                continue;

            $string = trim($text->text());
            if (empty($string))
                continue;

            $country_class = '';
            if (method_exists($text->parent()->parent(),"find") && $text->parent()->parent()->find("b")) {
                $country_class = $text->parent()->parent()->find("b",0)->class;
            }
            if(FALSE !== strpos($country_class, 'country-flag'))
                continue;

            $tmp[] = htmlspecialchars_decode(html_entity_decode($string));
            // FIXME 查找校对内容中是否有当前值 优先使用校对内容,没有获取翻译内容
            $key = count($tmp) - 1;
//            dump($string);
            $string = html_entity_decode($string);
            if (!empty($textData) && isset($textData[$string])){
//                dump("数据库:".$textData[$string]);
                $text->outertext = $textData[$string];
            }else{
//                dump("翻译:".$tran_string[$key]);
                $text->outertext = $tran_string[$key];
            }
        }
        // 按照节点还原 description、keywords
        $tmp[] = $description;
        $key = count($tmp) - 1;
        if (isset($description->attr['content'])){
            $dom->find("meta[name=description]")[0]->attr['content'] = $tran_string[$key];
        }
        $tmp[] = $keywords;
        $key = count($tmp) - 1;
        if (isset($description->attr['keywords'])){
            $dom->find("meta[name=keywords]")[0]->attr['content'] = $tran_string[$key];
        }

        // 保存修改 清除缓存
        $html_string = $dom->save();
        $dom->clear();
        return $html_string;
    }
}