PluginProbe
PublishPress Statuses – Custom Post Status and Workflow / trunk
PublishPress Statuses – Custom Post Status and Workflow vtrunk
1.3.6 1.3.4 1.3.3 1.3.2 trunk 1.0.4.1 1.0.5 1.0.6 1.0.6.2 1.0.6.3 1.0.6.4 1.0.6.5 1.0.6.6 1.0.6.7 1.0.6.8 1.0.6.9 1.0.7 1.0.8 1.0.9 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.14-rc All 38 releases
publishpress-statuses / StatusesUI.php

StatusesUI.php in PublishPress Statuses – Custom Post Status and Workflow trunk, at StatusesUI.php

1,486 lines 63.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace PublishPress_Statuses;
3
4 // Custom Status management: Statuses Screen
5 class StatusesUI {
6 private static $instance = null;
7 private $version;
8
9 public static function instance() {
10 if ( is_null(self::$instance) ) {
11 self::$instance = new \PublishPress_Statuses\StatusesUI(false);
12 self::$instance->load();
13 }
14
15 return self::$instance;
16 }
17
18 public function __construct($do_load = true)
19 {
20 $this->version = PUBLISHPRESS_STATUSES_VERSION;
21
22 if ($do_load) {
23 $this->load();
24 }
25 }
26
27 private function load() {
28 $plugin_page = \PP_Statuses_Functions::getPluginPage();
29
30 add_filter('presspermit_edit_status_default_tab', [$this, 'fltEditStatusDefaultTab']);
31
32 // Register our settings
33 if ('publishpress-statuses-settings' === $plugin_page) {
34 add_action('admin_init', [$this, 'register_settings']);
35 }
36
37 if ('publishpress_custom_status_options' === \PP_Statuses_Functions::POST_key('option_page')) {
38 add_action('admin_init', function() {
39 $this->handle_settings();
40 });
41 }
42
43 // Methods for handling the actions of creating, making default, and deleting post stati
44
45 // @todo: REST
46 if ((0 === strpos($plugin_page, 'publishpress-statuses'))
47 && !\PP_Statuses_Functions::empty_POST('submit')
48 ) {
49 add_action('init', function() {
50 $this->handle_add_custom_status();
51 $this->handle_edit_custom_status();
52 $this->handle_delete_custom_status();
53 }, 20);
54 }
55
56 $title = '';
57
58 if (('publishpress-statuses' === $plugin_page)
59 && ('edit-status' === \PP_Statuses_Functions::REQUEST_key('action'))) {
60 $status_name = \PP_Statuses_Functions::REQUEST_key('name');
61
62 if ($status_obj = get_post_status_object($status_name)) {
63 // translators: %s is the status label
64 $title = sprintf(__('Edit Post Status: %s', 'publishpress-statuses'), $status_obj->label);
65
66 // translators: %s is the status label
67 $custom_html_title = sprintf(__('%s Status - Edit', 'publishpress-statuses'), $status_obj->label);
68 }
69
70 } elseif ('publishpress-statuses-add-new' === $plugin_page) {
71 if (!\PP_Statuses_Functions::empty_REQUEST('taxonomy')) {
72 if ($tx = get_taxonomy(\PP_Statuses_Functions::REQUEST_key('taxonomy'))) {
73 $title = sprintf(
74 // translators: %s is status type: "Workflow", "Visibility", "Revision", etc.
75 __('Add %s Status', 'publishpress-statuses'),
76 $tx->label
77 );
78 }
79 }
80
81 if (empty($title)) {
82 $title = __('Add Post Status', 'publishpress-statuses');
83 $custom_html_title = sprintf(__('Add Status', 'publishpress-statuses'));
84 }
85
86 } elseif ('publishpress-statuses-settings' === $plugin_page) {
87 $title = __('PublishPress Statuses Settings', 'publishpress-statuses');
88 $custom_html_title = sprintf(__('Statuses Settings', 'publishpress-statuses'));
89
90 } else {
91 $title = __('Post Statuses', 'publishpress-statuses');
92 $custom_html_title = __('Statuses', 'publishpress-statuses');
93
94 if ($status_type = \PP_Statuses_Functions::REQUEST_key('status_type')) { // @todo: implement hook in Permissions
95 $_title = $title;
96
97 if ('visibility' == $status_type) {
98 $title = __('Visibility Statuses', 'publishpress-statuses');
99 } else {
100 $title = apply_filters('publishpress_statuses_admin_title', $title, $status_type);
101 }
102
103 if ($title != $_title) {
104 $custom_html_title = $title;
105 }
106 }
107 }
108
109 $pp_statuses = \PublishPress_Statuses::instance();
110
111 $pp_statuses->title = $title;
112
113 if (empty($custom_html_title)) {
114 $custom_html_title = $title;
115 }
116
117 add_filter('admin_title', function($admin_title, $_title) use ($custom_html_title) {
118 return $custom_html_title;
119 }, 10, 2);
120
121 add_action('init', [$this, 'loadAdminMessages'], 999);
122
123 do_action('publishpress_plugin_screen', \PublishPress_Statuses::instance());
124 }
125
126 /**
127 * Handles a form's POST request to add a custom status
128 */
129 public function handle_add_custom_status()
130 {
131 if (('add-status' === \PP_Statuses_Functions::POST_key('action'))
132 && \PP_Statuses_Functions::empty_REQUEST('settings_module')) {
133 require_once(__DIR__ . '/StatusHandler.php');
134 \PublishPress_Statuses\StatusHandler::handleAddCustomStatus();
135 }
136 }
137
138 /**
139 * Handles a POST request to edit a custom status
140 */
141 public function handle_edit_custom_status()
142 {
143 if (('edit-status' === \PP_Statuses_Functions::POST_key('action'))
144 && \PP_Statuses_Functions::empty_REQUEST('settings_module')) {
145 require_once(__DIR__ . '/StatusHandler.php');
146 \PublishPress_Statuses\StatusHandler::handleEditCustomStatus();
147
148 } elseif (('edit-status-labels' === \PP_Statuses_Functions::POST_key('action'))
149 && \PP_Statuses_Functions::empty_REQUEST('settings_module')) {
150 require_once(__DIR__ . '/StatusHandler.php');
151 \PublishPress_Statuses\StatusHandler::handleEditCustomStatusLabels();
152 }
153 }
154
155 /**
156 * Handles a GET request to delete a specific term
157 *
158 * @since 0.7
159 */
160 public function handle_delete_custom_status()
161 {
162 if ('delete-status' === (\PP_Statuses_Functions::POST_key('action'))
163 && \PP_Statuses_Functions::empty_REQUEST('settings_module')) {
164 require_once(__DIR__ . '/StatusHandler.php');
165 \PublishPress_Statuses\StatusHandler::handleDeleteCustomStatus();
166 }
167 }
168
169 /**
170 * Handles a POST request to edit general status settings
171 */
172 public function handle_settings()
173 {
174 if (!\PP_Statuses_Functions::empty_POST('action')
175 && ('publishpress_custom_status_options' === \PP_Statuses_Functions::POST_key('option_page'))
176 ) {
177 require_once(__DIR__ . '/StatusHandler.php');
178 \PublishPress_Statuses\StatusHandler::settings_validate_and_save();
179 }
180 }
181
182 /**
183 * Add item to Array without overwrite any item, in case an item is already set for the position.
184 *
185 * @param $array
186 * @param $position
187 * @param $item
188 */
189 private function addItemToArray(&$array, $position, $item)
190 {
191 if (isset($array[$position])) {
192 $this->addItemToArray($array, $position + 1, $item);
193 } else {
194 $array[$position] = $item;
195 }
196 }
197
198 public function loadAdminMessages() {
199 // Mechanism for "Edit again" link if we redirect back to Statuses screen after Edit Status update
200 // phpcs:ignore Squiz.PHP.CommentedOutCode.Found
201 /*
202 if (!empty($_REQUEST['name'])) {
203 if ($status_obj = get_post_status_object(sanitize_key($_REQUEST['name']))) {
204 $status_name = ' ("' . $status_obj->label . '")';
205 $url = \PublishPress_Statuses::getLink(['page' => 'publishpress-statuses', 'action' => 'edit-status', 'name' => sanitize_key($_REQUEST['name'])]);
206 $edit_again = '&nbsp;&nbsp;<a href="' . esc_url($url) . '">' . esc_html__('Edit again', 'publishpress-statuses') . '</a>';
207 }
208 }
209 */
210
211 if (empty($status_name)) {
212 $status_name = '';
213 $edit_again = '';
214 }
215
216 \PublishPress_Statuses::instance()->messages = [
217 'status-added' => __('Post status created. Select a tab for further configuration.', 'publishpress-statuses'),
218 // translators: %1$s is the status name, %2$s is the edit link
219 'status-updated' => sprintf(__('Post status %1$s updated. %2$s', 'publishpress-statuses'), $status_name, $edit_again),
220 'settings-updated' => sprintf(__('Settings updated', 'publishpress-statuses')),
221 'status-missing' => __("That post status doesn't seem to exist. Was a required plugin or setting deactivated?", 'publishpress-statuses'),
222 'default-status-changed' => __('Default post status has been changed.', 'publishpress-statuses'),
223 // translators: %1$s is the status name, %2$s is the edit link
224 'term-updated' => sprintf(__('Post status %1$s updated. %2$s', 'publishpress-statuses'), $status_name, $edit_again),
225 'status-deleted' => __('Post status deleted.', 'publishpress-statuses'),
226 'status-position-updated' => __("Status order updated.", 'publishpress-statuses'),
227 ];
228 }
229
230 /**
231 * Register settings for notifications so we can partially use the Settings API
232 * (We use the Settings API for form generation, but not saving)
233 *
234 * @since 0.7
235 */
236 public function register_settings()
237 {
238 $group_name = \PublishPress_Statuses::SETTINGS_SLUG;
239
240 if (!empty($group_name)) {
241 add_settings_section(
242 $group_name . '_general',
243 false,
244 '__return_false',
245 $group_name
246 );
247
248 add_settings_field(
249 'post_types',
250 __('Use on these Post Types:', 'publishpress-statuses'),
251 [$this, 'settings_post_types_option'],
252 $group_name,
253 $group_name . '_general',
254 ['class' => 'pp-settings-workflow']
255 );
256
257 add_settings_field(
258 'moderation_statuses_default_by_sequence',
259 __('Workflow Guidance:', 'publishpress-statuses'),
260 [$this, 'settings_moderation_statuses_default_by_sequence_option'],
261 $group_name,
262 $group_name . '_general',
263 ['class' => 'pp-settings-workflow']
264 );
265
266 add_settings_field(
267 'hide_manual_status_selectors',
268 __('Manual Status Selection:', 'publishpress-statuses'),
269 [$this, 'settings_hide_manual_status_selectors_option'],
270 $group_name,
271 $group_name . '_general',
272 ['class' => 'pp-settings-workflow']
273 );
274
275 add_settings_field(
276 'hide_manual_status_selectors',
277 __('New Status Position:', 'publishpress-statuses'),
278 [$this, 'settings_new_statuses_main_workflow_option'],
279 $group_name,
280 $group_name . '_general',
281 ['class' => 'pp-settings-workflow']
282 );
283
284 if (defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) {
285 add_settings_field(
286 'privacy_statuses_enabled',
287 __('Custom Visibility:', 'publishpress-statuses'),
288 [$this, 'settings_privacy_statuses_enabled'],
289 $group_name,
290 $group_name . '_general',
291 ['class' => 'pp-settings-visibility']
292 );
293 }
294
295 add_settings_field(
296 'default_privacy',
297 __('Default Visibility Status:', 'publishpress-statuses'),
298 [$this, 'settings_default_privacy_option'],
299 $group_name,
300 $group_name . '_general',
301 ['class' => 'pp-settings-visibility']
302 );
303
304 if (defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) {
305 add_settings_field(
306 'custom_privacy_edit_caps',
307 __('Custom Visibility Editing:', 'publishpress-statuses'),
308 [$this, 'settings_custom_privacy_edit_caps'],
309 $group_name,
310 $group_name . '_general',
311 ['class' => 'pp-settings-visibility']
312 );
313 }
314
315 $show_edit_caps_setting = (function_exists('presspermit') && defined('PRESSPERMIT_COLLAB_VERSION') && defined('PRESSPERMIT_STATUSES_VERSION'));
316
317 add_settings_field(
318 'status_dropdown_pending_status_regulation',
319 __('Pending Review Status:', 'publishpress-statuses'),
320 [$this, 'settings_pending_status_regulation_option'],
321 $group_name,
322 $group_name . '_general',
323 ['class' => 'pp-settings-integration']
324 );
325
326 if (defined('PUBLISHPRESS_VERSION')) {
327 add_settings_field(
328 'planner_add_post_custom_statuses',
329 __('Planner Integration:', 'publishpress-statuses'),
330 [$this, 'settings_planner_add_post_custom_statuses_option'],
331 $group_name,
332 $group_name . '_general',
333 ['class' => 'pp-settings-integration']
334 );
335 }
336
337 if ($show_edit_caps_setting) {
338 add_settings_field(
339 'supplemental_cap_moderate_any',
340 __('Permissions Integration:', 'publishpress-statuses'),
341 [$this, 'settings_supplemental_cap_moderate_any_option'],
342 $group_name,
343 $group_name . '_general',
344 ['class' => 'pp-settings-integration']
345 );
346 }
347
348 add_settings_field(
349 'force_editor_detection',
350 __('Gutenberg / Classic Editor:', 'publishpress-statuses'),
351 [$this, 'settings_force_editor_detection_option'],
352 $group_name,
353 $group_name . '_general',
354 ['class' => 'pp-settings-editor']
355 );
356
357 add_settings_field(
358 'label_storage',
359 __('Status Label Customization:', 'publishpress-statuses'),
360 [$this, 'settings_label_storage_option'],
361 $group_name,
362 $group_name . '_general',
363 ['class' => 'pp-settings-editor']
364 );
365
366 if (!defined('PUBLISHPRESS_STATUSES_NO_PLANNER_IMPORT')) {
367 $terms = get_terms(['taxonomy' => 'post_status', 'hide_empty' => false]);
368
369 if ($show_import_setting = !empty($terms)
370 && (get_option('publishpress_version') || get_site_option('edit_flow_version', false) || get_option('pps_version') || defined('PP_STATUSES_ENABLE_PLANNER_IMPORT'))
371 ) {
372 add_settings_field(
373 'import_operation',
374 __('Import Operation:', 'publishpress-statuses'),
375 [$this, 'settings_import_operation_option'],
376 $group_name,
377 $group_name . '_general',
378 ['class' => 'pp-settings-advanced']
379 );
380 }
381 }
382
383 add_settings_field(
384 'backup_operation',
385 __('Backup / Restore:', 'publishpress-statuses'),
386 [$this, 'settings_backup_operation_option'],
387 $group_name,
388 $group_name . '_general',
389 ['class' => 'pp-settings-advanced']
390 );
391
392 do_action('publishpress_statuses_add_settings_field', $group_name);
393 }
394 }
395
396 public function settings_supplemental_cap_moderate_any_option() {
397 $module = \PublishPress_Statuses::instance();
398
399 echo '<div class="c-input-group">';
400
401 echo sprintf(
402 '<input type="hidden" name="%s" value="0" />',
403 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[supplemental_cap_moderate_any]'
404 ) . ' ';
405
406 $checked = $module->options->supplemental_cap_moderate_any ? 'checked' : '';
407
408 echo sprintf(
409 '<input type="checkbox" name="%s" id="supplemental_cap_moderate_any" value="1" autocomplete="off" %s>',
410 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[supplemental_cap_moderate_any]',
411 esc_attr($checked)
412 ) . ' ';
413
414 echo '<label for="supplemental_cap_moderate_any">';
415 esc_html_e('Supplemental Role of Editor covers custom statuses', 'publishpress-statuses');
416 echo '</label>';
417
418 echo '</div>';
419 }
420
421 public function settings_planner_add_post_custom_statuses_option() {
422 $module = \PublishPress_Statuses::instance();
423
424 echo '<div class="c-input-group">';
425
426 echo sprintf(
427 '<input type="hidden" name="%s" value="0" />',
428 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[planner_add_post_custom_statuses]'
429 ) . ' ';
430
431 $checked = $module->options->planner_add_post_custom_statuses ? 'checked' : '';
432
433 echo sprintf(
434 '<input type="checkbox" name="%s" id="planner_add_post_custom_statuses" value="1" autocomplete="off" %s>',
435 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[planner_add_post_custom_statuses]',
436 esc_attr($checked)
437 ) . ' ';
438
439 echo '<label for="planner_add_post_custom_statuses">';
440 esc_html_e('Include custom statuses in Add New pop-up on Calendar', 'publishpress-statuses');
441 echo '</label>';
442
443 echo '</div>';
444 }
445
446 public function settings_hide_manual_status_selectors_option() {
447 $module = \PublishPress_Statuses::instance();
448
449 echo '<div class="c-input-group">';
450
451 echo sprintf(
452 '<input type="hidden" name="%s" value="0" />',
453 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[hide_manual_status_selectors]'
454 ) . ' ';
455
456 $checked = $module->options->hide_manual_status_selectors ? 'checked' : '';
457
458 echo sprintf(
459 '<input type="checkbox" name="%s" id="hide_manual_status_selectors" value="1" autocomplete="off" %s>',
460 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[hide_manual_status_selectors]',
461 esc_attr($checked)
462 ) . ' ';
463
464 echo '<label for="hide_manual_status_selectors">';
465 esc_html_e('Hide status selection dropdown from non-Administrators in Gutenberg editor', 'publishpress-statuses');
466 echo '</label>';
467
468 echo '</div>';
469 }
470
471 public function settings_moderation_statuses_default_by_sequence_option() {
472 $module = \PublishPress_Statuses::instance();
473
474 echo '<div class="c-input-group">';
475
476 echo '<div>';
477
478 echo sprintf(
479 '<input type="hidden" name="%s" value="0" />',
480 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[moderation_statuses_default_by_sequence]'
481 ) . ' ';
482
483 $checked = ($module->options->moderation_statuses_default_by_sequence && ('none' !== $module->options->moderation_statuses_default_by_sequence)) ? 'checked' : '';
484
485 echo sprintf(
486 '<input type="radio" name="%s" id="moderation_statuses_default_to_next" value="1" autocomplete="off" %s>',
487 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[moderation_statuses_default_by_sequence]',
488 esc_attr($checked)
489 ) . ' ';
490
491 echo '<label for="moderation_statuses_default_to_next">';
492 esc_html_e('Sequence by default: Publish button defaults to next status in workflow', 'publishpress-statuses');
493 echo '</label>';
494
495 echo '</div><div style="margin-top: 12px;">';
496
497 $checked = !$module->options->moderation_statuses_default_by_sequence ? 'checked' : '';
498
499 echo sprintf(
500 '<input type="radio" name="%s" id="moderation_statuses_default_to_highest" value="0" autocomplete="off" %s>',
501 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[moderation_statuses_default_by_sequence]',
502 esc_attr($checked)
503 ) . ' ';
504
505 echo '<label for="moderation_statuses_default_to_highest">';
506 esc_html_e('Bypass by default: Publish button defaults to maximum available status', 'publishpress-statuses');
507 echo '</label>';
508
509 echo '</div><div style="margin-top: 12px;">';
510
511 $checked = $module->options->moderation_statuses_default_by_sequence === 'none' ? 'checked' : '';
512
513 echo sprintf(
514 '<input type="radio" name="%s" id="moderation_statuses_no_workflow" value="none" autocomplete="off" %s>',
515 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[moderation_statuses_default_by_sequence]',
516 esc_attr($checked)
517 ) . ' ';
518
519 echo '<label for="moderation_statuses_no_workflow">';
520 esc_html_e('No workflow guidance', 'publishpress-statuses');
521 echo '</label>';
522
523 echo '</div></div>';
524
525 ?>
526 <script type="text/javascript">
527 /* <![CDATA[ */
528 jQuery(document).ready(function ($) {
529 <?php if ($module->options->moderation_statuses_default_by_sequence):?>
530 $('tr.pp-statuses-settings-status-declutter').show();
531 <?php endif;?>
532
533 $('#moderation_statuses_default_to_next').on('change', function() {
534 $('tr.pp-statuses-settings-status-declutter').toggle($(this).val());
535 });
536
537 $('#moderation_statuses_default_to_highest').on('change', function() {
538 $('tr.pp-statuses-settings-status-declutter').toggle($(this).val());
539 });
540 });
541 /* ]]> */
542 </script>
543
544 <?php
545 $status_dropdown_disabled = $module->options->hide_manual_status_selectors;
546
547 echo '<br><br><div class="c-input-group status_dropdown_current_branch_only" ';
548 if ($status_dropdown_disabled) echo 'style="display: none"';
549 echo ' >';
550
551 echo sprintf(
552 '<input type="hidden" name="%s" value="0" />',
553 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[status_dropdown_show_current_branch_only]'
554 ) . ' ';
555
556 $checked = $module->options->status_dropdown_show_current_branch_only ? 'checked' : '';
557
558 echo sprintf(
559 '<input type="checkbox" name="%s" id="status_dropdown_show_current_branch_only" value="1" autocomplete="off" %s>',
560 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[status_dropdown_show_current_branch_only]',
561 esc_attr($checked)
562 ) . ' ';
563
564 echo '<label for="status_dropdown_show_current_branch_only">';
565 esc_html_e('Hide sub-statuses in the dropdown unless the post is set to the parent status or a sibling', 'publishpress-statuses');
566 echo '</label>';
567 ?>
568
569 <p class="pp-option-footnote">
570 <?php
571 _e('Sub-statuses may be nested below any top-level status. They function as branches in the Main Workflow or in an Alternate Workflow.', 'publishpress-statuses');
572 ?>
573 </p>
574
575 <script type="text/javascript">
576 /* <![CDATA[ */
577 jQuery(document).ready(function ($) {
578 $('#hide_manual_status_selectors').on('click', function() {
579 $('div.status_dropdown_current_branch_only').toggle($(this).val());
580 });
581 });
582 /* ]]> */
583 </script>
584
585 <?php
586 echo '</div>';
587 }
588
589 public function settings_new_statuses_main_workflow_option() {
590 $module = \PublishPress_Statuses::instance();
591
592 echo '<div class="c-input-group">';
593
594 echo sprintf(
595 '<input type="hidden" name="%s" value="0" />',
596 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[new_statuses_main_workflow]'
597 ) . ' ';
598
599 $checked = $module->options->new_statuses_main_workflow ? 'checked' : '';
600
601 echo sprintf(
602 '<input type="checkbox" name="%s" id="new_statuses_main_workflow" value="1" autocomplete="off" %s>',
603 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[new_statuses_main_workflow]',
604 esc_attr($checked)
605 ) . ' ';
606
607 echo '<label for="new_statuses_main_workflow">';
608 esc_html_e('Add new statuses to Main Workflow by default', 'publishpress-statuses');
609 echo '</label>';
610
611 echo '</div>';
612 }
613
614 public function settings_pending_status_regulation_option() {
615 $module = \PublishPress_Statuses::instance();
616
617 echo '<div class="c-input-group">';
618
619 $option_val = !empty($module->options->pending_status_regulation) ? $module->options->pending_status_regulation : '';
620
621 echo sprintf(
622 '<select id="pending_status_regulation" name="%s" autocomplete="off">',
623 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[pending_status_regulation]'
624 );
625
626 ?>
627 <option value='' <?php if (empty($option_val)) echo "selected";?>><?php esc_html_e('Available to all users', 'publishpress-statuses');?></option>
628 <option value='1' <?php if ($option_val) echo "selected";?>><?php esc_html_e('Available to specified roles only', 'publishpress-statuses');?></option>
629 </select>
630
631 <p class="pp-option-footnote">
632 <?php
633 if ($option_val) {
634 esc_html_e('Users can only assign a custom status to a post if their role allows it. With the current setting, the same control is applied to the Pending Review status.', 'publishpress-statuses');
635 } else {
636 esc_html_e('Users can only assign a custom status to a post if their role allows it. With the current setting, those limitations will not be applied for the Pending Review status.', 'publishpress-statuses');
637 }
638 ?>
639 </p>
640
641 <p class="pp-option-footnote pp-pending-specified" <?php if (!$option_val) echo 'style="display:none;"';?>>
642 <?php
643 printf(
644 // translators: %1$s and %2$s are link markup
645 esc_html__('View or set roles at %1$s Statuses > Statuses > Pending Review > Roles %2$s', 'publishpress-statuses'),
646 '<a href="' . esc_url(admin_url('admin.php?action=edit-status&name=pending&page=publishpress-statuses&pp_tab=roles')) . '">',
647 '</a>'
648 );
649 ?>
650 </p>
651
652 <?php
653 echo '</div>';
654 }
655
656 public function settings_force_editor_detection_option() {
657 $module = \PublishPress_Statuses::instance();
658
659 echo '<div class="c-input-group">';
660
661 $option_val = !empty($module->options->force_editor_detection) ? $module->options->force_editor_detection : '';
662
663 echo sprintf(
664 '<select name="%s" autocomplete="off">',
665 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[force_editor_detection]'
666 );
667
668 ?>
669 <option value='' <?php if (empty($option_val)) echo "selected";?>><?php esc_html_e('Automatic Detection', 'publishpress-statuses');?></option>
670 <option value='classic' <?php if ('classic' === $option_val) echo "selected";?>><?php esc_html_e('Using Classic Editor', 'publishpress-statuses');?></option>
671 <option value='gutenberg' <?php if ('gutenberg' === $option_val) echo "selected";?>><?php esc_html_e('Using Gutenberg Editor', 'publishpress-statuses');?></option>
672 </select>
673
674 <p class="pp-option-footnote">
675 <?php
676 esc_html_e('If custom statuses in the post editor are not loaded correctly, prevent incorrect detection of editor by specifying it here.', 'publishpress-statuses');
677 ?>
678 </p>
679
680 <?php
681 echo '</div>';
682 }
683
684 public function settings_label_storage_option() {
685 $module = \PublishPress_Statuses::instance();
686
687 echo '<div class="c-input-group">';
688
689 $option_val = !empty($module->options->label_storage) ? $module->options->label_storage : '';
690
691 echo sprintf(
692 '<select name="%s" autocomplete="off">',
693 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[label_storage]'
694 );
695
696 ?>
697 <option value='' <?php if (empty($option_val)) echo "selected";?>><?php esc_html_e('For all plugin statuses', 'publishpress-statuses');?></option>
698 <option value='user' <?php if ('user' === $option_val) echo "selected";?>><?php esc_html_e('For user-created plugin statuses only', 'publishpress-statuses');?></option>
699 </select>
700
701 <p class="pp-option-footnote">
702 <?php
703 esc_html_e('This controls which statuses can have their labels customized by editing Status properties. If a non-default entry is stored, it will override any language file strings.', 'publishpress-statuses');
704 ?>
705 </p>
706
707 <?php
708 echo '</div>';
709 }
710
711 public function settings_post_types_option($unused = [])
712 {
713 $pp = \PublishPress_Statuses::instance();
714
715 if (empty($pp->module)) {
716 return;
717 }
718
719 if (empty($post_types)) {
720 $post_types = [
721 'post' => __('Posts'),
722 'page' => __('Pages'),
723 ];
724
725 $custom_post_types = $pp->get_supported_post_types();
726
727 foreach ($custom_post_types as $custom_post_type => $args) {
728 $post_types[$custom_post_type] = $args->label;
729 }
730 }
731 ?>
732
733 <div class="pp-statuses-post-types">
734
735 <?php
736 foreach ($post_types as $post_type => $title) {
737 echo sprintf(
738 '<input type="hidden" name="%s" value="0" />',
739 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[post_types][' . esc_attr($post_type) . ']'
740 ) . ' ';
741
742 echo '<label for="' . esc_attr($post_type) . '-' . esc_attr($pp->module->slug) . '">';
743 echo '<input id="' . esc_attr($post_type) . '-' . esc_attr($pp->module->slug) . '" name="'
744 . esc_attr($pp->options_group_name) . '[post_types][' . esc_attr($post_type) . ']"';
745
746 if (isset($pp->options->post_types[$post_type])) {
747 checked($pp->options->post_types[$post_type], true);
748 }
749
750 // Defining post_type_supports in the functions.php file or similar should disable the checkbox
751 disabled(post_type_supports($post_type, 'pp_custom_statuses'), true);
752 echo ' type="checkbox" value="1" />&nbsp;&nbsp;&nbsp;' . esc_html($title) . '</label>';
753
754 // Leave a note to the admin as a reminder that add_post_type_support has been used somewhere in their code
755 if (post_type_supports($post_type, 'pp_custom_statuses')) {
756 // translators: %1$s is the post type name, %2$s is the pp_custom_statuses feature
757 echo '&nbsp&nbsp;&nbsp;<span class="description">' . sprintf(esc_html__('Disabled because add_post_type_support(\'%1$s\', \'%2$s\') is included in a loaded file.', 'publishpress-statuses'), esc_html($post_type), 'pp_custom_statuses') . '</span>';
758 }
759 }
760 ?>
761
762 </div>
763
764 <p class="pp-option-footnote">
765 <?php
766 _e('Note: Post types can also be specified for each individual status.', 'publishpress-statuses');
767 ?>
768 </p>
769 <?php
770 }
771
772 public function settings_privacy_statuses_enabled($unused = []) {
773 $module = \PublishPress_Statuses::instance();
774
775 echo '<div class="c-input-group">';
776
777 echo sprintf(
778 '<input type="hidden" name="%s" value="0" />',
779 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[privacy_statuses_enabled]'
780 ) . ' ';
781
782 $checked = get_option('presspermit_privacy_statuses_enabled', 1) ? 'checked' : '';
783
784 echo sprintf(
785 '<input type="checkbox" name="%s" id="privacy_statuses_enabled" value="1" autocomplete="off" %s>',
786 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[privacy_statuses_enabled]',
787 esc_attr($checked)
788 ) . ' ';
789
790 echo '<label for="privacy_statuses_enabled">';
791 esc_html_e('Enable custom Visibility Statuses', 'publishpress-statuses');
792 echo '</label>';
793
794 echo '</div>';
795 }
796
797 public function settings_custom_privacy_edit_caps($unused = []) {
798 $module = \PublishPress_Statuses::instance();
799
800 echo '<div class="c-input-group">';
801
802 echo sprintf(
803 '<input type="hidden" name="%s" value="0" />',
804 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[custom_privacy_edit_caps]'
805 ) . ' ';
806
807 $checked = !empty($module->options->custom_privacy_edit_caps) ? 'checked' : '';
808
809 echo sprintf(
810 '<input type="checkbox" name="%s" id="custom_privacy_edit_caps" value="1" autocomplete="off" %s>',
811 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[custom_privacy_edit_caps]',
812 esc_attr($checked)
813 ) . ' ';
814
815 echo '<label for="custom_privacy_edit_caps">';
816 esc_html_e('Posts with custom Visibility also require status-specific capabilities for editing', 'publishpress-statuses');
817 echo '</label>';
818
819 echo '</div>';
820 }
821
822 public function settings_default_privacy_option($unused = [])
823 {
824 $pp = \PublishPress_Statuses::instance();
825
826 if (empty($pp->module)) {
827 return;
828 }
829
830 if (empty($post_types)) {
831 $post_types = [
832 'post' => __('Posts'),
833 'page' => __('Pages'),
834 ];
835
836 $custom_post_types = $pp->get_supported_post_types();
837
838 foreach ($custom_post_types as $custom_post_type => $args) {
839 if (!\PublishPress_Statuses::DisabledForPostType($custom_post_type)) {
840 $post_types[$custom_post_type] = $args->label;
841 }
842 }
843 }
844 ?>
845
846 <div class="pp-statuses-post-types">
847
848 <table id="pp_statuses_default_privacy">
849 <?php
850
851 $do_force_option = true; // @todo
852
853 $options = \PublishPress_Statuses::instance()->options;
854
855 foreach ($post_types as $post_type => $title) {
856 $setting = (isset($pp->options->default_privacy[$post_type])) ? $pp->options->default_privacy[$post_type] : '';
857
858 echo sprintf(
859 '<input type="hidden" name="%s" value="" />',
860 esc_attr(\PublishPress_Statuses::SETTINGS_SLUG) . '[default_privacy][' . esc_attr($post_type) . ']'
861 ) . ' ';
862
863 ?>
864 <tr>
865
866 <th>
867 <?php
868 esc_html_e($title) . ' ';
869 ?>
870 </th>
871
872 <td style="text-align: left">
873 <select name="<?php echo esc_attr($pp->options_group_name) . '[default_privacy][' . esc_attr($post_type) . ']';?>" autocomplete="off">
874 <option value=""><?php esc_html_e('Published'); ?></option>
875
876 <?php foreach (get_post_stati(['private' => true], 'object') as $status_obj) :
877 $selected = ($status_obj->name == $setting) ? ' selected ' : '';
878 ?>
879 <option value="<?php echo esc_attr($status_obj->name); ?>" <?php echo esc_attr($selected); ?>><?php echo esc_html($status_obj->label); ?></option>
880 <?php endforeach; ?>
881 </select>
882
883 <?php if ($do_force_option) :
884 $force_default_privacy = (is_object($options) && !empty($options->force_default_privacy) && !empty($options->force_default_privacy[$post_type])) ? $options->force_default_privacy[$post_type] : false;
885
886 $id = 'force_default_privacy-' . $post_type;
887 $name = esc_attr($pp->options_group_name) . "[force_default_privacy[$post_type]]";
888 $style = 'display:inline';
889
890 $checked = ($force_default_privacy) ? ' checked ' : '';
891 $disabled = '';
892 ?>
893 <input name='<?php echo esc_attr($name); ?>' type='hidden' value='0' />
894 &nbsp;<label style='<?php echo esc_attr($style); ?>' for="<?php echo esc_attr($id); ?>"><input
895 type="checkbox" <?php echo esc_attr($checked); ?><?php echo esc_attr($disabled); ?>id="<?php echo esc_attr($id); ?>"
896 name="<?php echo esc_attr($pp->options_group_name) . '[force_default_privacy][' . esc_attr($post_type) . ']'; ?>"
897 value="1" autocomplete="off" /><?php if ($do_force_option) : ?>&nbsp;<?php esc_html_e('lock', 'publishpress-statuses'); ?><?php endif; ?>
898 </label>
899 <?php endif; ?>
900
901 </td>
902
903 </tr>
904 <?php
905 }
906 ?>
907 </table>
908
909 <?php
910 $lock_publication = is_object($options) && !empty($options->lock_publication);
911
912 $id = 'lock_publication';
913 $name = esc_attr($pp->options_group_name) . '[lock_publication]';
914 $checked = ($lock_publication) ? ' checked ' : '';
915 ?>
916
917 <input name='<?php echo esc_attr($name); ?>' type='hidden' value='0' />
918 &nbsp;<label for="<?php echo esc_attr($id); ?>"><input
919 type="checkbox" <?php echo esc_attr($checked); ?> id="<?php echo esc_attr($id); ?>"
920 name="<?php echo esc_attr($pp->options_group_name) . '[lock_publication]'; ?>"
921 value="1" />
922
923 <?php
924 esc_html_e('Locking also prevents posts from being unpublished', 'publishpress-statuses');
925 ?>
926 </label>
927
928 <p class="pp-option-footnote">
929 <?php
930 $role = @get_role('administrator');
931
932 if (defined('PUBLISHPRESS_CAPS_VERSION') && !empty($options) && !empty($options->lock_publication)) {
933 $admin_disclaimer = (!empty($role) && $role->has_cap('pp_unpublish_posts'))
934 ? sprintf(esc_html__('This setting does not apply to %1$s Administrators%2$s.', 'publishpress-statuses'), "<a href='" . admin_url('admin.php?page=pp-capabilities&pp_caps_tab=publishpress-statuses') . "'>", '</a>')
935 : sprintf(esc_html__('You may assign a %1$s role capability %2$s to bypass this locking.', 'publishpress-statuses'), "<a href='" . admin_url('admin.php?page=pp-capabilities&pp_caps_tab=publishpress-statuses') . "'>", '</a>');
936
937 } else {
938 $admin_disclaimer = (!empty($role) && $role->has_cap('pp_unpublish_posts'))
939 ? esc_html__('This setting does not apply to Administrators.', 'publishpress-statuses')
940 : '';
941 }
942
943 printf(
944 esc_html__('If this setting is unchecked, the lock will only prevent selection of a different visibility status. %1$s %2$s See documentation%3$s.', 'publishpress-statuses'),
945 $admin_disclaimer, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
946 '<a href="https://publishpress.com/knowledge-base/how-to-lock-visibility-statuses/" target="_blank">',
947 '</a>'
948 );
949 ?>
950 </p>
951
952 </div>
953 <?php
954 }
955
956 public function settings_import_operation_option() {
957 $module = \PublishPress_Statuses::instance();
958 ?>
959
960 <div class="c-input-group">
961
962 <select name="publishpress_statuses_import_operation" autocomplete="off">
963
964 <option value=''><?php esc_html_e('Select...', 'publishpress-statuses');?></option>
965
966 <?php if (get_option('pps_version')):?>
967 <option value='do_status_control_import'><?php esc_html_e('Re-run Planner import (with Status Control properties, ordering)', 'publishpress-statuses');?></option>
968 <option value='do_planner_import_only'><?php esc_html_e('Re-run Planner import (ignoring Status Control configuration)', 'publishpress-statuses');?></option>
969 <?php else:?>
970 <option value='do_planner_import'><?php esc_html_e('Re-run Planner import', 'publishpress-statuses');?></option>
971 <?php endif;?>
972 </select>
973
974 <p class="pp-option-footnote">
975 <?php
976 esc_html_e('Status color, icon and position is automatically imported from PublishPress Planner. Select an option above to re-run the import, giving priority to Planner-defined status position.', 'publishpress-statuses');
977 ?>
978 </p>
979
980 </div>
981
982 <?php
983 }
984
985 public function settings_backup_operation_option() {
986 $module = \PublishPress_Statuses::instance();
987
988 $meta_missing = array_fill_keys(['color', 'icon', 'labels', 'post_type', 'backup_color', 'backup_icon', 'backup_labels', 'backup_post_type', 'backup_color_', 'backup_icon_', 'backup_labels_', 'backup_post_type_'], true);
989
990 $all_statuses = \PublishPress_Statuses::getPostStati(['internal' => false], 'object');
991
992 $_terms = get_terms(['taxonomy' => \PublishPress_Statuses::TAXONOMY_PRE_PUBLISH, 'hide_empty' => false]);
993
994 if ($_terms) {
995 foreach($_terms as $term) {
996 $term_meta = get_term_meta($term->term_id);
997
998 foreach (array_keys($meta_missing) as $prop) {
999 if (!empty($term_meta[$prop])) {
1000 if (in_array($prop, ['color', 'icon', 'labels', 'post_types'])) {
1001 // "Use defaults" operation only applies to our built-in statuses
1002 if (empty($all_statuses[$term->slug]) || empty($all_statuses[$term->slug]->pp_builtin)) {
1003 continue;
1004 }
1005 }
1006
1007 unset($meta_missing[$prop]);
1008 }
1009 }
1010
1011 if (!$meta_missing) {
1012 break;
1013 }
1014 }
1015 }
1016 ?>
1017
1018 <div class="c-input-group">
1019
1020 <select name="publishpress_statuses_backup_operation" autocomplete="off">
1021
1022 <option value=''><?php esc_html_e('Select...', 'publishpress-statuses');?></option>
1023
1024 <option value='backup_status_properties'><?php esc_html_e('Back up current colors, icons, labels and post types', 'publishpress-statuses');?></option>
1025
1026 <option value=''></option>
1027
1028 <?php if (empty($backup_missing['backup_color'])):?>
1029 <option value='restore_status_colors'><?php esc_html_e('Restore backup of status colors', 'publishpress-statuses');?></option>
1030 <?php endif;?>
1031
1032 <?php if (empty($backup_missing['backup_icon'])):?>
1033 <option value='restore_status_icons'><?php esc_html_e('Restore backup of status icons', 'publishpress-statuses');?></option>
1034 <?php endif;?>
1035
1036 <?php if (empty($backup_missing['backup_labels'])):?>
1037 <option value='restore_status_labels'><?php esc_html_e('Restore backup of status labels', 'publishpress-statuses');?></option>
1038 <?php endif;?>
1039
1040 <?php if (empty($backup_missing['backup_post_type'])):?>
1041 <option value='restore_status_post_types'><?php esc_html_e('Restore backup of status post types', 'publishpress-statuses');?></option>
1042 <?php endif;?>
1043
1044 <option value=''></option>
1045
1046 <?php if (empty($backup_missing['backup_color_'])):?>
1047 <option value='restore_status_colors_auto'><?php esc_html_e('Restore auto-backup of status colors', 'publishpress-statuses');?></option>
1048 <?php endif;?>
1049
1050 <?php if (empty($backup_missing['backup_icon_'])):?>
1051 <option value='restore_status_icons_auto'><?php esc_html_e('Restore auto-backup of status icons', 'publishpress-statuses');?></option>
1052 <?php endif;?>
1053
1054 <?php if (empty($backup_missing['backup_labels_'])):?>
1055 <option value='restore_status_labels_auto'><?php esc_html_e('Restore auto-backup of status labels', 'publishpress-statuses');?></option>
1056 <?php endif;?>
1057
1058 <?php if (empty($backup_missing['backup_post_type_'])):?>
1059 <option value='restore_status_post_types_auto'><?php esc_html_e('Restore auto-backup of status post types', 'publishpress-statuses');?></option>
1060 <?php endif;?>
1061
1062
1063 <option value=''></option>
1064
1065 <?php if (empty($backup_missing['color'])):?>
1066 <option value='default_status_colors'><?php esc_html_e('Use default status colors', 'publishpress-statuses');?></option>
1067 <?php endif;?>
1068
1069 <?php if (empty($backup_missing['icon'])):?>
1070 <option value='default_status_icons'><?php esc_html_e('Use default status icons', 'publishpress-statuses');?></option>
1071 <?php endif;?>
1072
1073 <?php if (empty($backup_missing['labels'])):?>
1074 <option value='default_status_labels'><?php esc_html_e('Use default status labels', 'publishpress-statuses');?></option>
1075 <?php endif;?>
1076
1077 <?php if (empty($backup_missing['post_type'])):?>
1078 <option value='default_status_post_types'><?php esc_html_e('Use default status post types', 'publishpress-statuses');?></option>
1079 <?php endif;?>
1080
1081 <?php if (get_option('publishpress_version') || defined('PP_STATUSES_OFFER_PLANNER_DEFAULTS')):?>
1082 <option value='default_status_colors_planner'><?php esc_html_e("Use Planner plugin's default status colors", 'publishpress-statuses');?></option>
1083 <?php endif;?>
1084
1085 <?php if (get_option('publishpress_version') || defined('PP_STATUSES_OFFER_PLANNER_DEFAULTS')):?>
1086 <option value='default_status_icons_planner'><?php esc_html_e("Use Planner plugin's default status icons", 'publishpress-statuses');?></option>
1087 <?php endif;?>
1088
1089 </select>
1090
1091 </div>
1092 <?php
1093 }
1094
1095 public function fltEditStatusDefaultTab($default_tab) {
1096 if (!$default_tab = \PP_Statuses_Functions::REQUEST_key('pp_tab')) {
1097 $default_tab = 'name';
1098 }
1099
1100 return $default_tab;
1101 }
1102
1103 /**
1104 * Set up configuration page to administer statuses.
1105 */
1106 public function render_admin_page()
1107 {
1108 $plugin_page = \PP_Statuses_Functions::getPluginPage();
1109
1110 $action = \PP_Statuses_Functions::GET_key('action');
1111 $enable_left_col = false;
1112
1113 /** Edit Status screen **/
1114 if (('publishpress-statuses' === $plugin_page) && ('edit-status' == $action) && !\PP_Statuses_Functions::empty_REQUEST('name')) {
1115 $status_name = \PP_Statuses_Functions::REQUEST_key('name');
1116
1117 $status_obj = \PublishPress_Statuses::getStatusBy('id', $status_name);
1118
1119 $status_label = ($status_obj && !empty($status_obj->label)) ? $status_obj->label : $status_name;
1120
1121 $tx_obj = get_taxonomy($status_obj->taxonomy);
1122
1123 if (('post_status' == $status_obj->taxonomy) || !$tx_obj || empty($tx_obj->labels) || empty($tx_obj->labels->singular_name)) {
1124 // translators: %s is the status name
1125 $title = sprintf(__('Edit Status: %s', 'publishpress-statuses'), $status_label);
1126 } else {
1127 // translators: %s is the status name
1128 $title = sprintf(__('Edit %1$s: %2$s', 'publishpress-statuses'), $tx_obj->labels->singular_name, $status_label);
1129 }
1130
1131 \PublishPress\ModuleAdminUI_Base::instance()->module->title = $title;
1132 \PublishPress\ModuleAdminUI_Base::instance()->default_header('');
1133
1134 require_once(__DIR__ . '/StatusEditUI.php');
1135 \PublishPress_Statuses\StatusEditUI::display();
1136
1137 } elseif (('publishpress-statuses' === $plugin_page) && ('edit-status-labels' == $action) && !\PP_Statuses_Functions::empty_REQUEST('name')) {
1138 $status_name = \PP_Statuses_Functions::REQUEST_key('name');
1139
1140 $status_obj = \PublishPress_Statuses::getStatusBy('id', $status_name);
1141
1142 $status_label = ($status_obj && !empty($status_obj->label)) ? $status_obj->label : $status_name;
1143
1144 $tx_obj = get_taxonomy($status_obj->taxonomy);
1145
1146 if (('post_status' == $status_obj->taxonomy) || !$tx_obj || empty($tx_obj->labels) || empty($tx_obj->labels->singular_name)) {
1147 // translators: %s is the status name
1148 $title = sprintf(__('Edit Status Labels: %s', 'publishpress-statuses'), $status_label);
1149 } else {
1150 // translators: %s is the status name
1151 $title = sprintf(__('Edit %1$s Labels: %2$s', 'publishpress-statuses'), $tx_obj->labels->singular_name, $status_label);
1152 }
1153
1154 \PublishPress\ModuleAdminUI_Base::instance()->module->title = $title;
1155 \PublishPress\ModuleAdminUI_Base::instance()->default_header('');
1156
1157 require_once(__DIR__ . '/StatusEditUI.php');
1158 \PublishPress_Statuses\StatusEditUI::display(['action' => $action]);
1159
1160 /** Statuses screen **/
1161 } elseif (('publishpress-statuses' === $plugin_page) && (!$action || ('statuses' == $action))) {
1162 add_action('publishpress_header_button', function() {
1163 $status_type = \PP_Statuses_Functions::REQUEST_key('status_type');
1164
1165 $args = [
1166 'action' => 'add-new',
1167 'status_type' => $status_type
1168 ];
1169
1170 switch ($status_type) {
1171 case 'visibility' :
1172 $args['taxonomy'] = 'post_visibility_pp';
1173 break;
1174
1175 default:
1176 if ($_taxonomy = apply_filters('publishpress_statuses_status_type_to_taxonomy', '', $status_type)) {
1177 $args['taxonomy'] = $_taxonomy;
1178 }
1179 }
1180
1181 $url = \PublishPress_Statuses::getLink(
1182 $args
1183 );
1184
1185 if (('visibility' != $status_type) || (defined('PRESSPERMIT_STATUSES_VERSION') && get_option('presspermit_privacy_statuses_enabled') )) {
1186 if (('revision' != $status_type) || defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) {
1187 echo '<a class="button primary add-new" title="'
1188 . esc_attr__("Add New Pre-Publication Status", 'publishpress-statuses')
1189 . '" href="' . esc_url($url) . '">' . esc_html__('Add New', 'publishpress-statuses') . '</a>';
1190 }
1191 }
1192 });
1193
1194 $status_type = \PP_Statuses_Functions::REQUEST_key('status_type');
1195
1196 \PublishPress\ModuleAdminUI_Base::instance()->default_header();
1197
1198 if ('visibility' == $status_type) {
1199 if (!defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) :?>
1200 <div class="pp-statuses-config-notice">
1201 <?php
1202 printf(
1203 // translators: %1$s and %2$s is link markup
1204 esc_html__('For custom Visibility Statuses, %1$supgrade to PublishPress Statuses Pro%2$s.', 'publishpress-statuses'),
1205 '<a href="' . esc_url('https://publishpress.com/statuses/') . '">',
1206 '</a>'
1207 );
1208 ?>
1209 </div>
1210
1211 <?php elseif (!get_option('presspermit_privacy_statuses_enabled')) :?>
1212 <div class="pp-statuses-config-notice">
1213 <?php
1214 $url = admin_url('admin.php?page=publishpress-statuses-settings');
1215
1216 printf(
1217 // translators: %1$s and %2$s is link markup
1218 esc_html__('Note: Custom Visibility Statuses are %1$sdisabled%2$s.', 'publishpress-statuses'),
1219 '<a href="' . esc_url($url) . '">',
1220 '</a>'
1221 );
1222 ?>
1223 </div>
1224
1225 <?php endif;
1226 }
1227
1228 // @todo: adapt old nav tab for status types (Pre-publication, Publication & Privacy, Revision Statuses)
1229 ?>
1230 <div class='nav-tab-wrapper'>
1231 <a href="<?php
1232 if (!$status_type = \PP_Statuses_Functions::REQUEST_key('status_type')) {
1233 $status_type = 'moderation';
1234 }
1235
1236 echo esc_url(\PublishPress_Statuses::getLink(['action' => 'statuses', 'status_type' => 'moderation'])); ?>"
1237 class="nav-tab<?php
1238 if (!$action || ('moderation' == $status_type)) {
1239 echo ' nav-tab-active';
1240 } ?>"><?php
1241 _e('Pre-Publication', 'publishpress-statuses'); ?></a>
1242
1243 <a href="<?php
1244 echo esc_url(\PublishPress_Statuses::getLink(['action' => 'statuses', 'status_type' => 'visibility'])); ?>"
1245 class="nav-tab<?php
1246 if ('visibility' == $status_type) {
1247 echo ' nav-tab-active';
1248 } ?>"><?php
1249 _e('Visibility', 'publishpress-statuses'); ?></a>
1250
1251 <?php
1252
1253 if (!defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) :?>
1254 <a href="<?php
1255 echo esc_url(\PublishPress_Statuses::getLink(['action' => 'statuses', 'status_type' => 'revision'])); ?>"
1256 class="nav-tab<?php
1257 if ('revision' == $status_type) {
1258 echo ' nav-tab-active';
1259 } ?>"><?php
1260 _e('Revision', 'publishpress-statuses'); ?>
1261
1262 <?php
1263 $badge =
1264 [
1265 'text' => 'PRO',
1266 'bg_color' => '#8B5CF6',
1267 'class' => 'pp-pro-badge'
1268 ];
1269 $badge_text = isset($badge['text']) ? esc_html($badge['text']) : 'PRO';
1270 $badge_color = isset($badge['color']) ? esc_attr($badge['color']) : '#8B5CF6';
1271 $badge_bg_color = isset($badge['bg_color']) ? esc_attr($badge['bg_color']) : '#8B5CF6';
1272 $badge_class = isset($badge['class']) ? esc_attr($badge['class']) : '';
1273
1274 printf(
1275 '<span class="pp-tab-badge %s" style="background: %s; color: white; font-size: 10px; font-weight: 600; padding: 2px 4px; border-radius: 10px; margin-left: 0; text-transform: uppercase; letter-spacing: 0.5px; box-shadow: 0 1px 3px rgba(0,0,0,0.2);">%s</span>',
1276 esc_html($badge_class),
1277 esc_html($badge_bg_color),
1278 esc_html($badge_text)
1279 );
1280 ?>
1281
1282 </a>
1283 <?php endif;
1284
1285 do_action('publishpress_statuses_table_tabs', $status_type);
1286 ?>
1287 </div>
1288 <?php
1289
1290 require_once(__DIR__ . '/StatusListTable.php');
1291 $wp_list_table = new \PublishPress_Statuses\StatusListTable();
1292 $wp_list_table->prepare_items();
1293
1294 do_action('publishpress_statuses_list_table_init', $status_type, $wp_list_table);
1295 ?>
1296
1297 <div id='co-l-right' class='pp-statuses-co-l-right'>
1298 <div class='col-wrap' style="overflow: auto;">
1299 <?php
1300 $wp_list_table->display(); ?>
1301 <?php
1302 wp_nonce_field('custom-status-sortable', 'custom-status-sortable'); ?>
1303 </div>
1304 </div>
1305
1306 <?php
1307 /** Add New Status **/
1308 } elseif (isset($plugin_page) && ('publishpress-statuses-add-new' === $plugin_page)) {
1309 $status_type = \PP_Statuses_Functions::REQUEST_key('status_type');
1310
1311 if (('visibility' == $status_type) && ! defined('PRESSPERMIT_STATUSES_VERSION')) {
1312 return;
1313 }
1314
1315 if (!$title = apply_filters('publishpress_statuses_management_title', '', $status_type)) {
1316 $title = ('visibility' == $status_type) ? __('Add New Visibility Status', 'publishpress-statuses') : __('Add New Pre-Publication Status', 'publishpress-statuses');
1317 }
1318
1319 if (!$descript = apply_filters('publishpress_statuses_management_descript', '', $status_type)) {
1320 $descript = ('visibility' == $status_type) ? __('This status can be assigned to customize post privacy.', 'publishpress-statuses') : __('This status can be assigned to an unpublished post using the Post Status dropdown.', 'publishpress-statuses');
1321 }
1322
1323 \PublishPress\ModuleAdminUI_Base::instance()->module->title = $title;
1324 \PublishPress\ModuleAdminUI_Base::instance()->default_header($descript);
1325
1326 $enable_left_col = true;
1327
1328 /** Status Settings **/
1329 } elseif (isset($plugin_page) && ('publishpress-statuses-settings' === $plugin_page)) {
1330 \PublishPress\ModuleAdminUI_Base::instance()->module->title = __('PublishPress Statuses Settings', 'publishpress-statuses');
1331 \PublishPress\ModuleAdminUI_Base::instance()->default_header();
1332
1333 $enable_left_col = true;
1334 }
1335
1336 if (!empty($enable_left_col)) :?>
1337 <div class="pp-columns-wrapper pp-enable-sidebar">
1338 <div class='pp-column-left pp-statuses-col-left'>
1339 <div class='col-wrap'>
1340 <div class='form-wrap'>
1341 <?php
1342 $current_tab = (!empty($_REQUEST['pp_tab'])) ? wp_unslash($_REQUEST['pp_tab']) : 'workflow'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1343
1344 if ('publishpress-statuses-add-new' === $plugin_page) :
1345 require_once(__DIR__ . '/StatusAddNewUI.php');
1346
1347 elseif ('publishpress-statuses-settings' === $plugin_page) :?>
1348 <div class="wrap publishpress-admin">
1349 <div class="pp-columns-wrapper<?php echo (!defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) ? ' pp-enable-sidebar' : '' ?>">
1350 <div class="pp-column-left">
1351 <h2 class="nav-tab-wrapper">
1352 <?php
1353 $tabs = [
1354 'workflow' => __('Workflow', 'publishpress-statuses'),
1355 'visibility' => __('Visibility', 'publishpress-statuses'),
1356 'integration' => __('Integration', 'publishpress-statuses'),
1357 'editor' => __('Editor', 'publishpress-statuses'),
1358 'advanced' => __('Advanced', 'publishpress-statuses'),
1359 'license' => __('License', 'publishpress-statuses'),
1360 ];
1361
1362 if (!defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) {
1363 unset($tabs['license']);
1364 }
1365
1366 foreach ($tabs as $tab => $tab_caption) : ?>
1367 <a
1368 href="#pp-tab-<?php echo esc_attr($tab);?>"
1369 data-section="<?php echo esc_attr($tab);?>"
1370 class="nav-tab<?php if ($current_tab === $tab) : ?> nav-tab-active<?php endif; ?>">
1371
1372 <?php echo esc_html($tab_caption); ?>
1373 </a>
1374 <?php endforeach; ?>
1375 </h2>
1376
1377 <div class="pp-module-settings">
1378
1379 </div>
1380
1381 </div><!-- .pp-column-left -->
1382 <?php if (!defined('PUBLISHPRESS_STATUSES_PRO_VERSION')) { ?>
1383 <div class="pp-column-right">
1384 <?php /* echo $context['pro_sidebar']; */ // phpcs:ignore Squiz.PHP.CommentedOutCode.Found, WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1385 </div><!-- .pp-column-right -->
1386 <?php } ?>
1387 </div><!-- .pp-columns-wrapper -->
1388 </div>
1389
1390 <script type="text/javascript">
1391 /* <![CDATA[ */
1392 jQuery(document).ready(function ($) {
1393 $('form > table > tbody > tr').hide();
1394 $('tr.pp-settings-<?php echo esc_attr($current_tab);?>').show();
1395
1396 $('.nav-tab-wrapper .nav-tab').on('click', function (e) {
1397 $('.form-table > tbody > tr').hide();
1398
1399 $('.nav-tab-wrapper a').removeClass('nav-tab-active');
1400 $(this).addClass('nav-tab-active');
1401
1402 $('input[name="pp_tab"]').val($(this).attr('data-section'));
1403 $('tr.pp-settings-' + $(this).attr('data-section')).show();
1404 });
1405 });
1406 /* ]]> */
1407 </script>
1408 <?php
1409 require_once(__DIR__ . '/StatusSettingsUI.php');
1410 endif;?>
1411 </div>
1412 </div>
1413 </div>
1414
1415 <?php if ('publishpress-statuses' != $plugin_page) :
1416 do_action('publishpress_statuses_settings_sidebar');
1417 endif; ?>
1418
1419 </div>
1420 <?php endif;
1421
1422 if (did_action('publishpress_default_header')) {
1423 \PublishPress\ModuleAdminUI_Base::defaultFooter(
1424 'publishpress-statuses',
1425 'PublishPress Statuses',
1426 'https://publishpress.com/statuses',
1427 'https://publishpress.com/documentation/statuses-start/',
1428 PUBLISHPRESS_STATUSES_URL . '/common/assets/publishpress-logo.png'
1429 );
1430 }
1431 ?>
1432 </div>
1433 <?php
1434 }
1435
1436 /**
1437 * Generate the color picker
1438 * $current_value Selected icon for the status
1439 * fieldname The name for the <select> field
1440 * $attributes Insert attributes different to name and class. For example: 'id' => "something"
1441 */
1442 public static function colorPicker($current_value = '', $fieldname = 'icon', $attributes = [])
1443 {
1444 // Load Color Picker
1445 if (is_admin()) {
1446 wp_enqueue_style('wp-color-picker');
1447 wp_enqueue_script(
1448 'publishpress-color-picker',
1449 PUBLISHPRESS_STATUSES_URL . 'common/libs/color-picker/color-picker.js',
1450 ['wp-color-picker'],
1451 false,
1452 true
1453 );
1454 }
1455
1456 // Set default value if empty
1457 if (! empty($current_value)) {
1458 $pp_color = $current_value;
1459 } else {
1460 $pp_color = \PublishPress_Statuses::DEFAULT_COLOR;
1461 }
1462
1463 echo '<input type="text" aria-required="true" size="7" maxlength="7" name="' . esc_attr($fieldname) . '" value="' . esc_attr($pp_color) . '" class="pp-color-picker" data-default-color="' . esc_attr($pp_color) . '" />';
1464 }
1465
1466 /**
1467 * Given a form field and a description, prints either the error associated with the field or the description.
1468 *
1469 * @param string $field The form field for which to check for an error
1470 * @param string $description Unlocalized string to display if there was no error with the given field
1471 *
1472 */
1473 public static function printErrorOrDescription($field, $description)
1474 {
1475 if ($form_errors = \PublishPress_Statuses::instance()->form_errors): ?>
1476 <div class="form-error">
1477 <?php if (!empty($form_errors[$field])):?>
1478 <p><?php echo esc_html($form_errors[$field]); ?></p>
1479 <?php endif;?>
1480 </div>
1481 <?php else: ?>
1482 <p class="description"><?php echo esc_html($description); ?></p>
1483 <?php endif;
1484 }
1485 }
1486