| 1 |
<?php |
| 2 |
/* |
| 3 |
Name: 简单 SEO |
| 4 |
URI: https://mp.weixin.qq.com/s/LzGWzKCEl5SdJCQdBvFipg |
| 5 |
Description: 简单 SEO 扩展实现最简单快捷的方式设置 WordPress 站点的 SEO。 |
| 6 |
Version: 2.0 |
| 7 |
*/ |
| 8 |
class WPJAM_SEO{ |
| 9 |
public static function __callStatic($method, $args){ |
| 10 |
return wpjam_call_option(static::class, $method, ...$args); |
| 11 |
} |
| 12 |
|
| 13 |
public static function get_fields(){ |
| 14 |
if(file_exists(ABSPATH.'robots.txt')){ |
| 15 |
$robots_field = ['type'=>'view', 'value'=>'博客的根目录下已经有 robots.txt 文件。<br />请直接编辑或� |
| 16 |
删除之后在后台自定义。']; |
| 17 |
}else{ |
| 18 |
$site_url = parse_url(site_url()); |
| 19 |
$path = !empty($site_url['path']) ? $site_url['path'] : ''; |
| 20 |
$robots = wpjam_remove_pre_tab("User-agent: * |
| 21 |
Disallow: /wp-admin/ |
| 22 |
Disallow: /wp-includes/ |
| 23 |
Disallow: /cgi-bin/ |
| 24 |
Disallow: $path/wp-content/plugins/ |
| 25 |
Disallow: $path/wp-content/themes/ |
| 26 |
Disallow: $path/wp-content/cache/ |
| 27 |
Disallow: $path/author/ |
| 28 |
Disallow: $path/trackback/ |
| 29 |
Disallow: $path/feed/ |
| 30 |
Disallow: $path/comments/ |
| 31 |
Disallow: $path/search/", 3); |
| 32 |
|
| 33 |
$robots_field = ['type'=>'textarea', 'value'=>$robots]; |
| 34 |
} |
| 35 |
|
| 36 |
if(file_exists(ABSPATH.'sitemap.xml')){ |
| 37 |
$wpjam_sitemap = '博客的根目录下已经有 sitemap.xml 文件。<br />删除之后才能使用插件自动生成的 sitemap.xml。'; |
| 38 |
}else{ |
| 39 |
$wpjam_sitemap = '首页/分类/标签:<a href="'.home_url('/sitemap.xml').'" target="_blank">'.home_url('/sitemap.xml').'</a> |
| 40 |
<br />前1000篇文章:<a href="'.home_url('/sitemap-1.xml').'" target="_blank">'.home_url('/sitemap-1.xml').'</a> |
| 41 |
<br />1000-2000篇文章:<a href="'.home_url('/sitemap-2.xml').'" target="_blank">'.home_url('/sitemap-2.xml').'</a> |
| 42 |
<br />以此类推...'; |
| 43 |
} |
| 44 |
|
| 45 |
$wp_sitemap = 'sitemap 地址:<a href="'.home_url('/wp-sitemap.xml').'" target="_blank">'.home_url('/wp-sitemap.xml').'</a>'; |
| 46 |
|
| 47 |
return [ |
| 48 |
'home_set' => ['title'=>'首页设置', 'type'=>'fieldset', 'wrap_tag'=>'fieldset', 'fields'=>[ |
| 49 |
'home_title' => ['title'=>'标题:', 'class'=>'regular-text, expandable', 'placeholder'=>'不填则使用标题'], |
| 50 |
'home_description' => ['title'=>'描述:', 'type'=>'textarea'], |
| 51 |
'home_keywords' => ['title'=>'� |
| 52 |
�键字:', 'class'=>'regular-text, expandable'], |
| 53 |
]], |
| 54 |
'post_set' => ['title'=>'文章和分类页', 'type'=>'fieldset', 'group'=>true, 'fields'=>[ |
| 55 |
'individual' => ['type'=>'select', 'options'=>['0'=>'自动获取摘要和� |
| 56 |
�键字', '1'=>[ |
| 57 |
'label' => '单独设置 SEO TDK', |
| 58 |
'fields' => ['list_table'=>['value'=>1, 'options'=>['1'=>'编辑和列表页都可设置', '0'=>'� |
| 59 |
可在编辑页设置', 'only'=>'� |
| 60 |
可在列表页设置']]] |
| 61 |
]]], |
| 62 |
], 'description' => ['文章摘要作为页面的 Meta Description,文章的标签作为页面的 Meta Keywords。<br />分类和标签的描述作为页面的 Meta Description,页面没有 Meta Keywords。', ['show_if'=>['individual', 0]]]], |
| 63 |
'unique' => ['title'=>'确保生成并唯一', 'label'=>'如果当前主题或� |
| 64 |
�他插件也会生成摘要和� |
| 65 |
�键字,或当前主题不标准,可以通过勾选该选项「确保生成并唯一」。'], |
| 66 |
'robots' => ['title'=>'robots.txt']+$robots_field, |
| 67 |
'sitemap' => ['title'=>'Sitemap', 'options'=>[0=>['label'=>'使用 WPJAM 生成的','description'=>$wpjam_sitemap], 'wp'=>['label'=>'使用 WordPress � |
| 68 |
置的','description'=>$wp_sitemap]]] |
| 69 |
]; |
| 70 |
} |
| 71 |
|
| 72 |
public static function get_value($type='title'){ |
| 73 |
if($type == 'meta'){ |
| 74 |
return wpjam_fill(['description', 'keywords'], fn($k)=> self::get_value($k)); |
| 75 |
} |
| 76 |
|
| 77 |
if(is_front_page()){ |
| 78 |
if(get_query_var('paged') < 2){ |
| 79 |
$value = self::get_setting('home_'.$type); |
| 80 |
} |
| 81 |
}elseif(is_tag() || is_category() || is_tax()){ |
| 82 |
if(get_query_var('paged') < 2){ |
| 83 |
if(self::get_setting('individual')){ |
| 84 |
$value = get_term_meta(get_queried_object_id(), 'seo_'.$type, true); |
| 85 |
} |
| 86 |
|
| 87 |
if(empty($value) && $type == 'description'){ |
| 88 |
$value = term_description(); |
| 89 |
} |
| 90 |
} |
| 91 |
}elseif(is_singular()){ |
| 92 |
if(self::get_setting('individual')){ |
| 93 |
$value = get_post_meta(get_the_ID(), 'seo_'.$type, true); |
| 94 |
} |
| 95 |
|
| 96 |
if(empty($value)){ |
| 97 |
if($type == 'description'){ |
| 98 |
$value = get_the_excerpt(); |
| 99 |
}elseif($type == 'keywords'){ |
| 100 |
$value = ($tags = get_the_tags()) ? implode(',', wp_list_pluck($tags, 'name')) : ''; |
| 101 |
} |
| 102 |
} |
| 103 |
} |
| 104 |
|
| 105 |
if(!empty($value)){ |
| 106 |
$value = wp_strip_all_tags($value, true); |
| 107 |
|
| 108 |
return $type == 'title' ? esc_textarea($value) : "<meta name='{$type}' content='".esc_attr($value)."' />\n"; |
| 109 |
} |
| 110 |
} |
| 111 |
|
| 112 |
public static function get_rewrite_rule(){ |
| 113 |
return [ |
| 114 |
['sitemap\.xml?$', 'index.php?module=sitemap', 'top'], |
| 115 |
['sitemap-(.*?)\.xml?$', 'index.php?module=sitemap&action=$matches[1]', 'top'], |
| 116 |
]; |
| 117 |
} |
| 118 |
|
| 119 |
public static function redirect($action){ |
| 120 |
if(!$action){ |
| 121 |
$items = array_merge([[home_url(), str_replace(' ', 'T', get_lastpostmodified('GMT')).'+00:00', 'daily', '1.0']], get_terms(['taxonomy'=>array_diff(array_keys(get_taxonomies(['public' => true])), ['post_format'])])); |
| 122 |
}elseif(is_numeric($action)){ |
| 123 |
$items = wpjam_get_posts(['posts_per_page'=>1000, 'paged'=>$action, 'post_type'=>array_diff(array_keys(get_post_types(['public' => true])), ['page', 'attachment'])]); |
| 124 |
}else{ |
| 125 |
$sitemap = apply_filters('wpjam_'.$action.'_sitemap', ''); |
| 126 |
} |
| 127 |
|
| 128 |
$sitemap ??= implode(wpjam_map($items, function($item){ |
| 129 |
if(is_a($item, 'WP_Post')){ |
| 130 |
$item = [get_permalink($item->ID), str_replace(' ', 'T', $item->post_modified_gmt).'+00:00', 'weekly', 0.8]; |
| 131 |
}elseif(is_a($item, 'WP_Term')){ |
| 132 |
$item = [get_term_link($item), str_replace(' ', 'T', get_lastpostmodified('GMT')).'+00:00', 'daily', $item->taxonomy == 'category' ? 0.6 : 0.4]; |
| 133 |
} |
| 134 |
|
| 135 |
return "\t<url>\n".implode(wpjam_map(['loc', 'lastmod', 'changefreq', 'priority'], fn($k, $i)=> "\t\t<{$k}>{$item[$i]}</{$k}>\n"))."\t</url>\n"; |
| 136 |
})); |
| 137 |
|
| 138 |
header("Content-Type:text/xml"); |
| 139 |
|
| 140 |
echo '<?xml version="1.0" encoding="UTF-8"?> |
| 141 |
<?xml-stylesheet type="text/xsl" href="'.(new WP_Sitemaps_Renderer())->get_sitemap_stylesheet_url().'"?> |
| 142 |
<!-- generated-on="'.date('d. F Y').'" --> |
| 143 |
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n".$sitemap."\n".'</urlset>'."\n"; |
| 144 |
|
| 145 |
exit; |
| 146 |
} |
| 147 |
|
| 148 |
public static function filter_html($html){ |
| 149 |
$title = self::get_value('title'); |
| 150 |
$title = $title ? '<title>'.$title.'</title>' : ''; |
| 151 |
|
| 152 |
if($meta = self::get_value('meta')){ |
| 153 |
$title = ($title ?: '\1')."\n".implode($meta); |
| 154 |
$html = wpjam_preg_replace('#<meta\s+name=([\'"])('.implode('|', array_keys($meta)).')\1(.*?)\/>#is', '', $html); |
| 155 |
} |
| 156 |
|
| 157 |
return $title ? wpjam_preg_replace('#(<title>[^<]*<\/title>)#is', $title, $html) : $html; |
| 158 |
} |
| 159 |
|
| 160 |
public static function add_hooks(){ |
| 161 |
if(self::get_setting('unique')){ |
| 162 |
add_filter('wpjam_html', [self::class, 'filter_html']); |
| 163 |
}else{ |
| 164 |
wpjam_hook('wp_head', 'echo', fn()=> implode(self::get_value('meta'))); |
| 165 |
} |
| 166 |
|
| 167 |
wpjam_hook('robots_txt', '.', fn($public)=> $public ? self::get_setting('robots') : '', 10, 2); |
| 168 |
add_filter('document_title', fn($title)=> self::get_value('title') ?: $title); |
| 169 |
|
| 170 |
self::get_setting('sitemap') || wpjam_route('sitemap', self::class); |
| 171 |
|
| 172 |
if(self::get_setting('individual')){ |
| 173 |
wpjam_map([ |
| 174 |
'post' => ['context'=>'side', 'post_type'=>fn($v)=> $v != 'attachment' && is_post_type_viewable($v)], |
| 175 |
'term' => ['action'=>'edit', 'taxonomy'=>fn($v)=> is_taxonomy_viewable($v)] |
| 176 |
], fn($v, $t)=> wpjam_register_meta_option($t, 'seo', $v+[ |
| 177 |
'title' => 'SEO设置', |
| 178 |
'page_title' => 'SEO设置', |
| 179 |
'submit_text' => '设置', |
| 180 |
'list_table' => self::get_setting('list_table', 1), |
| 181 |
'fields' => [ |
| 182 |
'seo_description' => ['title'=>'SEO描述', 'class'=>'large-text', 'default'=>'', 'type'=>'textarea'], |
| 183 |
'seo_keywords' => ['title'=>'SEO� |
| 184 |
�键字','class'=>'large-text', 'default'=>''] |
| 185 |
] |
| 186 |
])); |
| 187 |
} |
| 188 |
} |
| 189 |
} |
| 190 |
|
| 191 |
wpjam_register_option('wpjam-seo', [ |
| 192 |
'title' => 'SEO设置', |
| 193 |
'model' => 'WPJAM_SEO', |
| 194 |
'plugin_page' => 'wpjam-seo', |
| 195 |
'current_tab' => 'seo', |
| 196 |
'menu_page' => ['tab_slug'=>'seo', 'order'=>20, 'summary'=>__FILE__] |
| 197 |
]); |
| 198 |
|