PluginProbe ʕ •ᴥ•ʔ
Admin Columns / 7.1.4
Admin Columns v7.1.4
7.1.4 7.0.19 2.3.5 2.4 2.4.1 2.4.10 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.6.1 2.5.6.2 2.5.6.3 2.5.6.4 3.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.7 3.1 3.1.1 3.1.10 3.1.2 3.1.3 3.1.5 3.2.3 3.2.7 3.3.1 3.4.1 3.4.6 3.4.8 4.0.1 4.0.3 4.1.6 4.2.2 4.2.5 4.3 4.3.2 4.4.1 4.4.4 4.4.5 4.5.5 4.6.1 4.7.18 4.7.19 4.7.20 4.7.7 7.0.13 7.0.14 7.0.16 trunk 1.0 1.1 1.1.3 1.2 1.2.1 1.3 1.3.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.5.1 1.4.6 1.4.6.1 1.4.6.2 1.4.6.3 1.4.6.4 1.4.7 1.4.8 1.4.9 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2 2.2.1 2.2.1.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.5.1 2.2.6 2.2.6.1 2.2.6.2 2.2.6.3 2.2.6.4 2.2.7 2.2.8 2.2.8.1 2.2.9 2.3.1 2.3.2 2.3.3
codepress-admin-columns / classes / Acf / Service / FieldSettings.php
codepress-admin-columns / classes / Acf / Service Last commit date
DateSaveFormat.php 2 days ago FieldSettings.php 2 days ago
FieldSettings.php
426 lines
1 <?php
2
3 declare(strict_types=1);
4
5 namespace AC\Acf\Service;
6
7 use AC\Acf;
8 use AC\Acf\ColumnMatcher;
9 use AC\Acf\FieldGroupCache;
10 use AC\Asset\Location\Absolute;
11 use AC\Asset\Script;
12 use AC\Asset\Style;
13 use AC\Column;
14 use AC\ListScreen;
15 use AC\ListScreenRepository\Storage;
16 use AC\Registerable;
17 use AC\TableScreen;
18 use AC\Type\EditorUrlFactory;
19 use AC\Type\TableId;
20 use AC\Type\Uri;
21 use AC\Type\Url\Site;
22 use AC\Type\Url\UtmTags;
23
24 class FieldSettings implements Registerable
25 {
26 private const PRO_ONLY_ACF_TYPES = [
27 'flexible_content',
28 'gallery',
29 'google_map',
30 'group',
31 'link',
32 'relationship',
33 'repeater',
34 'taxonomy',
35 ];
36
37 private const SUPPORTED_ACF_TYPES = [
38 'button_group',
39 'checkbox',
40 'color_picker',
41 'date_picker',
42 'date_time_picker',
43 'email',
44 'file',
45 'image',
46 'number',
47 'oembed',
48 'page_link',
49 'password',
50 'post_object',
51 'radio',
52 'range',
53 'select',
54 'text',
55 'textarea',
56 'time_picker',
57 'true_false',
58 'url',
59 'user',
60 'wysiwyg',
61 ];
62
63 private Storage $storage;
64
65 private FieldGroupCache $field_group_cache;
66
67 private ColumnMatcher $column_matcher;
68
69 private Absolute $location;
70
71 public function __construct(
72 Storage $storage,
73 FieldGroupCache $field_group_cache,
74 ColumnMatcher $column_matcher,
75 Absolute $location
76 ) {
77 $this->storage = $storage;
78 $this->field_group_cache = $field_group_cache;
79 $this->column_matcher = $column_matcher;
80 $this->location = $location;
81 }
82
83 public function register(): void
84 {
85 if (! Acf::is_active()) {
86 return;
87 }
88
89 add_filter('acf/field_group/additional_field_settings_tabs', [$this, 'add_tab']);
90 add_action('acf/field_group/render_field_settings_tab/admin_columns', [$this, 'render_tab']);
91 add_action('acf/field_group/admin_enqueue_scripts', [$this, 'enqueue_scripts']);
92 }
93
94 public function enqueue_scripts(): void
95 {
96 $style = new Style('ac-acf-field-settings', $this->location->with_suffix('assets/css/acf-field-settings.css'));
97 $style->enqueue();
98
99 $script = new Script('ac-acf-field-settings', $this->location->with_suffix('assets/js/acf-field-settings.js'), ['jquery']);
100 $script->enqueue();
101
102 wp_localize_script('ac-acf-field-settings', 'ac_acf_field_settings', [
103 'nonce' => wp_create_nonce('ac-ajax'),
104 'adding' => __('Adding...', 'codepress-admin-columns'),
105 'added' => __('Added', 'codepress-admin-columns'),
106 'edit_column' => __('Edit column →', 'codepress-admin-columns'),
107 'add_as_column' => $this->get_add_column_label(),
108 ]);
109 }
110
111 public function add_tab(array $tabs): array
112 {
113 $tabs['admin_columns'] = __('Admin Columns', 'codepress-admin-columns');
114
115 return $tabs;
116 }
117
118 private function get_add_column_label(): string
119 {
120 return __('Add as column', 'codepress-admin-columns');
121 }
122
123 public function render_tab(array $field): void
124 {
125 if ($this->is_pro_only_field($field)) {
126 $this->render_pro_only_upsell($field);
127
128 return;
129 }
130
131 if (! $this->is_field_supported($field)) {
132 acf_render_field_setting(
133 $field,
134 [
135 'label' => '',
136 'type' => 'message',
137 'name' => 'ac_unsupported',
138 'message' => '<p style="color:#50575e;">'
139 . esc_html__('This field type cannot be used as an admin column.', 'codepress-admin-columns')
140 . '</p>',
141 ]
142 );
143
144 return;
145 }
146
147 $this->render_table_screen_rows($field);
148 }
149
150 private function render_pro_only_upsell(array $field): void
151 {
152 $url = (new UtmTags(new Site(Site::PAGE_ADDON_ACF), 'acf-field-settings-upsell'))->get_url();
153
154 acf_render_field_setting(
155 $field,
156 [
157 'label' => '',
158 'type' => 'message',
159 'name' => 'ac_pro_upsell',
160 'message' => $this->get_upsell_html(
161 __('This field type is supported in Admin Columns Pro', 'codepress-admin-columns'),
162 __('Add this field as a column with sorting, filtering, and inline editing.', 'codepress-admin-columns'),
163 $url,
164 __('Learn more →', 'codepress-admin-columns')
165 ),
166 ]
167 );
168 }
169
170 private function render_table_screen_rows(array $field): void
171 {
172 $table_screens = $this->resolve_table_screens($field);
173
174 if (! $table_screens) {
175 return;
176 }
177
178 $meta_key = $field['name'] ?? '';
179 $has_meta_key = $meta_key !== '' && $meta_key !== 'new_field';
180
181 $rows_html = '';
182
183 foreach ($table_screens as $table_screen) {
184 $table_id = (string)$table_screen->get_id();
185 $label = $table_screen->get_labels()->get_plural();
186
187 if (! $has_meta_key) {
188 $rows_html .= $this->render_unavailable_row($label);
189
190 continue;
191 }
192
193 $match = $this->find_column_in_list_screens($table_screen->get_id(), $meta_key);
194
195 if ($match) {
196 $url = EditorUrlFactory::create($table_screen->get_id(), false, $match['list_screen']->get_id())
197 ->with_arg('open_columns', (string)$match['column']->get_id());
198
199 $rows_html .= $this->render_added_row($label, $url);
200 } else {
201 $rows_html .= $this->render_available_row($table_id, $label);
202 }
203 }
204
205 $intro = '<p class="ac-acf-intro">'
206 . esc_html__('Add this field as a column in the list tables below. Once added, you can open that specific column in Admin Columns to configure it.', 'codepress-admin-columns')
207 . '</p>';
208
209 if (! $has_meta_key) {
210 $intro .= '<div class="ac-acf-notice">'
211 . sprintf(
212 esc_html__('Enter a %1$s under the %2$s tab to enable adding this field as a column.', 'codepress-admin-columns'),
213 '<strong>' . esc_html__('Field Name', 'codepress-admin-columns') . '</strong>',
214 '<strong>' . esc_html__('General', 'codepress-admin-columns') . '</strong>'
215 )
216 . '</div>';
217 }
218
219 $helper = '<p class="ac-acf-helper">'
220 . esc_html__('Column settings are managed in Admin Columns after creation.', 'codepress-admin-columns')
221 . '</p>';
222
223 acf_render_field_setting(
224 $field,
225 [
226 'label' => __('Admin Columns', 'codepress-admin-columns'),
227 'type' => 'message',
228 'name' => 'ac_field_settings',
229 'message' => $intro . '<div class="ac-acf-list">' . $rows_html . '</div>' . $helper,
230 ]
231 );
232
233 $this->render_upsell($field, $table_screens);
234 }
235
236 private function render_added_row(string $label, Uri $editor_url): string
237 {
238 return sprintf(
239 '<div class="ac-acf-card ac-acf-card--added" data-state="added">'
240 . '<div class="ac-acf-card-main">'
241 . '<span class="ac-acf-card-name">%s</span>'
242 . '<span class="ac-acf-status"><span class="ac-acf-badge">&#10003;</span><span class="ac-acf-card-status">%s</span></span>'
243 . '</div>'
244 . '<div class="ac-acf-card-actions">'
245 . '<a href="%s" target="_blank" class="ac-acf-link">%s</a>'
246 . '</div>'
247 . '</div>',
248 esc_html($label),
249 esc_html__('Added', 'codepress-admin-columns'),
250 esc_url((string)$editor_url),
251 esc_html__('Edit column →', 'codepress-admin-columns')
252 );
253 }
254
255 private function render_available_row(string $table_id, string $label): string
256 {
257 return sprintf(
258 '<div class="ac-acf-card" data-state="available" data-table-id="%s">'
259 . '<div class="ac-acf-card-main">'
260 . '<span class="ac-acf-card-name">%s</span>'
261 . '</div>'
262 . '<div class="ac-acf-card-actions">'
263 . '<button type="button" class="button ac-acf-add-column">%s</button>'
264 . '</div>'
265 . '</div>',
266 esc_attr($table_id),
267 esc_html($label),
268 esc_html($this->get_add_column_label())
269 );
270 }
271
272 private function render_unavailable_row(string $label): string
273 {
274 return sprintf(
275 '<div class="ac-acf-card ac-acf-card--unavailable">'
276 . '<div class="ac-acf-card-main">'
277 . '<span class="ac-acf-card-name">%s</span>'
278 . '</div>'
279 . '<div class="ac-acf-card-actions">'
280 . '<button type="button" class="button" disabled>%s</button>'
281 . '</div>'
282 . '</div>',
283 esc_html($label),
284 esc_html($this->get_add_column_label())
285 );
286 }
287
288 /**
289 * @param TableScreen[] $table_screens
290 */
291 private function render_upsell(array $field, array $table_screens): void
292 {
293 $labels = [];
294
295 foreach ($table_screens as $table_screen) {
296 $labels[] = strtolower($table_screen->get_labels()->get_plural());
297 }
298
299 $labels = array_slice($labels, 0, 3);
300
301 if ($labels) {
302 $last = array_pop($labels);
303 $content_label = $labels
304 ? implode(', ', $labels) . ' & ' . $last
305 : $last;
306
307 $description = sprintf(
308 __(
309 'Make this column editable, sortable, and filterable – and manage your %s faster right from the overview.',
310 'codepress-admin-columns'
311 ),
312 $content_label
313 );
314 } else {
315 $description = __(
316 'Make this column editable, sortable, and filterable – and manage your content faster right from the overview.',
317 'codepress-admin-columns'
318 );
319 }
320
321 $url = (new UtmTags(new Site(Site::PAGE_ADDON_ACF), 'acf-field-settings'))->get_url();
322
323 acf_render_field_setting(
324 $field,
325 [
326 'label' => '',
327 'type' => 'message',
328 'name' => 'ac_upsell',
329 'message' => $this->get_upsell_html(
330 __('Unlock powerful column features', 'codepress-admin-columns'),
331 $description,
332 $url,
333 __('Get Admin Columns Pro →', 'codepress-admin-columns')
334 ),
335 ]
336 );
337 }
338
339 private function get_upsell_html(string $title, string $description, string $url, string $link_text): string
340 {
341 return sprintf(
342 '<div class="ac-acf-upsell">'
343 . '<strong>%s</strong><br>'
344 . '%s <a href="%s" target="_blank">%s</a>'
345 . '</div>',
346 esc_html($title),
347 esc_html($description),
348 esc_url($url),
349 esc_html($link_text)
350 );
351 }
352
353 private function is_pro_only_field(array $field): bool
354 {
355 if ($field['type'] === 'select' && ! empty($field['multiple'])) {
356 return true;
357 }
358
359 return $this->is_sub_field($field) || in_array($field['type'], self::PRO_ONLY_ACF_TYPES, true);
360 }
361
362 private function is_field_supported(array $field): bool
363 {
364 return in_array($field['type'], self::SUPPORTED_ACF_TYPES, true);
365 }
366
367 private function is_sub_field(array $field): bool
368 {
369 if (isset($field['parent_repeater'])
370 || isset($field['parent_group'])
371 || isset($field['parent_layout'])
372 || isset($field['_clone'])
373 ) {
374 return true;
375 }
376
377 $parent = $field['parent'] ?? 0;
378
379 if ($parent) {
380 $parent_field = acf_get_field($parent);
381
382 if ($parent_field && in_array($parent_field['type'], ['group', 'repeater', 'flexible_content'], true)) {
383 return true;
384 }
385 }
386
387 return false;
388 }
389
390 /**
391 * @return TableScreen[]
392 */
393 private function resolve_table_screens(array $field): array
394 {
395 static $cache = [];
396
397 $parent = $field['parent'] ?? 0;
398
399 if (! isset($cache[$parent])) {
400 $cache[$parent] = $this->field_group_cache->get_table_screens_for_group((int)$parent);
401 }
402
403 return $cache[$parent];
404 }
405
406 /**
407 * @return array{list_screen: ListScreen, column: Column}|null
408 */
409 private function find_column_in_list_screens(TableId $table_id, string $meta_key): ?array
410 {
411 foreach ($this->storage->find_all_by_table_id($table_id) as $list_screen) {
412 $column = $this->column_matcher->find_column($list_screen, $meta_key);
413
414 if ($column) {
415 return [
416 'list_screen' => $list_screen,
417 'column' => $column,
418 ];
419 }
420 }
421
422 return null;
423 }
424
425 }
426