Archives: Snippets | Page 11

Allow Inline SVG in WordPress Content Editor

Is inline SVG allowed in WordPress post content by default? Partly. WordPress saves inline <svg> markup only for users with the unfiltered_html capability, and the Classic editor’s Visual tab strips it for everyone.

The steps below are for pasting SVG code (<svg>, <path>, <rect> and so on) straight into the editor. To upload SVG files to the media library instead, see allow SVG file uploads in WordPress.

Allow Inline SVG in the Classic Editor (TinyMCE)

TinyMCE, the editor behind the Classic editor and the Classic block, removes any element that isn’t in its HTML5 schema, and SVG elements aren’t. Add this code to your child theme’s functions.php to stop it:

function override_mce_options( $initArray ) {
    $opts = '*[*]';
    $initArray['valid_elements']          = $opts;
    $initArray['extended_valid_elements'] = $opts;
    return $initArray;
}
add_filter( 'tiny_mce_before_init', 'override_mce_options' );

How It Works

tiny_mce_before_init filters the settings array WordPress passes to TinyMCE before the editor loads. WordPress applies it to the Classic editor and to the Classic block in the block editor.

valid_elements tells TinyMCE which tags and attributes to keep. The value *[*] means any element with any attribute, so SVG markup survives when you switch between the Visual and Text tabs.

Note that *[*] turns off TinyMCE’s element filtering for all tags, not only SVG.

TinyMCE lowercases viewBox to viewbox. That is harmless, because the browser’s HTML parser restores the correct case for inline SVG.

What WordPress Saves: unfiltered_html and KSES

The TinyMCE setting only changes the editor in the browser. What ends up in the database is decided on the server by KSES, WordPress’s HTML filter:

  • Administrators and Editors on a single site have unfiltered_html. Their content isn’t filtered, so inline SVG is saved as written.
  • Authors and Contributors don’t have it. KSES strips <svg>, <path> and the other SVG tags on save, whatever the editor shows.
  • On multisite, only Super Admins have unfiltered_html. Setting DISALLOW_UNFILTERED_HTML to true in wp-config.php removes it from everyone.

In the block editor, the Custom HTML block follows the same rule. You don’t need the TinyMCE filter for it, since that block doesn’t use TinyMCE, but users without unfiltered_html still lose the SVG when the post is saved.

Allow Safe SVG Tags for Authors and Contributors

If users without unfiltered_html need simple inline icons, add the SVG elements and attributes to the KSES allowlist for post content. Anything not listed, such as <script> tags and onload attributes, is still removed:

function savvy_allow_inline_svg( $tags, $context ) {
    if ( 'post' !== $context ) {
        return $tags;
    }

    $tags['svg'] = array(
        'xmlns'       => true,
        'viewbox'     => true,
        'width'       => true,
        'height'      => true,
        'fill'        => true,
        'class'       => true,
        'role'        => true,
        'aria-hidden' => true,
        'aria-label'  => true,
        'focusable'   => true,
    );
    $tags['g']      = array( 'fill' => true, 'stroke' => true, 'transform' => true );
    $tags['title']  = array();
    $tags['path']   = array( 'd' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, 'fill-rule' => true, 'clip-rule' => true, 'transform' => true );
    $tags['circle'] = array( 'cx' => true, 'cy' => true, 'r' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true );
    $tags['rect']   = array( 'x' => true, 'y' => true, 'width' => true, 'height' => true, 'rx' => true, 'ry' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true );

    return $tags;
}
add_filter( 'wp_kses_allowed_html', 'savvy_allow_inline_svg', 10, 2 );

Attribute names go in lowercase (viewbox), because KSES compares them in lowercase. Keep the list short and avoid allowing <use>, <foreignObject>, href or style unless you need them.

FAQs

Common questions about inline SVG in the WordPress editor:

Is inline SVG allowed in WordPress post content by default?
Only for users with the unfiltered_html capability (Administrators and Editors on a single site), and only in the Code editor, Text tab or Custom HTML block. For other roles, WordPress strips the SVG on save.
Why does my SVG disappear when I switch to the Visual tab?
TinyMCE removes elements that aren't in its HTML5 schema, and SVG elements aren't included. Set valid_elements to *[*] with the tiny_mce_before_init filter.
Does the tiny_mce_before_init filter affect the block editor?
Only the Classic block, which still runs TinyMCE. Blocks such as Custom HTML don't use TinyMCE, so the filter has no effect on them.
Is it safe to allow inline SVG for all users?
Not by giving them unfiltered_html, which also lets them add scripts. Allow a short list of SVG tags and attributes through wp_kses_allowed_html instead, so KSES keeps removing scripts and event handlers.

Fix HTTP Error When Uploading Images in WordPress

There are several situations where you may get an HTTP Error when trying to upload images to the WordPress media library:

  • Problematic file name (special characters, etc.).
  • File size exceeds what the server allows (upload_max_size).
  • Insufficient PHP memory on the server.
  • Insufficient storage space on the server.
Getting HTTP Error when uploading images in WordPress?

HTTP error in WordPress media library.

Start by checking the file name and try reducing the file size. To increase memory, add the following code to the wp-config.php file in your site root:

define( 'WP_MEMORY_LIMIT', '256M' );

You can also do this via the .htaccess file, but if your hosting provider blocks this you may get a 500 Internal Server Error, so be careful and do not use this method if that is the case (simply remove the line).

php_value memory_limit 256M

If you have access to the php.ini file, you can do it with:

memory_limit = 256M

In some cases ModSecurity on the server can prevent you from uploading files. You can disable it via cPanel or try the following lines in .htaccess (disable if you get an error). Note that ModSecurity exists for good reason – securing your WordPress site:

<IfModule mod_security.c>SecFilterEngine Off 
SecFilterScanPOST Off 
</IfModule>

Here is a broader post on solving WordPress image upload issues.

WordPress .gitignore File

The .gitignore file tells Git not to track certain files in the project. For WordPress, here is a recommended .gitignore file you can modify for your project. For more on the mu-plugins directory included in the file, see the linked guide.

# -----------------------------------------------------------------
# .gitignore for WordPress
# -----------------------------------------------------------------

# ignore everything in the root except the "wp-content" directory.
/*
!wp-content/

# ignore all files starting with .
.*

# track this file .gitignore (i.e. do NOT ignore it)
!.gitignore

# track .editorconfig file (i.e. do NOT ignore it)
!.editorconfig

# track readme.md in the root (i.e. do NOT ignore it)
!readme.md

# ignore all files that start with ~
~*

# ignore OS generated files
ehthumbs.db
Thumbs.db

# ignore Editor files
*.sublime-project
*.sublime-workspace
*.komodoproject

# ignore log files and databases
*.log
*.sql
*.sqlite

# ignore compiled files
*.com
*.class
*.dll
*.exe
*.o
*.so

# ignore packaged files
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

# ignore everything in the "wp-content" directory, except:
# "mu-plugins" directory
# "plugins" directory
# "themes" directory
wp-content/*
!wp-content/mu-plugins/
!wp-content/plugins/
!wp-content/themes/

# ignore these plugins from the core
wp-content/plugins/hello.php
wp-content/plugins/akismet/

# ignore specific themes
wp-content/themes/twenty*/

# ignore node/grunt dependency directories
node_modules/

Display Product Weight on WooCommerce Archive Pages

To add product weight on WooCommerce archive pages, right below the product title, add the following code to your child theme functions.php file or to a plugin such as Code Snippets that allows adding functions like this.

WooCommerce 3.0+

/**
 * Show product weight on archive pages
 */
add_action( 'woocommerce_after_shop_loop_item', 'savvy_show_weights', 9 );

function savvy_show_weights() {

    global $product;
    $weight = $product->get_weight();

    if ( $product->has_weight() ) {
        echo '<div class="product-meta"><span class="product-meta-label">Weight: </span>' . $weight . get_option('woocommerce_weight_unit') . '</div></br>';
    }
}

Display Product Dimensions on WooCommerce Archive Pages

To add product dimensions on WooCommerce archive pages below the product title, add the following code to your child theme functions.php file or to a plugin such as Code Snippets.

WooCommerce 3.0+

/**
 * Show product dimensions on archive pages for WC 3+
 */
add_action( 'woocommerce_after_shop_loop_item', 'savvy_show_dimensions', 9 );

function savvy_show_dimensions() {
    global $product;
    $dimensions = wc_format_dimensions($product->get_dimensions(false));

        if ( $product->has_dimensions() ) {
                echo '<div class="product-meta"><span class="product-meta-label">Dimensions: </span>' . $dimensions . '</div>';
        }
}

WooCommerce below 3.0


/**
 * Show product dimensions on archive pages WC 3 and below
 */
add_action( 'woocommerce_after_shop_loop_item_title', 'wc_show_dimensions', 9 );

function wc_show_dimensions() {
	global $product;
	$dimensions = $product->get_dimensions();

        if ( ! empty( $dimensions ) ) {
                echo '<span class="dimensions">' . $dimensions . '</span>';
        }
}

Add Content to WooCommerce Product Description

If you want to add content to WooCommerce product descriptions site-wide, use the following code. Add it to your theme’s functions.php file and change the text on line 5 as desired. Note that this code adds the information at the end of the product description content.

function change_woocommerce_description( $content ) {
    // Only for single product pages in woocommerce
    if ( is_product() ) {
        // The custom content to add
        $custom_content = '<p class="custom-content">' . __("This is the last line in the description", "woocommerce").'</p>';
        // Inserting the custom content at the end of the current product description
        $content .= $custom_content;
    }
    return $content;
}
add_filter( 'the_content', 'change_woocommerce_description' );

More on changing and adding fields to WooCommerce products in the post How to add custom fields to the WooCommerce product page.

Auto Add Product to Cart on Visit in WooCommerce

The following code lets you add a product to the cart automatically:

/**
 * Automatically add product to cart on visit
 */
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
	if ( ! is_admin() ) {
		$product_id = 64; //replace with your own product id
		$found = false;
		//check if product already in cart
		if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
			foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
				$_product = $values['data'];
				if ( $_product->get_id() == $product_id )
					$found = true;
			}
			// if product not found, add it
			if ( ! $found )
				WC()->cart->add_to_cart( $product_id );
		} else {
			// if no products in cart, add it
			WC()->cart->add_to_cart( $product_id );
		}
	}
}

If you want to add a product automatically based on cart total, use this code:

/**
 * Add another product depending on the cart total
 */
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
  if ( ! is_admin() ) {
		global $woocommerce;
		$product_id = 2831; //replace with your product id
		$found = false;
		$cart_total = 30; //replace with your cart total needed to add above item

		if( $woocommerce->cart->total >= $cart_total ) {
			//check if product already in cart
			if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
				foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
					$_product = $values['data'];
					if ( $_product->get_id() == $product_id )
						$found = true;
				}
				// if product not found, add it
				if ( ! $found )
					$woocommerce->cart->add_to_cart( $product_id );
			} else {
				// if no products in cart, add it
				$woocommerce->cart->add_to_cart( $product_id );
			}
		}
	}
}

Take a look at the post How to add products to cart via link.

Send Email When Coupon Is Used in WooCommerce Order

The following snippet lets you send an email with the coupon details used in a specific order. You can change the recipient and the message as desired. The code runs when the user who placed the order reaches the WooCommerce Thank You page.

/**
 * Send an email each time an order with coupon(s) is completed
 * The email contains coupon(s) used during checkout process
 *
 */ 
function woo_email_order_coupons( $order_id ) {
        $order = new WC_Order( $order_id );
        
        if( $order->get_used_coupons() ) {
        
          $to = '[email protected]';
	        $subject = 'New Order Completed';
	        $headers = 'From: My Name <[email protected]>' . "rn";
	        
	        $message = 'A new order has been completed.n';
	        $message .= 'Order ID: '.$order_id.'n';
	        $message .= 'Coupons used:n';
	        
	        foreach( $order->get_used_coupons() as $coupon) {
		        $message .= $coupon.'n';
	        }
	        @wp_mail( $to, $subject, $message, $headers );
        }
}
add_action( 'woocommerce_thankyou', 'woo_email_order_coupons' );

Smooth Scroll to ID with jQuery

A short snippet I use often when I need to scroll to a specific element (by ID). Simply change ‘600’ to the speed you want the scroll to run (ms). You can also change the selector a[href*="#"] to whatever selector you choose.

$('a[href*="#"]').on('click', function (e) {
	e.preventDefault();

	$('html, body').animate({
		scrollTop: $($(this).attr('href')).offset().top
	}, 600, 'linear');
});

Nice, right? Check out the demo I created on Codepen. If you run into smooth scrolling issues or frontend scrolling performance problems, take a look at the link above.

Here is also a post on how to create on-scroll animations using the AOS library.

Limit Image Upload Size in WordPress

There are situations where you want to limit content editors from uploading images beyond a certain size. You can even be more specific and allow uploads of a specific pixel size. Add the following code to your functions.php file:

/* 
 * Check image resolution (px) before crunching
 */
function savvy_validate_image_size( $file ) {
    $image = getimagesize($file['tmp_name']);
    $minimum = array(
        'width' => '460',
        'height' => '460'
    );
    $maximum = array(
        'width' => '1280',
        'height' => '1280'
    );
    $image_width = $image[0];
    $image_height = $image[1];

    $too_small = "Image dimensions are too small. Minimum size is {$minimum['width']} by {$minimum['height']} pixels. Uploaded image is $image_width by $image_height pixels.";
    $too_large = "Image dimensions are too large. Maximum size is {$maximum['width']} by {$maximum['height']} pixels. Uploaded image is $image_width by $image_height pixels.";

    if ( $image_width < $minimum['width'] || $image_height < $minimum['height'] ) {
        $file['error'] = $too_small;
        return $file;
    }
    elseif ( $image_width > $maximum['width'] || $image_height > $maximum['height'] ) {
        $file['error'] = $too_large;
        return $file;
    }
    else
        return $file;
}
add_filter('wp_handle_upload_prefilter','savvy_validate_image_size');

You can change the minimum and maximum width and height (pixels) on lines 6-12. Take a look at the broader post on image sizes in WordPress.