in_array($f['type'],['text','url','image'],true)&&!in_array($f['key'],['metaKey','code','html'],true)));} public static function clean($raw,string $type): array { if(!is_array($raw)){return [];}$out=[]; foreach(self::fields($type) as $field){$key=$field['key'];$value=$raw[$key]??null;if(!is_array($value)){continue;}$source=Document::choice($value['source']??'',self::SOURCES,'');if(!$source){continue;}$out[$key]=['source'=>$source,'metaKey'=>Document::text($value['metaKey']??'',80),'fallback'=>Document::text($value['fallback']??'',5000),'before'=>Document::text($value['before']??'',200),'after'=>Document::text($value['after']??'',200)];}return $out; } public static function public_meta(int $id,string $key,bool $array=false) { $post=get_post($id);if(!$post||post_password_required($post)||!preg_match('/^[a-zA-Z][a-zA-Z0-9_-]{0,79}$/D',$key)||is_protected_meta($key,'post')){return '';} // Native values stay in protected storage and bypass third-party field adapters. if(str_starts_with($key,'digibl_field_')){return NativeFields::public_value($id,$key,$array);} $registered=array_merge(get_registered_meta_keys('post'),get_registered_meta_keys('post',$post->post_type)); $allowed=array_keys(array_filter($registered,static function($m){$rest=$m['show_in_rest']??false;if(!$rest){return false;}$context=is_array($rest)?($rest['schema']['context']??['view']):['view'];return in_array('view',$context,true);})); $allowed=apply_filters('digibl_public_dynamic_meta_keys',$allowed,$post->post_type); if(!in_array($key,(array)$allowed,true)){return '';} $value=get_post_meta($id,$key,true);if($array&&function_exists('get_field')){$acf=get_field($key,$id);if(is_array($acf)){$value=$acf;}}return is_scalar($value)||($array&&is_array($value))?$value:''; } public static function value(array $binding,int $id,array $row=[]) { $post=get_post($id);$source=$binding['source'];if($post&&post_password_required($post)&&!in_array($source,['site-title','site-description'],true)){return '';} if($source==='row-field'){$key=$binding['metaKey']??'';return preg_match('/^[a-zA-Z][a-zA-Z0-9_-]{0,79}$/D',$key)&&is_scalar($row[$key]??null)?$row[$key]:'';} switch($source){ case 'site-title':return get_bloginfo('name'); case 'site-description':return get_bloginfo('description'); case 'post-title':return $post?get_the_title($post):''; case 'post-url':return $post?get_permalink($post):''; case 'post-id':return $post?(string)$id:''; case 'post-date':return $post?get_the_date('',$post):''; case 'modified-date':return $post?get_the_modified_date('',$post):''; case 'post-excerpt':return $post?wp_strip_all_tags($post->post_excerpt?:wp_trim_words(strip_shortcodes($post->post_content),28)):''; case 'author-name':return $post?get_the_author_meta('display_name',$post->post_author):''; case 'featured-image':return $post?(int)get_post_thumbnail_id($id):0; case 'custom-field':return self::public_meta($id,$binding['metaKey']??''); }return ''; } public static function apply(array $node,int $context,array $row=[]): array { foreach(self::fields($node['type']) as $field){$key=$field['key'];$binding=$node['bindings'][$key]??null;if(!$binding){continue;}$value=self::value($binding,$context,$row);if($value===''||$value===null||$value===0){$value=$binding['fallback'];} if($field['type']==='image'){$original=$node['props'][$key];$image=is_numeric($value)?['id'=>absint($value)]:['url'=>(string)$value];$node['props'][$key]=Document::image(array_merge($original,['id'=>0,'url'=>''],$image));} elseif($field['type']==='url'){$node['props'][$key]=Document::link((string)$value);} else{$node['props'][$key]=Document::text($binding['before'].$value.$binding['after'],5000);} }return $node; } }