/wp-content/plugins/wp-dpla/includes/class-wp-dpla-query.php

https://github.com/livinglab/openlab · PHP · 185 lines · 138 code · 37 blank · 10 comment · 19 complexity · a46bc583f1b5bdff0c6e50651d385f23 MD5 · raw file

  1. <?php
  2. class WP_DPLA_Query {
  3. protected $_dpla;
  4. protected $fetched_items = array();
  5. public function get_items_markup() {
  6. $post = get_post();
  7. if ( empty( $post->ID ) ) {
  8. return '';
  9. }
  10. $tkey = $this->get_transient_key( $post->ID );
  11. $items = get_transient( $tkey );
  12. // Six hours by default
  13. $expiration = $this->get_expiration();
  14. if ( false === $items ) {
  15. $items = $this->get_random_items_for_post();
  16. set_transient( $tkey, $items, $expiration );
  17. }
  18. if ( empty( $items ) ) {
  19. return '';
  20. }
  21. $items_markup = '<h3 class="dpla-results-header">' . __( 'Related items from the Digital Public Library of America', 'wp-dpla' ) . '</h3>';
  22. $items_markup .= '<ul class="dpla-results">';
  23. foreach ( $items as $item ) {
  24. $item_markup = '<li>';
  25. $item_markup .= '<div class="dpla-thumbnail">';
  26. $item_markup .= '<a href="' . esc_attr( $item['item_url'] ) . '">';
  27. $item_markup .= '<img alt="' . esc_attr( $item['title'] ) . '" src="' . esc_attr( $item['thumbnail'] ) . '" />';
  28. $item_markup .= '</a>';
  29. $item_markup .= '</div>';
  30. $item_markup .= '<div class="dpla-data">';
  31. $item_markup .= '<span class="dpla-title">';
  32. $item_markup .= '<a href="' . esc_attr( $item['item_url'] ) . '">';
  33. $item_markup .= esc_html( $item['title'] );
  34. $item_markup .= '</a>';
  35. $item_markup .= '</span>';
  36. $item_markup .= '<span class="dpla-provider">';
  37. $item_markup .= '<a href="' . esc_attr( $item['provider_url'] ) . '">';
  38. $item_markup .= esc_html( $item['provider_name'] );
  39. $item_markup .= '</a>';
  40. $item_markup .= '</span>';
  41. $item_markup .= '</div>';
  42. $item_markup .= '</li>';
  43. $items_markup .= $item_markup;
  44. }
  45. $items_markup .= '</ul>';
  46. return $items_markup;
  47. }
  48. protected function get_transient_key( $post_id ) {
  49. return 'dpla_random_posts_post_' . $post_id;
  50. }
  51. protected function get_expiration() {
  52. $expiration = (int) apply_filters( 'wp_dpla_cache_expiration_time', 6 * 60 * 60 );
  53. // Prevent API flooding - don't allow a value less than
  54. // 10 minutes
  55. if ( $expiration < 600 ) {
  56. $expiration = 600;
  57. }
  58. return $expiration;
  59. }
  60. public function get_random_items_for_post( $args = array() ) {
  61. $retval = array();
  62. $post = get_post();
  63. if ( isset( $post->ID ) ) {
  64. $terms = wp_get_post_tags( $post->ID );
  65. if ( ! empty( $terms ) ) {
  66. $search_terms = array();
  67. foreach ( wp_list_pluck( $terms, 'name' ) as $raw_term ) {
  68. $search_terms[] = urlencode( $raw_term );
  69. }
  70. $args['search_term'] = implode( ' OR ', $search_terms );
  71. // We'll get random items, but we first do a
  72. // preliminary query to get a range
  73. $pre_args = $args;
  74. $pre_args['page'] = 1;
  75. $pre_args['per_page'] = 1;
  76. $pre_args['fields'] = implode( ',', array(
  77. 'isShownAt',
  78. 'sourceResource.title',
  79. 'object',
  80. 'provider',
  81. ) );
  82. $pre_query = $this->create_query( $pre_args );
  83. $this->total_count = $pre_query->getTotalCount();
  84. $item_count = isset( $args['per_page'] ) ? (int) $args['per_page'] : 4;
  85. if ( $item_count > $this->total_count ) {
  86. $item_count = $this->total_count;
  87. }
  88. for ( $i = 0; $i < $item_count; $i++ ) {
  89. $retval[] = $this->get_random_item_by_search_term( $args['search_term'] );
  90. }
  91. }
  92. }
  93. return $retval;
  94. }
  95. protected function get_random_item_by_search_term( $search_term ) {
  96. $qargs = array(
  97. 'search_term' => $search_term,
  98. 'per_page' => 1,
  99. 'page' => rand( 1, $this->total_count ),
  100. );
  101. $query = $this->create_query( $qargs );
  102. $documents = $query->getDocuments();
  103. $item = array_pop( $documents );
  104. // No dupes
  105. if ( in_array( $item['isShownAt'], $this->fetched_items ) ) {
  106. return $this->get_random_item_by_search_term( $search_term );
  107. } else {
  108. $this->fetched_items[] = $item['isShownAt'];
  109. }
  110. // sometimes a field is empty
  111. if ( ! isset( $item['sourceResource']['title'], $item['object'], $item['isShownAt'], $item['provider']['name'], $item['provider']['@id'] ) ) {
  112. return $this->get_random_item_by_search_term( $search_term );
  113. }
  114. // We need a thumbnail
  115. if ( ! isset( $item['object'] ) || empty( $item['object'] ) ) {
  116. return $this->get_random_item_by_search_term( $search_term );
  117. }
  118. // sometimes a field is not a string
  119. if ( ! is_string( $item['sourceResource']['title'] ) || ! is_string( $item['object'] ) || ! is_string( $item['isShownAt'] ) || ! is_string( $item['provider']['name'] ) || ! is_string( $item['provider']['@id'] ) ) {
  120. return $this->get_random_item_by_search_term( $search_term );
  121. }
  122. // If the title is an array, just take the first item
  123. $title = is_array( $item['sourceResource']['title'] ) ? array_pop( array_reverse( $item['sourceResource']['title'] ) ) : $item['sourceResource']['title'];
  124. return array(
  125. 'title' => $title,
  126. 'thumbnail' => $item['object'],
  127. 'item_url' => $item['isShownAt'],
  128. 'provider_name' => $item['provider']['name'],
  129. 'provider_url' => $item['provider']['@id'],
  130. );
  131. }
  132. protected function create_query( $args ) {
  133. $r = wp_parse_args( $args, array(
  134. 'per_page' => 4,
  135. 'page' => 1,
  136. 'search_term' => '',
  137. ) );
  138. return $this->get_dpla()->createSearchQuery()->withSourceResourceField( 'title', $r['search_term'] )->withPaging( $r['page'], $r['per_page'] )->execute();
  139. }
  140. protected function get_dpla() {
  141. if ( ! isset( $this->_dpla ) ) {
  142. $api_key = get_option( 'dpla_api_key' );
  143. require_once __DIR__ . '/dpla/class-wp-dpla-dpla.php';
  144. $this->_dpla = new \TFN\WP_DPLA_DPLA( $api_key );
  145. }
  146. return $this->_dpla;
  147. }
  148. }