File: /www/wwwroot/www.sceybwg.com/wp-content/themes/Modular/extends/wpjam-module/public/module.php
<?php
/**
* @config orderby=order
**/
#[config(['orderby'=>'order'])]
class WPJAM_Module_Type extends WPJAM_Register{
public function __get($key){
$value = parent::__get($key);
if(!is_null($value)){
return $value;
}
if($key == 'label'){
if($this->image){
return ['image'=>$this->image, 'label'=>$this->title, 'class'=>'preview'];
}
if($this->remixicon){
$icon = wpjam_tag('i', ['ri-'.wpjam_remove_prefix($this->remixicon, 'ri-')]);
}elseif($this->dashicon){
$icon = wpjam_tag('span', ['dashicons', 'dashicons-'.$this->dashicon]);
}
return wpjam_join(' ', [$icon ?? '', $this->title]);
}elseif($key == 'post_type'){
return 'post';
}elseif($key == 'taxonomy'){
return 'category';
}elseif($key == 'title_display'){
return true;
}elseif($key == 'title_custom'){
return $this->title_display;
}
}
public function get_fields($action_key, $id=0){
if($action_key == 'title'){
$type = $this->title_display ? 'checkbox' : 'view';
return [
'title' => ['type'=>'text', 'required', 'class'=>'all-options', 'label'=>true],
'title_display' => ['type'=>$type, 'before'=>'显示:', 'fields'=>($this->title_custom ? [
'title_position' => ['before'=>'位置:', 'type'=>'radio', 'options'=>['left'=>'左','center'=>'中','right'=>'右']],
'title_color' => ['before'=>'颜色:', 'type'=>'color', 'value'=>'#000']
] : []), ($type == 'view' ? 'value' : 'label')=>'模块标题在页面上'.($type == 'view' ? '不': '').'显示']
];
}elseif($action_key == 'setting'){
$fields = [
'background_color' => ['title'=>'背景色', 'type'=>'color', 'value'=>'#FFF', 'alpha'=>true],
'margin' => ['title'=>'下边距', 'type'=>'number', 'class'=>'small-text', 'value'=>0],
'border_radius' => ['title'=>'圆角', 'type'=>'checkbox', 'options'=>['top'=>'上圆角','bottom'=>'下圆角'], 'value'=>['top', 'bottom']]
];
}elseif(in_array($action_key, ['create', 'edit'])){
$fields = [
'title' => ['title'=>'标题', 'type'=>'fieldset', 'fields'=>wpjam_map($this->get_fields('title', $id), [self::class, 'prepend_settting_name'])],
'excerpt' => ['title'=>'简介', 'type'=>'textarea'],
'hides' => ['title'=>'隐藏', 'type'=>'checkbox', 'name'=>'setting[platform_hides]'],
'setting' => ['title'=>'设置', 'type'=>'fieldset', 'fields'=>wpjam_map($this->get_fields('setting', $id), [self::class, 'prepend_settting_name'])]
];
if(!$this->excerpt){
unset($fields['excerpt']);
}
$platforms = wpjam_get_module_platforms('objects');
$platforms = $this->platforms ? wpjam_pick($platforms, $this->platforms) : $platforms;
if($platforms && count($platforms) > 1){
$fields['hides']['options'] = wpjam_map($platforms, fn($v)=> $v->title);
$fields['hides']['max_items'] = count($platforms)-1;
}else{
unset($fields['hides']);
}
if($this->content_path){
$fields = $this->append_path_fields($fields, 'content');
}
}
$args = ($object = wpjam_get_post_object($id)) ? $object->setting : [];
$args = array_merge($args, ['id'=>$id, 'type_object'=>$this]);
$fields = wpjam_merge(($fields ?? []), $this->call_method('get_fields', $action_key, $args) ?: []);
$fields = apply_filters('wpjam_module_type_fields', $fields, $action_key, $this->name, $args);
if(in_array($action_key, ['add_item', 'edit_item']) && $this->item_path !== false){
return $this->append_path_fields($fields);
}
return $fields;
}
public function is_over($count){
$max = $this->max_modules;
return $max && $count >= $max ? wpjam_throw('over_max_modules', '最多'.$max.'个'.$this->title.'模块') : false;
}
protected static function append_path_fields($fields, $prepend=''){
$path_fields = wpjam_filter($fields, fn($field, $k)=> str_starts_with($k, 'page_key_'));
$fields = array_diff_key($fields, $path_fields);
return $fields + wpjam_merge(wpjam_get_module_path_fields($prepend), $path_fields);
}
public static function prepend_settting_name($field, $key){
if($key != 'title' && is_array($field)){
if(!empty($field['fields'])){
$field['fields'] = wpjam_map($field['fields'], [self::class, 'prepend_settting_name']);
}
if(!isset($field['type']) || !in_array($field['type'], ['fieldset', 'fields'])){
$field['name'] = 'setting['.$key.']';
}
}
return $field;
}
public static function get_options(){
return wp_list_pluck(self::get_registereds(), 'label');
}
public static function get_defaults(){
return [
'slider' => [
'title' => '幻灯片',
'model' => 'WPJAM_Slider_Module',
'dashicon' => 'images-alt2',
'max_items' => 10,
'items' => true
],
'nav' => [
'title' => '快捷导航',
'model' => 'WPJAM_Nav_Module',
'dashicon' => 'share',
'max_items' => 15,
'items' => true
],
'cube' => [
'title' => '图片魔方',
'model' => 'WPJAM_Cube_Module',
'dashicon' => 'layout'
],
'text-list' => [
'title' => '文本列表',
'model' => 'WPJAM_Text_List_Module',
'dashicon' => 'editor-ul',
'max_items' => 10,
'items' => true
],
'text' => [
'title' => '简单文本',
'model' => 'WPJAM_Text_Module',
'dashicon' => 'editor-textcolor',
'content_path' => true
]
];
}
}
/**
* @post_type module
**/
#[post_type('module')]
class WPJAM_Module extends WPJAM_Post{
use WPJAM_Items_Trait;
public function __get($key){
if($key == 'shared'){
return is_object_in_term($this->id, 'module_page', WPJAM_Module_Page::get_shared());
}elseif($key == 'items'){
return $this->get_items();
}elseif($key == 'setting'){
$value = $this->_module_setting ?: [];
if(!empty($value['background_color']) && strlen($value['background_color']) == 7 && isset($value['background_opacity'])){
$value['background_color'] .= str_pad(dechex(round(255*$value['background_opacity'], 0)), 2, '0', STR_PAD_LEFT);
}
return $value;
}elseif($key == 'type'){
return $this->_module_type;
}elseif($key == '_type_object'){
return WPJAM_Module_Type::get($this->type);
}elseif($key == 'model'){
return $this->_type_object->model;
}elseif(in_array($key, ['data', 'module'])){
return [
'id' => $this->id,
'type' => $this->type,
'model' => $this->model,
'status' => $this->status,
'title' => $this->title,
'excerpt' => $this->excerpt,
'setting' => $this->setting,
'content' => $this->items
];
}
return parent::__get($key);
}
public function get_type_fields($action_key){
return $this->_type_object->get_fields($action_key, $this->id);
}
public function get_items(){
return $this->get_unserialized();
}
public function update_items($items){
return $this->save(['content'=>array_values($items)]);
}
protected function validate_item($item=null, $key=null, $action=''){
if($action == 'add' && ($max = $this->_type_object->max_items) && count($this->items) >= $max){
return new WP_Error('over_quota', '最多'.$max.'个'.$this->_type_object->title);
}
return isset($item['page_key']) ? WPJAM_Module_Platform::validate_item($item) : true;
}
protected function sanitize_item($item, $id=null){
return array_filter($item, fn($v)=> !is_null($v));
}
protected function after_delete_item($key){
$this->items || $this->unpublish();
}
protected function parse_by_field($value, $field){
return ($value && $field['type'] == 'img') ? wpjam_get_thumbnail($value, wpjam_get($field, 'size')) : $value;
}
protected function parse_by_fields($data, $fields){
return wpjam_map($data, fn($v, $k)=> isset($fields[$k]) ? $this->parse_by_field($v, $fields[$k]) : $v);
}
protected function parse_item($item, $args=[]){
$item = apply_filters('wpjam_module_item', $item);
$parsed = WPJAM_Module_Platform::parse_item($item);
return wpjam_reduce($args['fields'] ?? [], fn($c, $v, $k)=> str_starts_with($k, 'page_key_') ? $c : wpjam_set($c, $k, $this->parse_by_field($item[$k] ?? '', $v)), $parsed);
}
protected function parse_items(...$args){
$items = count($args) > 1 ? array_shift($args) : $this->items;
$args = ['fields'=>$this->get_type_fields('edit_item')]+$args[0];
return array_values(array_map(fn($item)=> $this->parse_item($item, $args), $items));
}
protected function render_items(...$args){
$items = count($args) > 1 ? array_shift($args) : $this->items;
return ['items'=>$items, 'args'=>['sortable'=>true, 'max_items'=> $this->_type_object->max_items]+$args[0]];
}
public function is_publishable(){
$this->items || wpjam_throw('empty_'.$this->type, '未设置'.$this->_type_object->title.',不能发布');
$items = wp_is_numeric_array($this->items) ? $this->items : [$this->items];
$fields = $this->get_type_fields('edit_item') ?: [];
$key = array_find_key($fields, fn($field, $key)=> (isset($field['required']) || in_array('required', $field, true)) && array_find($items, fn($item)=> empty($item[$key])));
return $key ? new WP_Error('empty_'.$key, $fields[$key]['title'].'不能为空') : true;
}
public function is_deletable($label='删除'){
if(self::page('is_shared')){
return count(wp_get_post_terms($this->id, 'module_page')) > 1 ? new WP_Error('shared_module_in_use', '不可'.$label.'已被页面使用的模块') : true;
}else{
return $this->shared ? new WP_Error('shared_module', '不可'.$label.'共用模块') : true;
}
}
public function unpublish(){
$result = $this->is_deletable('撤回');
return is_wp_error($result) ? $result : parent::unpublish();
}
public function copy_to($data){
$object = !empty($data['to_page']) ? wpjam_get_term_object($data['to_page']) : null;
return $object ? $object->add_module(array_merge($this->data, ['status'=>'draft'])) : new WP_Error('invalid_page', '无效的模块页面');
}
public function show_if($action_key){
if($action_key == 'delete'){
return ['title'=> !self::page('is_shared') && $this->shared ? '移除' : '删除'];
}
}
public function parse($args=[]){
$args = $args ?: (($platform = WPJAM_Module_Platform::get_current()) ? $platform->get_arg('module_page') : []);
if(array_any([
[$this->_type_object->platforms, false],
[($this->setting['platform_hides'] ?? []), true]
], fn($v)=> $v[0] && $v[1] === in_array($args['platform'], $v[0]))){
return;
}
$args['border_radius'] = !empty($args['module_page']) ? (int)($args['module_page']->border_radius) : 0;
$data = [
'id' => $this->id,
'type' => $this->type,
'status' => $this->status,
'title' => $this->parse_title($args),
'excerpt' => $this->parse_excerpt($args),
'setting' => $this->parse_setting($args),
'style' => $this->parse_style($args),
'content' => $this->parse_content($args),
];
return method_exists($this, 'parse_module') ? $this->parse_module($data, $args) : $data;
}
protected function parse_title($args){
return $args['platform'] == 'template' ? $this->title : html_entity_decode($this->title);
}
protected function parse_excerpt($args){
return $args['platform'] == 'template' ? $this->excerpt : html_entity_decode($this->excerpt);
}
protected function parse_content($args){
return $this->_type_object->items ? $this->parse_items($args) : $this->parse_by_fields($this->get_unserialized(), $this->get_type_fields('edit'));
}
protected function parse_setting($args){
$setting = wpjam_except($this->setting, ['background_color', 'border_radius', 'margin']);
if($this->_type_object->title_display){
$setting['title_display'] = (bool)($setting['title_display'] ?? false);
}else{
$setting['title_display'] = false;
}
if($this->_type_object->title_custom){
$setting['title_position'] ??= 'left';
$setting['title_color'] ??= '';
}else{
$setting['title_position'] = '';
$setting['title_color'] = '';
}
return $this->parse_by_fields($setting, $this->get_type_fields('setting'));
}
protected function parse_style($args){
$setting = $this->setting;
if(!empty($setting['margin'])){
$style[] = 'margin-bottom:'.$setting['margin'].$args['unit'];
}
if(!empty($setting['background_color'])){
$style[] = 'background:'.$setting['background_color'];
}
if($args['border_radius']){
$radius_value = $args['border_radius'];
$border_radius = $setting['border_radius'] ?? ['top', 'bottom'];
if($border_radius){
$radius_value .= $args['unit'];
$radius_style = array_map(fn($k)=> in_array($k, $border_radius) ? $radius_value.' '.$radius_value : '0 0', ['top', 'bottom']);
$style[] = 'border-radius:'.implode(' ', $radius_style);
}
}
return !empty($style) ? implode('; ', $style).';' : '';
}
public function render(){
if(method_exists($this, 'render_module')){
$data = $this->render_module($this->data);
return [
'title' => $this->render_title(),
'content' => is_array($data['content']) ? '' : $data['content'],
'setting' => is_array($data['setting']) ? '' : $data['setting'],
]+$data;
}
return [
'id' => $this->id,
'type' => $this->type,
'model' => $this->model,
'status' => $this->status,
'title' => $this->render_title(),
'excerpt' => $this->excerpt,
'content' => $this->render_content(),
'setting' => $this->render_setting(),
];
}
protected function render_title(){
if($this->_type_object->title_display && !empty($this->setting['title_display'])){
if($this->_type_object->title_custom){
$style = ['color'=> $this->setting['title_color'] ?? ''];
$display = '居'.wpjam_get($this->get_type_fields('title'), 'title_display.fields.title_position.options.'.($this->setting['title_position'] ?: 'left'));
}
}else{
$display = '不';
}
return wpjam_tag('strong', ['style'=>($style ?? [])], wpjam_join(' — ', [
$this->title,
$this->status == 'draft' ? wpjam_tag('span', ['post-state'], '待发布') : '',
!self::page('is_shared') && $this->shared ? wpjam_tag('span', ['shared-module'], '共用模块') : ''
]))->after('span', ['title-display'], '标题在页面上'.($display ?? '').'显示');
}
protected function render_content(){
return $this->get_unserialized();
}
protected function render_setting(){
$rendered = [];
$setting = $this->setting;
foreach($this->get_type_fields('setting') as $key => $field){
if(!in_array($field['type'], ['color', 'fieldset', 'view']) && !empty($field['title']) && !in_array($key, ['border_radius'])){
$value = $setting[$key] ?? '';
if(isset($field['options'])){
$value = wpjam_array($value);
$value = wpjam_map($value, fn($v)=> $field['options'][$v] ?? $v);
if(count($value) == 0){
continue;
}elseif(count($value) == 1){
$value = reset($value);
}
}
$rendered[$key] = [$field['title'], $value];
}
}
return $rendered;
}
public function get_module($args=[]){ // compact
return $this->parse($args);
}
public static function create_instance(...$args){
$type = get_post_meta($args[0], '_module_type', true);
$object = WPJAM_Module_Type::get($type);
$model = $object ? $object->model : null;
return $model ? new $model(...$args) : null;
}
protected static function sanitize_data($data, $id=0){
$data['meta_input'] = wpjam_array(wpjam_pull($data, ['type', 'setting']), fn($k)=> '_module_'.$k);
return parent::sanitize_data($data, $id);
}
public static function get($id){
$object = self::get_instance($id);
return $object ? $object->data : [];
}
public static function delete($id, $force_delete=true){
$result = parent::delete($id, $force_delete);
return is_wp_error($result) && $result->get_error_code() == 'shared_module' ? self::page('remove_module', $id) : $result;
}
public static function bulk_delete($ids){
try{
wp_defer_term_counting(true);
wpjam_map($ids, fn($id)=> wpjam_try([self::class, 'delete'], $id));
return true;
}catch(Exception $e){
return wpjam_catch($e);
}finally{
wp_defer_term_counting(false);
}
}
public static function get_actions(){
$page = self::page();
return [
'add' =>['title'=>'新建', 'page_title'=>'新建模块', 'next'=>'create'],
'create' =>['title'=>'新建', 'page_title'=>'新建模块', 'dismiss'=>true, 'response'=>'add', 'callback'=>[$page, 'add_module']],
]+(wpjam_get_data_parameter('mode') == 'sort' ? [] : [
'edit' =>['title'=>'编辑', 'page_title'=>'编辑模块'],
'publish' =>['title'=>'发布', 'direct'=>true, 'confirm'=>true, 'show_if'=>['status', '=', 'draft']],
'unpublish' =>['title'=>'撤回', 'direct'=>true, 'confirm'=>true, 'show_if'=>['status', '=', 'publish']],
'delete' =>['title'=>'删除', 'direct'=>true, 'confirm'=>true, 'bulk'=>true, 'order'=>9, 'show_if'=>[self::class, 'show_if']],
]+(self::page('is_shared') ? [] : [
'copy_to' =>['title'=>'复制到', 'page_title'=>'复制模块到...', 'show_if'=>['status', '=', 'publish']],
'empty' =>['title'=>'清空所有', 'page_title'=>'清空模块', 'direct'=>true, 'confirm'=>true, 'overall'=>true, 'callback'=> fn()=> self::bulk_delete($page->get_module_ids())],
'add_shared'=>['title'=>'添加共用', 'page_title'=>'添加共用模块', 'class'=>'button-primary', 'response'=>'add', 'dismiss'=>true, 'overall'=>true, 'callback'=> [$page, 'add_shared_module']]
]))+self::get_item_actions();
}
public static function get_fields($action_key='', $id=0){
$page = self::page();
$object = $id ? self::get_instance($id) : null;
if($action_key == ''){
$sort = wpjam_get_data_parameter('mode') == 'sort';
return [
'sort' => ['title'=>'排序', 'show_admin_column'=>$sort],
'title' => ['title'=>'标题', 'show_admin_column'=>true, 'required'],
'type' => ['title'=>'类型', 'show_admin_column'=>true, 'filterable'=>true, 'options'=>WPJAM_Module_Type::get_active('title')],
'status' => ['title'=>'状态', 'show_admin_column'=>false, 'filterable'=>true, 'options'=>['publish'=>'已发布', 'draft'=>'待发布']],
'setting' => ['title'=>'设置', 'show_admin_column'=>!$sort],
'content' => ['title'=>'内容', 'show_admin_column'=>!$sort],
];
}elseif($action_key == 'add'){
return [
'view' => '<strong>请选择模块类型:</strong>',
'type' => ['type'=>'radio', 'options'=>WPJAM_Module_Type::get_options(), 'required'],
];
}elseif($action_key == 'add_shared'){
return ['shared' => wpjam_get_post_id_field('module', ['title'=>'', 'required', 'query_args'=>[
'module_page_id' => WPJAM_Module_Page::get_shared(),
'post_status' => 'publish',
'exclude' => $page->get_module_ids()
]])];
}elseif($action_key == 'copy_to'){
$options = wpjam_except(WPJAM_Module_Page::get_options(), $page->id);
$options += $object->shared ? [] : [(WPJAM_Module_Page::get_shared())=>'共用模块'];
return ['to_page' => ['title'=>'复制到', 'type'=>'select', 'options'=>$options]];
}
$type = $object ? $object->type : wpjam_get_data_parameter('type');
$fields = [WPJAM_Module_Type::get($type), 'get_fields']($action_key, $id);
$action_key == 'create' && $page->is_modules_over($type);
if(in_array($action_key, ['create', 'edit'])){
$fields = $page->border_radius ? $fields : wpjam_except($fields, 'setting.fields.border_radius');
}elseif(in_array($action_key, ['add_item', 'edit_item'])){
$fields = wpjam_map($fields, fn($v)=> isset($v['name']) ? wpjam_set($v, 'name', preg_replace('/item\[(.*)\]/', '$1', $v['name'])) : $v);
}
return ($id && $object->shared ? ['tips'=>'<span class="red">对共用模块的修改将会应用到所有使用该模块的页面中</span>'] : [])+$fields;
}
public static function get_views(){
$ids = self::page('get_module_ids');
$posts = self::get_by_ids($ids);
if(!$posts){
return [];
}
$counts = array_count_values(array_column(array_filter($posts), 'post_status'));
$views = ['all'=>['filter'=>['status'=>null, 'mode'=>null], 'label'=>'全部', 'count'=>array_sum($counts)]];
$views += wpjam_map(['publish'=>'已发布', 'draft'=>'待发布'], fn($v, $k)=> isset($counts[$k]) ? ['filter'=>['status'=>$k], 'label'=>$v, 'count'=>$counts[$k]] : null);
$views += ['sort'=>['filter'=>['mode'=>'sort'], 'label'=>'快捷排序']];
return $views;
}
public static function query_items($args){
return self::page('parse_modules', $args, false);
}
public static function render_item($item){
$object = self::get_instance($item['id']);
if($object){
$item = array_merge($item, $object->render());
$setting = $object->setting;
if(is_array($item['setting'])){
foreach($item['setting'] as &$_item){
if(is_array($_item)){
$title = $_item[0].':';
$length = mb_strlen($title);
if($length < 5){
$title .= str_repeat(' ', 5-$length);
}
$value = $_item[1];
$value = is_array($value) ? implode(', ', $value) : $value;
$_item = $title.wpjam_tag('strong', [], $value);
}
}
$item['setting'] = implode(wpjam_tag('br'), $item['setting']);
}else{
$margin = $setting['margin'] ?? 0;
$item['setting'] .= $item['setting'] ? wpjam_tag('br') : '';
$item['setting'] .= '下边距: '.wpjam_tag('strong', [], $margin);
}
if($bg_color = wpjam_pull($setting, 'background_color')){
$item['content'] = is_array($item['content']) ? $item['content'] : ['text'=>$item['content']];
$item['content'] += ['wrap'=>wpjam_tag('div', ['style'=>'width:calc(100% - 20px); float:left; padding:10px; background:'.$bg_color.';'])];
}
if(wpjam_get_data_parameter('mode') == 'sort'){
unset($item['row_actions']['id']);
}
}
return $item;
}
public static function get_list_table(){
wpjam_map(['script', 'style'], fn($t)=> wpjam_map(WPJAM_Module_Type::get_active($t), fn($v)=> wpjam_admin($t, $v)));
wpjam_admin('style', [
'td.column-title{min-width:150px;}',
'td.column-type{min-width:120px;}',
'td.column-setting{width:240px;}',
'td.column-sort, th.column-sort{width:6em;}',
'td.column-sort .row-actions{left:inherit;}',
'td.column-title span.title-display{font-size:smaller; color:#999;}',
'#type_options label{width:120px;}'
]);
$page = self::page();
return [
'title' => self::page('is_shared') ? $page->name : '「'.$page->name.'」页面模块',
'plural' => 'modules',
'singular' => 'module',
'model' => self::class,
'sortable' => ['callback'=>[$page, 'move_module']],
];
}
public static function page($method='', ...$args){
$object = wpjam_get_term_object(wpjam_get_data_parameter('page_id'));
return $method ? $object->$method(...$args) : $object;
}
public static function get_path_fields($item_key='item'){
return wpjam_get_module_path_fields($item_key); // 兼容
}
}
class WPJAM_Modules{
private $page_id;
public function __construct($page_id){
$this->page_id = (int)$page_id;
}
public function get_ids($sorted=false){
$ids = wpjam_get_posts([
'post_type' => 'module',
'post_status' => 'any',
'posts_per_page' => -1,
'fields' => 'ids',
'module_page_id' => $this->page_id
]);
if($sorted){
$orders = get_term_meta($this->page_id, 'orders', true) ?: [];
$orders = array_intersect(array_unique($orders), $ids);
$ids = array_merge(array_diff($ids, $orders), $orders);
}
return array_values($ids);
}
public function is_over($type=''){
if($this->page_id != WPJAM_Module_Page::get_shared()){
$ids = $this->get_ids();
$max = wpjam_get_post_type_setting('module', 'max_modules');
$max && count($ids) >= $max && wpjam_throw('over_max_modules', '最多'.$max.'个模块');
if($type && $type != 'shared'){
$object = WPJAM_Module_Type::get($type);
$object && $object->is_over(count(array_filter($ids, fn($id)=> get_post_meta($id, '_module_type', true) == $type)));
}
}
return false;
}
public function add($data){
return $this->is_over($data['type']) ?: wpjam_try(['WPJAM_Module', 'insert'], $data+[
'status' => 'draft',
'tax_input' => ['module_page'=>[$this->page_id]]
]);
}
public function add_shared($shared){
$shared = is_array($shared) ? wpjam_get($shared, 'shared') : $shared;
$object = $shared ? wpjam_get_post_object($shared) : null;
(!$object || !$object->shared) && wpjam_throw('invalid_shared_module', '无效的共用模块');
$this->is_over($object->type) ?: wpjam_try('wp_set_post_terms', $shared, [$this->page_id], 'module_page', true);
return $shared;
}
public function remove($id){
$page_ids = wp_get_post_terms($id, 'module_page', ['fields'=>'ids']);
$page_ids = array_diff($page_ids, [$this->page_id]);
return wp_set_post_terms($id, $page_ids, 'module_page');
}
public function move($id, $data){
$ids = $this->get_ids(true);
if(isset($data['module'])){
array_diff($data['module'], $ids) && wp_die('无效的ID');
$ids = $data['module'];
}else{
$ids = wpjam_move($ids, $id, $data);
}
return is_wp_error($ids) ? $ids : update_term_meta($this->page_id, 'orders', $ids);
}
public function import($data){
try{
wp_defer_term_counting(true);
foreach(array_reverse($data) as $item){
$id = $this->add(wp_array_slice_assoc($item, ['type', 'setting', 'title', 'excerpt', 'content', 'status']));
if(is_wp_error($id)){
return $id;
}
}
remove_filter('sanitize_title', '__return_empty_string');
}finally{
wp_defer_term_counting(false);
}
return true;
}
public function parse($args=[], $parsed=true){
if($args === false){
$args = [];
$parsed = false;
}
$args = wp_parse_args($args, ['type'=>'', 'status'=>($parsed ? 'publish' : '')]);
$filter = wpjam_filter($args, fn($v, $k)=> in_array($k, ['type', 'status']) && $v && $v != 'any');
$modules = [];
foreach(WPJAM_Module::update_caches($this->get_ids(true)) as $id => $post){
$object = WPJAM_Module::get_instance($id);
if(!$object || !wpjam_matches($object, $filter)){
continue;
}
if($parsed){
$module = $object->parse($args);
if($module && !empty($module['content'])){
$modules[] = $module;
}
}else{
$modules[] = $object->data;
}
}
return $parsed ? array_reduce(['query', 'parse'], fn($c, $k)=> wpjam_map($c, fn($m)=> ($cb = wpjam_pull($m, $k)) ? $cb($m, $args) : $m), $modules) : $modules;
}
}
function wpjam_register_module_type($key, $args){
return WPJAM_Module_Type::register($key, $args);
}
function wpjam_unregister_module_type($key){
WPJAM_Module_Type::unregister($key);
}
function wpjam_set_max_modules($value=0, $type=''){
if($type){
$object = WPJAM_Module_Type::get($type);
$object && ($object->max_modules = $value);
}else{
wpjam_update_post_type_setting('module', 'max_modules', $value);
}
}
wpjam_register_post_type('module', [
'label' => '模块',
'supports' => ['title'],
'public' => false,
'show_ui' => false,
'rewrite' => false,
'query_var' => false,
'model' => 'WPJAM_Module',
]);