File: /www/wwwroot/softfox.com.cn/wp-content/plugins/wpjam-basic/public/wpjam-admin.php
<?php
if(!function_exists('get_screen_option')){
function get_screen_option($option, $key=false){
$screen = get_current_screen();
if($screen){
if(in_array($option, ['post_type', 'taxonomy'])){
return $screen->$option ?? null;
}
$value = $screen->get_option($option);
if($key){
if(is_array($value)){
return $value[$key] ?? null;
}elseif(is_object($value)){
return $value->$key ?? null;
}
}else{
return $value;
}
}
}
}
function wpjam_add_screen_item($option, ...$args){
$screen = get_current_screen();
if($screen){
$items = $screen->get_option($option) ?: [];
if(count($args) >= 2){
$key = $args[0];
if(isset($items[$key])){
return;
}
$items[$key] = $args[1];
}else{
$items[] = $args[0];
}
$screen->add_option($option, $items);
}
}
function wpjam_add_admin_menu($args=[]){
if(!empty($args['menu_slug']) && !empty($args['menu_title'])){
$object = wpjam_get_items_object('menu_page');
$name = array_pull($args, 'menu_slug');
$parent = array_pull($args, 'parent');
$args = $parent ? ['subs' => [$name => $args]] : wp_parse_args($args, ['subs'=>[]]);
$key = $parent ?: $name;
$item = $object->get_item($key);
if($item){
$subs = array_merge($item['subs'], $args['subs']);
$args = array_merge($item, $args, ['subs'=>$subs]);
}
$object->set_item($key, $args);
}
}
function wpjam_add_admin_load($args){
$loads = wp_is_numeric_array($args) ? $args : [$args];
foreach($loads as $load){
$type = array_get($load, 'type');
if(!$type){
if(isset($load['base'])){
$type = 'builtin_page';
}elseif(isset($load['plugin_page'])){
$type = 'plugin_page';
}
}
if($type && in_array($type, ['builtin_page', 'plugin_page'])){
wpjam_add_item('admin_load', array_merge($load, ['type'=>$type]));
}
}
}
function wpjam_add_admin_ajax($name, $callback){
wpjam_add_item('admin_ajax', $name, $callback);
add_action('wp_ajax_'.$name, 'wpjam_admin_ajax');
}
function wpjam_add_admin_error($message='', $type='success'){
if(is_wp_error($message)){
$message = $message->get_error_message();
$type = 'error';
}
if($message && $type){
wpjam_add_screen_item('admin_errors', ['message'=>$message, 'type'=>$type]);
}
}
function wpjam_admin_menu(){
if(is_network_admin()){
$builtins = [
'settings' => 'settings.php',
'theme' => 'themes.php',
'themes' => 'themes.php',
'plugins' => 'plugins.php',
'users' => 'users.php',
'sites' => 'sites.php',
];
}elseif(is_user_admin()){
$builtins = [
'dashboard' => 'index.php',
'users' => 'profile.php',
];
}else{
$builtins = [
'dashboard' => 'index.php',
'management'=> 'tools.php',
'options' => 'options-general.php',
'theme' => 'themes.php',
'themes' => 'themes.php',
'plugins' => 'plugins.php',
'posts' => 'edit.php',
'media' => 'upload.php',
'links' => 'link-manager.php',
'pages' => 'edit.php?post_type=page',
'comments' => 'edit-comments.php',
'users' => current_user_can('edit_users') ? 'users.php' : 'profile.php',
];
foreach(get_post_types(['_builtin'=>false, 'show_in_menu'=>true]) as $ptype) {
$builtins[$ptype.'s'] = 'edit.php?post_type='.$ptype;
}
}
$rendering = doing_action(wpjam_get_admin_prefix().'admin_menu');
if($rendering){
do_action('wpjam_admin_init');
}
$menus = apply_filters('wpjam_'.wpjam_get_admin_prefix().'pages', wpjam_get_items('menu_page'));
$object = new WPJAM_Args();
foreach($menus as $slug => $args){
$menu = $object->set_args($args);
$parent = $builtins[$slug] ?? '';
if(!$parent){
$slug = $menu->menu_slug = $menu->menu_slug ?? $slug;
$parent = $slug;
if($rendering || $GLOBALS['plugin_page'] == $slug){
$menu = wpjam_parse_admin_menu($menu, '', $rendering);
if(!$rendering){
if(!$menu || !$menu->subs){
break;
}
}
}
}
$subs = $menu ? $menu->subs : [];
if($subs){
uasort($subs, function ($sub1, $sub2){
$pos1 = $sub1['position'] ?? 10;
$pos2 = $sub2['position'] ?? 10;
if($pos1 == $pos2){
$order1 = $sub1['order'] ?? 10;
$order2 = $sub2['order'] ?? 10;
return $order2 <=> $order1;
}else{
return $pos1 <=> $pos2;
}
});
if($parent == $slug){
$sub = $subs[$slug] ?? null;
if(!$sub){
$sub = array_except($args, ['position', 'subs', 'page_title']);
if(!empty($sub['sub_title'])){
$sub['menu_title'] = $sub['sub_title'];
}
}
$subs = array_merge([$slug=>$sub], $subs);
}
foreach($subs as $sub_slug => $sub_args){
$sub_args['menu_slug'] = $sub_args['menu_slug'] ?? $sub_slug;
if($rendering || $GLOBALS['plugin_page'] == $sub_args['menu_slug']){
$sub_menu = $object->set_args($sub_args);
$sub_menu = wpjam_parse_admin_menu($sub_menu, $parent, $rendering);
if(!$rendering){
break 2;
}
}
}
}
}
}
function wpjam_parse_admin_menu($menu, $parent='', $rendering){
if(is_numeric($menu->menu_slug) || !$menu->menu_title){
return;
}
$admin_page = ($parent && strpos($parent, '.php')) ? $parent : 'admin.php';
$network = $menu->pull('network', ($admin_page == 'admin.php'));
$slug = $menu->menu_slug;
if(($network === 'only' && !is_network_admin()) || (!$network && is_network_admin())){
return;
}
$menu->page_title = $menu->page_title ?? $menu->menu_title;
$menu->capability = $menu->capability ?? 'manage_options';
if($menu->map_meta_cap && is_callable($menu->map_meta_cap)){
wpjam_register_capability($menu->capability, $menu->map_meta_cap);
}
if(!str_contains($slug, '.php')){
$menu->admin_url = $admin_url = add_query_arg(['page'=>$slug], $admin_page);
if($menu->query_args){
$query_data = wpjam_generate_query_data($menu->query_args);
$null_queries = array_filter($query_data, 'is_null');
if($null_queries){
if($GLOBALS['plugin_page'] == $slug){
wp_die('「'.implode('」,「', array_keys($null_queries)).'」参数无法获取');
}
return;
}
$menu->query_data = $query_data;
$menu->admin_url = $queried_url = add_query_arg($query_data, $admin_url);
wpjam_add_item('queried_menu', ['search'=>"href='".esc_url($admin_url)."'", 'replace'=>"href='".$queried_url."'"]);
}
}
if($GLOBALS['plugin_page'] == $slug && ($parent || (!$parent && !$menu->subs))){
$GLOBALS['current_admin_url'] = wpjam_admin_url($menu->admin_url);
$object = wpjam_add_plugin_page($menu->get_args());
}else{
$object = null;
}
if($rendering){
if(str_contains($slug, '.php')){
if($GLOBALS['pagenow'] == explode('?', $slug)[0]){
wpjam_add_item('parent_files', $slug, ($parent ?: $slug));
}
$callback = null;
}else{
$callback = $object ? [$object, 'render'] : '__return_true';
}
$args = [$menu->page_title, $menu->menu_title, $menu->capability, $slug, $callback, $menu->position];
if($parent){
$hook = add_submenu_page($parent, ...$args);
}else{
array_splice($args, 5, 0, (string)$menu->icon);
$hook = add_menu_page(...$args);
}
if($object){
$object->page_hook = $hook;
}
}
return $menu;
}
function wpjam_admin_init($plugin_page=null){
if(!$plugin_page){
$plugin_page = $_POST['plugin_page'] ?? null;
}
$GLOBALS['plugin_page'] = $plugin_page;
do_action('wpjam_admin_init');
if($plugin_page){
wpjam_admin_menu();
}
$screen_id = wpjam_get_current_screen_id();
if($screen_id == 'upload'){
$GLOBALS['hook_suffix'] = $screen_id;
$screen_id = '';
}
set_current_screen($screen_id);
}
function wpjam_admin_action_update(){
// 为了实现多个页面使用通过 option 存储。这个可以放弃了,使用 AJAX + Redirect
// 注册设置选项,选用的是:'admin_action_' . $_REQUEST['action'] hook,
// 因为在这之前的 admin_init 检测 $plugin_page 的合法性
$referer_origin = parse_url(wpjam_get_referer());
if(!empty($referer_origin['query'])){
$referer_args = wp_parse_args($referer_origin['query']);
if(!empty($referer_args['page'])){
wpjam_admin_init($referer_args['page']); // 实现多个页面使用同个 option 存储。
}
}
}
function wpjam_admin_load(...$args){
$loads = [];
$object = WPJAM_Plugin_Page::get_current();
$type = $object ? 'plugin_page' : 'builtin_page';
foreach(wpjam_get_items('admin_load') as $load){
if($load['type'] != $type){
continue;
}
if($type == 'plugin_page'){
$by_tab = true;
if(!empty($load['plugin_page'])){
if(is_callable($load['plugin_page'])){
if(!call_user_func($load['plugin_page'], $args[0], $args[1])){
continue;
}else{
$by_tab = false;
}
}else{
if(!wpjam_compare($args[0], (array)$load['plugin_page'])){
continue;
}
}
}
if($by_tab){
if(!empty($load['current_tab'])){
if(!$args[1] || !wpjam_compare($args[1], (array)$load['current_tab'])){
continue;
}
}else{
if($args[1]){
continue;
}
}
}
}elseif($type == 'builtin_page'){
if(!empty($load['screen']) && is_callable($load['screen'])){
if(call_user_func($load['screen'], $args[0])){
continue;
}
}
foreach(['base', 'post_type', 'taxonomy'] as $key){
if(!empty($load[$key]) && !wpjam_compare($args[0]->$key, (array)$load[$key])){
continue 2;
}
}
}
$load['order'] = $load['order'] ?? 10;
$loads[] = $load;
}
usort($loads, function ($load1, $load2){
$order1 = $load1['order'] ?? 10;
$order2 = $load2['order'] ?? 10;
return $order2 <=> $order1;
});
foreach($loads as $load){
if(!empty($load['page_file'])){
foreach((array)$load['page_file'] as $file){
if(is_file($file)){
include $file;
}
}
}
if(!empty($load['callback'])){
if(is_callable($load['callback'])){
call_user_func_array($load['callback'], $args);
}
}elseif(!empty($load['model'])){
foreach(['load', $load['type'].'_load'] as $method){
if(method_exists($load['model'], $method)){
call_user_func_array([$load['model'], $method], $args);
}
}
}
}
}
function wpjam_admin_ajax(){
$callback = wpjam_get_item('admin_ajax', $_REQUEST['action']);
if(!$callback || !is_callable($callback)){
wp_die('0', 400);
}
add_filter('wp_die_ajax_handler', ['WPJAM_Error', 'filter_wp_die_handler']);
wpjam_send_json(wpjam_call($callback));
}
function wpjam_admin_errors(){
$errors = get_screen_option('admin_errors') ?: [];
foreach($errors as $error){
echo wpjam_wrap_tag($error['message'], 'p')->wrap('div', ['is-dismissible', 'notice', 'notice-'.$error['type']]);
}
}
function wpjam_admin_notices(){
$object = WPJAM_Notice::get_instance();
$object->render();
}
function wpjam_admin_enqueue_scripts(){
$screen = get_current_screen();
if($screen->base == 'customize'){
return;
}elseif($screen->base == 'post'){
wp_enqueue_media(['post'=>wpjam_get_admin_post_id()]);
}else{
wp_enqueue_media();
}
$ver = get_plugin_data(WPJAM_BASIC_PLUGIN_FILE)['Version'];
$static = WPJAM_BASIC_PLUGIN_URL.'static';
wp_enqueue_script('thickbox');
wp_enqueue_style('thickbox');
wp_enqueue_style('wpjam-style', $static.'/style.css', ['wp-color-picker', 'editor-buttons'], $ver);
wp_enqueue_script('wpjam-script', $static.'/script.js', ['jquery', 'thickbox', 'wp-backbone', 'jquery-ui-sortable', 'jquery-ui-tooltip', 'jquery-ui-tabs', 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-ui-autocomplete', 'wp-color-picker'], $ver);
wp_enqueue_script('wpjam-form', $static.'/form.js', ['wpjam-script', 'mce-view'], $ver);
$setting = [
'screen_base' => $screen->base,
'screen_id' => $screen->id,
'post_type' => $screen->post_type,
'taxonomy' => $screen->taxonomy,
'admin_url' => $GLOBALS['current_admin_url'] ?? '',
];
$params = array_except($_REQUEST, wp_removable_query_args());
$params = array_except($params, ['page', 'tab', '_wp_http_referer', '_wpnonce']);
if($GLOBALS['plugin_page']){
$setting['plugin_page'] = $GLOBALS['plugin_page'];
$setting['current_tab'] = $GLOBALS['current_tab'] ?? null;
$query_data = wpjam_get_plugin_page_setting('query_data') ?: [];
$_query_data = wpjam_get_current_tab_setting('query_data') ?: [];
$query_data = array_merge($query_data, $_query_data);
if($query_data){
$params = array_except($params, array_keys($query_data));
$setting['query_data'] = array_map(function($query_item){
return is_null($query_item) ? null : sanitize_textarea_field($query_item);
}, $query_data);
}
}else{
foreach(['taxonomy', 'post_type'] as $key){
if($screen->$key){
$params = array_except($params, $key);
}
}
}
if($params){
if(isset($params['data'])){
$params['data'] = urldecode($params['data']);
}
$params = map_deep($params, 'sanitize_textarea_field');
}
$setting['params'] = $params ?: new stdClass();
$list_table = $screen->get_option('list_table');
if($list_table){
$setting['list_table'] = $list_table->get_setting();
}
wp_localize_script('wpjam-script', 'wpjam_page_setting', $setting);
}
function wpjam_admin_url($path='', $scheme='admin'){
$prefix = wpjam_get_admin_prefix();
return call_user_func($prefix.'admin_url', $path, $scheme);
}
function wpjam_ajax_upload(){
$name = wpjam_get_post_parameter('file_name');
if(!check_ajax_referer('upload-'.$name, false, false)){
wp_die('invalid_nonce');
}
return wpjam_upload($name, $relative=true);
}
function wpjam_ajax_page_action(){
$action = wpjam_get_post_parameter('page_action');
$type = wpjam_get_post_parameter('action_type');
$object = WPJAM_Page_Action::get($action);
if($object){
return $object->callback($type);
}
do_action_deprecated('wpjam_page_action', [$action, $type], 'WPJAM Basic 4.6');
$callback = wpjam_get_filter_name($GLOBALS['plugin_page'], 'ajax_response');
if(is_callable($callback)){
$result = call_user_func($callback, $action);
$result = (is_wp_error($result) || is_array($result)) ? $result : [];
wpjam_send_json($result);
}else{
wp_dir('invalid_callback');
}
}
function wpjam_ajax_query(){
$items = [];
$data_type = wpjam_get_post_parameter('data_type');
$object = $data_type ? wpjam_get_data_type_object($data_type) : null;
if($object){
$args = wpjam_get_post_parameter('query_args', ['default'=>[]]);
$items = $object->query_items($args) ?: [];
if(is_wp_error($items)){
$items = [['label'=>$items->get_error_message(), 'value'=>$items->get_error_code()]];
}
}
return ['items'=>$items];
}
function wpjam_get_current_screen_id(){
if(did_action('current_screen')){
return get_current_screen()->id;
}
if(isset($_POST['screen_id'])){
$screen_id = $_POST['screen_id'];
}elseif(isset($_POST['screen'])){
$screen_id = $_POST['screen'];
}else{
$ajax_action = $_REQUEST['action'] ?? '';
if($ajax_action == 'fetch-list'){
$screen_id = $_GET['list_args']['screen']['id'];
}elseif($ajax_action == 'inline-save-tax'){
$screen_id = 'edit-'.sanitize_key($_POST['taxonomy']);
}elseif(in_array($ajax_action, ['get-comments', 'replyto-comment'])){
$screen_id = 'edit-comments';
}else{
$screen_id = false;
}
}
if($screen_id){
if('-network' === substr($screen_id, -8)){
if(!defined('WP_NETWORK_ADMIN')){
define('WP_NETWORK_ADMIN', true);
}
}elseif('-user' === substr($screen_id, -5)){
if(!defined('WP_USER_ADMIN')){
define('WP_USER_ADMIN', true);
}
}
}
return $screen_id;
}
function wpjam_get_admin_prefix(){
if(is_network_admin()){
return 'network_';
}elseif(is_user_admin()){
return 'user_';
}else{
return '';
}
}
function wpjam_get_page_summary($type='page'){
return get_screen_option($type.'_summary');
}
function wpjam_set_page_summary($summary, $type='page', $append=true){
add_screen_option($type.'_summary', ($append ? get_screen_option($type.'_summary') : '').$summary);
}
function wpjam_admin_tooltip($text, $tooltip){
return '<div class="wpjam-tooltip">'.$text.'<div class="wpjam-tooltip-text">'.wpautop($tooltip).'</div></div>';
}
function wpjam_get_referer(){
$referer = wp_get_original_referer() ?: wp_get_referer();
$removable = array_merge(wp_removable_query_args(), ['_wp_http_referer', 'action', 'action2', '_wpnonce']);
return remove_query_arg($removable, $referer);
}
function wpjam_get_admin_post_id(){
if(isset($_GET['post'])){
return (int)$_GET['post'];
}elseif(isset($_POST['post_ID'])){
return (int)$_POST['post_ID'];
}else{
return 0;
}
}
function wpjam_add_plugin_page($args, $name=null){
$name = $name ?: array_pull($args, 'menu_slug');
if($name){
return WPJAM_Plugin_Page::register($name, $args);
}
}
function wpjam_add_tab_page($args, $name=null){
$name = $name ?: array_pull($args, 'tab_slug');
if($name && !empty($args['title'])){
return WPJAM_Tab_Page::register($name, $args);
}
}
function wpjam_register_plugin_page_tab($name, $args){
return WPJAM_Tab_Page::register($name, $args);
}
function wpjam_register_page_action($name, $args){
return WPJAM_Page_Action::register($name, $args);
}
function wpjam_get_page_button($name, $args=[]){
$object = WPJAM_Page_Action::get($name);
return $object ? $object->get_button($args) : '';
}
function wpjam_get_builtin_list_table($class_name, $screen=null){
global $wp_list_table;
if(!$wp_list_table){
$screen = $screen ?: get_current_screen();
$wp_list_table = _get_list_table($class_name, ['screen'=>$screen]);
}
return $wp_list_table;
}
function wpjam_register_list_table($name, $args=[]){
return wpjam_add_item('list_table', $name, $args);
}
function wpjam_register_list_table_action($name, $args){
return WPJAM_List_Table::register($name, $args, 'action');
}
function wpjam_unregister_list_table_action($name, $args=[]){
WPJAM_List_Table::unregister($name, $args, 'action');
}
function wpjam_register_list_table_column($name, $field){
return WPJAM_List_Table::register($name, $field, 'column');
}
function wpjam_unregister_list_table_column($name, $field=[]){
WPJAM_List_Table::unregister($name, $field, 'column');
}
function wpjam_register_list_table_view($name, $view=[]){
return WPJAM_List_Table::register($name, $view, 'view');
}
function wpjam_register_dashboard($name, $args){
return wpjam_add_item('dashboard', $name, $args);
}
function wpjam_register_dashboard_widget($name, $args){
return wpjam_add_item('dashboard_widget', $name, $args);
}
function wpjam_dashboard_widget($dashboard, $widgets=[]){
$widgets = array_map(function($widget) use($dashboard){ return array_merge($widget, compact('dashboard')); }, $widgets);
$widgets = array_merge($widgets, wpjam_get_items('dashboard_widget'));
$widgets = $dashboard == 'dashboard' ? apply_filters('wpjam_dashboard_widgets', $widgets) : $widgets;
foreach($widgets as $widget_id => $widget){
$widget['dashboard'] = $widget['dashboard'] ?? 'dashboard';
if($widget['dashboard'] == $dashboard){
$widget_id = $widget['id'] ?? $widget_id;
$title = $widget['title'];
$callback = $widget['callback'] ?? wpjam_get_filter_name($widget_id, 'dashboard_widget_callback');
$context = $widget['context'] ?? 'normal'; // 位置,normal 左侧, side 右侧
$priority = $widget['priority'] ?? 'core';
$args = $widget['args'] ?? [];
// 传递 screen_id 才能在中文的父菜单下,保证一致性。
add_meta_box($widget_id, $title, $callback, get_current_screen(), $context, $priority, $args);
}
}
}
function wpjam_get_plugin_page_setting($key='', $using_tab=false){
$object = WPJAM_Plugin_Page::get_current();
if($object){
$is_tab = $object->function == 'tab';
if(str_ends_with($key, '_name')){
$using_tab = $is_tab;
$default = $GLOBALS['plugin_page'];
}else{
$using_tab = $using_tab ? $is_tab : false;
$default = null;
}
if($using_tab){
$object = $object->tab_object;
}
}
if(!$object){
return null;
}
return $key ? ($object->$key ?: $default) : $object->to_array();
}
function wpjam_get_current_tab_setting($key=''){
return wpjam_get_plugin_page_setting($key, true);
}
function wpjam_line_chart($counts_array, $labels, $args=[], $type = 'Line'){
WPJAM_Chart::line($counts_array, $labels, $args, $type);
}
function wpjam_bar_chart($counts_array, $labels, $args=[]){
wpjam_line_chart($counts_array, $labels, $args, 'Bar');
}
function wpjam_donut_chart($counts, $args=[]){
WPJAM_Chart::donut($counts, $args);
}
function wpjam_get_chart_parameter($key){
return WPJAM_Chart::get_parameter($key);
}
add_action('plugins_loaded', function(){
wpjam_register_page_action('delete_notice', [
'button_text' => '删除',
'tag' => 'span',
'class' => 'hidden delete-notice',
'callback' => ['WPJAM_Notice', 'ajax_delete'],
'direct' => true,
]);
if($GLOBALS['pagenow'] == 'options.php'){
add_action('admin_action_update', 'wpjam_admin_action_update', 9);
}elseif(wp_doing_ajax()){
if(wpjam_get_current_screen_id()){
add_action('admin_init', 'wpjam_admin_init', 9);
wpjam_add_admin_ajax('wpjam-page-action', 'wpjam_ajax_page_action');
wpjam_add_admin_ajax('wpjam-upload', 'wpjam_ajax_upload');
wpjam_add_admin_ajax('wpjam-query', 'wpjam_ajax_query');
}
}else{
$menu_action = wpjam_get_admin_prefix().'admin_menu';
$notices_action = wpjam_get_admin_prefix().'admin_notices';
add_action($menu_action, 'wpjam_admin_menu', 9);
add_action($notices_action, 'wpjam_admin_errors');
add_action($notices_action, 'wpjam_admin_notices');
add_action('admin_enqueue_scripts', 'wpjam_admin_enqueue_scripts', 9);
}
add_action('current_screen', ['WPJAM_Admin', 'on_current_screen'], 9);
add_filter('admin_url', ['WPJAM_Admin', 'filter_admin_url'], 9, 4);
});