0) { $p = get_post($id); if ($p && $p->post_type === 'page' && $p->post_status !== 'trash') { return self::describe($p, 'option'); } } $ids = get_posts(array( 'post_type' => 'page', 'post_status' => array('publish', 'draft', 'pending', 'private'), 'meta_key' => self::META_KEY, 'posts_per_page' => 1, 'fields' => 'ids', )); if (!empty($ids)) { $p = get_post((int) $ids[0]); if ($p) { return self::describe($p, 'meta'); } } $p = get_page_by_path(self::SLUG, OBJECT, 'page'); if ($p && $p->post_status !== 'trash') { return self::describe($p, 'slug'); } $found = get_posts(array( 'post_type' => 'page', 'post_status' => array('publish', 'draft'), 's' => 'accessibility statement', 'posts_per_page' => 5, )); foreach ($found as $cand) { // Needs both words: "Accessibility Services" is not a statement. if (preg_match('/accessib/i', $cand->post_title) && preg_match('/statement/i', $cand->post_title)) { return self::describe($cand, 'title'); } } return null; } private static function describe($p, $source) { return array( 'id' => (int) $p->ID, 'url' => (string) get_permalink($p), 'status' => (string) $p->post_status, 'source' => $source, 'title' => (string) $p->post_title, ); } /** * The statement kept in the AllAccessible dashboard, fetched fresh * (the on-page menu reads the same endpoint). '' when the account has none. */ public static function statement_html() { if (!class_exists('AllAccessible_ApiClient')) { return ''; } $client = AllAccessible_ApiClient::get_instance(); if (!method_exists($client, 'get_statement_html')) { return ''; } return wp_kses_post((string) $client->get_statement_html(true)); } /** * "Tell us about a problem" block from the assigned contact details. * Empty string when neither email nor phone is set. * * @param array $c contact_email, contact_phone */ public static function contact_block(array $c) { $email = sanitize_email(isset($c['contact_email']) ? $c['contact_email'] : ''); $phone = sanitize_text_field(isset($c['contact_phone']) ? $c['contact_phone'] : ''); if ($email === '' && $phone === '') { return ''; } $contact = $email !== '' ? sprintf('%1$s', esc_attr($email)) : ''; if ($phone !== '') { $contact .= ($contact !== '' ? ' ' . esc_html__('or call', 'allaccessible') . ' ' : '') . esc_html($phone); } return '
' . esc_html__('If something on this site is hard to use, please let us know', 'allaccessible') . ': ' . $contact . '. ' . esc_html__('Include the page address and what went wrong.', 'allaccessible') . '
'; } /** * Create the page: dashboard statement + contact block, as an ordinary * WordPress page the customer edits afterwards. Registration with * AllAccessible happens in the browser; PHP only reports the URL. * * @param array $a contact_email, contact_phone, publish (bool) * @return array|WP_Error describe() of the new page */ public static function create_page(array $a) { $publish = !empty($a['publish']); $contact = array( 'contact_email' => sanitize_email(isset($a['contact_email']) ? $a['contact_email'] : ''), 'contact_phone' => sanitize_text_field(isset($a['contact_phone']) ? $a['contact_phone'] : ''), ); update_option(self::OPTION_CONTACT, $contact, false); $body = self::statement_html(); if (trim(strip_tags($body)) === '') { $body = '' . esc_html__('Accessibility statement', 'allaccessible') . '
' . "\n"; } /* ───────────────────────── Admin guide (AJAX + UI) ───────────────────────── */ /** AJAX: create | adopt | registered | footer | status. Admin-only, nonce-checked. */ public static function ajax_handle() { if (!current_user_can('manage_options')) { wp_send_json_error(array('message' => __('Unauthorized', 'allaccessible')), 403); } check_ajax_referer(self::AJAX_ACTION, '_wpnonce'); $do = isset($_POST['do']) ? sanitize_key($_POST['do']) : ''; switch ($do) { case 'create': $r = self::create_page(array( 'contact_email' => isset($_POST['contact_email']) ? sanitize_email(wp_unslash($_POST['contact_email'])) : '', 'contact_phone' => isset($_POST['contact_phone']) ? sanitize_text_field(wp_unslash($_POST['contact_phone'])) : '', 'publish' => isset($_POST['publish']) && (string) $_POST['publish'] === '1', )); break; case 'adopt': $r = self::adopt_existing(isset($_POST['page_id']) ? (int) $_POST['page_id'] : 0); break; case 'refresh': $r = self::refresh_page(); break; case 'registered': // the browser posted statementUrl to the app and got 200 $url = isset($_POST['url']) ? esc_url_raw(wp_unslash($_POST['url'])) : ''; update_option(self::OPTION_REGISTERED, $url, false); $r = array('registered' => $url); break; case 'footer': $on = isset($_POST['on']) && (string) $_POST['on'] === '1'; update_option(self::OPTION_FOOTER, $on, false); $r = array('footer' => $on); break; case 'status': $r = array(); break; default: $r = new WP_Error('aacb_bad_action', __('Unknown action', 'allaccessible')); } if (is_wp_error($r)) { wp_send_json_error(array('message' => $r->get_error_message())); } wp_send_json_success(array_merge(self::status(), array('result' => $r))); } /** * The guide. $context = 'dashboard' | 'wizard'. Three states: * a page we do not own was found → offer to use it or create a new one * a page we own exists → status, link-it, footer toggle, edit * nothing → two questions (contact, publish/draft) * Everything here is admin-initiated; nothing runs on page load. */ public static function render_guide($context = 'dashboard') { $s = self::status(); $nonce = wp_create_nonce(self::AJAX_ACTION); $owned = $s['page'] && ($s['page']['source'] === 'option' || $s['page']['source'] === 'meta'); $found = $s['page'] && !$owned; $saved = get_option(self::OPTION_CONTACT, array()); $saved = is_array($saved) ? $saved : array(); ?>