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