PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.6.0
Secure Custom Fields v6.6.0
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 7 months ago
Render.php
273 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 );
89
90 if ( empty( $this->field['value'] ) ) {
91 $div_attrs['class'] .= ' -empty';
92 }
93
94 echo '<div ' . acf_esc_attrs( $div_attrs ) . '>'; // Main wrapper div.
95
96 acf_hidden_input( array( 'name' => $this->field['name'] ) );
97
98 $this->actions( 'top' );
99 $this->no_value_message();
100 $this->clones();
101 $this->layouts();
102 $this->actions( 'bottom' );
103 $this->add_layout_menu();
104 $this->more_layout_actions();
105
106 echo '</div>'; // End main wrapper div.
107 }
108
109 /**
110 * Renders the no value message.
111 *
112 * @since 6.5
113 *
114 * @return void
115 */
116 private function no_value_message() {
117 // translators: %s the button label used for adding a new layout.
118 $no_value_message = __( 'Click the "%s" button below to start creating your layout', 'secure-custom-fields' );
119 $no_value_message = apply_filters( 'acf/fields/flexible_content/no_value_message', $no_value_message, $this->field );
120 $no_value_message = sprintf( $no_value_message, $this->field['button_label'] );
121
122 echo '<div class="no-value-message">' . acf_esc_html( $no_value_message ) . '</div>';
123 }
124
125 /**
126 * Renders the ACF clone indexes for the layouts.
127 *
128 * @since 6.5
129 *
130 * @return void
131 */
132 private function clones() {
133 echo '<div class="clones">';
134
135 if ( ! empty( $this->layouts ) ) {
136 foreach ( $this->layouts as $layout ) {
137 $clone = new Layout( $this->field, $layout, 'acfcloneindex', array() );
138 $clone->render();
139 }
140 }
141
142 echo '</div>';
143 }
144
145 /**
146 * Renders the layouts for a Flexible Content field.
147 *
148 * @since 6.5
149 *
150 * @return void
151 */
152 private function layouts() {
153 echo '<div class="values">';
154
155 $disabled_layouts = ! empty( $this->layout_meta['disabled'] ) ? $this->layout_meta['disabled'] : array();
156 $renamed_layouts = ! empty( $this->layout_meta['renamed'] ) ? $this->layout_meta['renamed'] : array();
157
158 if ( ! empty( $this->field['value'] ) ) {
159 foreach ( $this->field['value'] as $order => $value ) {
160 if ( ! is_array( $value ) ) {
161 continue;
162 }
163
164 if ( empty( $this->layouts[ $value['acf_fc_layout'] ] ) ) {
165 continue;
166 }
167
168 $layout = new Layout(
169 $this->field,
170 $this->layouts[ $value['acf_fc_layout'] ],
171 $order,
172 $value,
173 in_array( $order, $disabled_layouts, true ),
174 ! empty( $renamed_layouts[ $order ] ) ? $renamed_layouts[ $order ] : '',
175 );
176
177 $layout->render();
178 }
179 }
180
181 echo '</div>';
182 }
183
184 /**
185 * Renders top-level actions for the Flexible Content field.
186 *
187 * @since 6.5
188 *
189 * @param string $which The location of the actions, either 'top' or 'bottom'.
190 * @return void
191 */
192 private function actions( string $which = '' ) {
193 if ( 'top' === $which ) {
194 ?>
195 <div class="acf-actions acf-fc-top-actions">
196 <button class="acf-btn acf-btn-clear acf-fc-expand-all">
197 <?php esc_html_e( 'Expand All', 'secure-custom-fields' ); ?>
198 </button>
199 <button class="acf-btn acf-btn-clear acf-fc-collapse-all">
200 <?php esc_html_e( 'Collapse All', 'secure-custom-fields' ); ?>
201 </button>
202 <span class="acf-separator"></span>
203 <a class="acf-button button button-primary" href="#" data-name="add-layout" data-context="top-actions">
204 <i class="acf-icon -plus small"></i>
205 <?php echo acf_esc_html( $this->field['button_label'] ); ?>
206 </a>
207 </div>
208 <?php
209 } else {
210 ?>
211 <div class="acf-actions">
212 <a class="acf-button button button-primary" href="#" data-name="add-layout" data-context="bottom-actions">
213 <i class="acf-icon -plus small"></i>
214 <?php echo acf_esc_html( $this->field['button_label'] ); ?>
215 </a>
216 </div>
217 <?php
218 }
219 }
220
221 /**
222 * Renders the dropdown menu to add more layouts.
223 *
224 * @since 6.5
225 *
226 * @return void
227 */
228 private function add_layout_menu() {
229 echo '<script type="text-html" class="tmpl-popup"><ul>';
230 foreach ( $this->layouts as $layout ) {
231 $safe_label = acf_esc_html( $layout['label'] );
232 $atts = array(
233 'href' => '#',
234 'data-layout' => $layout['name'],
235 'data-min' => $layout['min'],
236 'data-max' => $layout['max'],
237 'title' => $safe_label,
238 );
239 printf( '<li><a %s>%s</a></li>', acf_esc_attrs( $atts ), $safe_label ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped above.
240 }
241 echo '</ul></script>';
242 }
243
244 /**
245 * Renders the dropdown menu for additional layout actions.
246 *
247 * @since 6.5
248 *
249 * @return void
250 */
251 private function more_layout_actions() {
252 ?>
253 <script type="text-html" class="tmpl-more-layout-actions">
254 <ul role="menu" tabindex="-1">
255 <li>
256 <a class="acf-rename-layout" data-action="rename-layout" href="#" role="menuitem">
257 <?php esc_html_e( 'Rename', 'secure-custom-fields' ); ?>
258 </a>
259 </li>
260 <li>
261 <a class="acf-toggle-layout disable" data-action="toggle-layout" href="#" role="menuitem">
262 <?php esc_html_e( 'Disable', 'secure-custom-fields' ); ?>
263 </a>
264 <a class="acf-toggle-layout enable" data-action="toggle-layout" href="#" role="menuitem">
265 <?php esc_html_e( 'Enable', 'secure-custom-fields' ); ?>
266 </a>
267 </li>
268 </ul>
269 </script>
270 <?php
271 }
272 }
273