| Server IP : 43.141.50.122 / Your IP : 113.219.202.141 Web Server : Apache System : Linux VM-8-5-opencloudos 6.6.34-9.oc9.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jun 19 19:35:45 CST 2024 x86_64 User : www ( 1000) PHP Version : 8.1.27 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/wwwroot/wordpress/wordpress/wp-content/plugins/wpjam-basic/includes/ |
Upload File : |
<?php
class WPJAM_Post{
use WPJAM_Instance_Trait;
protected $id;
protected function __construct($id){
$this->id = (int)$id;
}
public function __get($key){
if(in_array($key, ['id', 'post_id'])){
return $this->id;
}elseif($key == 'views'){
return (int)get_post_meta($this->id, 'views', true);
}elseif($key == 'permalink'){
return get_permalink($this->id);
}elseif($key == 'ancestors'){
return get_post_ancestors($this->id);
}elseif($key == 'children'){
return get_children($this->id);
}elseif($key == 'viewable'){
return is_post_publicly_viewable($this->id);
}elseif($key == 'format'){
return get_post_format($this->id) ?: '';
}elseif($key == 'taxonomies'){
return get_object_taxonomies($this->post);
}elseif($key == 'type_object'){
return wpjam_get_post_type_object($this->post_type);
}elseif($key == 'icon'){
return (string)$this->get_type_setting('icon');
}elseif($key == 'thumbnail'){
return $this->supports('thumbnail') ? get_the_post_thumbnail_url($this->id, 'full') : '';
}elseif($key == 'images'){
return $this->supports('images') ? array_values(get_post_meta($this->id, 'images', true) ?: []) : [];
}elseif($key == 'post'){
return get_post($this->id);
}else{
$_post = get_post($this->id);
if($key == 'data'){
return $_post->to_array();
}elseif(!str_starts_with($key, 'post_') && isset($_post->{'post_'.$key})){
return $_post->{'post_'.$key};
}else{
return $_post->$key ?? $this->meta_get($key);
}
}
}
public function __isset($key){
return $this->$key !== null;
}
public function __call($method, $args){
if(in_array($method, ['get_content', 'get_excerpt', 'get_first_image_url'])){
$function = 'wpjam_get_post_'.wpjam_remove_prefix($method, 'get_');
return $function($this->post, ...$args);
}elseif(in_array($method, ['get_thumbnail_url', 'get_images'])){
$method = str_replace('get_', 'parse_', $method);
return $this->$method(...$args);
}
return $this->call_dynamic_method($method, ...$args);
}
public function get_type_setting($key){
return $this->type_object ? $this->type_object->$key : null;
}
public function supports($feature){
return post_type_supports($this->post_type, $feature);
}
public function save($data){
$status = array_get($data, 'post_status') ?: array_get($data, 'status');
if($status == 'publish'){
$result = $this->is_publishable();
if(is_wp_error($result) || !$result){
return $result ?: new WP_Error('unpublishable', '不可发布');
}
}
return self::update($this->id, $data, false);
}
public function set_status($status){
return $this->save(['post_status'=>$status]);
}
public function publish(){
return $this->set_status('publish');
}
public function unpublish(){
return $this->set_status('draft');
}
public function is_publishable(){
return true;
}
public function get_unserialized(){
return wpjam_unserialize($this->content, fn($fixed)=> $this->save(['content'=>$fixed])) ?: [];
}
public function get_terms($taxonomy='post_tag'){
return get_the_terms($this->id, $taxonomy) ?: [];
}
public function set_terms($terms='', $taxonomy='post_tag', $append=false){
return wp_set_post_terms($this->id, $terms, $taxonomy, $append);
}
public function in_term($taxonomy, $terms=null){
return is_object_in_term($this->id, $taxonomy, $terms);
}
public function in_taxonomy($taxonomy){
return is_object_in_taxonomy($this->post, $taxonomy);
}
public function parse_thumbnail_url($size='thumbnail', $crop=1){
if($this->thumbnail){
$thumbnail = $this->thumbnail;
}elseif($this->images){
$thumbnail = $this->images[0];
}else{
$thumbnail = apply_filters('wpjam_post_thumbnail_url', '', $this->post);
}
return $thumbnail ? wpjam_get_thumbnail($thumbnail, ($size ?: ($this->get_type_setting('thumbnail_size') ?: 'thumbnail')), $crop) : '';
}
public function parse_images($large_size='', $thumbnail_size='', $full_size=true){
if(!$this->images){
return [];
}
if(count($this->images) == 1){
$image = $this->images[0];
$query = wpjam_parse_image_query($image);
if(!$query){
$query = wpjam_get_image_size($image, 'url');
$query = $query ?: ['width'=>0, 'height'=>0];
update_post_meta($this->id, 'images', [add_query_arg($query, $image)]);
}
$orientation = $query['orientation'] ?? '';
}else{
$orientation = '';
}
$setting = $this->get_type_setting('images_sizes');
if($setting){
$sizes['large'] = $setting[0];
$sizes['thumbnail'] = $setting[1];
if($orientation == 'landscape'){
if(!empty($setting[2])){
$sizes['thumbnail'] = $setting[2];
}
}elseif($orientation == 'portrait'){
if(!empty($setting[3])){
$sizes['thumbnail'] = $setting[3];
}
}
}else{
$sizes = [
'large' => $this->get_type_setting('large_size') ?: 'large',
'thumbnail' => $this->get_type_setting('thumbnail_size') ?: 'thumbnail',
];
}
foreach(['large'=>$large_size, 'thumbnail'=>$thumbnail_size] as $key => $value){
if($value === false){
unset($sizes[$key]);
}elseif($value){
$sizes[$key] = $value;
}
}
foreach($this->images as $image){
if(!$sizes || $full_size){
$sizes['full'] = 'full';
}
$parsed = array_map(fn($s)=> wpjam_get_thumbnail($image, $s), $sizes);
$query = wpjam_parse_image_query($image);
if($query){
if(!empty($query['orientation'])){
$parsed['orientation'] = $query['orientation'];
}
$parsed = array_merge($parsed, wpjam_fill(['width', 'height'], fn($k)=> $query[$k] ?? 0));
}
if(isset($sizes['thumbnail'])){
$size = wpjam_parse_size($sizes['thumbnail']);
$parsed = array_merge($parsed, wpjam_array(['width', 'height'], fn($k, $v)=> ['thumbnail_'.$v, $size[$v] ?? 0]));
}
$images[] = count($sizes) == 1 ? reset($parsed) : $parsed;
}
return $images;
}
public function parse_for_json($args=[]){
$args = wp_parse_args($args, [
'list_query' => false,
'content_required' => false,
'raw_content' => false,
'suppress_filter' => false,
]);
$size = $args['thumbnail_size'] ?? ($args['size'] ?? null);
$json = array_merge(
[
'id' => $this->id,
'type' => $this->type,
'post_type' => $this->post_type,
'status' => $this->status,
'views' => $this->views,
'icon' => $this->icon,
'title' => $this->parse_field('title'),
'excerpt' => $this->parse_field('excerpt'),
'thumbnail' => $this->get_thumbnail_url($size),
'user_id' => (int)$this->author,
],
$this->parse_field('author'),
$this->parse_field('date', $args),
$this->parse_field('modified'),
$this->parse_field('password'),
$this->parse_field('name')
);
if($this->supports('page-attributes')){
$json['menu_order'] = (int)$this->menu_order;
}
if($this->supports('post-formats')){
$json['format'] = $this->format;
}
if($this->supports('images')){
$json['images'] = $this->parse_images();
}
if($args['list_query']){
return $json;
}
foreach(wpjam_get_post_options($this->post_type) as $option){
$json = array_merge($json, $option->prepare($this->id));
}
foreach(array_filter($this->taxonomies, fn($tax)=> $tax != 'post_format' && is_taxonomy_viewable($tax)) as $taxonomy){
$json[$taxonomy] = array_map('wpjam_get_term', $this->get_terms($taxonomy));
}
$json = array_merge($json, $this->parse_field('content', $args));
return $args['suppress_filter'] ? $json : apply_filters('wpjam_post_json', $json, $this->id, $args);
}
protected function parse_field($field, $args=[]){
if(in_array($field, ['title', 'excerpt'])){
return $this->supports($field) ? html_entity_decode(call_user_func('get_the_'.$field, $this->id)) : '';
}elseif($field == 'name'){
if($this->viewable){
return [
'name' => urldecode($this->name),
'post_url' => str_replace(home_url(), '', $this->permalink)
];
}
}elseif($field == 'author'){
if($this->supports($field)){
return ['author' => wpjam_get_user($this->author)];
}
}elseif($field == 'content'){
if((is_single($this->id) || is_page($this->id) || $args['content_required'])){
if($this->supports('editor')){
if($args['raw_content']){
$parsed['raw_content'] = $this->content;
}
$parsed['content'] = wpjam_get_post_content($this->post);
$parsed['multipage'] = (bool)$GLOBALS['multipage'];
if($parsed['multipage']){
$parsed['numpages'] = $GLOBALS['numpages'];
$parsed['page'] = $GLOBALS['page'];
}
}else{
if(is_serialized($this->content)){
$parsed['content'] = $this->get_unserialized();
}
}
}
}elseif(in_array($field, ['date', 'modified'])){
$timestamp = get_post_timestamp($this->id, $field);
$prefix = $field == 'modified' ? 'modified_' : '';
$parsed = [
$prefix.'timestamp' => $timestamp,
$prefix.'time' => wpjam_human_time_diff($timestamp),
$prefix.'date' => wpjam_date('Y-m-d', $timestamp),
];
if($field == 'date' && !$args['list_query'] && is_main_query()){
$current_posts = $GLOBALS['wp_query']->posts;
if($current_posts && in_array($this->id, array_column($current_posts, 'ID'))){
if(is_new_day()){
$GLOBALS['previousday'] = $GLOBALS['currentday'];
$parsed['day'] = wpjam_human_date_diff($parsed['date']);
}else{
$parsed['day'] = '';
}
}
}
}elseif($field == 'password'){
if($this->password){
return [
'password_protected' => true,
'password_required' => post_password_required($this->id),
];
}
}
return $parsed ?? [];
}
public function meta_get($key){
return wpjam_get_metadata('post', $this->id, $key, null);
}
public function meta_exists($key){
return metadata_exists('post', $this->id, $key);
}
public function meta_input(...$args){
if($args){
return wpjam_update_metadata('post', $this->id, ...$args);
}
}
public function value_callback($field){
if($field == 'tax_input'){
return wpjam_fill($this->taxonomies, fn($tax)=> array_column($this->get_terms($tax), 'term_id'));
}
return $this->post->$field ?? $this->meta_get($field);
}
// update/insert 方法同时支持 title 和 post_xxx 字段写入 post 中,meta 字段只支持 meta_input
// update_callback 方法只支持 post_xxx 字段写入 post 中,其他字段都写入 meta_input
public function update_callback($data, $defaults){
$current = $this->data;
$keys = [...array_keys($current), 'tax_input'];
$post_data = wpjam_pull($data, $keys);
$post_data = array_diff_assoc($post_data, $current);
$result = $post_data ? $this->save($post_data) : true;
if(!is_wp_error($result) && $data){
return $this->meta_input($data, $defaults);
}
return $result;
}
public static function get_instance($post=null, $post_type=null, $wp_error=false){
$post = $post ?: get_post();
$post = static::validate($post, $post_type);
if(is_wp_error($post)){
return $wp_error ? $post : null;
}
$model = wpjam_get_post_type_setting(get_post_type($post), 'model') ?: 'WPJAM_Post';
return self::instance($post->ID, fn($id)=> $model::create_instance($id));
}
public static function validate($post_id, $post_type=null){
$post = $post_id ? self::get_post($post_id) : null;
if(!$post || !($post instanceof WP_Post)){
return new WP_Error('invalid_id');
}
if(!post_type_exists($post->post_type)){
return new WP_Error('invalid_post_type');
}
$post_type ??= static::get_current_post_type();
if($post_type && $post_type !== 'any' && !in_array($post->post_type, (array)$post_type)){
return new WP_Error('invalid_post_type');
}
return $post;
}
public static function validate_by_field($value, $field){
$post_type = is_numeric($value) ? get_post_type($value) : null;
if($post_type && (!$field->post_type || in_array($post_type, (array)$field->post_type))){
return (int)$value;
}
return new WP_Error('invalid_post_id', [$field->_title]);
}
public static function get($post){
$data = self::get_post($post, ARRAY_A);
if($data){
$data['id'] = $data['ID'];
if(is_serialized($data['post_content'])){
$data['post_content'] = unserialize($data['post_content']);
}
foreach($data as $key => $value){
if(str_starts_with($key, 'post_')){
$data[wpjam_remove_prefix($key, 'post_')] = $value;
}
}
}
return $data;
}
public static function insert($data){
try{
$data = static::prepare_data($data);
$meta = wpjam_pull($data, 'meta_input');
if(isset($data['post_type'])){
if(!post_type_exists($data['post_type'])){
wpjam_throw('invalid_post_type');
}
}else{
$data['post_type'] = static::get_current_post_type() ?: 'post';
}
if(empty($data['post_status'])){
$cap = get_post_type_object($data['post_type'])->cap->publish_posts;
$data['post_status'] = current_user_can($cap) ? 'publish' : 'draft';
}
$data = wp_parse_args($data, [
'post_author' => get_current_user_id(),
'post_date' => wpjam_date('Y-m-d H:i:s'),
]);
$post_id = wp_insert_post(wp_slash($data), true, true);
if($meta && !is_wp_error($post_id)){
wpjam_update_metadata('post', $post_id, $meta);
}
return $post_id;
}catch(Exception $e){
return wpjam_catch($e);
}
}
public static function update($post_id, $data, $validate=true){
try{
if($validate){
wpjam_throw_if_error(self::validate($post_id));
}
$data = static::prepare_data($data, $post_id);
$data = array_merge($data, ['ID'=>$post_id]);
$meta = wpjam_pull($data, 'meta_input');
$result = wp_update_post(wp_slash($data), true, true);
if($meta && !is_wp_error($result)){
wpjam_update_metadata('post', $post_id, $meta);
}
return $result;
}catch(Exception $e){
return wpjam_catch($e);
}
}
public static function delete($post_id, $force=true){
return wpjam_catch([self::class, 'before_delete'], $post_id) ?: (wp_delete_post($post_id, $force) ?: new WP_Error('delete_error', '删除失败'));
}
protected static function sanitize_data($data, $post_id=0){
foreach(['title', 'content', 'excerpt', 'name', 'status', 'author', 'parent', 'password', 'date', 'date_gmt', 'modified', 'modified_gmt'] as $key){
if(!isset($data['post_'.$key]) && isset($data[$key])){
$data['post_'.$key] = $data[$key];
}
}
if(isset($data['post_content']) && is_array($data['post_content'])){
$data['post_content'] = serialize($data['post_content']);
}
if($post_id){
$data['ID'] = $post_id;
if(isset($data['post_date']) && !isset($data['post_date_gmt'])){
$current_date_gmt = get_post($post_id)->post_date_gmt;
if($current_date_gmt && $current_date_gmt != '0000-00-00 00:00:00'){
$data['post_date_gmt'] = get_gmt_from_date($data['post_date']);
}
}
}
return $data;
}
public static function get_by_ids($post_ids){
return array_map('get_post', self::update_caches($post_ids));
}
public static function update_caches($post_ids, $update_term_cache=false, $update_meta_cache=false){
$post_ids = array_filter(wp_parse_id_list($post_ids));
if(!$post_ids){
return [];
}
_prime_post_caches($post_ids, $update_term_cache, $update_meta_cache);
$posts = array_filter(wp_cache_get_multiple($post_ids, 'posts'));
if(!$update_meta_cache){
wpjam_lazyload('post_meta', array_keys($posts));
}
do_action('wpjam_update_post_caches', $posts);
return $posts;
}
public static function get_post($post, $output=OBJECT, $filter='raw'){
if($post && is_numeric($post)){ // 不存在情况下的缓存优化
$found = false;
$cache = wp_cache_get($post, 'posts', false, $found);
if($found){
if(is_wp_error($cache)){
return $cache;
}elseif(!$cache){
return null;
}
}else{
$_post = WP_Post::get_instance($post);
if(!$_post){ // 防止重复 SQL 查询。
wp_cache_add($post, false, 'posts', 10);
return null;
}
}
}
return get_post($post, $output, $filter);
}
public static function get_current_post_type(){
$called = get_called_class();
$object = $called != 'WPJAM_Post' ? WPJAM_Post_Type::get($called, 'model', 'WPJAM_Post') : null;
return $object ? $object->name : null;
}
public static function get_path($args, $item=[]){
$id = is_array($args) ? (int)array_get($args, $item['post_type'].'_id') : $args;
if(!$id){
return new WP_Error('invalid_id', [wpjam_get_post_type_setting($item['post_type'], 'title')]);
}
return $item['platform'] == 'template' ? get_permalink($id) : str_replace('%post_id%', $id, $item['path']);
}
public static function get_path_fields($args){
$post_type = $args['post_type'];
$object = get_post_type_object($post_type);
return $object ? [$post_type.'_id' => wpjam_get_post_id_field(['post_type'=>$post_type, 'required'=>true])] : [];
}
public static function get_field($args){
$post_type = wpjam_pull($args, 'post_type');
$title = wpjam_pull($args, 'title');
if(is_null($title) && $post_type && is_string($post_type)){
$title = wpjam_get_post_type_setting($post_type, 'title');
}
return wp_parse_args($args, [
'title' => $title,
'type' => 'text',
'class' => 'all-options',
'data_type' => 'post_type',
'post_type' => $post_type,
'placeholder' => '请输入'.$title.'ID或者输入关键字筛选',
'show_in_rest' => ['type'=>'integer']
]);
}
public static function query_items($args){
if(wpjam_pull($args, 'data_type')){
return wpjam_get_posts(wp_parse_args($args, [
's' => $args['search'] ?? null,
'posts_per_page' => $args['number'] ?? 10,
'suppress_filters' => false,
]));
}
if(isset($args['number'])){
$args['posts_per_page'] = $args['number'];
}
$args['post_status'] = wpjam_pull($args, 'status') ?: 'any';
$args['post_type'] ??= static::get_current_post_type();
$wp_query = $GLOBALS['wp_query'];
$wp_query->query($args);
return [
'items' => $wp_query->posts,
'total' => $wp_query->found_posts
];
}
public static function query_calendar($args){
$args['monthnum'] = $args['month'];
$args['posts_per_page'] = -1;
$args['post_status'] = wpjam_pull($args, 'status') ?: 'any';
$args['post_type'] ??= static::get_current_post_type();
$wp_query = $GLOBALS['wp_query'];
$wp_query->query($args);
foreach($wp_query->posts as $post){
$date = explode(' ', $post->post_date)[0];
$items[$date][] = $post;
}
return $items ?? [];
}
public static function get_filterable_fields(){
return ['status'];
}
public static function get_views(){
$post_type = static::get_current_post_type();
if($post_type && get_current_screen()->base != 'edit'){
$counts = wp_count_posts($post_type);
$views = ['all'=>['filter'=>['status'=>null, 'show_sticky'=>null], 'label'=>'全部', 'count'=>array_sum((array)$counts)]];
foreach(get_post_stati(['show_in_admin_status_list'=>true], 'objects') as $status => $object){
if(!empty($counts->$status)){
$views[$status] = ['filter'=>['status'=>$status], 'label'=>$object->label, 'count'=>$counts->$status];
}
}
return $views;
}
}
public static function filter_fields($fields, $id){
if($id && !is_array($id) && !isset($fields['title']) && !isset($fields['post_title'])){
$field = ['title'=>wpjam_get_post_type_setting($id, 'title').'标题', 'type'=>'view', 'value'=>get_the_title($id)];
$fields = array_merge(['title'=>$field], $fields);
}
return $fields;
}
public static function get_meta($post_id, ...$args){
// _deprecated_function(__METHOD__, 'WPJAM Basic 6.0', 'wpjam_get_metadata');
return wpjam_get_metadata('post', $post_id, ...$args);
}
public static function update_meta($post_id, ...$args){
// _deprecated_function(__METHOD__, 'WPJAM Basic 6.0', 'wpjam_update_metadata');
return wpjam_update_metadata('post', $post_id, ...$args);
}
public static function update_metas($post_id, $data, $meta_keys=[]){
return static::update_meta($post_id, $data, $meta_keys);
}
}
/**
* @config menu_page, admin_load, register_json, init
**/
#[config('menu_page', 'admin_load', 'register_json', 'init')]
class WPJAM_Post_Type extends WPJAM_Register{
public function __get($key){
if($key == 'title'){
return $this->labels ? $this->labels->singular_name : $this->label;
}elseif($key != 'name' && property_exists('WP_Post_Type', $key)){
$object = get_post_type_object($this->name);
if($object){
return $object->$key;
}
}
$value = parent::__get($key);
if($key == 'model'){
if(!$value || !class_exists($value) || !is_subclass_of($value, 'WPJAM_Post')){
return 'WPJAM_Post';
}
}elseif($key == 'permastruct'){
$value ??= $this->call_model('get_'.$key);
$value = $value ? trim($value, '/') : $value;
}
return $value;
}
public function __set($key, $value){
if($key != 'name' && property_exists('WP_Post_Type', $key)){
$object = get_post_type_object($this->name);
if($object){
$object->$key = $value;
}
}
parent::__set($key, $value);
}
protected function preprocess_args($args){
$args = parent::preprocess_args($args);
$args = wp_parse_args($args, ['plural'=>$this->name.'s', '_jam'=>true]);
if($args['_jam']){
if(!is_array(array_get($args, 'taxonomies'))){
unset($args['taxonomies']);
}
return wp_parse_args($args, [
'public' => true,
'show_ui' => true,
'hierarchical' => false,
'rewrite' => true,
'permastruct' => false,
'supports' => ['title'],
]);
}
return $args;
}
public function get_menu_slug(){
if(is_null($this->menu_slug)){
$menu_page = $this->get_arg('menu_page');
if($menu_page && is_array($menu_page)){
$this->menu_slug = wp_is_numeric_array($menu_page) ? rest($menu_page)['menu_slug'] : $menu_page['menu_slug'];
}
}
return $this->menu_slug;
}
public function to_array(){
$this->filter_args();
if(doing_filter('register_post_type_args')){
if(!$this->_builtin && $this->permastruct){
$this->permastruct = str_replace(
['%post_id%', '%postname%'],
['%'.$this->name.'_id%', '%'.$this->name.'%'],
$this->permastruct
);
if(strpos($this->permastruct, '%'.$this->name.'_id%')){
if($this->hierarchical){
$this->permastruct = false;
}else{
$this->query_var ??= false;
}
}
if($this->permastruct){
$this->rewrite = $this->rewrite ?: true;
}
}
if($this->_jam){
if($this->hierarchical){
$this->supports = [...$this->supports, 'page-attributes'];
}
if($this->rewrite){
$this->rewrite = is_array($this->rewrite) ? $this->rewrite : [];
$this->rewrite = wp_parse_args($this->rewrite, ['with_front'=>false, 'feeds'=>false]);
}
}
if($this->menu_icon){
$this->menu_icon = wpjam_fix('add', 'prev', $this->menu_icon, 'dashicons-');
}
}
return $this->args;
}
public function get_fields($id=0, $action_key=''){
if(in_array($action_key, ['add', 'set'])){
if($action_key == 'add'){
$fields['post_type'] = ['type'=>'hidden', 'value'=>$this->name];
$fields['post_status'] = ['type'=>'hidden', 'value'=>'draft'];
}
$fields['post_title'] = ['title'=>'标题', 'type'=>'text', 'required'];
if($this->supports('excerpt')){
$fields['post_excerpt'] = ['title'=>'摘要', 'type'=>'textarea', 'class'=>'', 'rows'=>3];
}
if($this->supports('thumbnail')){
$fields['_thumbnail_id'] = ['title'=>'头图', 'type'=>'img', 'size'=>'600x0', 'name'=>'meta_input[_thumbnail_id]'];
}
}
if($this->supports('images')){
$size = $this->images_sizes ? $this->images_sizes[0] : '';
$fields['images'] = [
'title' => '头图',
'name' => 'meta_input[images]',
'type' => 'mu-img',
'item_type' => 'url',
'show_in_rest' => false,
'size' => $size,
'max_items' => $this->images_max_items
];
}
if($this->supports('video')){
$fields['video'] = ['title'=>'视频', 'type'=>'url', 'name'=>'meta_input[video]'];
}
foreach($this->get_items('_fields') as $key => $field){
if(in_array($action_key, ['add', 'set']) && empty($field['name']) && !property_exists('WP_Post', $key)){
$field['name'] = 'meta_input['.$key.']';
}
$fields[$key] = $field;
}
return $fields ?? [];
}
public function register_option($list_table=false){
if(!wpjam_get_post_option($this->name.'_base')){
$fields = $list_table ? [$this, 'get_fields'] : $this->get_fields();
if($fields){
wpjam_register_post_option($this->name.'_base', [
'post_type' => $this->name,
'title' => '基础信息',
'page_title' => '设置'.$this->title,
'fields' => $fields,
'list_table' => $this->show_ui,
'action_name' => 'set',
'row_action' => false,
'order' => 99,
]);
}
}
}
public function get_support($feature){
$support = get_all_post_type_supports($this->name)[$feature] ?? false;
if($support && is_array($support) && wp_is_numeric_array($support) && count($support) == 1){
return reset($support);
}
return $support;
}
public function supports($feature){
return post_type_supports($this->name, $feature);
}
public function get_size($type='thumbnail', $orientation=null){
return $this->{$type.'_size'} ?: $type;
}
public function get_taxonomies(...$args){
$taxonomies = get_object_taxonomies($this->name);
$output = 'objects';
$filters = [];
if($args){
if(is_array($args[0])){
$output = $args[1] ?? 'objects';
$filters = $args[0];
}else{
$output = $args[0];
}
}
if($filters || $output == 'objects'){
$objects = array_filter(wpjam_fill($taxonomies, 'wpjam_get_taxonomy_object'));
if($filters){
$objects = wp_filter_object_list($objects, $filters);
}
return $output == 'objects' ? $objects : array_keys($objects);
}
return $taxonomies;
}
public function in_taxonomy($taxonomy){
return is_object_in_taxonomy($this->name, $taxonomy);
}
public function is_viewable(){
return is_post_type_viewable($this->name);
}
public function reset_invalid_parent($value=0){
$wpdb = $GLOBALS['wpdb'];
$post_ids = $wpdb->get_col($wpdb->prepare("SELECT p1.ID FROM {$wpdb->posts} p1 LEFT JOIN {$wpdb->posts} p2 ON p1.post_parent = p2.ID WHERE p1.post_type=%s AND p1.post_parent > 0 AND p2.ID is null", $this->name)) ?: [];
array_walk($post_ids, fn($id)=> wp_update_post(['ID'=>$id, 'post_parent'=>$value]));
return count($post_ids);
}
public function filter_labels($labels){
$labels = (array)$labels;
$name = $labels['name'];
$search = $this->hierarchical ? ['撰写新', '写文章', '页面', 'page', 'Page'] : ['撰写新', '写文章', '文章', 'post', 'Post'];
$replace = ['添加', '添加'.$name, $name, $name, ucfirst($name)];
foreach($labels as $key => &$label){
if($key == 'all_items'){
$label = '所有'.$name;
}elseif($key == 'archives'){
$label = $name.'归档';
}elseif($label && $label != $name){
$label = str_replace($search, $replace, $label);
}
}
return array_merge($labels, (array)($this->labels ?? []));
}
public function filter_link($link, $post){
return get_post_type($post) == $this->name ? str_replace('%'.$this->name.'_id%', $post->ID, $link) : $link;
}
public function registered_callback($name, $object){
if($this->name == $name){
if($this->permastruct){
if(strpos($this->permastruct, '%'.$name.'_id%')){
add_rewrite_tag('%'.$name.'_id%', '([0-9]+)', 'post_type='.$name.'&p=');
remove_rewrite_tag('%'.$name.'%');
add_filter('post_type_link', [$this, 'filter_link'], 1, 2);
}
add_permastruct($name, $this->permastruct, array_merge($object->rewrite, ['feed'=>$this->rewrite['feeds']]));
}
$callback = $this->registered_callback;
if($callback && is_callable($callback)){
$callback($name, $object);
}
}
}
public function registered(){
if($this->_jam){
if(is_admin() && $this->show_ui){
add_filter('post_type_labels_'.$this->name, [$this, 'filter_labels']);
}
add_action('registered_post_type_'.$this->name, [$this, 'registered_callback'], 10, 2);
wpjam_load('init', fn()=> register_post_type($this->name, $this->to_array()));
if($this->options){
wpjam_map($this->options, fn($option, $name)=> wpjam_register_post_option($name, $option+['post_type'=>$this->name]));
}
}
}
public static function filter_register_args($args, $name){
if(did_action('init') || empty($args['_builtin'])){
$object = self::get($name);
$object = $object ? $object->update_args($args) : self::register($name, array_merge($args, ['_jam'=>false]));
return $object->to_array();
}
return $args;
}
}
class WPJAM_Posts{
public static function query($query, &$args=[]){
return new WP_Query(wp_parse_args(self::parse_query_vars($query, $args), [
'no_found_rows' => true,
'ignore_sticky_posts' => true,
]));
}
public static function parse($query, $args=[], $format=''){
$filter = wpjam_pull($args, 'filter');
$query = is_object($query) ? $query : self::query($query, $args);
if(!$filter && $query->get('related_query')){
$filter = 'wpjam_related_post_json';
}
if($format == 'date'){
$day = wpjam_pull($args, 'day');
}
while($query->have_posts()){
$query->the_post();
$id = get_the_ID();
$json = wpjam_get_post($id, $args);
if($json){
$json = $filter ? apply_filters($filter, $json, $id, $args) : $json;
if($format == 'date'){
$date = explode(' ', $json['date'])[0];
$number = (int)(explode('-', $date)[2]);
if($day && $number != $day){
continue;
}
$parsed[$date] ??= [];
$parsed[$date][] = $json;
}else{
$parsed[] = $json;
}
}
}
if(!empty($args['list_query'])){
wp_reset_postdata();
}
return $parsed ?? [];
}
public static function render($query, $args=[]){
$output = '';
$query = is_object($query) ? $query : self::query($query, $args);
if($query){
$callback = [];
foreach(['item_callback', 'wrap_callback'] as $name){
$value = wpjam_pull($args, $name);
$callback[$name] = ($value && is_callable($value)) ? $value : [self::class, $name];
}
$title_number = wpjam_pull($args, 'title_number');
$total_number = count($query->posts);
while($query->have_posts()){
$query->the_post();
if($title_number){
$args['title_number'] = zeroise($query->current_post+1, strlen($total_number));
}
$output .= $callback['item_callback'](get_the_ID(), $args);
}
wp_reset_postdata();
$output = $callback['wrap_callback']($output, $args);
}
return $output;
}
public static function item_callback($post_id, $args){
$args = wp_parse_args($args, [
'title_number' => 0,
'excerpt' => false,
'thumb' => true,
'size' => 'thumbnail',
'thumb_class' => 'wp-post-image',
'wrap_tag' => 'li'
]);
$title = get_the_title($post_id);
$item = wpjam_wrap($title);
if($args['title_number']){
$item->before('span', ['title-number'], $args['title_number'].'. ');
}
if($args['thumb'] || $args['excerpt']){
$item->wrap('h4');
if($args['thumb']){
$item->before(get_the_post_thumbnail($post_id, $args['size'], ['class'=>$args['thumb_class']]));
}
if($args['excerpt']){
$item->after(wpautop(get_the_excerpt($post_id)));
}
}
$item->wrap('a', ['href'=>get_permalink($post_id), 'title'=>strip_tags($title)], $item);
if($args['wrap_tag']){
$item->wrap($args['wrap_tag']);
}
return $item->render();
}
public static function wrap_callback($output, $args){
if(!$output){
return '';
}
$args = wp_parse_args($args, [
'title' => '',
'div_id' => '',
'class' => [],
'thumb' => true,
'wrap_tag' => 'ul'
]);
$output = wpjam_wrap($output);
if($args['wrap_tag']){
$args['class'] = (array)$args['class'];
if($args['thumb']){
$args['class'][] = 'has-thumb';
}
$output->wrap($args['wrap_tag'], $args['class']);
}
if($args['title']){
$output->before('h3', [], $args['title']);
}
if($args['div_id']){
$output->wrap('div', ['id'=>$args['div_id']], $output);
}
return $output->render();
}
public static function parse_query_vars($query_vars, &$args=[]){
$tax_query = $query_vars['tax_query'] ?? [];
$date_query = $query_vars['date_query'] ?? [];
$parser = fn($taxonomy, $term_id)=> array_merge(['taxonomy'=>$taxonomy, 'field'=>'term_id'], ($term_id == 'none' ? ['operator'=>'NOT EXISTS'] : ['terms'=>[$term_id]]));
$taxonomies = array_values(get_taxonomies(['_builtin'=>false]));
foreach(array_merge($taxonomies, ['category', 'post_tag']) as $taxonomy){
$query_key = wpjam_get_taxonomy_query_key($taxonomy);
$term_id = wpjam_pull($query_vars, $query_key);
if($term_id){
if($taxonomy == 'category' && $term_id != 'none'){
$query_vars[$query_key] = $term_id;
}else{
$tax_query[] = $parser($taxonomy, $term_id);
}
}
}
if(!empty($query_vars['taxonomy']) && empty($query_vars['term'])){
$term_id = wpjam_pull($query_vars, 'term_id');
if($term_id){
if(is_numeric($term_id)){
$taxonomy = wpjam_pull($query_vars, 'taxonomy');
$tax_query[] = $parser($taxonomy, $term_id);
}else{
$query_vars['term'] = $term_id;
}
}
}
foreach(['cursor'=>'before', 'since'=>'after'] as $key => $query_key){
$value = wpjam_pull($query_vars, $key);
if($value){
$date_query[] = [$query_key => wpjam_date('Y-m-d H:i:s', $value)];
}
}
if($args){
$post_type = wpjam_pull($args, 'post_type');
$orderby = wpjam_pull($args, 'orderby');
$number = wpjam_pull($args, 'number');
$days = wpjam_pull($args, 'days');
if($post_type){
$query_vars['post_type'] = $post_type;
}
if($orderby){
$query_vars['orderby'] = $orderby;
}
if($number){
$query_vars['posts_per_page'] = $number;
}
if($days){
$after = wpjam_date('Y-m-d', time() - DAY_IN_SECONDS * $days).' 00:00:00';
$column = wpjam_pull($args, 'column') ?: 'post_date_gmt';
$date_query[] = ['column'=>$column, 'after'=>$after];
}
}
if($tax_query){
$query_vars['tax_query'] = $tax_query;
}
if($date_query){
$query_vars['date_query'] = $date_query;
}
return $query_vars;
}
public static function get_related_query($post, $args=[]){
$post = get_post($post);
if($post){
$post_id = $post->ID;
$post_type = [get_post_type($post)];
$tt_ids = [];
foreach(get_object_taxonomies($post) as $taxonomy){
$terms = $taxonomy == 'post_format' ? [] : get_the_terms($post_id, $taxonomy);
if($terms){
$post_type = array_merge($post_type, get_taxonomy($taxonomy)->object_type);
$tt_ids = array_merge($tt_ids, array_column($terms, 'term_taxonomy_id'));
}
}
if($tt_ids){
return self::query([
'related_query' => true,
'post_status' => 'publish',
'post__not_in' => [$post_id],
'post_type' => array_unique($post_type),
'term_taxonomy_ids' => array_unique(array_filter($tt_ids)),
], $args);
}
}
return false;
}
public static function get_related_object_ids($tt_ids, $number, $page=1){
$tt_ids = implode(',', array_map('intval', $tt_ids));
$key = 'related_object_ids:'.$tt_ids.':'.$page.':'.$number;
$sql = 'SELECT object_id, count(object_id) as cnt FROM '.$GLOBALS['wpdb']->term_relationships.' WHERE term_taxonomy_id IN ('.$tt_ids.') GROUP BY object_id ORDER BY cnt DESC, object_id DESC LIMIT '.(($page-1)*$number).', '.$number;
return wpjam_transient($key, fn()=> $GLOBALS['wpdb']->get_col($sql), DAY_IN_SECONDS);
}
public static function parse_json_module($args){
$action = wpjam_pull($args, 'action');
if(!$action){
return;
}
$wp = $GLOBALS['wp'];
if(isset($wp->raw_query_vars)){
$wp->query_vars = $wp->raw_query_vars;
}else{
$wp->raw_query_vars = $wp->query_vars;
}
if($action == 'list'){
return self::parse_list_json_module($args);
}elseif($action == 'calendar'){
return self::parse_calendar_json_module($args);
}elseif($action == 'get'){
return self::parse_get_json_module($args);
}elseif($action == 'upload'){
return self::parse_media_json_module($args, 'post_type');
}
}
protected static function parse_json_query_vars($query_vars){
$post_type = $query_vars['post_type'] ?? '';
if(is_string($post_type) && strpos($post_type, ',') !== false){
$query_vars['post_type'] = wp_parse_list($post_type);
}
$taxonomies = $post_type ? get_object_taxonomies($post_type) : get_taxonomies(['public'=>true]);
$taxonomies = array_diff($taxonomies, ['post_format']);
foreach($taxonomies as $taxonomy){ // taxonomy 参数处理,同时支持 $_GET 和 $query_vars 参数
if($taxonomy == 'category'){
if(empty($query_vars['cat'])){
foreach(['category_id', 'cat_id'] as $cat_key){
$term_id = (int)wpjam_get_parameter($cat_key);
if($term_id){
$query_vars['cat'] = $term_id;
break;
}
}
}
}else{
$query_key = wpjam_get_taxonomy_query_key($taxonomy);
$term_id = (int)wpjam_get_parameter($query_key);
if($term_id){
$query_vars[$query_key] = $term_id;
}
}
}
$term_id = (int)wpjam_get_parameter('term_id');
$taxonomy = wpjam_get_parameter('taxonomy');
if($term_id && $taxonomy){
$query_vars['term_id'] = $term_id;
$query_vars['taxonomy'] = $taxonomy;
}
return self::parse_query_vars($query_vars);
}
protected static function parse_json_output($query_vars){
$post_type = $query_vars['post_type'] ?? '';
if($post_type && is_string($post_type)){
return wpjam_get_post_type_setting($post_type, 'plural') ?: $post_type.'s';
}
return 'posts';
}
/* 规则:
** 1. 分成主的查询和子查询($query_args['sub']=1)
** 2. 主查询支持 $_GET 参数 和 $_GET 参数 mapping
** 3. 子查询(sub)只支持 $query_args 参数
** 4. 主查询返回 next_cursor 和 total_pages,current_page,子查询(sub)没有
** 5. $_GET 参数只适用于 post.list
** 6. term.list 只能用 $_GET 参数 mapping 来传递参数
*/
public static function parse_list_json_module($args){
$output = wpjam_pull($args, 'output');
$sub = wpjam_pull($args, 'sub');
$is_main_query = !$sub; // 子查询不支持 $_GET 参数,置空之前要把原始的查询参数存起来
if($is_main_query){
$wp = $GLOBALS['wp'];
$wp_query = $GLOBALS['wp_query'];
$query_vars = array_merge($wp->query_vars, $args);
$number = (int)wpjam_get_parameter('number', ['fallback'=>'posts_per_page']);
$offset = (int)wpjam_get_parameter('offset');
if($number && $number != -1){
$query_vars['posts_per_page'] = $number > 100 ? 100 : $number;
}
if($offset){
$query_vars['offset'] = $offset;
}
$post__in = wpjam_get_parameter('post__in');
$post__in = $post__in ? wp_parse_id_list($post__in) : [];
if($post__in){
$query_vars['post__in'] = $post__in;
if(!isset($query_vars['orderby'])){
$query_vars['orderby'] = 'post__in';
}
if(!isset($query_vars['posts_per_page'])){
$query_vars['posts_per_page'] = -1;
}
}
$orderby = $query_vars['orderby'] ?? 'date';
$use_cursor = empty($query_vars['paged']) && empty($query_vars['s']) && !is_array($orderby) && in_array($orderby, ['date', 'post_date']);
if($use_cursor){
foreach(['cursor', 'since'] as $key){
$query_vars[$key] = (int)wpjam_get_parameter($key);
if($query_vars[$key]){
$query_vars['ignore_sticky_posts'] = true;
}
}
}
$query_vars = $wp->query_vars = self::parse_json_query_vars($query_vars);
$wp->query_posts();
}else{
$wp_query = self::query($args);
}
$posts_json = [];
$parsed = self::parse($wp_query, $args);
if($is_main_query){
if(is_front_page()){
$posts_json['is'] = 'home';
}elseif(is_author()){
$posts_json['is'] = 'author';
$posts_json['current_author'] = wpjam_get_user($wp_query->get('author'));
}elseif(is_category() || is_tag() || is_tax()){
$posts_json['is'] = is_category() ? 'category' : (is_tag() ? 'tag' : 'tax');
$term = $wp_query->get_queried_object();
if($term){
$posts_json['current_taxonomy'] = $term->taxonomy;
$posts_json['current_term'] = wpjam_get_term($term, $term->taxonomy);
}else{
$posts_json['current_taxonomy'] = null;
}
}elseif(is_post_type_archive()){
$posts_json['is'] = 'post_type_archive';
$pt_object = $wp_query->get_queried_object();
$posts_json['current_post_type'] = $pt_object ? $pt_object->name : null;
}elseif(is_search()){
$posts_json['is'] = 'search';
}elseif(is_archive()){
$posts_json['is'] = 'archive';
}
$nopaging = $wp_query->get('nopaging');
$total = $wp_query->found_posts;
$posts_json['total'] = $total;
if($nopaging){
$posts_json['total_pages'] = $total ? 1 : 0;
$posts_json['current_page'] = 1;
}else{
$posts_json['total_pages'] = $wp_query->max_num_pages;
$posts_json['current_page'] = $wp_query->get('paged') ?: 1;
}
if($use_cursor){
$posts_json['next_cursor'] = ($parsed && $wp_query->max_num_pages > 1) ? end($parsed)['timestamp'] : 0;
}
$output = $output ?: self::parse_json_output($query_vars);
}else{
$output = $output ?: 'posts';
}
$posts_json[$output] = $parsed;
return apply_filters('wpjam_posts_json', $posts_json, $wp_query, $output);
}
public static function parse_calendar_json_module($args){
$wp = $GLOBALS['wp'];
$wp_query = $GLOBALS['wp_query'];
$output = wpjam_pull($args, 'output');
$query_vars = array_merge($wp->query_vars, $args);
$query_vars['year'] = (int)wpjam_get_parameter('year') ?: wpjam_date('Y');
$query_vars['monthnum'] = (int)wpjam_get_parameter('month') ?: wpjam_date('m');
$args['day'] = (int)wpjam_get_parameter('day');
$wp->query_vars = $query_vars = self::parse_json_query_vars(wpjam_except($query_vars, 'day'));
$wp->query_posts();
$parsed = self::parse($wp_query, $args, 'date');
$output = $output ?: self::parse_json_output($query_vars);
return [$output=>$parsed];
}
public static function parse_get_json_module($args){
$wp = $GLOBALS['wp'];
$wp_query = $GLOBALS['wp_query'];
$wp->set_query_var('cache_results', true);
if(!empty($args['post_status'])){
$wp->set_query_var('post_status', $args['post_status']);
}
$query_vars = $wp->query_vars;
$post_type = array_get($args, 'post_type');
$post_type = $post_type == 'any' ? '' : $post_type;
if(!$post_type){
$ptypes = get_post_types(['_builtin'=>false, 'query_var'=>true], 'objects');
foreach(wp_list_pluck($ptypes, 'query_var')+['post'=>'name', 'page'=>'pagename'] as $ptype => $key){
if(!empty($query_vars[$key])){
$name = $query_vars[$key];
$post_type = $ptype;
break;
}
}
}
if(empty($name)){
if($post_type){
$key = is_post_type_hierarchical($post_type) ? 'pagename' : 'name';
$required = empty($query_vars[$key]);
}else{
$required = true;
}
$post_id = array_get($args, 'id') ?: (int)wpjam_get_parameter('id', ['required'=>$required]);
$post_type = $post_type ?: get_post_type($post_id);
if(!post_type_exists($post_type)){
wp_die('invalid_post_type');
}
if(!$post_type || ($post_id && get_post_type($post_id) != $post_type)){
wp_die('无效的参数:id', 'invalid_parameter');
}
$wp->set_query_var('post_type', $post_type);
if($post_id){
$wp->set_query_var('p', $post_id);
}
}
$wp->query_posts();
if(empty($post_id) && empty($args['post_status']) && !$wp_query->have_posts()){
$post_id = apply_filters('old_slug_redirect_post_id', null);
if(!$post_id){
wp_die('无效的文章 ID', 'invalid_post');
}
$wp->set_query_var('post_type', 'any');
$wp->set_query_var('p', $post_id);
$wp->set_query_var('name', '');
$wp->set_query_var('pagename', '');
$wp->query_posts();
}
$parsed = $wp_query->have_posts() ? self::parse($wp_query, $args) : [];
if(!$parsed){
wp_die('参数错误', 'invalid_parameter');
}
$parsed = current($parsed);
$output = array_get($args, 'output') ?: $parsed['post_type'];
$response = wpjam_pull($parsed, ['share_title', 'share_image', 'share_data']);
if(is_single($parsed['id']) || is_page($parsed['id'])){
wpjam_update_post_views($parsed['id']);
}
return array_merge($response, [$output => $parsed]);
}
public static function parse_media_json_module($args, $type=''){
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$media = array_get($args, 'media') ?: 'media';
$output = array_get($args, 'output') ?: 'url';
if(!isset($_FILES[$media])){
wp_die('无效的参数:media', 'invalid_parameter');
}
if($type == 'post_type'){
$pid = (int)wpjam_get_post_parameter('post_id', ['default'=>0]);
$id = wpjam_try('media_handle_upload', $media, $pid);
$url = wp_get_attachment_url($id);
$query = wpjam_get_image_size($id);
}else{
$upload = wpjam_try('wpjam_upload', $media);
$url = $upload['url'];
$query = wpjam_get_image_size($upload['file'], 'file');
}
if($query){
$url = add_query_arg($query, $url);
}
return $output ? [$output => $url] : $url;
}
public static function json_modules_callback($type='list', $args=[]){
if(strpos($type, '.')){
$parts = explode('.', $type);
$type = end($parts);
}
$post_type = wpjam_get_parameter('post_type');
$args = wp_parse_args($args, ['post_type'=>$post_type, 'action'=>$type, 'output'=>($type == 'get' ? 'post' : 'posts')]);
$modules[] = ['type'=>'post_type', 'args'=>array_filter($args)];
if($type == 'list'){
if($post_type && is_string($post_type)){
foreach(get_object_taxonomies($post_type, 'objects') as $taxonomy => $tax_object){
if($tax_object->hierarchical && $tax_object->public){
$modules[] = ['type'=>'taxonomy', 'args'=>['taxonomy'=>$taxonomy, 'hide_empty'=>0]];
}
}
}
}
return $modules;
}
public static function filter_clauses($clauses, $wp_query){
global $wpdb;
if($wp_query->get('related_query')){
$tt_ids = $wp_query->get('term_taxonomy_ids');
if($tt_ids){
$clauses['join'] .= "INNER JOIN {$wpdb->term_relationships} AS tr ON {$wpdb->posts}.ID = tr.object_id";
$clauses['where'] .= " AND tr.term_taxonomy_id IN (".implode(",",$tt_ids).")";
$clauses['groupby'] .= " tr.object_id";
$clauses['orderby'] = " count(tr.object_id) DESC, {$wpdb->posts}.ID DESC";
}
}else{
$orderby = $wp_query->get('orderby');
$order = $wp_query->get('order') ?: 'DESC';
if($orderby == 'comment_date'){
$comment_type = $wp_query->get('comment_type') ?: 'comment';
$type_str = $comment_type == 'comment' ? "'comment', ''" : "'".esc_sql($comment_type)."'";
$ct_where = "ct.comment_type IN ({$type_str}) AND ct.comment_parent=0 AND ct.comment_approved NOT IN ('spam', 'trash', 'post-trashed')";
$clauses['join'] = "INNER JOIN {$wpdb->comments} AS ct ON {$wpdb->posts}.ID = ct.comment_post_ID AND {$ct_where}";
$clauses['groupby'] = "ct.comment_post_ID";
$clauses['orderby'] = "MAX(ct.comment_ID) {$order}";
}elseif($orderby == 'views' || $orderby == 'comment_type'){
$meta_key = $orderby == 'comment_type' ? $wp_query->get('comment_count') : 'views';
$clauses['join'] .= "LEFT JOIN {$wpdb->postmeta} jam_pm ON {$wpdb->posts}.ID = jam_pm.post_id AND jam_pm.meta_key = '{$meta_key}' ";
$clauses['orderby'] = "(COALESCE(jam_pm.meta_value, 0)+0) {$order}, " . $clauses['orderby'];
}elseif(in_array($orderby, ['', 'date', 'post_date'])){
$clauses['orderby'] .= ", {$wpdb->posts}.ID {$order}";
}
}
return $clauses;
}
public static function filter_content_save_pre($content){
if($content && is_serialized($content)){
$name = current_filter();
$callback = 'wp_filter_post_kses';
if(has_filter($name, $callback)){
remove_filter($name, $callback);
add_filter($name, fn($content)=> $content && is_serialized($content) ? $content : $callback($content));
}
}
return $content;
}
}