summaryrefslogtreecommitdiff
blob: f2de7fc31347218065fc85e60e9b3ad79a20989f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php

// these are helpers for the shortcode and embed render endpoints
abstract class WPCOM_JSON_API_Render_Endpoint extends WPCOM_JSON_API_Endpoint {

	/*
	 * Figure out what scripts and styles to load.
	 * props to o2's o2_Read_API::poll() function for inspiration.
	 *
	 * In short we figure out what scripts load for a "normal" page load by executing wp_head and wp_footer
	 * then we render the embed/shortcode (to both get our result, and to have the shortcode files enqueue their resources)
	 * then we load wp_head and wp_footer again to see what new resources were added
	 * finally we find out the url to the source file and any extra info (like media or init js)
	 */
	function process_render( $callback, $callback_arg ) {
		global $wp_scripts, $wp_styles;

		// initial scripts & styles (to subtract)
		ob_start();
		wp_head();
		wp_footer();
		ob_end_clean();
		$initial_scripts = $wp_scripts->done;
		$initial_styles = $wp_styles->done;

		// actually render the shortcode, get the result, and do the resource loading again so we can subtract..
		ob_start();
		wp_head();
		ob_end_clean();
		$result = call_user_func( $callback, $callback_arg );
		ob_start();
		wp_footer();
		ob_end_clean();

		// find the difference (the new resource files)
		$loaded_scripts = array_diff( $wp_scripts->done, $initial_scripts );
		$loaded_styles = array_diff( $wp_styles->done, $initial_styles );
		return array(
			'result' => $result,
			'loaded_scripts' => $loaded_scripts,
			'loaded_styles' => $loaded_styles,
		);
	}

	/**
	 * Takes the list of styles and scripts and adds them to the JSON response
	 */
	function add_assets( $return, $loaded_scripts, $loaded_styles ) {
		global $wp_scripts, $wp_styles;
		// scripts first, just cuz
		if ( count( $loaded_scripts ) > 0 ) {
			$scripts = array();
			foreach ( $loaded_scripts as $handle ) {
				if ( !isset( $wp_scripts->registered[ $handle ] ) )
					continue;

				$src = $wp_scripts->registered[ $handle ]->src;

				// attach version and an extra query parameters
				$ver = $this->get_version( $wp_scripts->registered[ $handle ]->ver, $wp_scripts->default_version );
				if ( isset( $wp_scripts->args[ $handle ] ) ) {
					$ver = $ver ? $ver . '&amp;' . $wp_scripts->args[$handle] : $wp_scripts->args[$handle];
				}
				$src = add_query_arg( 'ver', $ver, $src );

				// add to an aray so we can return all this info
				$scripts[ $handle ] = array(
					'src' => $src,
				);
				$extra = $wp_scripts->print_extra_script( $handle, false );
				if ( !empty( $extra ) ) {
					$scripts[$handle]['extra'] = $extra;
				}
			}
			$return['scripts'] = $scripts;
		}
		// now styles
		if ( count( $loaded_styles ) > 0 ) {
			$styles = array();
			foreach ( $loaded_styles as $handle ) {
				if ( !isset( $wp_styles->registered[ $handle ] ) )
					continue;

				$src = $wp_styles->registered[ $handle ]->src;

				// attach version and an extra query parameters
				$ver = $this->get_version( $wp_styles->registered[ $handle ]->ver, $wp_styles->default_version );
				if ( isset( $wp_styles->args[ $handle ] ) ) {
					$ver = $ver ? $ver . '&amp;' . $wp_styles->args[$handle] : $wp_styles->args[$handle];
				}
				$src = add_query_arg( 'ver', $ver, $src );

				// is there a special media (print, screen, etc) for this? if not, default to 'all'
				$media = 'all';
				if ( isset( $wp_styles->registered[ $handle ]->args ) ) {
					$media = esc_attr( $wp_styles->registered[ $handle ]->args );
				}

				// add to an array so we can return all this info
				$styles[ $handle ] = array (
					'src' => $src,
					'media' => $media,
				);
			}

			$return['styles'] = $styles;
		}

		return $return;
	}

	/**
	 * Returns the 'version' string set by the shortcode so different versions of scripts/styles can be loaded
	 */
	function get_version( $this_scripts_version, $default_version ) {
		if ( null === $this_scripts_version ) {
			$ver = '';
		} else {
			$ver = $this_scripts_version ? $this_scripts_version : $default_version;
		}
		return $ver;
	}

	/**
	 * given a shortcode, process and return the result
	 */
	function do_shortcode( $shortcode ) {
		return do_shortcode( $shortcode );
	}

	/**
	 * given a one-line embed URL, process and return the result
	 */
	function do_embed( $embed_url ) {
		// in order for oEmbed to fire in the `$wp_embed->shortcode` method, we need to set a post as the current post
		$_posts = get_posts( array( 'posts_per_page' => 1, 'suppress_filters' => false ) );
		if ( ! empty( $_posts ) ) {
			global $post;
			$post = array_shift( $_posts );
		}

		global $wp_embed;
		return $wp_embed->shortcode( array(), $embed_url );
	}
}