Skip to content

Instantly share code, notes, and snippets.

@ApoGouv
Last active November 3, 2025 08:01
Show Gist options
  • Select an option

  • Save ApoGouv/daf833c23911c5f062f76a8e70ef23bc to your computer and use it in GitHub Desktop.

Select an option

Save ApoGouv/daf833c23911c5f062f76a8e70ef23bc to your computer and use it in GitHub Desktop.
WP - Optimizations, Security hardening and Cleanup.

🗺️ WordPress Optimization, Security & Cleanup Roadmap

This guide summarizes the files and methodology used for advanced hardening, performance tuning, and cleanup of a WordPress installation.

1. 📂 Server Configuration & .htaccess (01.htaccess)

This file is the primary layer for security and performance at the server level.

  • 🛡️ Security Hardening:
    • Disable server signature and directory browsing.
    • Force HTTPS (HSTS recommendation).
    • Prevent access to sensitive files and folders (wp-config.php, .htaccess, etc.).
    • Block common attacks: Author Scans, xmlrpc.php requests, and "bad" bot user agents.
    • Block Requests by Referer and/or specific file requested
    • Specify crucial Security HEADERS (e.g., X-Frame-Options, X-Content-Type-Options).
    • Protect System Files and Disable PHP execution in the /uploads directory.
    • Filter Request Methods
  • 🚀 Performance Tuning:
    • Enable Browser Caching for static assets (Leverage Browser Caching fix).
    • Enable File Compression (Gzip/Deflate) for faster page loads.

| ⚠️ Note | The advanced rules (e.g., blocking HTTP 1.0, complex bot rules) should be monitored, as they may occasionally cause conflicts with specific external services or niche crawlers. |


2. ⚙️ WordPress Core Configuration (wp-config.php)

This file manages critical configuration variables outside the database.

  • 🛡️ Security & Development:
    • Set secure cookies (HTTP-only, Secure).
    • Force WP Admin to SSL.
    • Disable Theme and Plugin backend editors to prevent code injection vulnerabilities.
    • Enable WP_DEBUG and error logging during development.
  • 🧹 Cleanup & Performance:
    • Limit Post Revisions to maintain a smaller, optimized database.
    • Change the update method (useful when migrating between environments).

3. 🧩 Theme Functions Organization (functions.php and Includes)

This methodology promotes cleaner, more manageable code by separating functionality into responsible files.

  • 03_functions.php: Acts as a master loader, using require_once() to safely load all custom files (cds-optimizations-n-tweaks.php, etc.) for improved readability and modularity.

3.1. ⚙️ Admin Tweaks (cds-wp-admin-tweaks-n-extras.php)

  • Custom Admin UX: Includes functions to enhance the admin area, such as adding a Featured Image column to the Posts list.

3.2. 🚀 Core Optimizations (cds-optimizations-n-tweaks.php)

  • 🧹 Head Cleanup: Removes unnecessary links, scripts, and meta tags from <head> (e.g., RSD, shortlinks, feed links, resource hints, global styles).
  • 🛡️ Security Obfuscation: Removes version numbers from the WordPress generator tag and specific plugin generators (WPML, Slider Revolution, Visual Composer/WPBakery).
  • 🧹 Script Cleanup: Removes comment-reply.min.js when not needed.
  • Performance Fix: Removes the bulky jQuery Migrate Script. (The external jQuery loading has been removed in favor of core stability).
  • 🚀 Caching Fix: Removes Query Strings (?ver=X.X.X) from script and style files for maximum caching efficiency via CDNs and browsers.

3.3. ✨ Extra Functions (varius_extra_functions.php)

  • 🛡️ Advanced Headers: Adds non-breaking security headers (e.g., X-Frame-Options).
  • 🗑️ Database Maintenance: Includes a controlled SQL snippet for manually clearing expired WordPress sessions (database cleanup).
  • 🖼️ Image Optimization: Functions to globally or conditionally disable srcset and sizes attributes.
  • ⏳ Performance: Adds &display=swap to Google Font URLs for better Cumulative Layout Shift (CLS) scores.

4. 💻 Advanced Server Configuration (wp_generic_security_server_config.md)

  • Contains highly effective security rules intended for the Apache Server Configuration (httpd.conf), which should be preferred over .htaccess for superior performance.
  • Rules include blocking access to sensitive file extensions, protecting core WP metadata, and advanced bot/scanner filtering.

5. 🧑‍💻 Plugin Development Standards (wp_generic_plugin_development.md)

  • Provides resources for professional WordPress plugin development best practices.
  • Includes a quick, step-by-step guide to setting up the WordPress Coding Standards (WPCS) locally using Composer, PHP Code Sniffer, and integration with VS Code.

6. 🔐 Database Security (wp_change_db_table_prefix.md)

  • A crucial security measure detailing the three steps required to change the default wp_ database table prefix to a unique value, protecting against common SQL injection attacks.

🛡️ 01_.htaccess.md - Core Security & Performance Configuration 🚀

# ======================================================================
# | GENERAL DIRECTIVES |
# ======================================================================

# Disable the server signature (Hides server version information)
ServerSignature Off

# Add default charset
AddDefaultCharset UTF-8

# Disable directory browsing (Prevents public from seeing file listings)
Options -Indexes

# ======================================================================
# | REWRITE RULES (mod_rewrite) |
# ======================================================================
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# ----------------------------------------------------------------------
# | HTTPS & WWW Redirection |
# ----------------------------------------------------------------------

# Redirect http to https (Standard/Simple)
#
# RewriteCond %{HTTPS} !=on
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
#

# Redirect www to non-www AND http to https
# This block ensures all requests are routed to the secure (https) canonical non-www domain.
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]

# Redirect non-www to www AND http to https
#
# RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
# RewriteCond %{HTTPS} off
# RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
# RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

# ----------------------------------------------------------------------
# | WordPress-Specific Security |
# ----------------------------------------------------------------------

# Block WordPress Author Scans (Prevents malicious users from finding valid usernames)
# EXCEPTION: Allows author filtering within the /wp-admin/ area.
RewriteCond %{QUERY_STRING} (author=\d+) [NC]
RewriteCond %{REQUEST_URI} !^/wp-admin/ [NC]
RewriteRule ^ - [NC,F,L]

# Block Requests by Referer
# You can get suspect referers from cPanel stats or Google Analytics.
# 'anonymousfox' is a common example.
RewriteCond %{HTTP_REFERER} anonymousfox\.co [NC]
RewriteRule ^ - [NC,F,L]

# Block Requests to a specific file (Example)
# RewriteCond %{REQUEST_URI} ^/entity.php [NC]
# RewriteRule ^ - [NC,F,L]

# ----------------------------------------------------------------------
# | Advanced Bot & Protocol Blocking |
# ----------------------------------------------------------------------

# /!\ START - CRITICAL ATTENTION /!\ (HTTP/1.0 and Empty User Agent)
# The following two rules block old/programmatic requests (wget/curl) which may break
# integrations or monitoring tools. Test thoroughly before deploying.

# Block HTTP/1.0 Requests
# Add exception for specific folders (e.g., uploads) or server's own IP (uncomment line below).
RewriteCond %{REQUEST_URI} !^/uploads [NC,OR]
RewriteCond %{REQUEST_URI} !^/wp\-content/uploads [NC]
# RewriteCond %{REMOTE_ADDR} !^(xxx\.xxx\.xxx\.xxx)
RewriteCond %{SERVER_PROTOCOL} ^HTTP/1\.0$
RewriteRule ^ - [NC,F,L]

# ----------------------------------------------------------------------

# Block Requests with Empty HTTP_USER_AGENT String
# Reg ex ^(?:\s|-)\*$ matches any whitespace character or the character "-"
RewriteCond %{REQUEST_URI} !^/uploads [NC,OR]
RewriteCond %{REQUEST_URI} !^/wp\-content/uploads [NC]
# RewriteCond %{REMOTE_ADDR} !^(xxx\.xxx\.xxx\.xxx)
RewriteCond %{HTTP_USER_AGENT} ^(?:\s|-)\*$
RewriteRule ^ - [NC,F,L]

# /!\ END - CRITICAL ATTENTION /!\

# Block common crawling spam Bots (Extensive list based on 6G Firewall principles)
RewriteCond %{HTTP_USER_AGENT} (?:virusbot|spambot|evilbot|acunetix|BLEXBot|domaincrawler\.com|LinkpadBot|MJ12bot|MJ12bot/v|majestic12\.co\.uk|AhrefsBot|TwengaBot|SemrushBot|nikto|winhttp|Xenu\s+Link\s+Sleuth|Baiduspider|HTTrack|clshttp|harvest|extract|grab|miner|python-requests|binlar|casper|checkpriv|choppy|cmsworld|diavol|dotbot|feedfinder|flicky|g00g1e|heritrix|httrack|kmccrew|loader|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|xxxyy|youda|zmeu|zune|ZoominfoBot|Konqueror|survey|SeznamBot|serendeputy|DuckDuckGo-Favicons-Bot|DuckDuckBot|Go-http-client|yak-linkfluence|libwww-perl) [NC]
RewriteRule ^(.*)$ - [F]

# ----------------------------------------------------------------------

# Protect System Files, Disable PHP in Uploads, Filter Request Methods
# (Comprehensive block - derived from tools like iThemes Security)

# Protect System Files (Deny access to core files/folders)
RewriteRule ^wp-admin/install\.php$ - [F]
RewriteRule ^wp-admin/includes/ - [F]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F]
RewriteRule ^wp-includes/theme-compat/ - [F]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule (^|.*/)\.(git|svn)/.* - [F]

# Disable PHP in WP Uploads folder (Prevents execution of malicious scripts)
RewriteRule ^wp\-content/uploads/.*\.(?:php\d*|pht|phtml?|phps)\.?$ - [NC,F]

# Filter Request Methods (Disable unused/dangerous HTTP methods)
# Disables connect, debug, move, put, trace and track
RewriteCond %{REQUEST_METHOD} ^(connect|debug|move|put|trace|track) [NC]
RewriteRule ^.* - [F]

# ----------------------------------------------------------------------
# | WordPress Permalinks - Default WP rules (CRITICAL FOR FUNCTIONALITY) |
# ----------------------------------------------------------------------
# NOTE: These rules must be placed within the mod_rewrite block.

# BEGIN WordPress

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

</IfModule>

# ======================================================================
# | DIRECT ACCESS CONTROL (FilesMatch) |
# ======================================================================

# 1. Block Access to Server/System Configuration Files
# This rule consolidates blocking for all Apache/System config files (e.g., .htaccess, .htpasswd, .ini).
<FilesMatch "^(?i:\.ht|php\.ini)$">
    Require all denied
</FilesMatch>

# 2. Block Access to CRITICAL WordPress Files
# This blocks the single most critical file (wp-config.php) and common attack vectors (xmlrpc.php).
<FilesMatch "^(wp-config\.php|xmlrpc\.php)$">
    Require all denied
</FilesMatch>

# 3. Block WP/Generic Backup, Log, and Metadata Files
# This single, comprehensive rule blocks various sensitive files, backup extensions, and metadata.
# It includes common targets like readme/license/changelog files, error logs, and backup files (.bak, .swp).
<FilesMatch "\.(phps|fla|psd|log|sh|cmd|exe|bat|csh|txt|zip|tar|gz|7z|rar|bak|swp)$|^.*((readme|license|changelog|error_log|-config|-sample)\.(php|md|log|txt|htm|html))">
    Require all denied
</FilesMatch>

# ======================================================================
# | SECURITY HEADERS (mod_headers) |
# ======================================================================

# /!\ Note: Security Headers can sometimes cause errors with external scripts/iframes.

<IfModule mod_headers.c>
	# Remove X-Powered-By header (Hides the software version)
    Header unset X-Powered-By
    Header always unset X-Powered-By

	# HTTP Strict Transport Security (HSTS)
  	# Forces client to use secure connections only.
  	# Increased max-age to 2 years (recommended for HSTS Preload submission).
  	# Use max-age=15768000 (6 months) if you prefer a shorter duration.
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
	
	# X-Frame-Options (Clickjacking Protection)
  	# 'SAMEORIGIN' prevents the page from being rendered in an iframe unless on the same domain.
    Header always set X-Frame-Options "SAMEORIGIN"

	# X-XSS-Protection (Cross-Site Scripting Filter)
    Header set X-XSS-Protection "1; mode=block"

	# X-Content-Type-Options (MIME-Type Sniffing Prevention)
  	# Prevents browsers from interpreting files as a different MIME type (e.g., script instead of image).
    # This helps reduce the danger of drive-by downloads and helps treat the content the right way.
    Header always set X-Content-Type-Options "nosniff"
	
    # Set the Referrer-Policy
    # no-referrer-when-downgrade - The origin, path, and querystring of the URL are sent as a referrer when
    #                              the protocol security level stays the same or improves,
    #                              but isn't sent to less secure destinations.
    Header set Referrer-Policy "no-referrer-when-downgrade"
	
	# Content Security Policy (Placeholder for best practice)
    # This is a critical security header that is site-specific. Implement carefully.
    # Header always set Content-Security-Policy "default-src 'self';"
	
	 # Activate CORS (Example for specific file types to support web fonts)
    <FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js|gif|png|jpe?g|svg|svgz|ico|webp)$">
        Header set Access-Control-Allow-Origin "*"
    </FilesMatch>
</IfModule>

# ======================================================================
# | PERFORMANCE (mod_expires & mod_deflate) |
# ======================================================================

# ETAGS: Remove `ETags` for better performance in clustered/load-balanced environments, 
# especially when using far-future expiry headers.
<IfModule mod_headers.c>
    Header unset ETag
</IfModule>
FileETag None

# Leverage Browser Caching (Fixes Google PageSpeed warning)
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"

    # Images
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 week"

    # Video/Audio
    ExpiresByType video/mp4 "access plus 1 year"
    ExpiresByType audio/mpeg "access plus 1 year"

    # CSS, JavaScript, Webfonts
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType application/x-font-woff "access plus 1 year"
    ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
    ExpiresByType font/ttf "access plus 1 year"
    ExpiresByType font/opentype "access plus 1 year"

    # HTML
    ExpiresByType text/html "access plus 1 hour"
</IfModule>

# Enable File Compression (Gzip/Deflate)
<IfModule mod_deflate.c>
    # Compress all output types (except images, which are already compressed)
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>

# ======================================================================
# | MEDIA TYPES (mod_mime) |
# ======================================================================

# OPTIONAL: Explicitly define MIME types for modern formats and better compatibility.
# This block ensures the correct Content-Type headers are sent for newer web formats 
# (e.g., AVIF, WebP, WebAssembly) regardless of the host server's default configuration.
# https://www.iana.org/assignments/media-types/media-types.xhtml
# https://httpd.apache.org/docs/current/mod/mod_mime.html#addtype

<IfModule mod_mime.c>
  	# Data interchange
    AddType application/atom+xml                        atom
    AddType application/json                            json map topojson
    AddType application/ld+json                         jsonld
    AddType application/rss+xml                         rss
    AddType application/geo+json                        geojson
    AddType application/rdf+xml                         rdf
    AddType application/xml                             xml

  	# JavaScript
    # Servers should use text/javascript for JavaScript resources.
    # https://html.spec.whatwg.org/multipage/scripting.html#scriptingLanguages
    AddType text/javascript                             js mjs

  	# Manifest files
    AddType application/manifest+json                   webmanifest
    AddType application/x-web-app-manifest+json         webapp
    AddType text/cache-manifest                         appcache

  	# Media files (Audio/Video/Images)
    AddType audio/mp4                                   f4a f4b m4a
    AddType audio/ogg                                   oga ogg opus
    AddType image/avif                                  avif
    AddType image/avif-sequence                         avifs
    AddType image/bmp                                   bmp
    AddType image/jxl                                   jxl
    AddType image/svg+xml                               svg svgz
    AddType image/webp                                  webp
    AddType video/mp4                                   f4v f4p m4v mp4
    AddType video/ogg                                   ogv
    AddType video/webm                                  webm
    AddType video/x-flv                                 flv

    # Serving `.ico` image files with a different media type prevents
    # Internet Explorer from displaying them as images:
    # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee
    AddType image/x-icon                                cur ico

  	# WebAssembly
    AddType application/wasm                            wasm

  	# Web fonts
    AddType font/woff                                   woff
    AddType font/woff2                                  woff2
    AddType application/vnd.ms-fontobject               eot
    AddType font/ttf                                    ttf
    AddType font/collection                             ttc
    AddType font/otf                                    otf

  	# Other
    AddType application/octet-stream                    safariextz
    AddType application/x-bb-appworld                   bbaw
    AddType application/x-chrome-extension              crx
    AddType application/x-opera-extension               oex
    AddType application/x-xpinstall                     xpi
    AddType text/calendar                               ics
    AddType text/markdown                               markdown md
    AddType text/vcard                                  vcard vcf
    AddType text/vnd.rim.location.xloc                  xloc
    AddType text/vtt                                    vtt
    AddType text/x-component                            htc

</IfModule>

🛡️ 01_b_wp-content_uploads_.htaccess.md - Prevent PHP Execution in Uploads 🚫

# ----------------------------------------------------------------------
# | CORE SECURITY: Block Direct Execution of PHP Scripts |
# ----------------------------------------------------------------------

# 🛡️ This rule blocks access and execution of any file ending with common PHP-related extensions.
<FilesMatch "\.(php|php\d+|phtml|phps|php-s)$">
    Require all denied
</FilesMatch>

# ----------------------------------------------------------------------
# | PREVENT DOUBLE EXTENSION ATTACKS / CGI Execution |
# ----------------------------------------------------------------------

# Disables execution of CGI/Scripts (e.g., shell.php.jpg) in this directory.
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi
Options -ExecCGI

# ----------------------------------------------------------------------
# | OPTIONAL: Force Download for SVG Files (Extra Security - Uncomment if needed) |
# ----------------------------------------------------------------------

# Note: Only uncomment if not using a plugin to sanitize SVGs; this breaks visual display.
# <FilesMatch "\.svg$">
#     Header set Content-Disposition "attachment"
# </FilesMatch>
<?php
// ======================================================================
// | SECURITY & SESSION HARDENING |
// ======================================================================

// 🍪 Secure Cookies (Add these at the very beginning of the file)
// Prevents XSS attacks from accessing session cookies (HttpOnly).
@ini_set('session.cookie_httponly', true);
// Ensures cookies are only sent over HTTPS.
@ini_set('session.cookie_secure', true);
// Prevents session ID leakage in URLs.
@ini_set('session.use_only_cookies', true);

// 🔒 Recommended: Set SameSite Cookie Attribute (for modern browsers)
// NOTE: This often requires PHP 7.3+ and a recent version of WordPress/Apache.
@ini_set('session.cookie_samesite', 'Strict');


//
// REST OF WP_CONFIG 
//


// ======================================================================
// | DEBUGGING & ERROR REPORTING (Production Settings) |
// ======================================================================

// ⚠️ CRITICAL: Ensure debugging is disabled and errors are hidden in production
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false); // Enable debug log in wp-content/debug.log
define('WP_DEBUG_DISPLAY', false);

// ======================================================================
// | CORE SECURITY & ACCESS CONTROL |
// ======================================================================

// 🔐 Require SSL for Admin and Logins
define( 'FORCE_SSL_ADMIN', true );

// 🚫 Disable the Plugin and Theme Editor (CRITICAL SECURITY)
// Prevents attackers who gain admin access from easily inserting malicious PHP code.
define( 'DISALLOW_FILE_EDIT', true );

// ======================================================================
// | PERFORMANCE & DATABASE OPTIMIZATION |
// ======================================================================

// 📝 Limit revisions to 2 (Saves database space)
define('WP_POST_REVISIONS', 2);
// OR to disable entirely: // define('WP_POST_REVISIONS', false);

// ⏳ Increase autosave interval (Fewer AJAX calls, saves server resources)
// Default is 60 seconds.
define('AUTOSAVE_INTERVAL', 120 );

// 🗑️ Trash cleanup: set the number of days before items are permanently deleted.
// Default is 30 days.
define('EMPTY_TRASH_DAYS', 30 );

// WP memory settings: Uncomment only if needed (default is usually sufficient)
// define('WP_MEMORY_LIMIT', '256M');

// 💨 Optional: Disable script concatenation in Admin panel.
// Set to FALSE if experiencing JS script conflicts (increases HTTP requests).
// Will increase load time slightly but you can debug and view each js file seperately.
define('CONCATENATE_SCRIPTS', false);

/**
 * The WP-CRON Problem: 
 * 
 * WP-CRON does not work the same way as a normal cron job. It instead checks for scheduled events each time a 
 * site page is loaded. 
 * This works just fine with a steady stream of moderate traffic but issues arise with the two extremes.
 * 
 * High traffic — If the site gets too much traffic, it is continuously checking it’s WP-CRON schedule, 
 *                increasing the work required by the server, and negatively impacting performance.
 * 
 * Low traffic — Conversely, if there is little to no traffic, the site does not check it’s scheduled items 
 *               quickly enough and may miss scheduled jobs, like a backup from a plugin or a scheduled post.
 *
 * Streamlining this function is a two-part process:
 *
 * 1. Creating a standard cron which will run any scheduled events on your site.
 *    e.g. wget -q -O - https://example.com/wp-cron.php?doing_wp_cron
 * -Replace https://example.com with your domain name.-
 *
 * 2. Stopping WP-CRON from constantly checking for those same scheduled events.
 */
// 🕒 Optional: Disable WP Cron for server-side cron replacement (MUST configure server cron first!)
// define('DISABLE_WP_CRON', true) ;

// 📁 Optional: Solve FTP credential issue (Local development environments only)
// e.g.: updating plugins in localhost
// define('FS_METHOD','direct');


// Following comes from wp-toolkit and they say it can prevent some
// DDoS attacks.
//
// Disable scripts concatenation for WordPress admin panel
// define( 'CONCATENATE_SCRIPTS', false );
//
// IF above rule is set to FALSE, also add following rules to
// .htaccess in order to deny URLs containing the string load-styes or load-scripts:
//
// # "Disable scripts concatenation for WordPress admin panel"
// <Directory "/home/example/public_html/wp-admin">
//   <FilesMatch (load-styles|load-scripts)\.php$>
//      Require all denied
//   </FilesMatch>
// </Directory>

// ======================================================================
// | EXTREME SECURITY (Leave commented unless fully understand implications) |
// ======================================================================

// Block external URL requests (Breaks many plugins/core functions)
// define( 'WP_HTTP_BLOCK_EXTERNAL', true );
// define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,*.github.com' );
<?php
/**
 * 🛠️ CubeDesigns - WordPress Core Optimizations and Tweaks 🛡️
 *
 * This file contains functions designed to improve performance, enhance security 
 * through obfuscation (removing version numbers), and clean up unnecessary HTML 
 * output from WordPress core and common plugins.
 *
 * Some of the below function are from the Plugin: Meta Generator and Version Info Remover
 * (https://wordpress.org/plugins/meta-generator-and-version-info-remover/)
 */

// ======================================================================
// | 🧹 HEADER & META TAG CLEANUP (Security & Performance) |
// ======================================================================

/************************************************************************
 * Removes various unnecessary links and meta tags from the <head> section.
 * @return void
 ***********************************************************************/
function cds_clean_the_header_outout() {
    // 🔒 Security: Remove WP Generator Vesion from header and RSS feeds
    remove_action( 'wp_head', 'wp_generator' ); 
    add_filter( 'the_generator', '__return_false' );
	
	// 🔗 Link/Meta Removal
    remove_action( 'wp_head', 'wlwmanifest_link' );         // Remove link for Windows Live Writer (legacy)..
    remove_action( 'wp_head', 'rsd_link' );                 // Remove Really Simple Discovery Link (XML-RPC).
	
	// 🔗 Shortlinks Cleanup: Removes the <link rel='shortlink'> tag and the HTTP header
    remove_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );
	remove_action( 'template_redirect', 'wp_shortlink_header', 11);
    
	// ➡️ Relational Links Cleanup (Index/Start/Prev/Next/Parent links)
	remove_action( 'wp_head', 'index_rel_link' );           // Remove Link to Home Page.
	remove_action( 'wp_head', 'start_post_rel_link', 10, 0 ); // Remove First Post Link.
    remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 ); // Remove Parent Post Link.
	remove_action( 'wp_head', 'adjacent_posts_rel_link', 10, 0 ); // Remove Prev-Next Links.
    remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 ); // Remove Prev-Next Links from Header.
    
    // ➡️ Feed Links (category/tag RSS/Atom feed links). If you don’t use feeds, these are pointless.
	remove_action( 'wp_head', 'feed_links', 2);        // Primary feed links (e.g., /feed/).
    remove_action( 'wp_head', 'feed_links_extra', 3 ); // Extra feed links (e.g., category feeds)
	
	// 💨 REST API Discovery Link (Performance/Obfuscation)
	// REST API still works, but no longer advertises its endpoint in the header.
	remove_action( 'wp_head', 'rest_output_link_wp_head', 10);
	
	// 🚫 oEmbed Discovery + Scripts (Performance)
	// Prevents WordPress from advertising oEmbed endpoints and loading extra JS.
	remove_action( 'wp_head', 'wp_oembed_add_discovery_links', 10);
	remove_action( 'wp_head', 'wp_oembed_add_host_js');
	
	// 🎨 Global Styles (Block Editor/Gutenberg)
	// Prevents WP from injecting the large default block editor CSS file.
	remove_action( 'wp_head', 'wp_enqueue_global_styles', 1);
	// Also remove the corresponding body class
	remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
}
add_action( 'after_setup_theme', 'cds_clean_the_header_outout' );

/************************************************************************
 * Remove Emoji Styles and Scripts (Performance)
 * Disables the loading of CSS and JavaScript used for native WordPress emojis.
 * @return void
 ***********************************************************************/
function cds_disable_wp_emojis() {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
	remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
	remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );	
	remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
	add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
	
	// Remove WP Emoji DNS prefetch from document head
	add_filter( 'emoji_svg_url', '__return_false' );
}
add_action( 'init', 'cds_disable_wp_emojis' );

/************************************************************************
 * Remove comment-reply.min.js (Performance)
 * Deregisters the script if threaded comments are not globally enabled.
 * @return void
 ***********************************************************************/
function cds_remove_comment_reply_js() {
	// Only deregister if not on a single post/page that allows comments
    if ( ! is_singular() ) {
        wp_deregister_script( 'comment-reply' );
    }
}
add_action('init', 'cds_remove_comment_reply_js', 10);


/************************************************************************
 * Remove jQuery Migrate Script (Performance & Stability)
 * Improves loading speed and avoids potential console warnings by removing 
 * the compatibility layer for older jQuery code.
 * @param WP_Scripts $scripts
 * @return void
 ***********************************************************************/
function cds_remove_jquery_migrate( $scripts ) {
    if ( ! is_admin() && isset( $scripts->registered['jquery'] ) ) {
        $script = $scripts->registered['jquery'];
        
        // Remove 'jquery-migrate' from the list of dependencies for 'jquery'
        if ( $script->deps ) {
            $script->deps = array_diff( $script->deps, array( 'jquery-migrate' ) );
        }
    }
}
// Use 'wp_default_scripts' to modify dependencies early
add_action( 'wp_default_scripts', 'cds_remove_jquery_migrate' );


// ======================================================================
// | 🔌 PLUGIN GENERATOR REMOVAL (Obfuscation) |
// ======================================================================

/************************************************************************
 * Remove Yoast SEO comments (HTML Cleanup & Obfuscation)
 * Removes the '' comments.
 * @return void
 ***********************************************************************/
function cbs_remove_yoast_seo_comments() {
    if ( class_exists( 'WPSEO_Frontend' ) ) {
        $instance = WPSEO_Frontend::get_instance();
        // Modern Yoast versions (v14+) use a filter for debug markers
        add_filter('wpseo_debug_markers', '__return_false', 9999);
        
        // Legacy method for older Yoast versions
        if ( method_exists( $instance, 'debug_mark') ) {
             remove_action( 'wpseo_head', array( $instance, 'debug_mark' ), 2 );
        }
    }
}
add_action('template_redirect', 'cbs_remove_yoast_seo_comments', 9999);


/************************************************************************
 * Remove WPML generator meta tag.
 * @return void
 ***********************************************************************/
if ( !empty ( $GLOBALS['sitepress'] ) ) {
    function cds_remove_wpml_generator() {
        remove_action(
            current_filter(),
            array ( $GLOBALS['sitepress'], 'meta_generator_tag' )
        );
    }
    add_action( 'wp_head', 'cds_remove_wpml_generator', 0 );
}


/************************************************************************
 * Remove Slider Revolution generator meta tag.
 ***********************************************************************/
add_filter( 'revslider_meta_generator', '__return_empty_string' );


/************************************************************************
 * Remove Visual Composer / WPBakery Page Builder generator meta tag.
 * @return void
 ***********************************************************************/
function cds_remove_visual_composer_generator() {
    if ( class_exists( 'Vc_Manager' ) || class_exists( 'Vc_Base' ) ) {
        // Correct way to target the class method used for meta data
        remove_action('wp_head', array(visual_composer(), 'addMetaData'));
    }
}
add_action('init', 'cds_remove_visual_composer_generator', 100);


// ======================================================================
// | 🗑️ CACHING & VERSIONING CLEANUP |
// ======================================================================

/************************************************************************
 * Removes Query Strings (version numbers) from script and style files.
 * * This is crucial for efficient caching and CDN delivery, as many services 
 * won't cache assets with query strings.
 * * ⚠️ NOTE on Cache-Busting: When this is active, you MUST manually clear 
 * your site and CDN cache after every core, theme, or plugin update to 
 * ensure visitors see the latest file versions.
 * @param string $target_url
 * @return string
 ***********************************************************************/
function cds_remove_appended_version_script_style( $target_url ) {
    // Check for 'ver=' argument
    if (strpos( $target_url, 'ver=' )) {
        $target_url = remove_query_arg( 'ver', $target_url );
    }
    // Check for 'version=' argument
    if (strpos( $target_url, 'version=' )) {
        $target_url = remove_query_arg( 'version', $target_url );
    }
    return $target_url;
}

// Set to high priority (20000) to ensure other functions don't re-add the version.
// add_filter('style_loader_src', 'cds_remove_appended_version_script_style', 20000);
// add_filter('script_loader_src', 'cds_remove_appended_version_script_style', 20000);
<?php
/**
 * 🛠️ CubeDesigns - WordPress Admin Tweaks and Extras 🌟
 *
 * This file contains utility functions to enhance the WordPress administrative 
 * experience, such as adding useful columns to post lists.
 */

// ======================================================================
// | 🖼️ FEATURED IMAGE COLUMN TWEAKS (Admin UX) |
// ======================================================================

/************************************************************************
 * Add a new 'Featured Image' column to the Posts list screen.
 * @param array $columns Existing column headers.
 * @return array Modified column headers.
 ***********************************************************************/
function cds_add_featured_image_column( $columns ) {
    // ➡️ We insert the column immediately after the Checkbox/Title columns
    $updated_columns = array();
    foreach ($columns as $key => $title) {
        $updated_columns[$key] = $title;
        if ($key === 'title') {
            // Insert the Featured Image column right after the post Title
            $updated_columns['featured_image_thumb'] = 'Featured Image';
        }
    }
    
    // Fallback - Append Featured Image column at the end
    if (!isset($updated_columns['featured_image_thumb'])) {
         $updated_columns['featured_image_thumb'] = 'Featured Image';
    }

    return $new_columns;
}
add_filter('manage_posts_columns' , 'cds_add_featured_image_column'); // Priority defaults to 10

/************************************************************************
 * Display the post's featured image thumbnail within the custom column.
 * @param string $column The name of the custom column.
 * @param int $post_id The ID of the current post.
 * @return void
 ***********************************************************************/
function cds_display_featured_image_column_data( $column, $post_id ) {
    switch ( $column ) {
        case 'featured_image_thumb':
            // 🖼️ Outputs the thumbnail with the default 'thumbnail' size (usually 150x150).
            // It will output an empty string if no featured image is set.
            echo get_the_post_thumbnail($post_id, 'thumbnail');
            break;
    }
}
add_action( 'manage_posts_custom_column' , 'cds_display_featured_image_column_data', 10, 2 ); 

#🛠️ CubeDesigns - Various Extra Functions and Optimizations 🚀

This file contains advanced, specific functions for security, database maintenance, image optimization, and performance tweaks.

Add to theme's functions.php snippets

<?php 
// ======================================================================
// | 🛡️ ADVANCED SECURITY HEADERS (WP Filter) |
// ======================================================================

/************************************************************************
 * Adds specific security headers via PHP's wp_headers filter.
 * NOTE: Critical headers (CSP, Referrer-Policy) are best handled in .htaccess, 
 * but these non-breaking headers are added here for defense-in-depth.
 * @param array $headers The default WP headers.
 * @return array The modified headers.
 ***********************************************************************/
function cds_additional_securityheaders( $headers ) {
  if ( ! is_admin() ) {
    // Prevents MIME-type sniffing attacks
	$headers['X-Content-Type-Options']      = 'nosniff';
	
	// Prevents site from being embedded in a malicious iframe
	$headers['X-Frame-Options']             = 'SAMEORIGIN';
	
	// ⚠️ CAUTION: The 'Permissions-Policy' and 'Content-Security-Policy' headers 
	// are complex and must be fully customized. The simple versions below are often 
	// TOO RESTRICTIVE and can break your site (e.g., Google Analytics).
	// 
	// $headers['Content-Security-Policy']   = "script-src 'self' 'unsafe-inline'"; 
	// $headers['Permissions-Policy']        = 'geolocation=(self), microphone=()';
  }

  return $headers;
}
add_filter( 'wp_headers', 'cds_additional_securityheaders' );

// ======================================================================
// | 🗑️ MAINTENANCE: CLEAR EXPIRED WP SESSIONS |
// ======================================================================

/************************************************************************
 * Manually cleans up expired wp_sessions from the database.
 * 💡 ACTIONABLE: Runs only for the specific Admin (ID 1) when the URL contains '?cds_debug'.
 * This is a safe, controlled way to clear database bloat.
 * @return void
 ***********************************************************************/
if ( current_user_can( 'manage_options' ) && get_current_user_id() == 1 && get_query_var('cds_debug') ) {
    global $wpdb;
    
   	// Get expired wp_sessions keys (limiting the size for safety)
    $expiration_keys = $wpdb->get_results( "
        SELECT option_name, option_value 
        FROM $wpdb->options 
        WHERE option_name LIKE '_wp_session_expires_%' 
        AND option_value < NOW() 
        LIMIT 0, 50000
    " );

	$expired_sessions = array();

	foreach( $expiration_keys as $expiration ) {
		// Get the session ID by parsing the option_name
		$session_id = str_replace("_wp_session_expires_", "", $expiration->option_name);

		$expired_sessions[] = $expiration->option_name; // _wp_session_expires_XXXXX
		$expired_sessions[] = "_wp_session_$session_id"; // _wp_session_XXXXX
	}

	// Delete all expired sessions in a single query
	if ( ! empty( $expired_sessions ) ) {
		$option_names = implode( "','", $expired_sessions );
		
		// DEBUG before delete if want to check
    	// highlight_string("<?php\n\$option_names =\n" . var_export($option_names) . ";\n");
		
		$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name IN ('$option_names')" );
	}
}

// ======================================================================
// | 🖼️ IMAGE OPTIMIZATION & RESPONSIVENESS |
// ======================================================================

/************************************************************************
 * Globally disable the automatic generation of srcset/sizes attributes.
 * ⚠️ CAUTION: Use this ONLY if you are manually handling all responsive 
 * image sizing in your theme (e.g., using a dedicated optimization plugin 
 * or custom markup). Disabling this can lead to large images loading.
 * @return int A value of 1 effectively disables srcset.
 ***********************************************************************/
function cds_disable_wp_responsive_images() {
	return 1;
}
add_filter('max_srcset_image_width', 'cds_disable_wp_responsive_images');


/************************************************************************
 * Remove srcset and sizes attributes for attached images on a specific page.
 * Useful for highly specific layouts where responsive attributes are unwanted.
 * @param array $attr The image attributes array.
 * @param object $attachment The attachment object.
 * @param string $size The image size.
 * @return array The modified attributes.
 ***********************************************************************/
function cds_clean_attached_image_attrs( $attr, $attachment, $size ) {
	// Limit to specific page. e.g. posts grid page with lots of images
    // If page is: #some_page_id
	// ➡️ CHANGE '137' to the specific page ID where you want this applied.
	if ( is_page(137) ) {
	    // DEBUG
		// highlight_string("<?php\n\$attr =\n" . var_export($attr, true) . ";\n");
		
        // Remove srcset and sizes
        if ( isset($attr["srcset"]) ) { unset($attr["srcset"]); }
        if ( isset($attr["sizes"]) ) { unset($attr["sizes"]); }
    }
    return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', 'cds_clean_attached_image_attrs', 10, 3 );

// ======================================================================
// | ⏳ PERFORMANCE: FONT LOADING OPTIMIZATION |
// ======================================================================

/************************************************************************
 * Adds 'display=swap' parameter to Google Font URLs for improved CLS/LCP scores.
 * Uses string replacement for faster, safer execution than XML parsing.
 * @param string $html The entire <link> tag HTML.
 * @param string $handle The registered style handle (e.g., 'Roboto').
 * @return string The modified <link> tag.
 ***********************************************************************/
function cds_style_loader_tag_filter($html, $handle) {
    // ➡️ CHANGE 'Roboto' to the handle used by the Google Font you want to optimize.
    if ($handle === 'Roboto') {
        // Simple and robust way to append &display=swap to the font URL
        $html = str_replace( '&#038;subset', '&display=swap&#038;subset', $html );
        $html = str_replace( '&subset', '&display=swap&subset', $html );
        $html = str_replace( 'googleapis.com/css', 'googleapis.com/css&display=swap', $html );
    }
    return $html;
}
add_filter('style_loader_tag', 'cds_style_loader_tag_filter', 10, 2);
<?php 
/**
 * 🧱 Theme Functions and Loader 🚀
 *
 * This file serves as the primary functions entry point for the theme.
 * It loads separate, logically grouped files for organization and maintenance.
 */

// ======================================================================
// | 🚀 PERFORMANCE & SECURITY FUNCTIONS |
// ======================================================================

/************************************************************************
 * Load the Optimization and Cleanup functions.
 * Contains various functions to improve page speed, enhance security, 
 * and clean up unnecessary WordPress outputs.
 ***********************************************************************/
require_once( get_stylesheet_directory() . './cds-optimizations-n-tweaks.php' );


// ======================================================================
// | ⚙️ ADMIN UX TWEAKS & EXTRAS |
// ======================================================================

/************************************************************************
 * Load the WordPress Admin Tweaks and Extras.
 * Contains functions to customize and enhance the WordPress admin area 
 * for better user experience (e.g., adding columns).
 ***********************************************************************/
require_once( get_stylesheet_directory() . './cds-wp-admin-tweaks-n-extras.php' );
# ######################################################################
# 🛡️ GENERIC WORDPRESS SECURITY CONFIGURATION (SERVER LEVEL) 🛡️
# NOTE: This file must be placed in httpd.conf or a Virtual Host file.
# It uses LocationMatch/Directory which is FORBIDDEN in .htaccess.
# ######################################################################

# 1. 🚫 BLOCK ACCESS TO SENSITIVE FILE EXTENSIONS
# Blocks direct access to common files used for system management, logs, or compromise.
<LocationMatch ".+\\.(?i:psd|log|cmd|exe|bat|csh|ini|sh)$">
    Require all denied
</LocationMatch>

# 2. 🗃️ BLOCK ACCESS TO WORDPRESS METADATA & CONFIG BACKUPS
# Blocks access to backup files, configuration backups, readme/changelog files.
<LocationMatch "(?i:(?:wp-config\\.bak|\\.wp-config\\.php\\.swp|(?:readme|license|changelog|-config|-sample)\\.(?:php|md|txt|htm|html)))">
    Require all denied
</LocationMatch>

# 3. 💨 DISABLE PHP EXECUTION IN VULNERABLE DIRECTORIES

# Disable PHP execution in cache directories (common attack storage locations)
<LocationMatch "(?i:.*/cache/.*\\.ph(?:p[345]?|t|tml))">
    Require all denied
</LocationMatch>

# Forbid execution of PHP scripts in the wp-content/uploads directory
# This acts as a robust server-level override. Ensure the path is correct.
<Directory "/home/example/public_html/wp-content/uploads">
    <FilesMatch "\.(php|php\d+|phtml|phps|php-s)$">
        Require all denied
    </FilesMatch>
</Directory>

# 4. 🕵️ BOT AND SCANNER PROTECTION (REQUIRES PATH MODIFICATION)

<IfModule mod_rewrite.c>
    # Block Author Scans (Harvesting usernames via ?author=N)
    <Directory "/home/example/public_html">
        RewriteEngine on
        RewriteCond %{QUERY_STRING} author=\d+ [NC]
        # Exclude wp-admin/ from the rule
        RewriteCond %{REQUEST_URI} !^/wp-admin/ [NC]
        RewriteRule .* - [F,L]
    </Directory>

    # Block Malicious/Aggressive User Agents (Scanners/Scrapers)
    # Review this list frequently and customize it to avoid blocking legitimate users.
    <Directory "/home/example/public_html">
        RewriteEngine on
        RewriteCond %{HTTP_USER_AGENT} "(?:acunetix|BLEXBot|domaincrawler\.com|LinkpadBot|MJ12bot/v|majestic12\.co\.uk|AhrefsBot|TwengaBot|SemrushBot|nikto|winhttp|Xenu\s+Link\s+Sleuth|Baiduspider|HTTrack|clshttp|harvest|extract|grab|miner|python-requests)" [NC]
        RewriteRule .* - [F,L]
    </Directory>
</IfModule>

🛠️ WP Plugin Development: Standards & Environment Setup

This guide focuses on integrating the official WordPress Coding Standards (WPCS) into your local development environment using Composer and PHP Code Sniffer (PHPCS) for best practices and code quality.

1. 📚 Core Development Resources

Resource Description Link
Plugin Basics The official starting point covering structure, security, and common functions. WordPress Plugin Basics
Best Practices Essential guidance on security, internationalization, configuration, and performance. Plugin Best Practices
Boilerplates Ready-made starting points to kick off plugin development with modern structure. Boilerplate Starting Points

2. 📝 WordPress Coding Standards (WPCS)

WPCS is a set of rules used to ensure consistency and readability in WordPress code, which is critical for contribution and maintenance.

Setup: Install WPCS for PHP Code Sniffer

This process installs the necessary tools locally within your plugin directory, ensuring your configuration doesn't conflict with other projects.

Step 1: Install PHP CodeSniffer Locally (via Composer)

Navigate to your plugin's root directory (e.g., /plugins/YOUR_PLUGIN/) and run:

composer require --dev squizlabs/php_codesniffer
  • Verification: Check the default standards installed.
    vendor/bin/phpcs -i
    • Expected Output (before WPCS): The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz and Zend
Step 2: Install WPCS Locally

Traditionally, you would install WPCS using Composer as well, which is often the cleaner method. However, since the provided steps use git clone, we will follow that, assuming Composer failed or a specific setup is required.

a. Navigate to the vendor folder:

cd vendor

b. Clone the WPCS repository: Clone the WPCS repository into a new folder named wpcs.

git clone -b master https://github.com/WordPress/WordPress-Coding-Standards.git wpcs

c. Add WPCS to PHPCS Configuration: You must now tell PHPCS where to find the newly cloned standards.

/home/ACCOUNT_NAME/public_html/wp-content/plugins/YOUR_PLUGIN/vendor/bin/phpcs --config-set installed_paths /home/ACCOUNT_NAME/public_html/wp-content/plugins/YOUR_PLUGIN/vendor/wpcs
  • 💡 IMPORTANT: You must replace /home/ACCOUNT_NAME/public_html/wp-content/plugins/YOUR_PLUGIN with the actual absolute path to your plugin's root directory.

d. Verification: Confirm that WPCS standards are now available.

vendor/bin/phpcs -i
  • Expected Output (with WPCS): The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, **WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra**

3. 🖥️ VS Code Integration (PHP Sniffer & Beautifier)

Integrating these tools directly into your IDE allows for real-time code quality checking and automatic fixing.

Step 1: Install the VS Code Plugin

Install the official PHP Sniffer & Beautifier extension:

Step 2: Configure settings.json

Open your VS Code settings.json (via Ctrl + Shift + P and searching for settings.json) and add the following settings.

{
    // ⚙️ General Editor Settings
    "editor.tabSize": 4,
    "editor.detectIndentation": false,
    "window.title": "${activeEditorLong}${separator}${rootName}",

    // 🕵️ PHP Sniffer & Beautifier (PHPSAB) Configuration
    "phpsab.standard": "WordPress", // 🎯 Set the default standard to WordPress
    "phpsab.snifferEnable": true,   // 🟢 Enable real-time suggestions and warnings
    "phpsab.snifferShowSources": true, // Show which rule is being violated

    // 🔨 Tool Paths (MUST BE ABSOLUTE PATHS)
    "phpsab.executablePathCBF": "/home/ACCOUNT_NAME/public_html/wp-content/plugins/YOUR_PLUGIN/vendor/bin/phpcbf",
    "phpsab.executablePathCS": "/home/ACCOUNT_NAME/public_html/wp-content/plugins/YOUR_PLUGIN/vendor/bin/phpcs",
    
    // Optional: Uncomment to enable auto-formatting on save using phpcbf
    // "editor.formatOnSave": true
}

💡 IMPORTANT: You must update the values for phpsab.executablePathCBF and phpsab.executablePathCS to point to the correct, absolute locations of the executable files within your plugin's local vendor/bin folder.

1. ⚙️ Update wp-config.php (The Critical First Step)

This step tells WordPress the new prefix it should use for all subsequent database interactions. This must be done first.

Action Code ⚠️ Critical Warning
Locate and Rename Find the line: $table_prefix = 'wp_';
Change it to: $table_prefix = 'newprefix_';
IMMEDIATE FATAL ERROR WARNING: If you run this step and do not immediately complete the database changes (Step 2 and 3), your site will immediately throw a database connection error (Error establishing a database connection) because the tables it's looking for won't exist yet.

2. 🗄️ Rename All Database Tables (SQL)

This step finds all tables with the old prefix and generates the queries needed to rename them.

a) Generate RENAME Queries (The Smart Way)

The provided SQL query is an efficient way to automatically generate all RENAME TABLE queries.

SET @database  = "your_database_name";
SET @oldprefix = "wp_";       -- <<--- Change this if using a different existing prefix!
SET @newprefix = "your_new_prefix_";

SELECT
    concat(
        "RENAME TABLE ",
        TABLE_NAME,
        " TO ",
        replace(TABLE_NAME, @oldprefix, @newprefix),
        ';'
    ) AS "SQL_COMMANDS"
FROM information_schema.TABLES 
WHERE 
    TABLE_SCHEMA = @database AND 
    TABLE_NAME LIKE @oldprefix; -- 💡 Limit to tables starting with the old prefix

NOTICE: change values of @database, @oldprefix and @newprefix BEFORE running the above query!

b) Execute the Generated Queries

The above query will generate further queries like:

RENAME oldprefix_options to newprefix_options;
RENAME oldprefix_users to newprefix_users;
  • Copy the output from the SQL_COMMANDS column.
  • Paste and Execute the resulting RENAME TABLE ... statements in your database interface (e.g., phpMyAdmin, Adminer, or SQL client).

3. 📝 Update Table Values (Internal Prefix References)

After renaming the tables, WordPress still stores the old prefix inside certain table columns. These must be updated, usually in wp_options and wp_usermeta.

a) Update Prefix in Options Table (*_options)

The core prefix is stored in the option_name field for a few system settings (most importantly, the user_roles array).

Table Name Update Query
newprefix_options UPDATE newprefix_options
SET option_name = REPLACE(option_name, 'oldprefix_', 'newprefix_')
WHERE option_name LIKE 'oldprefix_%';

b) Update Prefix in User Meta Table (*_usermeta)

User capabilities and preferences are stored using the prefix.

Table Name Update Query
newprefix_usermeta UPDATE newprefix_usermeta
SET meta_key = REPLACE(meta_key, 'oldprefix_', 'newprefix_')
WHERE meta_key LIKE 'oldprefix_%';

🗄️ BONUS: PHPMyAdmin GUI Method

The guide's method for using phpMyAdmin's GUI is a quick, visual alternative for Step 2 (renaming tables), but the subsequent manual steps are prone to error.

Step Action Improvement Note
Rename Tables (Step 1) Use the "Replace table prefix" feature in phpMyAdmin after selecting all tables. Recommended alternative to the RENAME SQL. This is the simplest way to execute Step 2.
Update Options/Usermeta (Step 2 & 3) Manually execute the UPDATE queries (from section 3 above) after the table rename. ⚠️ Do NOT rely on SELECT * queries to find and manually replace values. Use the robust REPLACE update queries in Section 3 for guaranteed consistency.

✅ Summary Checklist

Before celebrating, verify these key spots:

  • wp-config.php is updated with $table_prefix = 'newprefix_';.
  • 12 tables (or more, if plugins added tables) have been renamed in the database (e.g., wp_posts is now newprefix_posts).
  • The option_name column in the *_options table has been updated.
  • The meta_key column in the *_usermeta table has been updated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment