*/ public function groups() { return array( 'security' => array( 'label' => __( 'Security', 'codingcush-tweaks' ), 'icon' => 'shield', ), 'performance' => array( 'label' => __( 'Performance', 'codingcush-tweaks' ), 'icon' => 'performance', ), 'media' => array( 'label' => __( 'Media & Uploads', 'codingcush-tweaks' ), 'icon' => 'format-image', ), 'admin' => array( 'label' => __( 'Admin & Editor', 'codingcush-tweaks' ), 'icon' => 'admin-settings', ), ); } /** * Structure: id => group, class, fields (type, default, min/max, option keys). No strings to translate. * * @return array */ public function map() { static $map = null; if ( null !== $map ) { return $map; } $ns = __NAMESPACE__ . '\\Tweaks\\'; $map = array( // Security. 'disable_xmlrpc' => array( 'group' => 'security', 'class' => $ns . 'Disable_XMLRPC', ), 'disable_rest_logged_out' => array( 'group' => 'security', 'class' => $ns . 'Disable_REST_Logged_Out', ), 'hide_wp_version' => array( 'group' => 'security', 'class' => $ns . 'Hide_WP_Version', ), 'disable_file_edit' => array( 'group' => 'security', 'class' => $ns . 'Disable_File_Edit', ), 'stop_user_enumeration' => array( 'group' => 'security', 'class' => $ns . 'Stop_User_Enumeration', ), 'generic_login_errors' => array( 'group' => 'security', 'class' => $ns . 'Generic_Login_Errors', ), // Performance. 'heartbeat' => array( 'group' => 'performance', 'class' => $ns . 'Heartbeat', 'fields' => array( 'heartbeat_mode' => array( 'type' => 'select', 'default' => 'slow', 'options' => array( 'slow', 'no_dashboard', 'editor_only', 'off' ), ), 'heartbeat_interval' => array( 'type' => 'number', 'default' => 60, 'min' => 15, 'max' => 300, ), ), ), 'disable_emojis' => array( 'group' => 'performance', 'class' => $ns . 'Disable_Emojis', ), 'disable_embeds' => array( 'group' => 'performance', 'class' => $ns . 'Disable_Embeds', ), 'limit_revisions' => array( 'group' => 'performance', 'class' => $ns . 'Limit_Revisions', 'fields' => array( 'revisions_keep' => array( 'type' => 'number', 'default' => 5, 'min' => 0, 'max' => 100, ), ), ), 'disable_self_pingbacks' => array( 'group' => 'performance', 'class' => $ns . 'Disable_Self_Pingbacks', ), 'disable_dashicons' => array( 'group' => 'performance', 'class' => $ns . 'Disable_Dashicons', ), 'disable_rss' => array( 'group' => 'performance', 'class' => $ns . 'Disable_RSS', ), // Media & Uploads. 'upload_size' => array( 'group' => 'media', 'class' => $ns . 'Upload_Size', 'fields' => array( 'upload_size_mb' => array( 'type' => 'number', 'default' => 64, 'min' => 1, 'max' => 4096, ), ), ), 'allow_svg' => array( 'group' => 'media', 'class' => $ns . 'Allow_SVG', ), 'extra_file_types' => array( 'group' => 'media', 'class' => $ns . 'Extra_File_Types', 'fields' => array( 'extra_types' => array( 'type' => 'textarea', 'default' => "webp image/webp\nheic image/heic\nglb model/gltf-binary\ncsv text/csv\njson application/json", ), ), ), 'disable_big_image_scaling' => array( 'group' => 'media', 'class' => $ns . 'Disable_Big_Image_Scaling', ), // Admin & Editor. 'disable_comments' => array( 'group' => 'admin', 'class' => $ns . 'Disable_Comments', ), 'disable_block_editor' => array( 'group' => 'admin', 'class' => $ns . 'Disable_Block_Editor', 'fields' => array( 'classic_post_types' => array( 'type' => 'post_types', 'default' => array(), ), ), ), 'disable_update_emails' => array( 'group' => 'admin', 'class' => $ns . 'Disable_Update_Emails', ), 'hide_admin_bar' => array( 'group' => 'admin', 'class' => $ns . 'Hide_Admin_Bar', ), 'clean_dashboard' => array( 'group' => 'admin', 'class' => $ns . 'Clean_Dashboard', ), 'remove_head_clutter' => array( 'group' => 'admin', 'class' => $ns . 'Remove_Head_Clutter', ), ); return $map; } /** * Translated labels: id => title, desc, warning, field labels/options. Admin only (after init). * * @return array */ public function labels() { return array( 'disable_xmlrpc' => array( 'title' => __( 'Disable XML-RPC', 'codingcush-tweaks' ), 'desc' => __( 'Turns off the XML-RPC API and removes the X-Pingback header and RSD link. Stops the most common brute-force route. Turn back on if you use the Jetpack or mobile apps.', 'codingcush-tweaks' ), ), 'disable_rest_logged_out' => array( 'title' => __( 'Require login for the REST API', 'codingcush-tweaks' ), 'desc' => __( 'Visitors who are not logged in get a 401 from /wp-json/.', 'codingcush-tweaks' ), 'warning' => __( 'Contact forms, block themes and some page builders call the REST API for visitors. Test your forms after enabling.', 'codingcush-tweaks' ), ), 'hide_wp_version' => array( 'title' => __( 'Hide the WordPress version', 'codingcush-tweaks' ), 'desc' => __( 'Removes the generator meta tag, the version from RSS feeds and the version query string on core scripts and styles.', 'codingcush-tweaks' ), ), 'disable_file_edit' => array( 'title' => __( 'Disable the theme and plugin file editor', 'codingcush-tweaks' ), 'desc' => __( 'Removes the code editors from the admin so a stolen admin login cannot inject PHP. Same effect as DISALLOW_FILE_EDIT.', 'codingcush-tweaks' ), ), 'stop_user_enumeration' => array( 'title' => __( 'Stop user enumeration', 'codingcush-tweaks' ), 'desc' => __( 'Blocks ?author=1 scans and the public /wp-json/wp/v2/users list that attackers use to harvest usernames.', 'codingcush-tweaks' ), ), 'generic_login_errors' => array( 'title' => __( 'Generic login error messages', 'codingcush-tweaks' ), 'desc' => __( 'Replaces "the password for user X is incorrect" with a neutral message so a login attempt never confirms a username.', 'codingcush-tweaks' ), ), 'heartbeat' => array( 'title' => __( 'Heartbeat control', 'codingcush-tweaks' ), 'desc' => __( 'The Heartbeat API polls the server every 15-60 seconds from every open admin tab. Slow it down or disable it where you do not need it.', 'codingcush-tweaks' ), 'fields' => array( 'heartbeat_mode' => array( 'label' => __( 'Where', 'codingcush-tweaks' ), 'options' => array( 'slow' => __( 'Keep it running, use the interval below', 'codingcush-tweaks' ), 'no_dashboard' => __( 'Disable on the dashboard, keep in the editor', 'codingcush-tweaks' ), 'editor_only' => __( 'Disable everywhere except the post editor', 'codingcush-tweaks' ), 'off' => __( 'Disable everywhere (post locking and autosave stop)', 'codingcush-tweaks' ), ), ), 'heartbeat_interval' => array( 'label' => __( 'Interval (seconds)', 'codingcush-tweaks' ), ), ), ), 'disable_emojis' => array( 'title' => __( 'Disable emoji scripts', 'codingcush-tweaks' ), 'desc' => __( 'Removes the emoji detection script and styles from every page. Browsers render emoji natively anyway.', 'codingcush-tweaks' ), ), 'disable_embeds' => array( 'title' => __( 'Disable oEmbed', 'codingcush-tweaks' ), 'desc' => __( 'Removes the wp-embed script and oEmbed discovery links. Pasting a YouTube URL into a post still works; other sites embedding your posts will not.', 'codingcush-tweaks' ), ), 'limit_revisions' => array( 'title' => __( 'Limit post revisions', 'codingcush-tweaks' ), 'desc' => __( 'WordPress keeps every revision forever, which bloats the database. Keep only the most recent ones.', 'codingcush-tweaks' ), 'fields' => array( 'revisions_keep' => array( 'label' => __( 'Revisions to keep per post (0 disables revisions)', 'codingcush-tweaks' ), ), ), ), 'disable_self_pingbacks' => array( 'title' => __( 'Disable self-pingbacks', 'codingcush-tweaks' ), 'desc' => __( 'Stops WordPress from sending a pingback to your own site every time you link to one of your own posts.', 'codingcush-tweaks' ), ), 'disable_dashicons' => array( 'title' => __( 'Remove Dashicons for visitors', 'codingcush-tweaks' ), 'desc' => __( 'Dashicons (46 KB) load on the front end for everyone but are only used by the admin bar. Skips them for logged-out visitors.', 'codingcush-tweaks' ), ), 'disable_rss' => array( 'title' => __( 'Disable RSS feeds', 'codingcush-tweaks' ), 'desc' => __( 'Redirects every feed URL to the home page and removes feed links from the head. For sites that are not blogs.', 'codingcush-tweaks' ), ), 'upload_size' => array( 'title' => __( 'Change the maximum upload size', 'codingcush-tweaks' ), 'desc' => __( 'Sets the limit WordPress enforces in the media uploader.', 'codingcush-tweaks' ), 'fields' => array( 'upload_size_mb' => array( 'label' => __( 'Maximum upload size (MB)', 'codingcush-tweaks' ), ), ), ), 'allow_svg' => array( 'title' => __( 'Allow SVG uploads (sanitised)', 'codingcush-tweaks' ), 'desc' => __( 'Lets administrators and editors upload SVG files. Each file is sanitised on upload: scripts, event handlers, external references and foreign objects are stripped.', 'codingcush-tweaks' ), 'warning' => __( 'Only trusted users should upload SVGs. Uploads from Authors and Contributors stay blocked.', 'codingcush-tweaks' ), ), 'extra_file_types' => array( 'title' => __( 'Allow extra file types', 'codingcush-tweaks' ), 'desc' => __( 'Add upload types WordPress blocks by default, one per line as "extension mime/type".', 'codingcush-tweaks' ), 'warning' => __( 'Executable, script and web document types (php, js, html, css, svg, xml, exe, sh and similar) are always refused, whatever you enter here.', 'codingcush-tweaks' ), 'fields' => array( 'extra_types' => array( 'label' => __( 'Types to allow', 'codingcush-tweaks' ), 'placeholder' => "heic image/heic\nglb model/gltf-binary", ), ), ), 'disable_big_image_scaling' => array( 'title' => __( 'Keep original image size', 'codingcush-tweaks' ), 'desc' => __( 'WordPress scales any upload wider than 2560px and keeps the scaled copy. Turn that off to keep your originals as the full-size image.', 'codingcush-tweaks' ), ), 'disable_comments' => array( 'title' => __( 'Disable comments everywhere', 'codingcush-tweaks' ), 'desc' => __( 'Closes comments on every post type, hides existing comments and comment blocks, removes the Comments menu, admin-bar item and dashboard widget, and blocks the comments REST endpoint.', 'codingcush-tweaks' ), ), 'disable_block_editor' => array( 'title' => __( 'Use the classic editor for selected post types', 'codingcush-tweaks' ), 'desc' => __( 'Switches chosen post types back to the classic editor without installing another plugin.', 'codingcush-tweaks' ), 'fields' => array( 'classic_post_types' => array( 'label' => __( 'Post types', 'codingcush-tweaks' ), ), ), ), 'disable_update_emails' => array( 'title' => __( 'Stop automatic update emails', 'codingcush-tweaks' ), 'desc' => __( 'No more "Your site has updated to WordPress x.y" and plugin auto-update emails. Failure emails are still sent.', 'codingcush-tweaks' ), ), 'hide_admin_bar' => array( 'title' => __( 'Hide the admin bar for non-admins', 'codingcush-tweaks' ), 'desc' => __( 'Subscribers, customers and members see a clean front end. Administrators and editors keep the bar.', 'codingcush-tweaks' ), ), 'clean_dashboard' => array( 'title' => __( 'Clean up the dashboard', 'codingcush-tweaks' ), 'desc' => __( 'Removes the WordPress Events & News, Quick Draft, Activity and Welcome panels from the dashboard for every user.', 'codingcush-tweaks' ), ), 'remove_head_clutter' => array( 'title' => __( 'Remove head clutter', 'codingcush-tweaks' ), 'desc' => __( 'Drops the Windows Live Writer manifest, shortlink, REST discovery link and adjacent-post links from the HTML head.', 'codingcush-tweaks' ), ), ); } /** * Full definitions (structure + labels). Admin only. * * @return array */ public function all() { $labels = $this->labels(); $out = array(); foreach ( $this->map() as $id => $def ) { $label = isset( $labels[ $id ] ) ? $labels[ $id ] : array(); $def['title'] = isset( $label['title'] ) ? $label['title'] : $id; $def['desc'] = isset( $label['desc'] ) ? $label['desc'] : ''; $def['warning'] = isset( $label['warning'] ) ? $label['warning'] : ''; if ( ! empty( $def['fields'] ) ) { foreach ( $def['fields'] as $fid => $field ) { $fl = isset( $label['fields'][ $fid ] ) ? $label['fields'][ $fid ] : array(); $def['fields'][ $fid ]['label'] = isset( $fl['label'] ) ? $fl['label'] : $fid; $def['fields'][ $fid ]['placeholder'] = isset( $fl['placeholder'] ) ? $fl['placeholder'] : ''; if ( 'select' === $field['type'] ) { $opts = array(); foreach ( $field['options'] as $key ) { $opts[ $key ] = isset( $fl['options'][ $key ] ) ? $fl['options'][ $key ] : $key; } $def['fields'][ $fid ]['options'] = $opts; } } } $out[ $id ] = $def; } return $out; } /** * Default option array: every tweak off, every field at its default. * * @return array */ public static function defaults() { $defaults = array(); foreach ( ( new self() )->map() as $id => $def ) { $defaults[ $id ] = false; if ( ! empty( $def['fields'] ) ) { foreach ( $def['fields'] as $fid => $field ) { $defaults[ $fid ] = $field['default']; } } } return $defaults; } }