PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.9.1
Secure Custom Fields v6.9.1
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / includes / fields / FlexibleContent / Render.php
secure-custom-fields / includes / fields / FlexibleContent Last commit date
Layout.php 7 months ago Render.php 2 months ago
Render.php
274 lines
1 <?php
2 /**
3 * A helper class for rendering Flexible Content fields.
4 *
5 * @package SCF
6 */
7
8 namespace SCF\Fields\FlexibleContent;
9
10 // Exit if accessed directly.
11 defined( 'ABSPATH' ) || exit;
12
13 /**
14 * Class for rendering Flexible Content fields.
15 *
16 * @since 6.5
17 */
18 class Render {
19
20 /**
21 * The main field array used to render the Flexible Content field.
22 *
23 * @var array
24 */
25 private $field;
26
27 /**
28 * An array of layouts used by the Flexible Content field.
29 *
30 * @var array
31 */
32 private $layouts;
33
34 /**
35 * An array of meta for the layouts being rendered.
36 *
37 * @var array
38 */
39 private $layout_meta;
40
41 /**
42 * Constructs the class.
43 *
44 * @since 6.5
45 *
46 * @param array $field The flexible content field being rendered.
47 * @param array $layout_meta An array of meta for the layouts being rendered.
48 * @return void
49 */
50 public function __construct( $field, $layout_meta ) {
51 $this->field = $field;
52 $this->layout_meta = $layout_meta;
53 $this->setup();
54 }
55
56 /**
57 * Prepares the field for rendering.
58 *
59 * @since 6.5
60 *
61 * @return void
62 */
63 private function setup() {
64 $layouts = array();
65
66 if ( ! empty( $this->field['layouts'] ) ) {
67 foreach ( $this->field['layouts'] as $layout ) {
68 $layouts[ $layout['name'] ] = $layout;
69 }
70 }
71
72 $this->layouts = $layouts;
73 }
74
75 /**
76 * Renders the Flexible Content field.
77 *
78 * @since 6.5
79 *
80 * @return void
81 */
82 public function render() {
83 $div_attrs = array(
84 'class' => 'acf-flexible-content',
85 'data-min' => $this->field['min'],
86 'data-max' => $this->field['max'],
87 'data-button-label' => esc_attr( $this->field['button_label'] ),
88 'data-nonce' => wp_create_nonce( 'acf_field_' . $this->field['type'] . '_' . $this->field['key'] ),
89 );
90
91 if ( empty( $this->field['value'] ) ) {
92 $div_attrs['class'] .= ' -empty';
93 }
94
95 echo '<div ' . acf_esc_attrs( $div_attrs ) . '>'; // Main wrapper div.
96
97 acf_hidden_input( array( 'name' => $this->field['name'] ) );
98
99 $this->actions( 'top' );
100 $this->no_value_message();
101 $this->clones();
102 $this->layouts();
103 $this->actions( 'bottom' );
104 $this->add_layout_menu();
105 $this->more_layout_actions();
106
107 echo '</div>'; // End main wrapper div.
108 }
109
110 /**
111 * Renders the no value message.
112 *
113 * @since 6.5
114 *
115 * @return void
116 */
117 private function no_value_message() {
118 // translators: %s the button label used for adding a new layout.
119 $no_value_message = __( 'Click the "%s" button below to start creating your layout', 'secure-custom-fields' );
120 $no_value_message = apply_filters( 'acf/fields/flexible_content/no_value_message', $no_value_message, $this->field );
121 $no_value_message = sprintf( $no_value_message, $this->field['button_label'] );
122
123 echo '<div class="no-value-message">' . acf_esc_html( $no_value_message ) . '</div>';
124 }
125
126 /**
127 * Renders the ACF clone indexes for the layouts.
128 *
129 * @since 6.5
130 *
131 * @return void
132 */
133 private function clones() {
134 echo '<div class="clones">';
135
136 if ( ! empty( $this->layouts ) ) {
137 foreach ( $this->layouts as $layout ) {
138 $clone = new Layout( $this->field, $layout, 'acfcloneindex', array() );
139 $clone->render();
140 }
141 }
142
143 echo '</div>';
144 }
145
146 /**
147 * Renders the layouts for a Flexible Content field.
148 *
149 * @since 6.5
150 *
151 * @return void
152 */
153 private function layouts() {
154 echo '<div class="values">';
155
156 $disabled_layouts = ! empty( $this->layout_meta['disabled'] ) ? $this->layout_meta['disabled'] : array();
157 $renamed_layouts = ! empty( $this->layout_meta['renamed'] ) ? $this->layout_meta['renamed'] : array();
158
159 if ( ! empty( $this->field['value'] ) ) {
160 foreach ( $this->field['value'] as $order => $value ) {
161 if ( ! is_array( $value ) ) {
162 continue;
163 }
164
165 if ( empty( $this->layouts[ $value['acf_fc_layout'] ] ) ) {
166 continue;
167 }
168
169 $layout = new Layout(
170 $this->field,
171 $this->layouts[ $value['acf_fc_layout'] ],
172 $order,
173 $value,
174 in_array( $order, $disabled_layouts, true ),
175 ! empty( $renamed_layouts[ $order ] ) ? $renamed_layouts[ $order ] : '',
176 );
177
178 $layout->render();
179 }
180 }
181
182 echo '</div>';
183 }
184
185 /**
186 * Renders top-level actions for the Flexible Content field.
187 *
188 * @since 6.5
189 *
190 * @param string $which The location of the actions, either 'top' or 'bottom'.
191 * @return void
192 */
193 private function actions( string $which = '' ) {
194 if ( 'top' === $which ) {
195 ?>
196 <div class="acf-actions acf-fc-top-actions">
197 <button class="acf-btn acf-btn-clear acf-fc-expand-all">
198 <?php esc_html_e( 'Expand All', 'secure-custom-fields' ); ?>
199 </button>
200 <button class="acf-btn acf-btn-clear acf-fc-collapse-all">
201 <?php esc_html_e( 'Collapse All', 'secure-custom-fields' ); ?>
202 </button>
203 <span class="acf-separator"></span>
204 <a class="acf-button button button-primary" href="#" data-name="add-layout" data-context="top-actions">
205 <i class="acf-icon -plus small"></i>
206 <?php echo acf_esc_html( $this->field['button_label'] ); ?>
207 </a>
208 </div>
209 <?php
210 } else {
211 ?>
212 <div class="acf-actions">
213 <a class="acf-button button button-primary" href="#" data-name="add-layout" data-context="bottom-actions">
214 <i class="acf-icon -plus small"></i>
215 <?php echo acf_esc_html( $this->field['button_label'] ); ?>
216 </a>
217 </div>
218 <?php
219 }
220 }
221
222 /**
223 * Renders the dropdown menu to add more layouts.
224 *
225 * @since 6.5
226 *
227 * @return void
228 */
229 private function add_layout_menu() {
230 echo '<script type="text-html" class="tmpl-popup"><ul>';
231 foreach ( $this->layouts as $layout ) {
232 $safe_label = acf_esc_html( $layout['label'] );
233 $atts = array(
234 'href' => '#',
235 'data-layout' => $layout['name'],
236 'data-min' => $layout['min'],
237 'data-max' => $layout['max'],
238 'title' => $safe_label,
239 );
240 printf( '<li><a %s>%s</a></li>', acf_esc_attrs( $atts ), $safe_label ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped above.
241 }
242 echo '</ul></script>';
243 }
244
245 /**
246 * Renders the dropdown menu for additional layout actions.
247 *
248 * @since 6.5
249 *
250 * @return void
251 */
252 private function more_layout_actions() {
253 ?>
254 <script type="text-html" class="tmpl-more-layout-actions">
255 <ul role="menu" tabindex="-1">
256 <li>
257 <a class="acf-rename-layout" data-action="rename-layout" href="#" role="menuitem">
258 <?php esc_html_e( 'Rename', 'secure-custom-fields' ); ?>
259 </a>
260 </li>
261 <li>
262 <a class="acf-toggle-layout disable" data-action="toggle-layout" href="#" role="menuitem">
263 <?php esc_html_e( 'Disable', 'secure-custom-fields' ); ?>
264 </a>
265 <a class="acf-toggle-layout enable" data-action="toggle-layout" href="#" role="menuitem">
266 <?php esc_html_e( 'Enable', 'secure-custom-fields' ); ?>
267 </a>
268 </li>
269 </ul>
270 </script>
271 <?php
272 }
273 }
274