Code Library
My personal collection of reusable PHP, JS and CSS snippets.
Fluid Typography
Fonts scale with screen size
/* --- Fluid Typography --- */
/* H1 Hoofdtitel */
/* Minimaal 32px (mobiel), groeit mee, maximaal 56px (grote schermen) */
h1, .elementor-heading-title.elementor-size-default {
font-size: clamp(2rem, 5vw, 3.5rem) !important;
}
/* H2 Sectie titels */
/* Minimaal 26px, groeit mee, maximaal 40px */
h2, .elementor-widget-heading h2.elementor-heading-title {
font-size: clamp(1.625rem, 4vw, 2.5rem) !important;
}
/* H3 Subkopjes */
/* Minimaal 22px, groeit mee, maximaal 28px */
h3, .elementor-widget-heading h3.elementor-heading-title {
font-size: clamp(1.375rem, 2.5vw, 1.75rem) !important;
}
/* Body / Paragraaf tekst */
/* De !important zorgt dat dit wint van de widget-instellingen */
p, body, .elementor-widget-text-editor {
font-size: clamp(1rem, 0.5vw + 0.8rem, 1.125rem) !important;
}
/* Uitzondering voor kleine lettertjes (zoals copyright/footer) */
/* Geef deze widgets of secties de CSS-klasse: 'kleine-tekst' */
.kleine-tekst p, .kleine-tekst, small {
font-size: 0.875rem !important; /* 14px */
}
WordPress | Remove jQuery migrate
jQuery Migrate adds support for older jQuery versions, often useful for older themes. It’s rare that it’s needed so it’s best to remove it to take one request away from page loads.
functions.php
/************************************************************
* @description WordPress | Remove jQuery migrate
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function smartwp_remove_jquery_migrate( $scripts ) {
if ( !is_admin() && !empty( $scripts->registered['jquery'] ) ) {
$scripts->registered['jquery']->deps = array_diff( $scripts->registered['jquery']->deps, ['jquery-migrate'] );
}
}
add_action('wp_default_scripts', 'smartwp_remove_jquery_migrate');
WordPress | Custom logo top left in WP Admin
Adds a custom logo to the top left of the WordPress admin
functions.php
/************************************************************
* @description WordPress | Custom logo top left in WP Admin
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function smartwp_custom_logo_wp_dashboard() {
echo "<style type='text/css'>
#wpadminbar #wp-admin-bar-wp-logo > .ab-item .ab-icon:before {
background-image: url('" . get_bloginfo('stylesheet_directory') . "/admin-icon.png');
background-size: contain;
background-position: 0 0;
color:rgba(0, 0, 0, 0);
}
#wpadminbar #wp-admin-bar-wp-logo > .ab-item .ab-icon {
background-position: 0 0;
}";
}
WordPress | Create user
Create a user through a php snippet
functions.php
/************************************************************
* @description WordPress | Create user
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function smartwp_create_admin_user(){
$username = 'Systemedic';
$password = 'CHANGE_THIS_PASSWORD'; // Changed for security
$email = 'E-MAIL HERE';
//This will ensure it only tries to create the user once (based on email/username)
if ( !username_exists( $username ) && !email_exists( $email ) ) {
$userid = wp_create_user( $username, $password, $email );
$user = new WP_User( $userid );
$user->set_role( 'administrator' );
}
}
add_action('init', 'smartwp_create_admin_user');
Change wp-admin footer
Change WP-admin footer to show own text.
functions.php
/************************************************************
* @description Change wp-admin footer
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function remove_footer_admin () {
echo 'Development by <a href="https://systemedic.nl" target="_blank">Systemedic</a> | Questions & Support: <a href="https://mijn.systemedic.nl" target="_blank">Systemedic Support</a></p>';
}
add_filter('admin_footer_text', 'remove_footer_admin');
WordPress | Systemedic Dashboard Widget
Custom dashboard Widgets with links to Systemedic services and knowledgebase
functions.php
/************************************************************
* @description WordPress | Systemedic Dashboard Widget
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
// Add a custom dashboard widget
function my_custom_dashboard_widget() {
wp_add_dashboard_widget(
'custom_dashboard_widget', // Widget ID
'Systemedic Support', // Widget Title
'custom_dashboard_widget_display' // Callback function
);
}
add_action('wp_dashboard_setup', 'my_custom_dashboard_widget');
// The content of the widget
function custom_dashboard_widget_display() {
?>
<style>
.custom-dashboard-widget ul {
list-style-type: disc;
padding-left: 20px;
}
.custom-dashboard-widget img {
max-width: 100%;
height: auto;
}
</style>
<div class="custom-dashboard-widget">
<img src="https://mijn.systemedic.nl/templates/lagom2/assets/img/logo/logo_big.1582291681.png" alt="Systemedic Logo">
<ul>
<li>Do you have questions, problems, or ideas? Contact Systemedic:
<a href="https://mijn.systemedic.nl/submitticket.php?step=2&deptid=2" target="_blank">Contact Us</a>
</li>
<li>Have a question? Check the knowledge base first, you can view it here:
<a href="https://mijn.systemedic.nl/knowledgebase/29/WordPress" target="_blank">Knowledge Base</a>
</li>
<li>Want to keep your website in top condition? Discover our maintenance packages for a worry-free website.
<a href="https://mijn.systemedic.nl/store/onderhoudspakketten" target="_blank">Maintenance Packages</a>
</li>
</ul>
</div>
<?php
}
Disable Gutenberg block editor
Completely disables the Gutenberg editor and restores the Classic Editor.
functions.php
/************************************************************
* @description Disable Gutenberg block editor
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
// Disable Gutenberg on the back end.
add_filter( 'use_block_editor_for_post', '__return_false' );
// Disable Gutenberg for widgets.
add_filter( 'use_widgets_block_editor', '__return_false' );
add_action( 'wp_enqueue_scripts', function() {
// Remove CSS on the front end.
wp_dequeue_style( 'wp-block-library' );
// Remove Gutenberg theme.
wp_dequeue_style( 'wp-block-library-theme' );
// Remove inline global CSS on the front end.
wp_dequeue_style( 'global-styles' );
// Remove classic-themes CSS for backwards compatibility for button blocks.
wp_dequeue_style( 'classic-theme-styles' );
}, 20 );
Hide Woocommerce Payments menu item
Short snippet to hide the WooCommerce Payments Menu Item in the Wordpress Dashboard
functions.php
/************************************************************
* @description Hide Woocommerce Payments menu item
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function remove_payments_ad_tab(): void {
remove_menu_page("admin.php?page=wc-admin&task=woocommerce-payments");
}
add_action("admin_menu", "remove_payments_ad_tab", 999);
Display user role in HTML code
Adds the current user role as an HTML comment in the head for debugging.
functions.php
/************************************************************
* @description Display user role in HTML code
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function display_user_role_in_html_comment() {
if (is_user_logged_in()) {
$current_user = wp_get_current_user();
if (!empty($current_user->roles)) {
echo "\n\n";
}
} else {
echo "\n\n";
}
}
add_action('wp_head', 'display_user_role_in_html_comment');
robots.txt
Default robots.txt configuration to block bad bots and protect sensitive paths.
User-agent: *
Crawl-delay:10
Disallow: /wp-admin/ #no access to admin sections.
Disallow: /wp-login.php #no access to admin sections.
Disallow: /search/ #no access to internal search results.
Disallow: *?s=* #no access to internal search results.
Disallow: *?p=* #no access to pages if permalinks don't work.
Disallow: *&p=* #no access to pages if permalinks don't work.
Disallow: *&preview=* #no access to preview pages.
Disallow: /tag/ #no access to tag archive pages.
Disallow: /author/ #no access to author archive pages.
Disallow: /404-error/ #no access to 404 page.
Disallow: /*?orderby=
Disallow: /*?add-to-cart=
Disallow: /wp-content/plugins/
Disallow: /uploads/
Disallow: *category=*
Disallow: *categoria*
Disallow: *categorie*
Disallow: *filter* # Block bad bots
User-agent: Dotbot
Disallow: /
User-agent: Baiduspider
Disallow: /
User-agent: YandexBot
Disallow: /
User-agent: Sogou Spider
Disallow: /
User-agent: SeznamBot
Disallow: /
User-agent: Scrapy
Disallow: /
Sitemap: https://URL/sitemap_index.xml
Add custom product tabs
Add option to add custom tabs for products. Content can be filled from within product page.
functions.php
/************************************************************
* @description Add custom product tabs
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
// Add the 'Custom Tabs' tab under 'Product Data'
add_filter('woocommerce_product_data_tabs', 'add_custom_tabs_main', 10, 1);
function add_custom_tabs_main($tabs) {
// Add the main 'Custom Tabs' tab
$tabs['custom_tabs'] = array(
'label' => __('Custom Tabs', 'woocommerce'),
'target' => 'custom_tabs_content',
'priority' => 60, // Place the tab after standard tabs
);
return $tabs;
}
// Add content for the 'Custom Tabs' panel with Ingredients and Instructions
add_action('woocommerce_product_data_panels', 'custom_tabs_content');
function custom_tabs_content() {
global $post;
// Get the saved content of the fields
$ingredients = get_post_meta($post->ID, '_custom_ingredients', true);
$instructions = get_post_meta($post->ID, '_custom_instructions', true);
$ingredients_title = get_post_meta($post->ID, '_custom_ingredients_title', true); // Title Ingredients
$instructions_title = get_post_meta($post->ID, '_custom_instructions_title', true); // Title Instructions
// Tab content for Ingredients
echo '<div id="custom_tabs_content" class="panel woocommerce_options_panel">';
// Ingredients Title and WYSIWYG editor
echo '<div class="options_group">';
echo '<p class="form-field">';
echo '<label for="_custom_ingredients_title">' . __('Alternative tab name', 'woocommerce') . '</label>';
echo '<input type="text" id="_custom_ingredients_title" name="_custom_ingredients_title" value="' . esc_attr($ingredients_title) . '" />';
echo '</p>';
// Ingredients field with WYSIWYG editor
echo '<p class="form-field">';
echo '<label for="_custom_ingredients">' . __('Ingredients', 'woocommerce') . '</label>';
wp_editor($ingredients, '_custom_ingredients', array(
'textarea_name' => '_custom_ingredients',
'media_buttons' => true,
'textarea_rows' => 10,
'teeny' => true, // Minimal editor without many buttons
));
echo '</p>';
// Instructions Title and WYSIWYG editor
echo '<p class="form-field">';
echo '<label for="_custom_instructions_title">' . __('Alternative tab name', 'woocommerce') . '</label>';
echo '<input type="text" id="_custom_instructions_title" name="_custom_instructions_title" value="' . esc_attr($instructions_title) . '" />';
echo '</p>';
// Instructions field with WYSIWYG editor
echo '<p class="form-field">';
echo '<label for="_custom_instructions">' . __('Instructions', 'woocommerce') . '</label>';
wp_editor($instructions, '_custom_instructions', array(
'textarea_name' => '_custom_instructions',
'media_buttons' => true,
'textarea_rows' => 10,
'teeny' => true, // Minimal editor without many buttons
));
echo '</p>';
echo '</div>';
echo '</div>';
}
// Save the field data, including the tab titles
add_action('woocommerce_process_product_meta', 'save_custom_tabs_product_data');
function save_custom_tabs_product_data($post_id) {
// Save data for Ingredients, Instructions, and their titles
if (isset($_POST['_custom_ingredients'])) {
update_post_meta($post_id, '_custom_ingredients', wp_kses_post($_POST['_custom_ingredients']));
}
if (isset($_POST['_custom_instructions'])) {
update_post_meta($post_id, '_custom_instructions', wp_kses_post($_POST['_custom_instructions']));
}
if (isset($_POST['_custom_ingredients_title'])) {
update_post_meta($post_id, '_custom_ingredients_title', sanitize_text_field($_POST['_custom_ingredients_title']));
}
if (isset($_POST['_custom_instructions_title'])) {
update_post_meta($post_id, '_custom_instructions_title', sanitize_text_field($_POST['_custom_instructions_title']));
}
}
// Add tabs for Ingredients and Instructions on the product page, but only if they have content
add_filter('woocommerce_product_tabs', 'add_custom_product_tabs', 10, 1);
function add_custom_product_tabs($tabs) {
global $post;
// Get saved content for ingredients, instructions, and their titles
$ingredients = get_post_meta($post->ID, '_custom_ingredients', true);
$instructions = get_post_meta($post->ID, '_custom_instructions', true);
$ingredients_title = get_post_meta($post->ID, '_custom_ingredients_title', true);
$instructions_title = get_post_meta($post->ID, '_custom_instructions_title', true);
// Add Ingredients tab if there is content
if (!empty($ingredients)) {
$tabs['ingredients_tab'] = array(
'title' => !empty($ingredients_title) ? $ingredients_title : __('Ingredients', 'woocommerce'),
'priority' => 50,
'callback' => 'ingredients_tab_content',
);
}
// Add Instructions tab if there is content
if (!empty($instructions)) {
$tabs['instructions_tab'] = array(
'title' => !empty($instructions_title) ? $instructions_title : __('Instructions', 'woocommerce'),
'priority' => 51,
'callback' => 'instructions_tab_content',
);
}
return $tabs;
}
// Function to display the content of the Ingredients tab
function ingredients_tab_content() {
global $post;
$ingredients = get_post_meta($post->ID, '_custom_ingredients', true);
echo wpautop($ingredients);
}
// Function to display the content of the Instructions tab
function instructions_tab_content() {
global $post;
$instructions = get_post_meta($post->ID, '_custom_instructions', true);
echo wpautop($instructions);
}
Auto set paid WooCommerce orders to completed
Change the status of WooCommerce orders to completed when there is a payment.
functions.php
/************************************************************
* @description Auto set paid WooCommerce orders to completed
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_filter( 'woocommerce_payment_complete_order_status', 'bbloomer_autocomplete_processing_orders', 9999 );
function bbloomer_autocomplete_processing_orders() {
return 'completed';
}
E-mail before download
Allow users to enter an e-mail address before they can download a PDF. The email addresses will appear in an admin menu named ‘PDF Downloads’ and will be stored in the database
functions.php
/************************************************************
* @description E-mail before download
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
// Create table for storing PDF download submissions
function create_pdf_download_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'pdf_downloads';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
naam tinytext NOT NULL,
email varchar(100) NOT NULL,
tijd datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
pdf_url text NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// Direct call to create the table if it doesn't exist
create_pdf_download_table();
// Shortcode function for the PDF download form
function pdf_download_form_shortcode($atts) {
$atts = shortcode_atts(
array(
'pdf_url' => '', // Default no PDF URL
),
$atts,
'pdf_download_form'
);
if (empty($atts['pdf_url'])) {
return '<p>No PDF available for download.</p>';
}
if (isset($_POST['submit_form'])) {
if (!empty($_POST['naam']) && !empty($_POST['email'])) {
$naam = sanitize_text_field($_POST['naam']);
$email = sanitize_email($_POST['email']);
global $wpdb;
$table_name = $wpdb->prefix . 'pdf_downloads';
$wpdb->insert(
$table_name,
array(
'naam' => $naam,
'email' => $email,
'pdf_url' => $atts['pdf_url'],
)
);
$download_link = '<p>Thank you, ' . esc_html($naam) . '! Click here to download the PDF: <a href="' . esc_url($atts['pdf_url']) . '" target="_blank">Download PDF</a></p>';
return $download_link;
} else {
return '<p>Please fill in all fields.</p>';
}
}
ob_start(); ?>
<form method="post">
<label for="naam">Name:</label><br>
<input type="text" id="naam" name="naam" style="width: 50%;" required><br><br>
<label for="email">E-mail:</label><br>
<input type="email" id="email" name="email" style="width: 50%;" required><br><br>
<input type="submit" name="submit_form" value="Download PDF" style="width: 50%;">
</form>
<?php
return ob_get_clean();
}
add_shortcode('pdf_download_form', 'pdf_download_form_shortcode');
// Add admin menu for displaying submissions
function pdf_download_admin_menu() {
add_menu_page(
'PDF Downloads',
'PDF Downloads',
'manage_options',
'pdf-downloads',
'display_pdf_downloads_page',
'dashicons-media-document',
20
);
}
add_action('admin_menu', 'pdf_download_admin_menu');
// Function to display and delete submissions in admin
function display_pdf_downloads_page() {
global $wpdb;
$table_name = $wpdb->prefix . 'pdf_downloads';
// Delete a record if 'delete_id' parameter is set
if (isset($_GET['delete_id'])) {
$delete_id = intval($_GET['delete_id']);
$wpdb->delete($table_name, array('id' => $delete_id));
echo '<div class="notice notice-success is-dismissible"><p>Submission successfully deleted.</p></div>';
}
// Retrieve data to display
$downloads = $wpdb->get_results("SELECT * FROM $table_name");
echo '<div class="wrap"><h1>PDF Download Submissions</h1>';
echo '<table class="widefat fixed" cellspacing="0"><thead><tr><th>Name</th><th>Email</th><th>PDF URL</th><th>Time</th><th>Action</th></tr></thead><tbody>';
if (!empty($downloads)) {
foreach ($downloads as $download) {
echo '<tr>';
echo '<td>' . esc_html($download->naam) . '</td>';
echo '<td>' . esc_html($download->email) . '</td>';
echo '<td><a href="' . esc_url($download->pdf_url) . '" target="_blank">' . esc_html($download->pdf_url) . '</a></td>';
echo '<td>' . esc_html($download->tijd) . '</td>';
echo '<td><a href="' . esc_url(add_query_arg('delete_id', $download->id)) . '" onclick="return confirm(\'Are you sure you want to delete this submission?\');" class="button button-danger">Delete</a></td>';
echo '</tr>';
}
} else {
echo '<tr><td colspan="5">No submissions found.</td></tr>';
}
echo '</tbody></table></div>';
}
WordPress | Enforce Strong Passwords
Make sure users are using strong passwords with at least 8 characters and 1 capital and 1 number
functions.php
/************************************************************
* @description WordPress | Enforce Strong Passwords
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function force_strong_passwords($errors, $update, $user) {
if (empty($user->user_pass)) {
return;
}
if (strlen($user->user_pass) < 8 || !preg_match('/[A-Z]/', $user->user_pass) || !preg_match('/[0-9]/', $user->user_pass)) {
$errors->add('pass', 'Passwords must be at least 8 characters long and contain at least one uppercase letter and one number.');
}
}
add_action('user_profile_update_errors', 'force_strong_passwords', 10, 3);
WordPress | Prevent upload of PHP files
Prevent the upload of PHP files by users for enhanced security
functions.php
/************************************************************
* @description WordPress | Prevent upload of PHP files
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function prevent_php_upload($file) {
$file_type = wp_check_filetype($file['name']);
if ($file_type['ext'] == 'php') {
$file['error'] = 'PHP files are not allowed for upload.';
}
return $file;
}
add_filter('wp_handle_upload_prefilter', 'prevent_php_upload');
WordPress | Prevent faulty headers
Removes unnecessary headers like X-Pingback and others.
functions.php
/************************************************************
* @description WordPress | Prevent faulty headers
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function remove_unwanted_headers() {
header_remove('X-Pingback');
header_remove('X-Frame-Options');
header_remove('X-XSS-Protection');
header_remove('X-Content-Type-Options');
}
add_action('send_headers', 'remove_unwanted_headers');
WooCommerce: Rename Additional information tab
Rename the WooCommerce additional information tab to a title of your liking
functions.php
/************************************************************
* @description WooCommerce: Rename Additional information tab
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_filter( 'woocommerce_product_tabs', 'misha_rename_additional_info_tab' );
function misha_rename_additional_info_tab( $tabs ) {
$tabs[ 'additional_information' ][ 'title' ] = 'Specifications'; // Change 'Specifications' to your preferred title
return $tabs;
}
Change author slug: user nickname instead of username
Improves security by hiding the username in author URLs.
functions.php
/************************************************************
* @description Change author slug: user nickname instead of username
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action( 'user_profile_update_errors', 'set_user_nicename_to_nickname', 10, 3 );
function set_user_nicename_to_nickname( &$errors, $update, &$user ) {
if ( ! empty( $user->nickname ) ) {
$user->user_nicename = sanitize_title( $user->nickname, $user->display_name );
}
}
Limit Login attempts or get locked out
This handles the login attempts that can be made before being locked out for a certain amount of time
functions.php
/************************************************************
* @description Limit Login attempts or get locked out
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function limit_login_attempts() {
$max_attempts = 5;
$lockout_time = 60 * 5; // 5 minutes
if (is_user_logged_in()) {
return;
}
$attempts = get_transient('login_attempts');
if ($attempts === false) {
$attempts = 0;
}
if ($attempts >= $max_attempts) {
wp_die('Too many login attempts. Please try again later.');
}
add_action('wp_login_failed', function() use ($attempts, $lockout_time) {
set_transient('login_attempts', $attempts + 1, $lockout_time);
});
}
add_action('login_init', 'limit_login_attempts');
Default featured Image - Using Gutenberg
Set a default featured imaged for posts
functions.php
/************************************************************
* @description Default featured Image - Using Gutenberg
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function mytheme_set_default_thumbnail( $post ) {
if ( $post->post_type != 'post' ) {
return;
}
if ( !has_post_thumbnail( $post->ID ) ) {
$thumbnail_url = 'https://test.local/wp-content/uploads/2022/10/dev3.jpg'; // Change URL
$thumbnail_id = attachment_url_to_postid( $thumbnail_url );
set_post_thumbnail( $post->ID, $thumbnail_id );
}
}
add_action( 'rest_after_insert_post', 'mytheme_set_default_thumbnail', 10, 3 );
Default featured Image (Classic)
Set a default featured imaged for posts
functions.php
/************************************************************
* @description Default featured Image (Classic)
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function wpse55748_filter_post_thumbnail_html( $html ) {
// If there is no post thumbnail,
// Return a default image
if ( '' == $html ) {
return '<img src="' . get_template_directory_uri() . '/wp-content/uploads/2021/03/default.jpeg" width="150px" height="100px" class="default-img" />';
}
}
WooCommerce: Text in front of price
Place a default text in front of the price in Woocommerce
functions.php
/************************************************************
* @description WooCommerce: Text in front of price
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_filter( 'woocommerce_get_price_html', 'cw_change_product_price_display' );
add_filter( 'woocommerce_cart_item_price', 'cw_change_product_price_display' );
function cw_change_product_price_display( $price ) {
// Your additional text in a translatable string
$text = __('From');
// returning the text before the price
return $text . ' ' . $price;
}
Rename description tab in WooCommerce
Rename the WooCommerce description tab to a title of your liking
functions.php
/************************************************************
* @description Rename description tab in WooCommerce
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_filter( 'woocommerce_product_tabs', 'misha_rename_description_tab' );
function misha_rename_description_tab( $tabs ) {
$tabs[ 'description' ][ 'title' ] = 'Description'; // Change to desired title
return $tabs;
}
WordPress: Disable RSD and WLW
Disable the Windows Live Writer and Really Simple Discovery code
functions.php
/************************************************************
* @description WordPress: Disable RSD and WLW
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
remove_action ('wp_head', 'rsd_link');
remove_action ('wp_head', 'wlwmanifest_link');
Show custom field in shop page
Adds a custom field to the product display on the shop page.
functions.php
/************************************************************
* @description Show custom field in shop page
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action( 'woocommerce_after_shop_loop_item_title', 'bbloomer_woocommerce_product_excerpt', 35 );
function bbloomer_woocommerce_product_excerpt() {
global $post;
if ( is_home() || is_shop() || is_product_category() || is_product_tag() ) {
echo '<span class="flow_category">';
echo get_post_meta( $post->ID, 'flow', true );
echo '</span>';
}
}
Limit Post revisions
Limit the number of post revisions
functions.php
/************************************************************
* @description Limit Post revisions
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function limit_post_revisions($num, $post) {
// Set a max limit for revisions for all post types
$max_revisions = 5;
// Check if the post type is 'post'
if ($post->post_type == 'post') {
return $max_revisions;
} else {
return $num;
}
}
// Hook into the 'wp_revisions_to_keep' filter
add_filter('wp_revisions_to_keep', 'limit_post_revisions', 10, 2);
Page/Post duplicator
Easily create a duplicate of a page or post. Clone is set as draft and user is directed to edit screen
functions.php
/************************************************************
* @description Page/Post duplicator
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function rd_duplicate_post_as_draft(){
global $wpdb;
if (! ( isset( $_GET['post']) || isset( $_POST['post']) || ( isset($_REQUEST['action']) && 'rd_duplicate_post_as_draft' == $_REQUEST['action'] ) ) ) {
wp_die('No post to duplicate has been supplied!');
}
/*
* Nonce verification
*/
if ( !isset( $_GET['duplicate_nonce'] ) || !wp_verify_nonce( $_GET['duplicate_nonce'], basename( __FILE__ ) ) )
return;
/*
* get the original post id
*/
$post_id = (isset($_GET['post']) ? absint( $_GET['post'] ) : absint( $_POST['post'] ) );
/*
* and all the original post data then
*/
$post = get_post( $post_id );
/*
* if you don't want current user to be the new post author,
* then change next couple of lines to this: $new_post_author = $post->post_author;
*/
$current_user = wp_get_current_user();
$new_post_author = $current_user->ID;
/*
* if post data exists, create the post duplicate
*/
if (isset( $post ) && $post != null) {
/*
* new post data array
*/
$args = array(
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_author' => $new_post_author,
'post_content' => $post->post_content,
'post_excerpt' => $post->post_excerpt,
'post_name' => $post->post_name,
'post_parent' => $post->post_parent,
'post_password' => $post->post_password,
'post_status' => 'draft',
'post_title' => $post->post_title,
'post_type' => $post->post_type,
'to_ping' => $post->to_ping,
'menu_order' => $post->menu_order
);
/*
* insert the post by wp_insert_post() function
*/
$new_post_id = wp_insert_post( $args );
/*
* get all current post terms ad set them to the new post draft
*/
$taxonomies = get_object_taxonomies($post->post_type); // returns array of taxonomy names for post type, ex array("category", "post_tag");
foreach ($taxonomies as $taxonomy) {
$post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
}
/*
* duplicate all post meta just in two SQL queries
*/
$post_meta_infos = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$post_id");
if (count($post_meta_infos)!=0) {
$sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
foreach ($post_meta_infos as $meta_info) {
$meta_key = $meta_info->meta_key;
if( $meta_key == '_wp_old_slug' ) continue;
$meta_value = addslashes($meta_info->meta_value);
$sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";
}
$sql_query.= implode(" UNION ALL ", $sql_query_sel);
$wpdb->query($sql_query);
}
/*
* finally, redirect to the edit post screen for the new draft
*/
wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_post_id ) );
exit;
} else {
wp_die('Post creation failed, could not find original post: ' . $post_id);
}
}
add_action( 'admin_action_rd_duplicate_post_as_draft', 'rd_duplicate_post_as_draft' );
/*
* Add the duplicate link to action list for post_row_actions
*/
function rd_duplicate_post_link( $actions, $post ) {
if (current_user_can('edit_posts')) {
$actions['duplicate'] = '<a href="' . wp_nonce_url('admin.php?action=rd_duplicate_post_as_draft&post=' . $post->ID, basename(__FILE__), 'duplicate_nonce' ) . '" title="Duplicate this item" rel="permalink">Duplicate</a>';
}
return $actions;
}
add_filter('page_row_actions', 'rd_duplicate_post_link', 10, 2);
WordPress: Remove Widgets from admin dashboard
Cleans up the admin dashboard by removing default widgets.
functions.php
/************************************************************
* @description WordPress: Remove Widgets from admin dashboard
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function remove_dashboard_widgets() {
global $wp_meta_boxes;
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_drafts']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_activity']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
}
add_action('wp_dashboard_setup', 'remove_dashboard_widgets' );
WordPress: Hide Elementor Dashboard widget
Removes the Elementor Overview widget from the dashboard.
functions.php
/************************************************************
* @description WordPress: Hide Elementor Dashboard widget
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function plt_hide_elementor_dashboard_widgets() {
$screen = get_current_screen();
if ( !$screen ) {
return;
}
//Remove the "Elementor Overview" widget.
remove_meta_box('e-dashboard-overview', 'dashboard', 'normal');
}
add_action('wp_dashboard_setup', 'plt_hide_elementor_dashboard_widgets', 20);
WordPress: Disable generator tag
Removes the generator tag from the head for security.
functions.php
/************************************************************
* @description WordPress: Disable generator tag
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
remove_action('wp_head', 'wp_generator');
Add Mealie to Home Assistant
Explanation how to add the "meal of the day" from Mealie to Home Assistant
rest.yaml
# Add the following to rest.yaml
- resource: https://URL_HERE/api/groups/mealplans/today
scan_interval: 60 # the default is 30 seconds if you leave this line out, or change it to what you need.
headers:
Authorization: Bearer <API HERE>
sensor:
- name: "mealie_today"
value_template: "{{ value_json[0].recipe.name }}"
unique_id: mealie.today
- resource: https://URL HERE/api/groups/mealplans/today
scan_interval: 60 # the default is 30 seconds if you leave this line out, or change it to what you need.
headers:
Authorization: Bearer <API HERE>
sensor:
- name: "mealie_today_id"
value_template: "{{ value_json[0].recipe.id }}"
unique_id: mealie.today_id
Add DNSSEC to Oxxa
Explanation how to secure your domain with DNSSEC when the domain is registered at Oxxa
Instructions
- FLAG determines the usage of the key (ZSK=257 or KSK=256)
- PROTOCOL = 3 (default for DNSSEC)
- ALGORITHM can be multiple options. See https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml for the full list. Default = 3: DSA/SHA-1, 5: RSA/SHA1, 8: RSA/SHA-256, 12: ECC-GOST. Recommended if registrar supports it: 13: ECDSA Curve P-256 with SHA-256
- KEY = The digest part under the DS records.
Add code to header
Snippet to be placed in functions.php for placing the code in the header.
functions.php
/************************************************************
* @description Add code to header
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action('wp_head', 'your_function_name');
function your_function_name(){
?>
PASTE HEADER CODE HERE
<?php
};
Place code in footer
Snippet to be place in functions.php for code that needs to be in the footer
functions.php
/************************************************************
* @description Place code in footer
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action('wp_footer', 'your_function_name');
function your_function_name(){
?>
PASTE FOOTER CODE HERE
<?php
};
Auto populate ACF field with other acf field
Automatically fill an ACF field based on the value of another field upon saving.
functions.php
/************************************************************
* @description Auto populate ACF field with other acf field
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function my_acf_save_post( $post_id ) {
// get new value
$value = get_field('artist'); // changed from kunstenaar
// do something
update_field('artist_text', $value); // changed from kunstenaar_tekst
}
add_action('acf/save_post', 'my_acf_save_post', 20);
Display and sort custom taxonomy in wp-admin
Adds a dropdown filter for a custom taxonomy in the admin post list.
functions.php
/************************************************************
* @description Display and sort custom taxonomy in wp-admin
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action('restrict_manage_posts', 'tsm_filter_post_type_by_taxonomy');
function tsm_filter_post_type_by_taxonomy() {
global $typenow;
$post_type = 'artworks'; // change to your post type
$taxonomy = 'artists'; // change to your taxonomy
if ($typenow == $post_type) {
$selected = isset($_GET[$taxonomy]) ? $_GET[$taxonomy] : '';
$info_taxonomy = get_taxonomy($taxonomy);
wp_dropdown_categories(array(
'show_option_all' => sprintf( __( 'Show all %s', 'textdomain' ), $info_taxonomy->label ),
'taxonomy' => $taxonomy,
'name' => $taxonomy,
'orderby' => 'name',
'selected' => $selected,
'show_count' => true,
'hide_empty' => true,
));
};
}
/************************************************************
* @description filter by a custom taxonomy in admin
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_filter('parse_query', 'tsm_convert_id_to_term_in_query');
function tsm_convert_id_to_term_in_query($query) {
global $pagenow;
$post_type = 'artworks'; // change to your post type
$taxonomy = 'artists'; // change to your taxonomy
$q_vars = &$query->query_vars;
if ( $pagenow == 'edit.php' && isset($q_vars['post_type']) && $q_vars['post_type'] == $post_type && isset($q_vars[$taxonomy]) && is_numeric($q_vars[$taxonomy]) && $q_vars[$taxonomy] != 0 ) {
$term = get_term_by('id', $q_vars[$taxonomy], $taxonomy);
$q_vars[$taxonomy] = $term->slug;
}
}
Enable links in Excerpts - no word limit
By default WordPress strips all HTML options in Excerpts. With this code links are still shown and excerpt is shown in full, without word limit
functions.php
/************************************************************
* @description Enable links in Excerpts - no word limit
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function keep_my_links($text) {
global $post;
if ( '' == $text ) {
$text = get_the_content('');
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$text = preg_replace('@<script[^>]*?>.*?</script>@si', '', $text);
$text = strip_tags($text, '<a>');
}
return $text;
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'keep_my_links');
Redirect alias domain to subfolder
Redirect alias domain to subfolder while preserving alias url in browser
.htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?aliasdomain\.com$ [NC]
RewriteRule ^(.*)$ /subfolderofprimarydomain/$1 [L]
Maintenance HTML Page
A simple HTML page for when a website is in maintenance. The page doesn't need any other files.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Under Maintenance</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
@charset "UTF-8";
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: #f9f9f9;
overflow: hidden;
}
.crazy-cat {
display: flex;
position: relative;
width: 100%;
height: 100%;
z-index: 1;
}
.wrapper {
display: flex;
justify-content: center;
align-items: center;
}
.message {
width: 50%;
padding: 25px;
}
.message h1 {
font-size: 56px;
color: #5f5f5f;
font-family: "Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, AppleGothic, sans-serif;
font-weight: 100;
margin: 40px 0;
}
.message p {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 20px;
color: #808080;
margin: 40px 0;
line-height: 28px;
}
.message a {
display: inline-block;
background: #c7c7c7;
color: #696969;
text-align: center;
padding: 20px 40px;
font-size: 20px;
text-decoration: none;
border-radius: 6px;
transition: 0.3s;
}
.message a:hover {
background: #333;
color: #ccc;
}
.gear {
content: "";
font-family: "FontAwesome";
position: absolute;
animation: gear 50s infinite linear;
transform-origin: center;
top: -250px;
right: -250px;
font-size: 600px;
z-index: 0;
color: #eaeaea;
}
@keyframes gear {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@media (max-width: 760px) {
.message h1 {
font-size: 36px;
}
}
</style>
</head>
<body>
<div class="crazy-cat">
<div class="wrapper">
<div class="message">
<h1>Under Maintenance</h1>
<p>We are currently performing crucial migration work on our website. As a result, the site will be temporarily
unavailable. This also means that all transactions, including payments, are suspended until further notice.</p>
<a href="mailto:email@example.com">Contact us</a>
</div>
</div>
</div>
<div class="gear">
<i class="fa fa-cog" aria-hidden="true"></i>
</div>
</body>
</html>
Font sizes H1-H6
Default font sizes in px and em
style.css
H1 = 48px = 3em
H2 = 36px = 2.25em
H3 = 24px = 1.5em
H4 = 20px = 1.25em
H5 = 16px = 1em
H6 = 13px = 0.75em
Hide other shipping methods when “Free Shipping” is available
functions.php
/************************************************************
* @description Hide other shipping methods when “Free Shipping” is available
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
Remove comments section
Remove possibility to leave comments and reduce spam
functions.php
/************************************************************
* @description Remove comments section
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action('admin_init', function () {
// Redirect any user trying to access comments page
global $pagenow;
if ($pagenow === 'edit-comments.php') {
wp_safe_redirect(admin_url());
exit;
}
// Remove comments metabox from dashboard
remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal');
// Disable support for comments and trackbacks in post types
foreach (get_post_types() as $post_type) {
if (post_type_supports($post_type, 'comments')) {
remove_post_type_support($post_type, 'comments');
remove_post_type_support($post_type, 'trackbacks');
}
}
});
// Close comments on the front-end
add_filter('comments_open', '__return_false', 20, 2);
add_filter('pings_open', '__return_false', 20, 2);
// Hide existing comments
add_filter('comments_array', '__return_empty_array', 10, 2);
// Remove comments page in menu
add_action('admin_menu', function () {
remove_menu_page('edit-comments.php');
});
// Remove comments links from admin bar
add_action('admin_bar_menu', function () {
remove_action('admin_bar_menu', 'wp_admin_bar_comments_menu', 60);
}, 0);
Reject all malicious URL request
Reject all malicious URL request to enhance security
functions.php
/************************************************************
* @description Reject all malicious URL request
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
global $user_ID; if($user_ID) {
if(!current_user_can('administrator')) {
if (strlen($_SERVER['REQUEST_URI']) > 255 ||
stripos($_SERVER['REQUEST_URI'], "eval(") ||
stripos($_SERVER['REQUEST_URI'], "CONCAT") ||
stripos($_SERVER['REQUEST_URI'], "UNION+SELECT") ||
stripos($_SERVER['REQUEST_URI'], "base64")) {
@header("HTTP/1.1 414 Request-URI Too Long");
@header("Status: 414 Request-URI Too Long");
@header("Connection: Close");
@exit;
}
}
}
Remove WordPress Version
Remove WordPress Version to enhance security
functions.php
/************************************************************
* @description Remove WordPress Version
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
// remove version from head
remove_action('wp_head', 'wp_generator');
// remove version from rss
add_filter('the_generator', '__return_empty_string');
// remove version from scripts and styles
function shapeSpace_remove_version_scripts_styles($src) {
if (strpos($src, 'ver=')) {
$src = remove_query_arg('ver', $src);
}
return $src;
}
add_filter('style_loader_src', 'shapeSpace_remove_version_scripts_styles', 9999);
add_filter('script_loader_src', 'shapeSpace_remove_version_scripts_styles', 9999);
Delete images when deleting products
Normally when you delete a product from WooCommerce the corresponding image isn't deleted. By placing the following code in functions.php the image will be deleted when deleting the product.
functions.php
/************************************************************
* @description Delete images when deleting products
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action( 'before_delete_post', 'delete_product_images', 10, 1 );
function delete_product_images( $post_id )
{
$product = wc_get_product( $post_id );
if ( !$product ) {
return;
}
$featured_image_id = $product->get_image_id();
$image_galleries_id = $product->get_gallery_image_ids();
if( !empty( $featured_image_id ) ) {
wp_delete_post( $featured_image_id );
}
if( !empty( $image_galleries_id ) ) {
foreach( $image_galleries_id as $single_image_id ) {
wp_delete_post( $single_image_id );
}
}
}
Access WordPress based on IP
Only allow access to WordPress only for specific IP's. Place code in .htaccess file
.htaccess
#####################################
#Only allow access to WordPress only for specific IP's.
#####################################
order deny,allow
deny from all
# IP address [name of location]
allow from [IP-here]
Year shortcode
Create a shortcode to show the current year, For use in the footer for example. Use [year] as shortcode.
functions.php
/************************************************************
* @description Year shortcode
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
function year_shortcode() {
$year = date('Y');
return $year;
}
add_shortcode('year', 'year_shortcode');
Keyboard control for slider
Make it possible to control a slider with the arrow keys on your keyboard.
script.js
/**
* @snippet Make it possible to control a slider with the arrow keys on your keyboard.
* @author Systemedic
* @URL https://systemedic.nl
jQuery(function() {
jQuery(document).keydown(function(eventObject) {
if(eventObject.which==37) { //left arrow
jQuery('.xxxx').click(); //Emulates click on prev button. Replace .xxxx with css class of prev arrow
} else if(eventObject.which==39) { //right arrow
jQuery('.xxxx').click(); //Emulates click on prev button. Replace .xxxx with css class of next arrow
}
});
});
WooCommerce Catalog mode for guest
Removes add to cart button and add a read more button for products instead of add to cart. Only for guest.
functions.php
/************************************************************
* @description WooCommerce Catalog mode for guest
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
add_action( 'init', 'systemedic_hide_price_add_cart_not_logged_in' );
function systemedic_hide_price_add_cart_not_logged_in() {
if ( ! is_user_logged_in() ) {
add_filter( 'woocommerce_is_purchasable', '__return_false');
add_action( 'woocommerce_single_product_summary', 'systemedic_print_login_to_see', 31 );
add_action( 'woocommerce_after_shop_loop_item', 'systemedic_print_login_to_see', 11 );
add_action( 'woocommerce_simple_add_to_cart', 'systemedic_print_login_to_see', 30 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
}
}
function systemedic_print_login_to_see() {
echo '<a href="' . get_permalink(wc_get_page_id('myaccount')) . '" rel="nofollow ugc">' . __('Login or register to see prices', 'theme_name') . '</a>';
}
Zipper - Archive Directory
Simple script to zip all files in a directory and include the DB file in case of Wordpress/Joomla installation.
zipper.php
<?php
/************************************************************
* @description Zipper - Archive Directory
* @author Systemedic
* @URL https://systemedic.nl
************************************************************/
/**
* @version 0.0.1
* @package Zipper.php
* @copyright Copyright (C) 2021 Zoran Tanevski. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @author Zoran Tanevski <zoran@tanevski.com> - http://tanevski.com
*/
if ( version_compare( PHP_VERSION, '5.6.0', '<' ) ) {
die('You cannot run this script on this version of PHP! Minimum version is: 5.6.0');
}
@ini_set('max_execution_time', 0);
@ini_set('max_input_time', -1);
@set_time_limit(0);
session_start();
/* ... [Full Zipper Script Content] ... */
/* Note: The full script content from your JSON is too large to display here entirely,
but in the real file you should paste the complete content of the Zipper script here.
I have included the header to indicate where it goes. */