class-acf-rest-embed-links.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. // Exit if accessed directly.
  3. if ( ! defined( 'ABSPATH' ) ) {
  4. exit;
  5. }
  6. // If class is already defined, return.
  7. if ( class_exists( 'ACF_Rest_Api' ) ) {
  8. return;
  9. }
  10. /**
  11. * Class ACF_Rest_Embed_Links
  12. *
  13. * Manage the addition of embed links on supported REST endpoints.
  14. */
  15. class ACF_Rest_Embed_Links {
  16. /** @var array Links to add to the response. These can be flagged as embeddable and expanded when _embed is passed with the request. */
  17. private $links = array();
  18. public function initialize() {
  19. $this->hook_link_handlers();
  20. }
  21. /**
  22. * Hook into all REST-enabled post type, taxonomy, and the user controllers in order to prepare links.
  23. */
  24. private function hook_link_handlers() {
  25. foreach ( get_post_types( array( 'show_in_rest' => true ) ) as $post_type ) {
  26. add_filter( "rest_prepare_{$post_type}", array( $this, 'load_item_links' ), 10, 3 );
  27. }
  28. foreach ( get_taxonomies( array( 'show_in_rest' => true ) ) as $taxonomy ) {
  29. add_filter( "rest_prepare_{$taxonomy}", array( $this, 'load_item_links' ), 10, 3 );
  30. }
  31. add_filter( 'rest_prepare_user', array( $this, 'load_item_links' ), 10, 3 );
  32. }
  33. /**
  34. * Add links to internal property for subsequent use in \ACF_Rest_Embed_Links::load_item_links().
  35. *
  36. * @param $post_id
  37. * @param array $field
  38. */
  39. public function prepare_links( $post_id, array $field ) {
  40. $links = acf_get_field_rest_links( $post_id, $field );
  41. if ( ! $links ) {
  42. return;
  43. }
  44. foreach ( $links as $link ) {
  45. // If required array keys are not provided, skip.
  46. if ( empty( $link['rel'] ) or empty( $link['href'] ) ) {
  47. continue;
  48. }
  49. // Use the 'rel' and 'href' to for a key. The key only prevents against the same object
  50. // appearing more than once within the same 'rel' property.
  51. $this->links[ $link['rel'] . ':' . $link['href'] ] = $link;
  52. }
  53. }
  54. /**
  55. * Hook into the rest_prepare_{$type} filters and add links for the object being prepared.
  56. *
  57. * @param WP_REST_Response $response
  58. * @param WP_Post|WP_User|WP_Term $item
  59. * @param WP_REST_Request $request
  60. * @return WP_REST_Response
  61. */
  62. public function load_item_links( $response, $item, $request ) {
  63. if ( empty( $this->links ) ) {
  64. return $response;
  65. }
  66. while ( $attributes = array_pop( $this->links ) ) {
  67. $response->add_link(
  68. acf_extract_var( $attributes, 'rel' ),
  69. acf_extract_var( $attributes, 'href' ),
  70. $attributes
  71. );
  72. }
  73. // Reset the links prop.
  74. $this->links = array();
  75. return $response;
  76. }
  77. }