WordPress 4.5
[autoinstalls/wordpress.git] / wp-includes / customize / class-wp-customize-partial.php
1 <?php
2 /**
3  * Customize API: WP_Customize_Partial class
4  *
5  * @package WordPress
6  * @subpackage Customize
7  * @since 4.5.0
8  */
9
10 /**
11  * Core Customizer class for implementing selective refresh partials.
12  *
13  * Representation of a rendered region in the previewed page that gets
14  * selectively refreshed when an associated setting is changed.
15  * This class is analogous of WP_Customize_Control.
16  *
17  * @since 4.5.0
18  */
19 class WP_Customize_Partial {
20
21         /**
22          * Component.
23          *
24          * @since 4.5.0
25          * @access public
26          * @var WP_Customize_Selective_Refresh
27          */
28         public $component;
29
30         /**
31          * Unique identifier for the partial.
32          *
33          * If the partial is used to display a single setting, this would generally
34          * be the same as the associated setting's ID.
35          *
36          * @since 4.5.0
37          * @access public
38          * @var string
39          */
40         public $id;
41
42         /**
43          * Parsed ID.
44          *
45          * @since 4.5.0
46          * @access private
47          * @var array {
48          *     @type string $base ID base.
49          *     @type array  $keys Keys for multidimensional.
50          * }
51          */
52         protected $id_data = array();
53
54         /**
55          * Type of this partial.
56          *
57          * @since 4.5.0
58          * @access public
59          * @var string
60          */
61         public $type = 'default';
62
63         /**
64          * The jQuery selector to find the container element for the partial.
65          *
66          * @since 4.5.0
67          * @access public
68          * @var string
69          */
70         public $selector;
71
72         /**
73          * IDs for settings tied to the partial.
74          *
75          * @access public
76          * @since 4.5.0
77          * @var array
78          */
79         public $settings;
80
81         /**
82          * The ID for the setting that this partial is primarily responsible for rendering.
83          *
84          * If not supplied, it will default to the ID of the first setting.
85          *
86          * @since 4.5.0
87          * @access public
88          * @var string
89          */
90         public $primary_setting;
91
92         /**
93          * Capability required to edit this partial.
94          *
95          * Normally this is empty and the capability is derived from the capabilities
96          * of the associated `$settings`.
97          *
98          * @since 4.5.0
99          * @access public
100          * @var string
101          */
102         public $capability;
103
104         /**
105          * Render callback.
106          *
107          * @since 4.5.0
108          * @access public
109          * @see WP_Customize_Partial::render()
110          * @var callable Callback is called with one argument, the instance of
111          *                 WP_Customize_Partial. The callback can either echo the
112          *                 partial or return the partial as a string, or return false if error.
113          */
114         public $render_callback;
115
116         /**
117          * Whether the container element is included in the partial, or if only the contents are rendered.
118          *
119          * @since 4.5.0
120          * @access public
121          * @var bool
122          */
123         public $container_inclusive = false;
124
125         /**
126          * Whether to refresh the entire preview in case a partial cannot be refreshed.
127          *
128          * A partial render is considered a failure if the render_callback returns false.
129          *
130          * @since 4.5.0
131          * @access public
132          * @var bool
133          */
134         public $fallback_refresh = true;
135
136         /**
137          * Constructor.
138          *
139          * Supplied `$args` override class property defaults.
140          *
141          * If `$args['settings']` is not defined, use the $id as the setting ID.
142          *
143          * @since 4.5.0
144          * @access public
145          *
146          * @param WP_Customize_Selective_Refresh $component Customize Partial Refresh plugin instance.
147          * @param string                         $id        Control ID.
148          * @param array                          $args      {
149          *     Optional. Arguments to override class property defaults.
150          *
151          *     @type array|string $settings All settings IDs tied to the partial. If undefined, `$id` will be used.
152          * }
153          */
154         public function __construct( WP_Customize_Selective_Refresh $component, $id, $args = array() ) {
155                 $keys = array_keys( get_object_vars( $this ) );
156                 foreach ( $keys as $key ) {
157                         if ( isset( $args[ $key ] ) ) {
158                                 $this->$key = $args[ $key ];
159                         }
160                 }
161
162                 $this->component       = $component;
163                 $this->id              = $id;
164                 $this->id_data['keys'] = preg_split( '/\[/', str_replace( ']', '', $this->id ) );
165                 $this->id_data['base'] = array_shift( $this->id_data['keys'] );
166
167                 if ( empty( $this->render_callback ) ) {
168                         $this->render_callback = array( $this, 'render_callback' );
169                 }
170
171                 // Process settings.
172                 if ( ! isset( $this->settings ) ) {
173                         $this->settings = array( $id );
174                 } else if ( is_string( $this->settings ) ) {
175                         $this->settings = array( $this->settings );
176                 }
177
178                 if ( empty( $this->primary_setting ) ) {
179                         $this->primary_setting = current( $this->settings );
180                 }
181         }
182
183         /**
184          * Retrieves parsed ID data for multidimensional setting.
185          *
186          * @since 4.5.0
187          * @access public
188          *
189          * @return array {
190          *     ID data for multidimensional partial.
191          *
192          *     @type string $base ID base.
193          *     @type array  $keys Keys for multidimensional array.
194          * }
195          */
196         final public function id_data() {
197                 return $this->id_data;
198         }
199
200         /**
201          * Renders the template partial involving the associated settings.
202          *
203          * @since 4.5.0
204          * @access public
205          *
206          * @param array $container_context Optional. Array of context data associated with the target container (placement).
207          *                                 Default empty array.
208          * @return string|array|false The rendered partial as a string, raw data array (for client-side JS template),
209          *                            or false if no render applied.
210          */
211         final public function render( $container_context = array() ) {
212                 $partial  = $this;
213                 $rendered = false;
214
215                 if ( ! empty( $this->render_callback ) ) {
216                         ob_start();
217                         $return_render = call_user_func( $this->render_callback, $this, $container_context );
218                         $ob_render = ob_get_clean();
219
220                         if ( null !== $return_render && '' !== $ob_render ) {
221                                 _doing_it_wrong( __FUNCTION__, __( 'Partial render must echo the content or return the content string (or array), but not both.' ), '4.5.0' );
222                         }
223
224                         /*
225                          * Note that the string return takes precedence because the $ob_render may just\
226                          * include PHP warnings or notices.
227                          */
228                         $rendered = null !== $return_render ? $return_render : $ob_render;
229                 }
230
231                 /**
232                  * Filters partial rendering.
233                  *
234                  * @since 4.5.0
235                  *
236                  * @param string|array|false   $rendered          The partial value. Default false.
237                  * @param WP_Customize_Partial $partial           WP_Customize_Setting instance.
238                  * @param array                $container_context Optional array of context data associated with
239                  *                                                the target container.
240                  */
241                 $rendered = apply_filters( 'customize_partial_render', $rendered, $partial, $container_context );
242
243                 /**
244                  * Filters partial rendering for a specific partial.
245                  *
246                  * The dynamic portion of the hook name, `$partial->ID` refers to the partial ID.
247                  *
248                  * @since 4.5.0
249                  *
250                  * @param string|array|false   $rendered          The partial value. Default false.
251                  * @param WP_Customize_Partial $partial           WP_Customize_Setting instance.
252                  * @param array                $container_context Optional array of context data associated with
253                  *                                                the target container.
254                  */
255                 $rendered = apply_filters( "customize_partial_render_{$partial->id}", $rendered, $partial, $container_context );
256
257                 return $rendered;
258         }
259
260         /**
261          * Default callback used when invoking WP_Customize_Control::render().
262          *
263          * Note that this method may echo the partial *or* return the partial as
264          * a string or array, but not both. Output buffering is performed when this
265          * is called. Subclasses can override this with their specific logic, or they
266          * may provide an 'render_callback' argument to the constructor.
267          *
268          * This method may return an HTML string for straight DOM injection, or it
269          * may return an array for supporting Partial JS subclasses to render by
270          * applying to client-side templating.
271          *
272          * @since 4.5.0
273          * @access public
274          *
275          * @param WP_Customize_Partial $partial Partial.
276          * @param array                $context Context.
277          * @return string|array|false
278          */
279         public function render_callback( WP_Customize_Partial $partial, $context = array() ) {
280                 unset( $partial, $context );
281                 return false;
282         }
283
284         /**
285          * Retrieves the data to export to the client via JSON.
286          *
287          * @since 4.5.0
288          * @access public
289          *
290          * @return array Array of parameters passed to the JavaScript.
291          */
292         public function json() {
293                 $exports = array(
294                         'settings'           => $this->settings,
295                         'primarySetting'     => $this->primary_setting,
296                         'selector'           => $this->selector,
297                         'type'               => $this->type,
298                         'fallbackRefresh'    => $this->fallback_refresh,
299                         'containerInclusive' => $this->container_inclusive,
300                 );
301                 return $exports;
302         }
303
304         /**
305          * Checks if the user can refresh this partial.
306          *
307          * Returns false if the user cannot manipulate one of the associated settings,
308          * or if one of the associated settings does not exist.
309          *
310          * @since 4.5.0
311          * @access public
312          *
313          * @return bool False if user can't edit one one of the related settings,
314          *                    or if one of the associated settings does not exist.
315          */
316         final public function check_capabilities() {
317                 if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) {
318                         return false;
319                 }
320                 foreach ( $this->settings as $setting_id ) {
321                         $setting = $this->component->manager->get_setting( $setting_id );
322                         if ( ! $setting || ! $setting->check_capabilities() ) {
323                                 return false;
324                         }
325                 }
326                 return true;
327         }
328 }