123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- <?php
- if ( ! defined( 'ABSPATH' ) ) {
- exit;
- }
- if ( class_exists( 'ACF_Rest_Api' ) ) {
- return;
- }
- class ACF_Rest_Api {
-
- private $request;
-
- private $embed_links;
- public function __construct() {
- add_filter( 'rest_pre_dispatch', array( $this, 'initialize' ), 10, 3 );
- add_action( 'rest_api_init', array( $this, 'register_field' ) );
- }
- public function initialize( $response, $handler, $request ) {
- if ( ! acf_get_setting( 'rest_api_enabled' ) ) {
- return;
- }
-
- $this->request = new ACF_Rest_Request();
- $this->request->parse_request( $request );
-
- $this->register_field();
-
- if ( acf_get_setting( 'rest_api_embed_links' ) ) {
- $this->embed_links = new ACF_Rest_Embed_Links();
- $this->embed_links->initialize();
- }
- }
-
- public function register_field() {
- if ( ! acf_get_setting( 'rest_api_enabled' ) ) {
- return;
- }
- if ( ! $this->request instanceof ACF_Rest_Request ) {
- $this->request = new ACF_Rest_Request();
- $this->request->parse_request( null );
- }
- $base = $this->request->object_sub_type;
-
-
- if ( ! $base ) {
- return;
- }
- if ( $this->request->child_object_type ) {
- $base = $this->request->child_object_type;
- }
-
- if ( acf_did( 'acf/register_rest_field' ) ) {
- global $wp_rest_additional_fields;
- if ( isset( $wp_rest_additional_fields[ $base ], $wp_rest_additional_fields[ $base ]['acf'] ) ) {
- return;
- }
- }
- register_rest_field(
- $base,
- 'acf',
- array(
- 'schema' => $this->get_schema(),
- 'get_callback' => array( $this, 'load_fields' ),
- 'update_callback' => array( $this, 'update_fields' ),
- )
- );
- }
-
- private function get_schema() {
- $schema = array(
- 'description' => 'ACF field data',
- 'type' => 'object',
- 'properties' => array(),
- 'arg_options' => array(
- 'validate_callback' => array( $this, 'validate_rest_arg' ),
- ),
- );
-
- $object_type = $this->request->object_type;
- if ( ! $object_type ) {
- return $schema;
- }
- $object_id = $this->request->get_url_param( 'id' );
- $child_id = $this->request->get_url_param( 'child_id' );
- $object_sub_type = $this->request->object_sub_type;
- if ( $child_id ) {
- $object_id = $child_id;
- }
- if ( ! $object_id ) {
- $field_groups = $this->get_field_groups_by_object_type( $object_type );
- } else {
- $field_groups = $this->get_field_groups_by_id( $object_id, $object_type, $object_sub_type );
- }
- if ( empty( $field_groups ) ) {
- return $schema;
- }
- foreach ( $field_groups as $field_group ) {
- foreach ( $this->get_fields( $field_group, $object_id ) as $field ) {
- $schema['properties'][ $field['name'] ] = acf_get_field_rest_schema( $field );
- }
- }
- return $schema;
- }
-
- public function validate_rest_arg( $value, $request, $param ) {
-
- $valid = rest_validate_request_arg( $value, $request, $param );
- if ( true !== $valid ) {
- return $valid;
- }
- foreach ( $value as $field_name => $field_value ) {
- $field = acf_get_field( $field_name );
- if ( ! $field ) {
- continue;
- }
-
- $valid = apply_filters( 'acf/validate_rest_value/type=' . $field['type'], true, $field_value, $field );
- if ( true !== $valid ) {
- return $valid;
- }
- }
- return true;
- }
-
- public function load_fields( $object, $field_name, $request, $object_sub_type ) {
-
- $fields = array();
-
- $object_id = acf_get_object_id( $object );
-
- $object_type = $this->request->object_type;
-
- if ( ! $object_id or ! $object_type ) {
- return $fields;
- }
- $object_sub_type = str_replace( '-revision', '', $object_sub_type );
-
- $field_groups = $this->get_field_groups_by_id( $object_id, $object_type, $object_sub_type );
- if ( empty( $field_groups ) ) {
- return $fields;
- }
-
- $post_id = $this->make_identifier( $object_id, $object_type );
-
- foreach ( $field_groups as $field_group ) {
- foreach ( $this->get_fields( $field_group, $object_id ) as $field ) {
- $value = acf_get_value( $post_id, $field );
- if ( $this->embed_links ) {
- $this->embed_links->prepare_links( $post_id, $field );
- }
-
- $format = $request->get_param( 'acf_format' ) ?: acf_get_setting( 'rest_api_format' );
- $value = acf_format_value_for_rest( $value, $post_id, $field, $format );
- $fields[ $field['name'] ] = $value;
- }
- }
-
- acf_get_store( 'values' )->reset();
- return $fields;
- }
-
- public function update_fields( $data, $object, $property, $request, $object_sub_type ) {
-
- if ( empty( $data ) ) {
- return true;
- }
-
-
- $object_id = acf_get_object_id( $object );
- $object_type = $this->request->object_type;
- if ( ! $object_id or ! $object_type ) {
- return new WP_Error(
- 'acf_rest_object_unknown',
- __( sprintf( 'Unable to determine the %s object ID or type. The %s property cannot be updated.', get_class( $object ), $property ), 'acf' ),
- array( 'status' => 400 )
- );
- }
-
- $post_id = $this->make_identifier( $object_id, $object_type );
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $field_group_scope = acf_extract_var( $data, '_acf_field_group_scope', array() );
-
- $field_groups = $this->get_field_groups_by_id( $object_id, $object_type, $object_sub_type, $field_group_scope );
- if ( empty( $field_groups ) ) {
- return true;
- }
-
- $all_fields = array();
- foreach ( $field_groups as $field_group ) {
- if ( $fields = $this->get_fields( $field_group, $object_id ) ) {
- $all_fields = array_merge( $fields, $all_fields );
- }
- }
- if ( $all_fields ) {
-
-
-
- $field_key_map = acf_extract_var( $data, '_acf_field_key_map', array() );
-
-
- foreach ( $data as $field_name => $value ) {
-
- if ( isset( $field_key_map[ $field_name ] ) ) {
- $field_name = $field_key_map[ $field_name ];
- }
- if ( $field = acf_search_fields( $field_name, $all_fields ) ) {
- acf_update_value( $value, $post_id, $field );
- }
- }
- }
- return true;
- }
-
-
- private function is_admin_mode( $data ) {
- return isset( $data['_acf_admin_mode'] ) && $data['_acf_admin_mode'];
- }
-
- private function make_identifier( $object_id, $object_type ) {
- $formats = array(
- 'user' => 'user_%s',
- 'term' => 'term_%s',
- 'comment' => 'comment_%s',
- );
- return isset( $formats[ $object_type ] )
- ? sprintf( $formats[ $object_type ], $object_id )
- : $object_id;
- }
-
- private function object_type_has_field_group( $object_type, $field_group, $location_types = array() ) {
- if ( ! isset( $field_group['location'] ) || ! is_array( $field_group['location'] ) ) {
- return false;
- }
- $location_types = empty( $location_types ) ? acf_get_location_types() : $location_types;
- foreach ( $field_group['location'] as $rule_group ) {
- $match = false;
- foreach ( $rule_group as $rule ) {
- $rule = acf_validate_location_rule( $rule );
- if ( ! isset( $location_types[ $rule['param'] ] ) ) {
- continue;
- }
-
- $location_type = $location_types[ $rule['param'] ];
- if ( ! isset( $location_type->object_type ) || $location_type->object_type !== (string) $object_type ) {
- continue;
- }
-
- if ( 'post' === $object_type && 'post_type' === $rule['param'] ) {
- if ( $rule['operator'] === '==' && $this->request->object_sub_type !== $rule['value'] ) {
- continue;
- }
- if ( $rule['operator'] === '!=' && $this->request->object_sub_type === $rule['value'] ) {
- continue;
- }
- $match = true;
- }
- if ( 'term' === $object_type && 'taxonomy' === $rule['param'] ) {
- if ( $rule['operator'] === '==' && $this->request->object_sub_type !== $rule['value'] ) {
- continue;
- }
- if ( $rule['operator'] === '!=' && $this->request->object_sub_type === $rule['value'] ) {
- continue;
- }
- $match = true;
- }
- if ( in_array( $object_type, array( 'user', 'comment' ) ) ) {
- $match = true;
- }
- }
- if ( $match ) {
- return true;
- }
- }
- return false;
- }
-
- private function get_field_groups_by_object_type( $object_type ) {
- $field_groups = acf_get_field_groups();
- $location_types = acf_get_location_types();
- $object_type_groups = array();
- foreach ( $field_groups as $field_group ) {
- if ( empty( $field_group['show_in_rest'] ) ) {
- continue;
- }
- if ( $this->object_type_has_field_group( $object_type, $field_group, $location_types ) ) {
- $object_type_groups[] = $field_group;
- }
- }
- return $object_type_groups;
- }
-
- private function get_field_groups_by_id( $object_id, $object_type, $object_sub_type = null, $scope = array() ) {
-
-
-
- if ( $object_type === 'term' && $object_sub_type === null ) {
- $term = get_term( $object_id );
- if ( ! $term instanceof WP_Term ) {
- return array();
- }
- $object_sub_type = $term->taxonomy;
- }
- switch ( $object_type ) {
- case 'user':
- $args = array(
- 'user_id' => $object_id,
- 'rest' => true,
- );
- break;
- case 'term':
- $args = array( 'taxonomy' => $object_sub_type );
- break;
- case 'comment':
- $comment = get_comment( $object_id );
- $post_type = get_post_type( $comment->comment_post_ID );
- $args = array( 'comment' => $post_type );
- break;
- case 'post':
- default:
- $args = array( 'post_id' => $object_id );
- $child_rest_base = $this->request->get_url_param( 'child_rest_base' );
- if ( $child_rest_base && 'post' === $object_type ) {
- $args['post_type'] = $object_sub_type;
- }
- }
-
- return array_filter(
- acf_get_field_groups( $args ),
- function ( $group ) use ( $scope ) {
- if ( $scope and ! in_array( $group['key'], $scope ) ) {
- return false;
- }
- return $group['show_in_rest'];
- }
- );
- }
-
- private function get_fields( $field_group, $object_id = null ) {
-
- $fields = array_filter(
- acf_get_fields( $field_group ),
- function ( $field ) {
- $field_type = acf_get_field_type( $field['type'] );
- return isset( $field_type->show_in_rest ) && $field_type->show_in_rest;
- }
- );
-
- $resource = array(
- 'type' => $this->request->object_type,
- 'sub_type' => $this->request->object_sub_type,
- 'id' => $object_id,
- );
- $http_method = $this->request->http_method;
-
- return (array) apply_filters( 'acf/rest/get_fields', $fields, $resource, $http_method );
- }
- }
|