├── README.md ├── accessibility-statement-generator.php ├── class-accessibility-statement-plugin.php ├── class-statement-generator.php ├── helpers.php └── settings-page.php /README.md: -------------------------------------------------------------------------------- 1 | # Accessibility Statement Feature Plugin 2 | 3 | A plugin to automatically generate the structure of an accessibility statement for a WordPress website. This plugin replicates the look and functionality of the Privacy Policy tool already found in WordPress. 4 | 5 | --- 6 | 7 | ## Getting started 8 | 9 | Requirements: 10 | 11 | - Git 12 | 13 | 1. `git clone git@github.com:10degrees/accessibility-statement-plugin.git accessibility-statement-generator` into `wp-content/plugins` 14 | 2. Activate the 'Accessibility Statement Generator' plugin in your Admin area. 15 | 3. Go to Settings > Accessibility to generate your accessibility statement. 16 | 17 | ## Features 18 | 19 | 1. Generate the basic structure of an accessibility statement for a site in a single click (content from https://www.w3.org/WAI/planning/statements/generator/#create) or: 20 | 2. Choose which page to use as the accessibility statement. 21 | 3. Display an 'Accessibility Statement Page' tag next to the accessibility statement page when viewing all pages. 22 | 23 | This plugin **does not** generate a full accessibility statement. It instead provides a page with useful headings and prompts to be used to understand what content an accessibility statement should contain. 24 | 25 | ## Branches 26 | 27 | ### advanced-version 28 | 29 | Initially we are focusing on the 'basic' version of the feature plugin (in the `master` branch), which replicates the Privacy Policy tool. In the `advanced-version` branch you can find a version of the plugin where the accessibility statement is generated using data inputted by the user. 30 | 31 | To view this version of the plugin: 32 | 1. `git fetch origin advanced-version` 33 | 2. `git checkout advanced-version` 34 | 35 | This version of the plugin has no build tooling, e.g. Gulp or Webpack, and so its JavaScript may not function on older browsers e.g. IE11. 36 | 37 | ## Related Links 38 | 39 | - https://core.trac.wordpress.org/ticket/50673 40 | - https://www.w3.org/WAI/planning/statements/generator/#create -------------------------------------------------------------------------------- /accessibility-statement-generator.php: -------------------------------------------------------------------------------- 1 | check_nonce( 'create_accessibility_statement' ) ) { 42 | wp_redirect( admin_url( 'options-general.php?page=accessibility-statement&failed-nonce=1' ) ); 43 | exit; 44 | } 45 | 46 | $default_accessibility_statement_content = StatementGenerator::get_default_content(); 47 | 48 | $accessibility_statement_id = wp_insert_post( 49 | array( 50 | 'post_title' => __( 'Accessibility Statement' ), 51 | 'post_status' => 'draft', 52 | 'post_type' => 'page', 53 | 'post_content' => $default_accessibility_statement_content, 54 | ), 55 | true 56 | ); 57 | 58 | if ( is_wp_error( $accessibility_statement_id ) ) { 59 | wp_redirect( admin_url( 'options-general.php?page=accessibility-statement&page-created-error=1' ) ); 60 | exit; 61 | } else { 62 | update_option( 'wp_page_for_accessibility_statement', $accessibility_statement_id ); 63 | 64 | wp_redirect( admin_url( 'post.php?post=' . $accessibility_statement_id . '&action=edit' ) ); 65 | exit; 66 | } 67 | } 68 | 69 | /** 70 | * Check a nonce 71 | * 72 | * @param string $nonce_field Nonce name. 73 | * 74 | * @return boolean True if we can verify the nonce, else false 75 | */ 76 | private function check_nonce( $nonce_field ) { 77 | if ( ! isset( $_POST[ $nonce_field ] ) || ! wp_verify_nonce( $_POST[ $nonce_field ], $nonce_field ) ) { 78 | return false; 79 | } 80 | 81 | return true; 82 | } 83 | 84 | /** 85 | * Set the accessibility statement page 86 | * 87 | * @return void 88 | */ 89 | public function set_accessibility_statement() { 90 | if ( ! $this->check_nonce( 'set_accessibility_statement' ) ) { 91 | wp_redirect( admin_url( 'options-general.php?page=accessibility-statement&failed-nonce=1' ) ); 92 | exit; 93 | } 94 | 95 | $accessibility_page_id = isset( $_POST['page_for_accessibility_statement'] ) ? (int) $_POST['page_for_accessibility_statement'] : 0; 96 | 97 | update_option( 'wp_page_for_accessibility_statement', $accessibility_page_id ); 98 | 99 | wp_redirect( admin_url( 'options-general.php?page=accessibility-statement&page-updated=1' ) ); 100 | exit; 101 | } 102 | 103 | /** 104 | * Display notices on settings page 105 | * 106 | * @return void 107 | */ 108 | public function add_admin_notices() { 109 | $screen = get_current_screen(); 110 | 111 | if ( 'settings_page_accessibility-statement' === $screen->id ) { 112 | $this->display_nonce_notices(); 113 | $this->display_update_statement_notices(); 114 | $this->display_create_statement_notices(); 115 | $this->display_selected_statement_notices(); 116 | } 117 | } 118 | 119 | /** 120 | * Display notices relating to nonce checks 121 | * 122 | * @return void 123 | */ 124 | private function display_nonce_notices() { 125 | if ( isset( $_GET['failed-nonce'] ) && $_GET['failed-nonce'] ) { 126 | add_settings_error( 127 | 'page_for_accessibility_statement', 128 | 'page_for_accessibility_statement', 129 | __( 'Nonce couldn\'t be verified.' ), 130 | 'error' 131 | ); 132 | } 133 | } 134 | 135 | /** 136 | * Display the notices related to the chosen Accessibility Statement page 137 | * 138 | * @return void 139 | */ 140 | private function display_selected_statement_notices() { 141 | $accessibility_statement_id = (int) get_option( 'wp_page_for_accessibility_statement' ); 142 | 143 | if ( ! empty( $accessibility_statement_id ) ) { 144 | $accessibility_statement = get_post( $accessibility_statement_id ); 145 | if ( ! $accessibility_statement instanceof WP_Post ) { 146 | add_settings_error( 147 | 'page_for_accessibility_statement', 148 | 'page_for_accessibility_statement', 149 | __( 'The currently selected Accessibility Statement page does not exist. Please create or select a new page.' ), 150 | 'error' 151 | ); 152 | } else { 153 | if ( 'trash' === $accessibility_statement->post_status ) { 154 | add_settings_error( 155 | 'page_for_accessibility_statement', 156 | 'page_for_accessibility_statement', 157 | sprintf( 158 | /* translators: %s: URL to Pages Trash. */ 159 | __( 'The currently selected Accessibility Statement page is in the Trash. Please create or select a new Accessibility Statement page or restore the current page.' ), 160 | 'edit.php?post_status=trash&post_type=page' 161 | ), 162 | 'error' 163 | ); 164 | } 165 | } 166 | } 167 | } 168 | 169 | /** 170 | * Display the notices related to creating an Accessibility Statement 171 | * 172 | * @return void 173 | */ 174 | private function display_create_statement_notices() { 175 | if ( isset( $_GET['page-created-error'] ) && $_GET['page-created-error'] ) { 176 | add_settings_error( 177 | 'page_for_accessibility_statement', 178 | 'page_for_accessibility_statement', 179 | __( 'Unable to create an Accessibility Statement.' ), 180 | 'error' 181 | ); 182 | } 183 | } 184 | 185 | /** 186 | * Display the notices related to updating the Accessiblity Statement page 187 | * 188 | * @return void 189 | */ 190 | private function display_update_statement_notices() { 191 | if ( isset( $_GET['page-updated'] ) && $_GET['page-updated'] ) { 192 | $accessibility_statement_updated_message = __( 'Accessibility Statement page updated successfully.' ); 193 | 194 | $accessibility_page_id = get_option( 'wp_page_for_accessibility_statement' ); 195 | 196 | if ( $accessibility_page_id ) { 197 | if ( 198 | 'publish' === get_post_status( $accessibility_page_id ) 199 | && current_user_can( 'edit_theme_options' ) 200 | && current_theme_supports( 'menus' ) 201 | ) { 202 | $accessibility_statement_updated_message = sprintf( 203 | /* translators: %s: URL to Customizer -> Menus. */ 204 | __( 'Accessibility Statement page setting updated successfully. Remember to update your menus!' ), 205 | esc_url( add_query_arg( 'autofocus[panel]', 'nav_menus', admin_url( 'customize.php' ) ) ) 206 | ); 207 | } 208 | } 209 | 210 | add_settings_error( 'page_for_accessibility_statement', 'page_for_accessibility_statement', $accessibility_statement_updated_message, 'success' ); 211 | } 212 | } 213 | 214 | /** 215 | * Add the post state for the Accessibility Statement 216 | * 217 | * @param array $post_states Array of post states. 218 | * @param WP_Post $post Current Post. 219 | * 220 | * @return array Array of post states 221 | */ 222 | public function add_post_state( $post_states, $post ) { 223 | if ( intval( get_option( 'wp_page_for_accessibility_statement' ) ) === $post->ID ) { 224 | $post_states['page_for_accessibility_statement'] = _x( 'Accessibility Statement Page', 'page label' ); 225 | } 226 | 227 | return $post_states; 228 | } 229 | 230 | /** 231 | * Add Settings page to Admin dashboard 232 | * 233 | * @return void 234 | */ 235 | public function add_settings_page() { 236 | add_options_page( __( 'Accessibility Statement', 'a11y-statement' ), __( 'Accessibility', 'a11y-statement' ), 'manage_options', 'accessibility-statement', array( $this, 'page_contents' ), 7 ); 237 | } 238 | 239 | /** 240 | * Get the Settings page contents 241 | * 242 | * @return void 243 | */ 244 | public function page_contents() { 245 | include 'settings-page.php'; 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /class-statement-generator.php: -------------------------------------------------------------------------------- 1 | ' . sprintf( __('Accessibility Statement for %s'), get_bloginfo( 'name', 'display' )) . ''; 19 | 20 | $strings[] .= '

' . __( 'We are committed to ensuring digital accessibility for people with disabilities. We are continually improving the user experience for everyone, and applying the relevant accessibility standards.' ) . '

'; 21 | 22 | $strings[] .= '

' . __( 'Measures to support accessibility' ) . '

'; 23 | $strings[] .= '

' . __( 'In this section you should list the measures you\'ve taken to support the accessibility of your site.' ) . '

'; 24 | $strings[] .= '

' . sprintf( __( 'We take the following measures to ensure accessibility of %s:' ), get_bloginfo( 'name', 'display' ) ) . '

'; 25 | 26 | $strings[] .= '

' . __( 'Conformance status' ) . '

'; 27 | $strings[] .= '

' . __( 'In this section you should explain what level (if any) of the WCAG this site conforms to. You should also explain whether the site is fully or partially conformant, and what this means.' ) . '

'; 28 | 29 | $strings[] .= '

' . __( 'Additional accessibility considerations' ) . '

'; 30 | $strings[] .= '

' . __( 'In this section you should explain any additional considerations, like areas where you have met the success criteria of higher WCAG levels.' ) . '

'; 31 | 32 | $strings[] .= '

' . __( 'Feedback' ) . '

'; 33 | $strings[] .= '

' . __( 'In this section you should provide the user with contact details should they find any accessibility barriers on the site. You should also provide a time window in which you aim to reply.' ) . '

'; 34 | 35 | $strings[] .= '

' . __( 'Compatibility with browsers and assisstive technology' ) . '

'; 36 | $strings[] .= '

' . __( 'In this section you should provide the user with a list of browsers, assistive technologies and operating systems the site is compatible with e.g. browser X with assistive technology Y on operating system Z.' ) . '

'; 37 | $strings[] .= '

' . __( 'You should also provide a list of browsers, assistive technologies and operating systems the site isn\'t compatible with, e.g. browsers older than 3 major versions.' ) . '

'; 38 | 39 | $strings[] .= '

' . __( 'Technical specifications' ) . '

'; 40 | $strings[] .= '

' . __( 'In this section you should list the technologies that the site relies on to work, e.g. HTML, JavaScript and CSS.' ) . '

'; 41 | 42 | $strings[] .= '

' . __( 'Limitations and alternatives' ) . '

'; 43 | $strings[] .= '

' . __( 'In this section you should list the known limitations the site has, why they occur, any potential solutions and a method of contact should the user require support.' ) . '

'; 44 | 45 | $strings[] .= '

' . __( 'Assessment approach' ) . '

'; 46 | $strings[] .= '

' . __( 'In this section you should list the ways the accessibility of the site has been assessed, e.g. External evaluation.' ) . '

'; 47 | 48 | $strings[] .= '

' . __( 'Evaluation report' ) . '

'; 49 | $strings[] .= '

' . __( 'In this section you should provide the user with a link to your evaluation report (if you have one).' ) . '

'; 50 | 51 | $strings[] .= '

' . __( 'Evaluation statement' ) . '

'; 52 | $strings[] .= '

' . __( 'In this section you should provide the user with a link to your evaluation statement (if you have one).' ) . '

'; 53 | 54 | $strings[] .= '

' . __( 'Other evidence' ) . '

'; 55 | $strings[] .= '

' . __( 'In this section you should provide any additional evidence.' ) . '

'; 56 | 57 | $strings[] .= '

' . __( 'Formal approval of this accessibility statement' ) . '

'; 58 | $strings[] .= '

' . __( 'In this section you should provide the details of who approved the accessibility statement, e.g. the Communication Department of your company.' ) . '

'; 59 | 60 | $strings[] .= '

' . __( 'Formal complaints' ) . '

'; 61 | $strings[] .= '

' . __( 'In this section you should provide a description of your complaints procedure, including a time frame for a response and a time frame for a proposed solution.' ) . '

'; 62 | 63 | $strings[] .= '

' . sprintf( __( 'This statement was created on the %s.' ), date( 'dS F Y' ) ) . '

'; 64 | 65 | if ( $use_blocks ) { 66 | foreach ( $strings as $key => $string ) { 67 | if ( 0 === strpos( $string, '

' ) ) { 68 | $strings[ $key ] = '' . $string . ''; 69 | } 70 | 71 | if ( 0 === strpos( $string, '

' ) ) { 72 | $strings[ $key ] = '' . $string . ''; 73 | } 74 | 75 | if ( 0 === strpos( $string, '

' ) ) { 76 | $strings[ $key ] = '' . $string . ''; 77 | } 78 | 79 | if ( 0 === strpos( $string, '

' ) ) { 80 | $strings[ $key ] = '' . $string . ''; 81 | } 82 | } 83 | } 84 | 85 | $content = implode( '', $strings ); 86 | 87 | /** 88 | * Filters the default content for the Accessibility Statement 89 | * 90 | * @param string $content The default Accessibility Statement content 91 | * @param bool $use_blocks Whether the content should be formatted for the block editor 92 | */ 93 | return apply_filters( 'wp_get_default_accessibility_statement_content', $content, $use_blocks ); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /helpers.php: -------------------------------------------------------------------------------- 1 | post_status ) { 30 | return false; 31 | } 32 | 33 | return true; 34 | } 35 | 36 | /** 37 | * Get the URL of the Accessibility Statement 38 | * 39 | * @return string URL of the Accessibility Statement 40 | */ 41 | function wp_get_accessibility_statement_page_url() { 42 | $url = ''; 43 | $accessibility_statement_id = (int) get_option( 'wp_page_for_accessibility_statement' ); 44 | 45 | if ( ! empty( $accessibility_statement_id ) && get_post_status( $accessibility_statement_id ) === 'publish' ) { 46 | $url = (string) get_permalink( $accessibility_statement_id ); 47 | } 48 | 49 | return apply_filters( 'accessibility_statement_url', $url, $accessibility_statement_id ); 50 | } 51 | -------------------------------------------------------------------------------- /settings-page.php: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 |

20 |

21 | 22 | $accessibility_statement_id, 27 | 'action' => 'edit', 28 | ), 29 | admin_url( 'post.php' ) 30 | ); 31 | 32 | $view_href = get_permalink( $accessibility_statement_id ); 33 | 34 | ?> 35 |

36 | Edit or view your Accessibility Statement page content.' ), 41 | esc_url( $edit_href ), 42 | esc_url( $view_href ) 43 | ); 44 | } else { 45 | printf( 46 | /* translators: 1: URL to edit Accessibility Statement page, 2: URL to preview Accessibility Statement page. */ 47 | __( 'Edit or preview your Accessibility Statement page content.' ), 48 | esc_url( $edit_href ), 49 | esc_url( $view_href ) 50 | ); 51 | } 52 | ?> 53 |

54 | 57 | 58 | 59 | 60 | 67 | 121 | 122 | 123 |
124 | --------------------------------------------------------------------------------