CMB2_Ajax

CMB2 ajax methods (i.e.

Defined (1)

The class is defined in the following location(s).

/includes/CMB2_Ajax.php  
  1. class CMB2_Ajax { 
  2.  
  3. // Whether to hijack the oembed cache system 
  4. protected $hijack = false; 
  5. protected $object_id = 0; 
  6. protected $embed_args = array(); 
  7. protected $object_type = 'post'; 
  8. protected $ajax_update = false; 
  9.  
  10. /** 
  11. * Instance of this class 
  12. * @since 2.2.2 
  13. * @var object 
  14. */ 
  15. protected static $instance; 
  16.  
  17. /** 
  18. * Get the singleton instance of this class 
  19. * @since 2.2.2 
  20. * @return object 
  21. */ 
  22. public static function get_instance() { 
  23. if ( ! ( self::$instance instanceof self ) ) { 
  24. self::$instance = new self(); 
  25.  
  26. return self::$instance; 
  27.  
  28. /** 
  29. * Constructor 
  30. * @since 2.2.0 
  31. */ 
  32. protected function __construct() { 
  33. add_action( 'wp_ajax_cmb2_oembed_handler', array( $this, 'oembed_handler' ) ); 
  34. add_action( 'wp_ajax_nopriv_cmb2_oembed_handler', array( $this, 'oembed_handler' ) ); 
  35. // Need to occasionally clean stale oembed cache data from the option value. 
  36. add_action( 'cmb2_save_options-page_fields', array( __CLASS__, 'clean_stale_options_page_oembeds' ) ); 
  37.  
  38. /** 
  39. * Handles our oEmbed ajax request 
  40. * @since 0.9.5 
  41. * @return object oEmbed embed code | fallback | error message 
  42. */ 
  43. public function oembed_handler() { 
  44.  
  45. // Verify our nonce 
  46. if ( ! ( isset( $_REQUEST['cmb2_ajax_nonce'], $_REQUEST['oembed_url'] ) && wp_verify_nonce( $_REQUEST['cmb2_ajax_nonce'], 'ajax_nonce' ) ) ) { 
  47. die(); 
  48.  
  49. // Sanitize our search string 
  50. $oembed_string = sanitize_text_field( $_REQUEST['oembed_url'] ); 
  51.  
  52. // Send back error if empty 
  53. if ( empty( $oembed_string ) ) { 
  54. wp_send_json_error( '<p class="ui-state-error-text">' . esc_html__( 'Please Try Again', 'cmb2' ) . '</p>' ); 
  55.  
  56. // Set width of embed 
  57. $embed_width = isset( $_REQUEST['oembed_width'] ) && intval( $_REQUEST['oembed_width'] ) < 640 ? intval( $_REQUEST['oembed_width'] ) : '640'; 
  58.  
  59. // Set url 
  60. $oembed_url = esc_url( $oembed_string ); 
  61.  
  62. // Set args 
  63. $embed_args = array( 'width' => $embed_width ); 
  64.  
  65. $this->ajax_update = true; 
  66.  
  67. // Get embed code (or fallback link) 
  68. $html = $this->get_oembed( array( 
  69. 'url' => $oembed_url,  
  70. 'object_id' => $_REQUEST['object_id'],  
  71. 'object_type' => isset( $_REQUEST['object_type'] ) ? $_REQUEST['object_type'] : 'post',  
  72. 'oembed_args' => $embed_args,  
  73. 'field_id' => $_REQUEST['field_id'],  
  74. ) ); 
  75.  
  76. wp_send_json_success( $html ); 
  77.  
  78. /** 
  79. * Retrieves oEmbed from url/object ID 
  80. * @since 0.9.5 
  81. * @param array $args Arguments for method 
  82. * @return string html markup with embed or fallback 
  83. */ 
  84. public function get_oembed_no_edit( $args ) { 
  85. global $wp_embed; 
  86.  
  87. $oembed_url = esc_url( $args['url'] ); 
  88.  
  89. // Sanitize object_id 
  90. $this->object_id = is_numeric( $args['object_id'] ) ? absint( $args['object_id'] ) : sanitize_text_field( $args['object_id'] ); 
  91.  
  92. $args = wp_parse_args( $args, array( 
  93. 'object_type' => 'post',  
  94. 'oembed_args' => $this->embed_args,  
  95. 'field_id' => false,  
  96. 'wp_error' => false,  
  97. ) ); 
  98.  
  99. $this->embed_args =& $args; 
  100.  
  101. /** 
  102. * Set the post_ID so oEmbed won't fail 
  103. * wp-includes/class-wp-embed.php, WP_Embed::shortcode() 
  104. */ 
  105. $wp_embed->post_ID = $this->object_id; 
  106.  
  107. // Special scenario if NOT a post object 
  108. if ( isset( $args['object_type'] ) && 'post' != $args['object_type'] ) { 
  109.  
  110. if ( 'options-page' == $args['object_type'] ) { 
  111.  
  112. // Bogus id to pass some numeric checks. Issue with a VERY large WP install? 
  113. $wp_embed->post_ID = 1987645321; 
  114.  
  115. // Ok, we need to hijack the oembed cache system 
  116. $this->hijack = true; 
  117. $this->object_type = $args['object_type']; 
  118.  
  119. // Gets ombed cache from our object's meta (vs postmeta) 
  120. add_filter( 'get_post_metadata', array( $this, 'hijack_oembed_cache_get' ), 10, 3 ); 
  121.  
  122. // Sets ombed cache in our object's meta (vs postmeta) 
  123. add_filter( 'update_post_metadata', array( $this, 'hijack_oembed_cache_set' ), 10, 4 ); 
  124.  
  125.  
  126. $embed_args = ''; 
  127.  
  128. foreach ( $args['oembed_args'] as $key => $val ) { 
  129. $embed_args .= " $key=\"$val\""; 
  130.  
  131. // Ping WordPress for an embed 
  132. $embed = $wp_embed->run_shortcode( '[embed' . $embed_args . ']' . $oembed_url . '[/embed]' ); 
  133.  
  134. // Fallback that WordPress creates when no oEmbed was found 
  135. $fallback = $wp_embed->maybe_make_link( $oembed_url ); 
  136.  
  137. return compact( 'embed', 'fallback', 'args' ); 
  138.  
  139. /** 
  140. * Retrieves oEmbed from url/object ID 
  141. * @since 0.9.5 
  142. * @param array $args Arguments for method 
  143. * @return string html markup with embed or fallback 
  144. */ 
  145. public function get_oembed( $args ) { 
  146. $oembed = $this->get_oembed_no_edit( $args ); 
  147.  
  148. // Send back our embed 
  149. if ( $oembed['embed'] && $oembed['embed'] != $oembed['fallback'] ) { 
  150. return '<div class="cmb2-oembed embed-status">' . $oembed['embed'] . '<p class="cmb2-remove-wrapper"><a href="#" class="cmb2-remove-file-button" rel="' . $oembed['args']['field_id'] . '">' . esc_html__( 'Remove Embed', 'cmb2' ) . '</a></p></div>'; 
  151.  
  152. // Otherwise, send back error info that no oEmbeds were found 
  153. return sprintf( 
  154. '<p class="ui-state-error-text">%s</p>',  
  155. sprintf( 
  156. /** translators: 1: results for. 2: link to codex.wordpress.org/Embeds */ 
  157. esc_html__( 'No oEmbed Results Found for %1$s. View more info at %2$s.', 'cmb2' ),  
  158. $oembed['fallback'],  
  159. '<a href="https://codex.wordpress.org/Embeds" target="_blank">codex.wordpress.org/Embeds</a>' 
  160. ); 
  161.  
  162. /** 
  163. * Hijacks retrieving of cached oEmbed. 
  164. * Returns cached data from relevant object metadata (vs postmeta) 
  165. * @since 0.9.5 
  166. * @param boolean $check Whether to retrieve postmeta or override 
  167. * @param int $object_id Object ID 
  168. * @param string $meta_key Object metakey 
  169. * @return mixed Object's oEmbed cached data 
  170. */ 
  171. public function hijack_oembed_cache_get( $check, $object_id, $meta_key ) { 
  172. if ( ! $this->hijack || ( $this->object_id != $object_id && 1987645321 !== $object_id ) ) { 
  173. return $check; 
  174.  
  175. if ( $this->ajax_update ) { 
  176. return false; 
  177.  
  178. return $this->cache_action( $meta_key ); 
  179.  
  180. /** 
  181. * Hijacks saving of cached oEmbed. 
  182. * Saves cached data to relevant object metadata (vs postmeta) 
  183. * @since 0.9.5 
  184. * @param boolean $check Whether to continue setting postmeta 
  185. * @param int $object_id Object ID to get postmeta from 
  186. * @param string $meta_key Postmeta's key 
  187. * @param mixed $meta_value Value of the postmeta to be saved 
  188. * @return boolean Whether to continue setting 
  189. */ 
  190. public function hijack_oembed_cache_set( $check, $object_id, $meta_key, $meta_value ) { 
  191.  
  192. if ( 
  193. ! $this->hijack 
  194. || ( $this->object_id != $object_id && 1987645321 !== $object_id ) 
  195. // only want to hijack oembed meta values 
  196. || 0 !== strpos( $meta_key, '_oembed_' ) 
  197. ) { 
  198. return $check; 
  199.  
  200. $this->cache_action( $meta_key, $meta_value ); 
  201.  
  202. // Anything other than `null` to cancel saving to postmeta 
  203. return true; 
  204.  
  205. /** 
  206. * Gets/updates the cached oEmbed value from/to relevant object metadata (vs postmeta) 
  207. * @since 1.3.0 
  208. * @param string $meta_key Postmeta's key 
  209. * @param mixed $meta_value (Optional) value of the postmeta to be saved 
  210. */ 
  211. protected function cache_action( $meta_key ) { 
  212. $func_args = func_get_args(); 
  213. $action = isset( $func_args[1] ) ? 'update' : 'get'; 
  214.  
  215. if ( 'options-page' === $this->object_type ) { 
  216.  
  217. $args = array( $meta_key ); 
  218.  
  219. if ( 'update' === $action ) { 
  220. $args[] = $func_args[1]; 
  221. $args[] = true; 
  222.  
  223. // Cache the result to our options 
  224. $status = call_user_func_array( array( cmb2_options( $this->object_id ), $action ), $args ); 
  225. } else { 
  226.  
  227. $args = array( $this->object_type, $this->object_id, $meta_key ); 
  228. $args[] = 'update' === $action ? $func_args : true; 
  229.  
  230. // Cache the result to our metadata 
  231. $status = call_user_func_array( $action . '_metadata', $args ); 
  232.  
  233. return $status; 
  234.  
  235. /** 
  236. * Hooks in when options-page data is saved to clean stale 
  237. * oembed cache data from the option value. 
  238. * @since 2.2.0 
  239. * @param string $option_key The options-page option key 
  240. * @return void 
  241. */ 
  242. public static function clean_stale_options_page_oembeds( $option_key ) { 
  243. $options = cmb2_options( $option_key )->get_options(); 
  244. if ( is_array( $options ) ) { 
  245.  
  246. $ttl = apply_filters( 'oembed_ttl', DAY_IN_SECONDS, '', array(), 0 ); 
  247. $now = time(); 
  248. $modified = false; 
  249.  
  250. foreach ( $options as $key => $value ) { 
  251. // Check for cached oembed data 
  252. if ( 0 === strpos( $key, '_oembed_time_' ) ) { 
  253. $cached_recently = ( $now - $value ) < $ttl; 
  254.  
  255. if ( ! $cached_recently ) { 
  256. $modified = true; 
  257. // Remove the the cached ttl expiration, and the cached oembed value. 
  258. unset( $options[ $key ] ); 
  259. unset( $options[ str_replace( '_oembed_time_', '_oembed_', $key ) ] ); 
  260. // Remove the cached unknown values 
  261. elseif ( '{{unknown}}' === $value ) { 
  262. $modified = true; 
  263. unset( $options[ $key ] ); 
  264. // Update the option and remove stale cache data 
  265. if ( $modified ) { 
  266. $updated = cmb2_options( $option_key )->set( $options ); 
  267.