official_website/app/common/util/SitemapUtil.php

369 lines
14 KiB
PHP
Raw Normal View History

2024-12-02 13:57:08 +08:00
<?php
namespace app\common\util;
use app\common\model\Basic as BasicModel;
use app\common\model\Contact as ContactModel;
use app\common\model\Column;
use app\common\model\ModelRecord;
use think\facade\Db;
use think\facade\View;
/**
* sitemap地图
*/
class SitemapUtil
{
/**
* 生成sitemap网站地图
*/
public function generateSitemap($type, $domain, $lang=""){
$sitemap = xn_cfg("sitemap");
$filters = [];
if(!empty($sitemap['filter'])){
$filters = explode(",",$sitemap['filter']);
}
//更新频率
$frequencys = [];
if(!empty($sitemap['frequency'])){
$frequencys = explode(",",$sitemap['frequency']);
}
//优先级别
$levels = [];
if(!empty($sitemap['level'])){
$levels = explode(",",$sitemap['level']);
}
//url模式
$url_model = xn_cfg("seo.url_model");
$where = [];
if(in_array("hide_column", $filters)){//隐藏栏目
array_push($where, ['status', '=', 1]);
}
if(in_array("outer_model", $filters)){//过滤外部模块
array_push($where, ['column_attr', '<>', 1]);
}
//查询模型
$mrList = ModelRecord::field("table, nid")->where(['is_delete'=>0, 'status'=>1, "reference_model"=>0])->select();
//查询栏目
$curlang = xn_cfg("base.lang");
if(empty($lang)){
$lang = $curlang;
}
array_push($where, ['lang', '=', $lang]);
$columns = Column::where($where)->order('level asc')->order('sort asc')->select();
$view_suffix = config('view.view_suffix');
if($url_model == 3){//静态化页面
$indexUrl = $domain;
}else{
$indexUrl = $domain."index.{$view_suffix}";
}
if($type == "xml"){
$this->xml_sitemap($columns, $indexUrl, $view_suffix, $mrList, $frequencys, $levels, $domain, $lang);
}elseif ($type == "txt"){
$this->txt_sitemap($columns, $mrList, $indexUrl, $domain, $lang);
}elseif ($type == "html"){
return $this->html_sitemap($columns, $mrList, $view_suffix, $domain, $lang);
}elseif($type == "all"){//生成全部网站地图
$this->txt_sitemap($columns, $mrList, $indexUrl, $domain, $lang);
$this->xml_sitemap($columns, $indexUrl, $view_suffix, $mrList, $frequencys, $levels, $domain, $lang);
$this->html_sitemap($columns, $mrList, $view_suffix, $domain, $lang);
}
}
/**
* 生成xml网站地图
*/
private function xml_sitemap($columns, $indexUrl, $view_suffix, $mrList, $frequencys, $levels, $domain, $lang){
$sitemap = new \app\common\util\SitemapXmlUtil($domain);
$home_lang = xn_cfg("base.home_lang");//默认语言
if($home_lang == $lang){
$xmlFile = "sitemap";
}else{
$xmlFile = $lang."/sitemap";
}
$sitemap->setXmlFile($xmlFile);
$sitemap->addItem($indexUrl, $levels[0], $frequencys[0], 'Today');
foreach ($columns as $column){
$column['visit_lang'] = $lang;
$columnUrl = getColumnUrl($column);
$columnUrl = $this->addPrefix($columnUrl, $domain);
$columnUrl = replaceSymbol($columnUrl);
$sitemap->addItem($columnUrl, $levels[1], $frequencys[1], strtotime($column['update_time']));
$column_model = $column['column_model'];
$is_find = false;
foreach ($mrList as $mr){
if($mr['nid'] == $column_model){
$is_find = true;
break;
}
}
if($is_find){
$column_id = $column["id"];
if ($column["column_attr"] == 2){//内链栏目
$column_id = $column['inner_column'];
}
$dataList = Db::name($column_model)->where('column_id', $column_id)->select();//数据列表
foreach ($dataList as $data){
$path = "/{$column_model}/detail";
$detailUrl = detailSetUrl($path, $data['id'], $data['column_id'], $column_model, $lang);
$detailUrl = $this->addPrefix($detailUrl, $domain);
$detailUrl = replaceSymbol($detailUrl);
$sitemap->addItem($detailUrl, $levels[2], $frequencys[2], strtotime($data['release_time']));
}
}
}
$sitemap->endSitemap();
}
/**
* 生成txt网站地图
*/
private function txt_sitemap($columns, $mrList, $indexUrl, $domain, $lang=""){
$datas = [];
array_push($datas, $indexUrl);//首页
foreach ($columns as $column){
$column['visit_lang'] = $lang;
$columnUrl = getColumnUrl($column);
$columnUrl = $this->addPrefix($columnUrl, $domain);
$columnUrl = replaceSymbol($columnUrl);
array_push($datas, $columnUrl);
$column_model = $column['column_model'];
$is_find = false;
foreach ($mrList as $mr){
if($mr['nid'] == $column_model){
$is_find = true;
break;
}
}
if($is_find){
$column_id = $column["id"];
if ($column["column_attr"] == 2){//内链栏目
$column_id = $column['inner_column'];
}
$dataList = Db::name($column_model)->where('column_id', $column_id)->select();//数据列表
foreach ($dataList as $data){
$path = "/{$column_model}/detail";
$detailUrl = detailSetUrl($path, $data['id'], $data['column_id'], $column_model, $lang);
$detailUrl = $this->addPrefix($detailUrl, $domain);
$detailUrl = replaceSymbol($detailUrl);
array_push($datas, $detailUrl);
}
}
}
$home_lang = xn_cfg("base.home_lang");//默认语言
if($home_lang == $lang){
$filename = "sitemap.txt";
}else{
$filename = $lang."/sitemap.txt";
}
$data = implode("\r\n", $datas);
@file_put_contents($filename, $data);
}
/**
* 生成html网站地图
*/
private function html_sitemap($columns, $mrList, $view_suffix, $domain, $lang=""){
$home_lang = xn_cfg("base.home_lang");//默认语言
if($home_lang == $lang){
$filename = "sitemap.{$view_suffix}";
}else{
$filename = $lang."/sitemap.{$view_suffix}";
}
$sitemapUrl = root_path()."/app/home/view/sitemap.{$view_suffix}";
//网站基本信息
$basic = [];
$basicArr = BasicModel::where(['lang'=>$lang])->select()->toArray();
$basicN = [];//基本属性返回
if(sizeof($basicArr) > 0) {
$basic = $basicArr[0];
$basicN['keyword']= $basic['keyword'];
$basicN['description']= $basic['description'];
}
$contactArr = ContactModel::where([['lang', '=', $lang]])->field('company_tel')->select()->toArray();
$contact = [];
if(sizeof($contactArr) > 0) {
$contact = $contactArr[0];
}
$basicN['logo']= $basic['web_logo']??"/static/404/images/foxcms_logo.svg";
//查询栏目数据
$navs = [];//顶层栏目
foreach ($columns as $column){
$column['visit_lang'] = $lang;
if($column['pid'] == 0){
$columnUrl = getColumnUrl($column);
$columnUrl = $this->addPrefix($columnUrl, $domain);
$column['link'] = replaceSymbol($columnUrl);
array_push($navs, $column);
}
}
$columnList = $this->channelLevel($domain, $columns);//排序好栏目
//栏目列表
foreach ($columns as $key=>$column){
$column_model = $column['column_model'];
$is_find = false;
foreach ($mrList as $mr){
if($mr['nid'] == $column_model){
$is_find = true;
break;
}
}
if($is_find){
$column_id = $column["id"];
if ($column["column_attr"] == 2){//内链栏目
$column_id = $column['inner_column'];
}
$dataList = Db::name($column_model)->where('column_id', $column_id)->where('lang', $lang)->select();//数据列表
foreach ($dataList as $kkey=>$data){
$path = "/{$column_model}/detail";
$detailUrl = detailSetUrl($path, $data['id'], $data['column_id'], $column_model, $lang);
$detailUrl = $this->addPrefix($detailUrl, $domain);
$detailUrl = replaceSymbol($detailUrl);
$data['link'] = $detailUrl;
$dataList[$kkey] = $data;
}
$column['data_list'] = $dataList;
$columns[$key] = $column;
}
}
$columnArticleList = $this->channelLevel($domain,$columns);//栏目文章数据列表
$caList = [];//返回栏目数据列表
foreach ($columnArticleList as $ca){
$this->cycleColumn($ca, $caList);
}
$content = View::fetch($sitemapUrl);
$content = str_replace("__basic.logo__", $basicN['logo'], $content);
$nav_content = "";
foreach ($navs as $k=>$vo){
$nav_content .= '<li>
<a class="foxui-link" href="'.$vo['link'].'">'.$vo['name'].'</a>
</li>';
}
$content = str_replace("__nav.content__", $nav_content, $content);
$column_content = "";
foreach ($columnList as $key=>$vo){
$column_content .= ' <div class="foxui-col-md-4 foxui-col-sm-8 foxui-col-xs-12">
<dl>
<dt>
<a class="foxui-ellipsis" href="'.$vo['link'].'">'.$vo['name'].'</a>
</dt>';
$column_content_child = "";
if (sizeof($vo['children']) > 0){
foreach ($vo['children'] as $key=>$voo){
$column_content_child .=' <dd>
<a class="foxui-link foxui-link-primary foxui-ellipsis" href="'.$voo['link'].'">'.$voo['name'].'</a>
</dd>';
}
}
$column_content .= $column_content_child;
$column_content .= '</dl>
</div>';
}
$content = str_replace(" __column.content__", $column_content, $content);
$ca_contet= "";
foreach ($caList as $key=>$vo){
if($vo['data_list'] && sizeof($vo['data_list']) > 0){
$ca_contet .='<h5 class="foxui-margin-bottom-16">'.$vo['name'].'</h5>
<div class="foxui-row foxui-gutter-y-6 foxui-gutter-x-xxxl-12 foxui-gutter-x-xxl-12 foxui-gutter-x-xl-12">';
$ca_contet_child = "";
foreach ($vo['data_list'] as $do) {
$ca_contet_child .='<div class="foxui-col-md-8 foxui-col-sm-12 foxui-col-xs-12">
<div class="item">';
$ca_contet_child .='<a class="foxui-link foxui-link-primary foxui-ellipsis" href = "'.($do['link']??"javascript:void(0)").'">';
$ca_contet_child .= $do['title']??"";
$ca_contet_child .='</a>';
$ca_contet_child .='</div>
</div>';
}
$ca_contet .= $ca_contet_child;
$ca_contet .='</div>';
}
}
$content = str_replace(" __ca.content__", $ca_contet, $content);
$content = str_replace("__contact.company_tel__", $contact['company_tel'], $content);
@file_put_contents($filename, $content);
}
/**
* 添加前缀
*/
protected function addPrefix($value, $domain = ""){
if(empty($value)){
return "";
}
if (preg_match('/(http:\/\/)|(https:\/\/)/i', $value)) {//判断是否存在
return $value;
}else{
if(str_starts_with($value, "/")){
$value = substr($value, 1, strlen($value));
}
$value = $domain.$value;
return $value;
}
}
/**
* 解析子栏目
*/
private function cycleColumn($ca, &$caList){
array_push($caList, $ca);
if(sizeof($ca['children']) > 0){
foreach ($ca['children'] as $k=>$cca){
$this->cycleColumn($cca, $caList);
}
}
return $caList;
}
/**
* 返回多层栏目
* @param $dataArr 操作的数组
* @param int $pid 一级PID的值
* @param string $fieldPri 唯一键名,如果是表则是表的主键
* @param string $fieldPid 父ID键名
* @param int $level 不需要传参数(执行时调用)
*/
private function channelLevel($domain, $dataArr, $pid = 0, $fieldPri = 'id', $fieldPid = 'pid', $level = 1)
{
if (empty($dataArr)) {
return array();
}
$rArr = [];
foreach ($dataArr as $v) {
if ($v[$fieldPid] == $pid) {
$arr = array();
$arr['id'] = $v->id;
$arr['pid'] = $v->pid;
$arr['name'] = $v->name;
$arr['status'] = $v->status;
$arr['sort'] = $v->sort;
$arr['data_list'] = $v->data_list;
$arr['column_model'] = $v->column_model;
$arr['level'] = $level;
$columnUrl = getColumnUrl($v);
$columnUrl = $this->addPrefix($columnUrl, $domain);
$columnUrl = replaceSymbol($columnUrl);
$arr['link'] = $columnUrl;
$arr['children'] = self::channelLevel($domain, $dataArr, $v[$fieldPri], $fieldPri, $fieldPid, $level + 1);
array_push($rArr, $arr);
}
}
return $rArr;
}
}