PluginProbe
WPJAM Basic / trunk
WPJAM Basic vtrunk
wpjam-basic / components / wpjam-posts.php

wpjam-posts.php in WPJAM Basic trunk, at components/wpjam-posts.php

250 lines 11.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Name: 文章设置
4 URI: https://mp.weixin.qq.com/s/XS3xk-wODdjX3ZKndzzfEg
5 Description: 文章设置把文章编辑的一些常用操作,提到文章列表页面,方便设置和操作
6 Version: 2.0
7 */
8 class WPJAM_Basic_Posts{
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 return [
15 'excerpt' => ['title'=>'文章摘要', 'sep'=>'&emsp;', 'fields'=>['excerpt_optimization' => ['before'=>'未设时:', 'options'=>[
16 0 => 'WordPress 默认方式截取',
17 1 => ['label'=>'按�
18 �中文最优方式截取', 'fields'=>['excerpt_length'=>['before'=>'长度:', 'type'=>'number', 'class'=>'small-text', 'value'=>200, 'after'=>'中文算2个字节,英文算1个字节']]],
19 2 => '直接不显示摘要'
20 ]]]],
21 'list' => ['title'=>'文章列表', 'fields'=>[
22 'support' => ['before'=>'支持:', 'sep'=>'&emsp;', 'type'=>'fields', 'fields'=>[
23 'post_list_ajax' => ['label'=>'�
24 �面 AJAX 操作', 'value'=>1],
25 'upload_external_images' => ['label'=>'上传外部图片操作'],
26 ]],
27 'display' => ['before'=>'显示:', 'sep'=>'&emsp;', 'type'=>'fields', 'fields'=>[
28 'post_list_set_thumbnail' => ['label'=>'文章缩略图', 'value'=>1],
29 'post_list_author_filter' => ['label'=>'作�
30 下拉选择框', 'value'=>1],
31 'post_list_sort_selector' => ['label'=>'排序下拉选择框', 'value'=>1]
32 ]]
33 ]],
34 'other' => ['title'=>'功能优化', 'fields'=>[
35 'remove' => ['before'=>'移除:', 'sep'=>'&emsp;', 'type'=>'fields', 'fields'=>[
36 'remove_post_tag' => ['label'=>'移除文章标签功能'],
37 'remove_page_thumbnail' => ['label'=>'移除页面特色图片'],
38 ]],
39 'add' => ['before'=>'增强:', 'sep'=>'&emsp;', 'type'=>'fields', 'fields'=>[
40 'add_page_excerpt' => ['label'=>'增加页面摘要功能'],
41 '404_optimization' => ['label'=>'增强404页面跳转'],
42 ]]
43 ]],
44 ];
45 }
46
47 public static function get_the_thumbnail($id, $base){
48 if($base == 'edit'){
49 $thumb = get_the_post_thumbnail($id, [50,50]) ?: '';
50 }else{
51 $thumb = wpjam_get_term_thumbnail_url($id, [100, 100]);
52 $thumb = $thumb ? wpjam_tag('img', ['class'=>'wp-term-image', 'src'=>$thumb, 'width'=>50, 'height'=>50]) : '';
53 }
54
55 return $thumb ?: '<span class="no-thumbnail">暂无图片</span>';
56 }
57
58 public static function get_widget(){
59 return [
60 'classname' => 'widget_posts',
61 'widget' => fn($instance)=> ('wpjam_get_'.(wpjam_pull($instance, 'type') ?: 'new').'_posts')(wpjam_except($instance, 'title')),
62 'fields' => function(){
63 $types = ['post'=>__('Post')]+array_reduce(get_post_types(['_builtin'=>false]), fn($c, $k)=> is_post_type_viewable($k) && get_object_taxonomies($k) ? $c+[$k=>wpjam_get_post_type_setting($k, 'title')] : $c, []);
64
65 $fields = [
66 'title' => ['type'=>'text', 'before'=>'列表标题:', 'class'=>'medium-text'],
67 'type' => ['type'=>'select', 'before'=>'列表类型:', 'options'=>['new'=>'最新', 'top_viewd'=>'最高浏览']],
68 'number' => ['type'=>'number', 'before'=>'文章数量:', 'class'=>'tiny-text', 'step'=>1, 'min'=>1],
69 'class' => ['type'=>'text', 'before'=>'列表样式:', 'class'=>'', 'after'=>'请输�
70 � ul 的 class'],
71 'post_type' => ['type'=>'checkbox', 'before'=>'文章类型:', 'options'=>$types],
72 'thumb' => ['type'=>'checkbox', 'class'=>'checkbox', 'label'=>'显示缩略图'],
73 ];
74
75 return count($types) <= 1 ? wpjam_except($fields, 'post_type') : $fields;
76 }
77 ];
78 }
79
80 // 解决文章类型改变之后跳转错误的问题,原始函数:'wp_old_slug_redirect''redirect_canonical'
81 public static function find_by_name($post_name, $post_type='', $post_status='publish'){
82 $args = array_filter(['post_status'=> $post_status]);
83 $with_type = $post_type ? $args+['post_type'=>$post_type] : [];
84 $meta = wpjam_get_by_meta('post', '_wp_old_slug', $post_name);
85 $posts = $meta ? WPJAM_Post::get_by_ids(array_column($meta, 'post_id')) : [];
86 $for_meta = $args+['post_type'=>array_values(array_diff(get_post_types(['public'=>true, 'exclude_from_search'=>false]), ['attachment']))];
87 $post = $posts ? wpjam_find([$with_type, $for_meta], fn($v)=>$v, fn($v)=> $v ? wpjam_find($posts, $v) : '') : null;
88
89 if(!$post){
90 $wpdb = $GLOBALS['wpdb'];
91 $types = array_map('esc_sql', array_diff(get_post_types(['public'=>true, 'hierarchical'=>false, 'exclude_from_search'=>false]), ['attachment']));
92 $where = "post_type in ('".implode( "', '", $types)."') AND ".$wpdb->prepare("post_name LIKE %s", $wpdb->esc_like($post_name).'%');
93 $ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE $where");
94 $posts = $ids ? WPJAM_Post::get_by_ids($ids) : [];
95 $post = $posts ? wpjam_find([$with_type, $args], fn($v)=>$v, fn($v)=> $v ? wpjam_find($posts, $v) : '') ?: array_first($posts) : null;
96 }
97
98 return $post ? $post->ID : null;
99 }
100
101 public static function upload_external_images($id){
102 $bulk = (int)($_POST['bulk'] ?? 0) == 2;
103 $content = get_post($id)->post_content;
104
105 if($content && !is_serialized($content) && preg_match_all('/<img.*?src=[\'"](.*?)[\'"].*?>/i', $content, $matches)){
106 $urls = array_unique($matches[1]);
107 $replace = wpjam_fetch_external_images($urls, $id);
108
109 return $replace ? WPJAM_Post::update($id, ['post_content'=>str_replace($urls, $replace, $content)]) : ($bulk ? true : wp_die('文章中无外部图片'));
110 }
111
112 return $bulk ? true : wp_die('文章中无图片');
113 }
114
115 public static function load($screen){
116 $base = $screen->base;
117 $object = wpjam_admin((in_array($base, ['post', 'edit', 'upload']) ? 'type' : 'tax').'_object');
118
119 if($base == 'post'){
120 self::get_setting('disable_trackbacks') && wpjam_style('label[for="ping_status"]{display:none !important;}');
121 self::get_setting('disable_autoembed') && $screen->is_block_editor && wpjam_script("wp.domReady(()=> wp.blocks.unregisterBlockType('core/embed'));\n");
122 }elseif(in_array($base, ['edit', 'upload'])){
123 $ptype = $screen->post_type;
124 $is_wc_shop = defined('WC_PLUGIN_FILE') && str_starts_with($ptype, 'shop_');
125
126 self::get_setting('post_list_author_filter', 1) && $object->supports('author') && add_action('restrict_manage_posts', function($ptype){ wp_dropdown_users([
127 'name' => 'author',
128 'capability' => 'edit_posts',
129 'orderby' => 'post_count',
130 'order' => 'DESC',
131 'show_option_all' => $ptype == 'attachment' ? '所有上传�
132 ' : '所有作�
133 ',
134 'selected' => (int)wpjam_param('author', 'data'),
135 'hide_if_only_one_author' => true,
136 ]);
137 }, 1);
138
139 self::get_setting('post_list_sort_selector', 1) && !$is_wc_shop && add_action('restrict_manage_posts', function($ptype){
140 [$columns, , $sortable] = $GLOBALS['wp_list_table']->get_column_info();
141
142 $orderby = wpjam_reduce($sortable, fn($c, $v, $k)=> isset($columns[$k]) ? wpjam_set($c, $k, wp_strip_all_tags($columns[$k])) : $c, []);
143
144 echo wpjam_fields([
145 'orderby' => ['options'=>[''=>'排序','ID'=>'ID']+$orderby+($ptype != 'attachment' ? ['modified'=>'修改时间'] : [])],
146 'order' => ['options'=>['desc'=>'降序','asc'=>'升序']]
147 ], [
148 'fields_type' => '',
149 'value_callback' => fn($k)=> sanitize_key(wpjam_param($k, 'data'))
150 ])."\n";
151 }, 99);
152
153 if($ptype != 'attachment'){
154 ($action = 'upload_external_images') && self::get_setting($action) && wpjam_register_list_table_action($action, [
155 'title' => '上传外部图片',
156 'page_title' => '上传外部图片',
157 'direct' => true,
158 'confirm' => true,
159 'bulk' => 2,
160 'order' => 9,
161 'callback' => [self::class, $action]
162 ]);
163
164 wpjam_style('#bulk-titles, ul.cat-checklist{height:auto; max-height: 14em;}');
165
166 if($ptype == 'page'){
167 wpjam_style('.fixed .column-template{width:15%;}');
168
169 wpjam_register_posts_column('template', '模板', 'get_page_template_slug');
170 }
171 }
172
173 $width_columns = wpjam_map($object->get_taxonomies(['show_admin_column'=>true]), fn($v)=> '.fixed .column-'.$v->column_name);
174 $width_columns = array_merge($width_columns, $object->supports('author') ? ['.fixed .column-author'] : []);
175
176 $width_columns && wpjam_style(implode(',', $width_columns).'{width:'.(['14', '12', '10', '8', '7'][count($width_columns)-1] ?? '6').'%}');
177
178 wpjam_style('.fixed .column-date{width:100px;}');
179 }elseif(in_array($base, ['edit-tags', 'term'])){
180 $base == 'edit-tags' && wpjam_style(['.fixed th.column-slug{width:16%;}', '.fixed th.column-description{width:22%;}']);
181
182 array_map(fn($v)=> $object->supports($v) ? '' : wpjam_style('.form-field.term-'.$v.'-wrap{display: none;}'), ['slug', 'description', 'parent']);
183 }
184
185 if($base == 'edit-tags' || ($base == 'edit' && !$is_wc_shop)){
186 wpjam_script(self::get_setting('post_list_ajax', 1) ? <<<'JS'
187 setTimeout(()=> {
188 wpjam.delegate('#the-list', '.editinline');
189 wpjam.delegate('#doaction');
190 }, 300);
191 JS : "wpjam.list_table.ajax = false;\n");
192
193 $base == 'edit' && wpjam_script(<<<'JS'
194 inlineEditPost.setBulk = wpjam.enhance(inlineEditPost.setBulk, ()=> $('#the-list').trigger('bulk_edit'));
195 inlineEditPost.edit = wpjam.enhance(inlineEditPost.edit, function(id){
196 return ($('#the-list').trigger('quick_edit', typeof(id) === 'object' ? this.getId(id) : id), false);
197 });
198 JS);
199
200 if(self::get_setting('post_list_ajax', 1)){
201 $pairs[] = ['/(<strong><a class="row-title"[^>]*>.*?<\/a>.*?)(<\/strong>)/is', '$1 [row_action name="set" class="row-action" dashicon="edit"]$2'];
202
203 if($base == 'edit'){
204 $pairs[] = ['/(<td class=\'[^\']*('.array_reduce($object->get_taxonomies(['show_in_quick_edit'=>true]), fn($c, $t)=> $c.'|'.preg_quote($t->column_name), 'column-author').')[^\']*\'.*?>.*?)(<\/td>)/is', '$1 <a title="快速编辑" href="javascript:;" class="editinline row-action dashicons dashicons-edit"></a>$3'];
205 }
206 }
207
208 if(self::get_setting('post_list_set_thumbnail', 1)
209 && $object->supports($base == 'edit' ? 'thumbnail,images' : 'thumbnail')
210 && ($base != 'edit'|| $ptype != 'product' || !defined('WC_PLUGIN_FILE'))
211 ){
212 $pairs[] = ['<a class="row-title" ', fn($id)=> '[row_action name="set" class="wpjam-thumbnail-wrap" fallback="1"]'.self::get_the_thumbnail($id, $base).'[/row_action]'];
213 }
214
215 isset($pairs) && add_filter('wpjam_single_row', fn($row, $id)=> array_reduce($pairs, fn($c, $p)=> is_callable($p[1]) ? str_replace($p[0], $p[1]($id).$p[0], $c) : wpjam_preg_replace($p[0], $p[1], $c), $row), 10, 2);
216 }
217 }
218
219 public static function init(){
220 self::get_setting('remove_post_tag') && unregister_taxonomy_for_object_type('post_tag', 'post');
221 self::get_setting('remove_page_thumbnail') && remove_post_type_support('page', 'thumbnail');
222 self::get_setting('add_page_excerpt') && add_post_type_support('page', 'excerpt');
223
224 self::get_setting('404_optimization') && wpjam_hook('old_slug_redirect_post_id', fn($id)=> $id ?: self::find_by_name(get_query_var('name'), get_query_var('post_type')));
225
226 if(self::get_setting('excerpt_optimization')){
227 remove_filter('get_the_excerpt', 'wp_trim_excerpt');
228
229 if(self::get_setting('excerpt_optimization') != 2){
230 remove_filter('the_excerpt', 'wp_filter_content_tags');
231 remove_filter('the_excerpt', 'shortcode_unautop');
232
233 wpjam_hook('get_the_excerpt', fn($text='', $post=null)=> $text ?: wpjam_get_post_excerpt($post, (self::get_setting('excerpt_length') ?: 200)), 9, 2);
234 }
235 }
236 }
237 }
238
239 wpjam_register_option('wpjam-basic', [
240 'title' => '文章设置',
241 'plugin_page' => 'wpjam-posts',
242 'current_tab' => 'posts',
243 'site_default' => true,
244 'model' => 'WPJAM_Basic_Posts',
245 'admin_load' => ['base'=>['edit', 'upload', 'post', 'edit-tags', 'term']],
246 'menu_page' => ['parent'=>'wpjam-basic', 'position'=>4, 'function'=>'tab', 'tabs'=>[
247 'posts' => ['title'=>'文章设置', 'order'=>20, 'summary'=>__FILE__, 'function'=>'option', 'option_name'=>'wpjam-basic']
248 ]],
249 ]);
250