Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 131 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 1 |
| CTA | |
0.00% |
0 / 131 |
|
0.00% |
0 / 9 |
702 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
| maybe_init_options | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| get_option_name_for_screen | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| handle_ajax_toggle | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
20 | |||
| add_screen_option_html | |
0.00% |
0 / 27 |
|
0.00% |
0 / 1 |
6 | |||
| add_toggle_script | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
| add_cta_to_add_new_button | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
12 | |||
| add_style | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
2 | |||
| is_core_post_type | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
72 | |||
| 1 | <?php |
| 2 | namespace NewfoldLabs\WP\Module\Patterns\Admin; |
| 3 | |
| 4 | /** |
| 5 | * CTA for the edit pages screen. |
| 6 | */ |
| 7 | class CTA { |
| 8 | |
| 9 | /** |
| 10 | * WordPress option name for posts |
| 11 | */ |
| 12 | const POST_OPTION_NAME = 'nfd_wb_cta_enabled_posts'; |
| 13 | |
| 14 | /** |
| 15 | * WordPress option name for pages |
| 16 | */ |
| 17 | const PAGE_OPTION_NAME = 'nfd_wb_cta_enabled_pages'; |
| 18 | |
| 19 | /** |
| 20 | * Nonce action name |
| 21 | */ |
| 22 | const NONCE_ACTION = 'nfd_wonderblocks_toggle'; |
| 23 | |
| 24 | /** |
| 25 | * Constructor. |
| 26 | */ |
| 27 | public function __construct() { |
| 28 | |
| 29 | $this->maybe_init_options(); |
| 30 | |
| 31 | \add_action( 'wp_ajax_toggle_wonderblocks_cta', array( $this, 'handle_ajax_toggle' ) ); |
| 32 | |
| 33 | if ( ! $this->is_core_post_type() ) { |
| 34 | return; |
| 35 | } |
| 36 | |
| 37 | \add_action( 'admin_head', array( $this, 'add_style' ) ); |
| 38 | \add_action( 'admin_footer', array( $this, 'add_cta_to_add_new_button' ), 10 ); |
| 39 | \add_action( 'admin_footer', array( $this, 'add_toggle_script' ), 20 ); |
| 40 | \add_filter( 'screen_settings', array( $this, 'add_screen_option_html' ), 10, 2 ); |
| 41 | } |
| 42 | |
| 43 | /** |
| 44 | * Initialize options if they don't exist |
| 45 | */ |
| 46 | private function maybe_init_options() { |
| 47 | if ( false === get_option( self::POST_OPTION_NAME ) ) { |
| 48 | add_option( self::POST_OPTION_NAME, true ); |
| 49 | } |
| 50 | if ( false === get_option( self::PAGE_OPTION_NAME ) ) { |
| 51 | add_option( self::PAGE_OPTION_NAME, true ); |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * Get the appropriate option name based on screen |
| 57 | * |
| 58 | * @param string $screen_id The screen ID |
| 59 | */ |
| 60 | private function get_option_name_for_screen( $screen_id ) { |
| 61 | return 'edit-page' === $screen_id ? self::PAGE_OPTION_NAME : self::POST_OPTION_NAME; |
| 62 | } |
| 63 | |
| 64 | /** |
| 65 | * Handle the AJAX toggle |
| 66 | */ |
| 67 | public function handle_ajax_toggle() { |
| 68 | \check_ajax_referer( self::NONCE_ACTION, 'nonce' ); |
| 69 | |
| 70 | if ( ! \current_user_can( 'manage_options' ) ) { |
| 71 | \wp_die( '', '', 403 ); |
| 72 | } |
| 73 | |
| 74 | $screen_id = isset( $_POST['screen_id'] ) ? \sanitize_text_field( $_POST['screen_id'] ) : 'edit-post'; |
| 75 | $enabled = (bool) ( 'true' === $_POST['nfd_wba_cta_button'] ); |
| 76 | $option_name = $this->get_option_name_for_screen( $screen_id ); |
| 77 | |
| 78 | $updated = \update_option( $option_name, $enabled ); |
| 79 | |
| 80 | if ( $updated ) { |
| 81 | \wp_send_json_success( |
| 82 | array( |
| 83 | 'enabled' => $enabled, |
| 84 | 'option_name' => $option_name, |
| 85 | 'screen_id' => $screen_id, |
| 86 | ) |
| 87 | ); |
| 88 | } else { |
| 89 | \wp_send_json_error( 'Failed to update option' ); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | /** |
| 94 | * Add the screen option HTML |
| 95 | * |
| 96 | * @param string $settings The current screen settings |
| 97 | * @param object $screen The current screen object |
| 98 | */ |
| 99 | public function add_screen_option_html( $settings, $screen ) { |
| 100 | if ( ! \in_array( $screen->id, array( 'edit-page', 'edit-post' ), true ) ) { |
| 101 | return $settings; |
| 102 | } |
| 103 | |
| 104 | $option_name = $this->get_option_name_for_screen( $screen->id ); |
| 105 | $enabled = \get_option( $option_name, true ); |
| 106 | |
| 107 | $html = '<fieldset class="metabox-prefs wonderblocks">'; |
| 108 | $html .= '<legend>' . esc_html__( 'WonderBlocks', 'nfd-wonder-blocks' ) . '</legend>'; |
| 109 | $html .= '<label>'; |
| 110 | $html .= '<input type="checkbox" id="wonderblocks-toggle"' . checked( $enabled, true, false ) . ' /> '; |
| 111 | $html .= esc_html__( 'Show WonderBlocks Button', 'nfd-wonder-blocks' ); |
| 112 | $html .= '</label>'; |
| 113 | $html .= '</fieldset>'; |
| 114 | $html .= \wp_nonce_field( self::NONCE_ACTION, 'wonderblocks_nonce', true, false ); |
| 115 | |
| 116 | $allowed_html = array( |
| 117 | 'fieldset' => array( |
| 118 | 'class' => true, |
| 119 | ), |
| 120 | 'legend' => array(), |
| 121 | 'label' => array(), |
| 122 | 'input' => array( |
| 123 | 'type' => true, |
| 124 | 'id' => true, |
| 125 | 'checked' => true, |
| 126 | 'name' => true, |
| 127 | 'value' => true, |
| 128 | ), |
| 129 | ); |
| 130 | |
| 131 | return \wp_kses( $settings . $html, $allowed_html ); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Add toggle script to footer |
| 136 | */ |
| 137 | public function add_toggle_script() { |
| 138 | $screen = \get_current_screen(); |
| 139 | ?> |
| 140 | <script> |
| 141 | document.addEventListener("DOMContentLoaded", function () { |
| 142 | const toggle = document.getElementById("wonderblocks-toggle"); |
| 143 | const nonceField = document.getElementById("wonderblocks_nonce"); |
| 144 | const ajaxUrl = "<?php echo esc_js( admin_url( 'admin-ajax.php' ) ); ?>"; |
| 145 | const screenId = "<?php echo esc_js( $screen->id ); ?>"; |
| 146 | const ctaButton = document.querySelector('.nfd-wba-cta-edit-screen'); |
| 147 | |
| 148 | if (!toggle || !nonceField || !ctaButton) return; |
| 149 | |
| 150 | toggle.addEventListener("change", function () { |
| 151 | const enabled = this.checked ? "true" : "false"; |
| 152 | const data = new FormData(); |
| 153 | data.append("action", "toggle_wonderblocks_cta"); |
| 154 | data.append("nonce", nonceField.value); |
| 155 | data.append("nfd_wba_cta_button", enabled); |
| 156 | data.append("screen_id", screenId); |
| 157 | |
| 158 | fetch( |
| 159 | ajaxUrl, |
| 160 | { |
| 161 | method: "POST", |
| 162 | body: data, |
| 163 | } |
| 164 | ) |
| 165 | .then((response) => response.json()) |
| 166 | .then((response) => { |
| 167 | if (response.success) { |
| 168 | ctaButton.style.display = enabled === "true" ? "inline-flex" : "none"; |
| 169 | } else { |
| 170 | toggle.checked = !toggle.checked; |
| 171 | console.error("Failed to update WonderBlocks setting:", response); |
| 172 | } |
| 173 | }) |
| 174 | .catch((error) => { |
| 175 | toggle.checked = !toggle.checked; |
| 176 | console.error("AJAX request failed:", error); |
| 177 | }); |
| 178 | }); |
| 179 | }); |
| 180 | </script> |
| 181 | <?php |
| 182 | } |
| 183 | |
| 184 | /** |
| 185 | * Add CTA to Add New button |
| 186 | */ |
| 187 | public function add_cta_to_add_new_button() { |
| 188 | $screen = \get_current_screen(); |
| 189 | $option_name = $this->get_option_name_for_screen( $screen->id ); |
| 190 | $enabled = \get_option( $option_name, true ); |
| 191 | |
| 192 | // Set the URL based on screen type |
| 193 | if ( 'edit-post' === $screen->id ) { |
| 194 | $url = \admin_url( 'post-new.php?wb-library=patterns&wb-category=text' ); |
| 195 | } elseif ( 'edit-page' === $screen->id ) { |
| 196 | $url = \admin_url( 'post-new.php?post_type=page&wb-library=patterns&wb-category=features' ); |
| 197 | } else { |
| 198 | // Default fallback URL |
| 199 | $url = \admin_url( 'post-new.php?wb-library=patterns' ); |
| 200 | } |
| 201 | |
| 202 | $svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="2.25 6 19.5 13.5" width="19px" height="19px"><path stroke-linecap="round" stroke-linejoin="round" d="M3.34 7.754c0-.552.447-.999.999-.999h5.328a1 1 0 0 1 .999.999v3.329a1 1 0 0 1-.999.999H4.339a.999.999 0 0 1-.999-.999V7.754Zm10.655 1.331a1 1 0 0 1 .999-.998h4.662c.552 0 .999.447.999.998v7.326a.999.999 0 0 1-.999.999h-4.662a1 1 0 0 1-.999-.999V9.085Zm-9.323 6.66a1 1 0 0 1 .998-.999h4.662a1 1 0 0 1 .999.999v1.998a1 1 0 0 1-.999.999H5.67a1 1 0 0 1-.998-.999v-1.998Z" style="fill:none;stroke-width:1.5px;paint-order:stroke;stroke:currentColor"/></svg>'; |
| 203 | |
| 204 | $cta_text = sprintf( |
| 205 | /* translators: %1$s: opening anchor tag, %2$s: closing anchor tag */ |
| 206 | _x( |
| 207 | '%1$sAdd With WonderBlocks%2$s', |
| 208 | 'Button label', |
| 209 | 'nfd-wonder-blocks' |
| 210 | ), |
| 211 | '<a class="page-title-action" href="' . \esc_url( $url ) . '">' . $svg . '<span class="text">', |
| 212 | '</span></a>' |
| 213 | ); |
| 214 | |
| 215 | ?> |
| 216 | <script> |
| 217 | document.addEventListener('DOMContentLoaded', function() { |
| 218 | const pageTitleAction = document.querySelector('.wrap .page-title-action'); |
| 219 | if (pageTitleAction) { |
| 220 | const newElement = document.createElement('div'); |
| 221 | newElement.innerHTML = <?php echo \wp_json_encode( $cta_text ); ?>; |
| 222 | newElement.classList.add('nfd-wba-cta-edit-screen'); |
| 223 | if (!<?php echo json_encode( $enabled ); ?>) { |
| 224 | newElement.style.display = 'none'; |
| 225 | } |
| 226 | pageTitleAction.insertAdjacentElement('afterend', newElement); |
| 227 | } |
| 228 | }); |
| 229 | </script> |
| 230 | <?php |
| 231 | } |
| 232 | |
| 233 | /** |
| 234 | * Add styles for the CTA |
| 235 | */ |
| 236 | public function add_style() { |
| 237 | ?> |
| 238 | <style> |
| 239 | .nfd-wba-cta-edit-screen { |
| 240 | display: inline-flex; |
| 241 | } |
| 242 | .nfd-wba-cta-edit-screen .page-title-action { |
| 243 | align-items: center; |
| 244 | border-color: #3d7e29; |
| 245 | background-color: #3d7e29; |
| 246 | color: #ffffff; |
| 247 | } |
| 248 | .nfd-wba-cta-edit-screen .page-title-action:hover, |
| 249 | .nfd-wba-cta-edit-screen .page-title-action:active { |
| 250 | border-color: #3F8F3C; |
| 251 | background-color: #3F8F3C; |
| 252 | color: #ffffff; |
| 253 | } |
| 254 | .nfd-wba-cta-edit-screen .page-title-action:focus { |
| 255 | border-color: #2f621f; |
| 256 | background-color: #2f621f; |
| 257 | box-shadow: 0 0 0 1px #2f621f; |
| 258 | } |
| 259 | |
| 260 | .nfd-wba-cta-edit-screen svg { |
| 261 | margin-right: 5px; |
| 262 | position: relative; |
| 263 | top: 4px; |
| 264 | } |
| 265 | @media only screen and (max-width: 433px) { |
| 266 | .nfd-wba-cta-edit-screen { |
| 267 | margin-top: 6px; |
| 268 | } |
| 269 | } |
| 270 | </style> |
| 271 | <?php |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * Check if we're on the edit pages screen |
| 276 | */ |
| 277 | private function is_core_post_type() { |
| 278 | if ( ! \is_admin() || ! \is_user_logged_in() ) { |
| 279 | return false; |
| 280 | } |
| 281 | |
| 282 | global $pagenow, $typenow; |
| 283 | |
| 284 | $is_core_post_type = ( 'edit.php' === $pagenow && ( |
| 285 | // Default post type (no post_type parameter) |
| 286 | ( ! isset( $_GET['post_type'] ) && empty( $typenow ) ) || |
| 287 | // Explicit post type check |
| 288 | ( isset( $_GET['post_type'] ) && in_array( $_GET['post_type'], array( 'post', 'page' ), true ) ) || |
| 289 | // Fallback to typenow |
| 290 | in_array( $typenow, array( 'post', 'page' ), true ) |
| 291 | ) ); |
| 292 | |
| 293 | return $is_core_post_type; |
| 294 | } |
| 295 | } |