Enable Gutenberg only for Pages

Here’s a quick way to enable Gutenberg only for pages and keep using the “Classic Editor” on other post types:

add_filter( 'gutenberg_can_edit_post_type', function ( $can_edit, $post_type ) {
    $can_edit = $post_type === 'page';

    return $can_edit;
}, 99, 2 );

Enqueue scripts & styles responsibly

So you have a fancy plugin that’s doing something awesome on a WordPress admin page. The plugin needs some CSS and/or JS to work so you enqueue them in the admin_enqueue_scripts hook. All good™. Hmm, not really. What you did is correct, but not very responsible. The fact is, I rarely see plugins that do their stuff on all admin pages, so why enqueue the scripts and/or styles everywhere?

Here’s a simple trick to make a plugin enqueue its scripts & styles only on certain admin pages.

Let’s say we have a plugin that enhances the new and edit post screens:

/**
 * Enqueue admin script on new and edit post screens.
 */
function myplugin_enqueue_admin_scripts() {
	wp_enqueue_script(
		'myplugin-admin-script',
		plugin_dir_url( __FILE__ ) . 'script.js',
		array( 'jquery' ),
		'0.1.0',
		true
	);
}

add_action( 'load-post.php', 'myplugin_enqueue_admin_scripts' );
add_action( 'load-post-new.php', 'myplugin_enqueue_admin_scripts' );

Notice that we’re not using the admin_enqueue_scripts hook? That’s the trick! Instead, we’re using the load-(page) hook so that our script will only load on those pages.

Further Reading

Get menu items as multidimensional array

There are times when we need to get menu items as a big multidimensional array so we can do some processing before finally displaying them. We can’t simply use wp_get_nav_menu_items() because it returns a flat array. The solution for this is pretty simple: use a custom walker.

/**
 * Nav menu walker
 */
class Bridge_Walker_Nav_Menu extends Walker_Nav_Menu {

	/**
	 * Prepare item
	 *
	 * @param  object $item  Menu Item.
	 * @param  array  $args  Arguments passed to walk().
	 * @param  int    $depth Item's depth.
	 * @return array
	 */
	protected function prepare_item( $item, $args, $depth ) {
		$title   = apply_filters( 'the_title', $item->title, $item->ID );
		$title   = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
		$classes = apply_filters( 'nav_menu_css_class', array_filter( $item->classes ), $item, $args, $depth );

		return array(
			'id'          => absint( $item->ID ),
			'order'       => (int) $item->menu_order,
			'parent'      => absint( $item->menu_item_parent ),
			'title'       => $title,
			'url'         => $item->url,
			'attr'        => $item->attr_title,
			'target'      => $item->target,
			'classes'     => $classes,
			'xfn'         => $item->xfn,
			'description' => $item->description,
			'object_id'   => absint( $item->object_id ),
			'object'      => $item->object,
			'type'        => $item->type,
			'type_label'  => $item->type_label,
			'children'    => array(),
		);
	}


	/**
	 * Traverse elements to create list from elements.
	 *
	 * This method should not be called directly, use the walk() method instead.
	 *
	 * @param object $element           Data object.
	 * @param array  $children_elements List of elements to continue traversing.
	 * @param int    $max_depth         Max depth to traverse.
	 * @param int    $depth             Depth of current element.
	 * @param array  $args              An array of arguments.
	 * @param array  $output            Passed by reference. Used to append additional content.
	 */
	public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
		if ( ! $element ) {
			return;
		}

		if ( ! is_array( $output ) ) {
			$output = array();
		}

		$id_field = $this->db_fields['id'];
		$id       = $element->$id_field;
		$item     = $this->prepare_item( $element, $args, $depth );

		if ( ! empty( $children_elements[ $id ] ) ) {
			foreach ( $children_elements[ $id ] as $child ) {
				$this->display_element(
					$child,
					$children_elements,
					1,
					( $depth + 1 ),
					$args,
					$item['children']
				);
			}

			unset( $children_elements[ $id ] );
		}

		$output[] = $item;
	}
}

Example Usage:

$menu_id   = 2;
$max_depth = 0; // All level.
$walker    = new Bridge_Walker_Nav_Menu;
$items     = $walker->walk( wp_get_nav_menu_items( $menu_id ), $max_depth );

Conditionally disable Jetpack’s Infinite Scroll

So you implemented Jetpack’s Infinite Scroll feature in your theme, but you don’t want it in a particular page, say a category archive page. Here’s the code you need to add to your theme’s functions.php file:

/**
 * Disable Jetpack's Infinite Scroll Conditionally
 *
 */
function _kucrut_disable_jetpack_infinite_scroll_conditionally() {
	if ( true === my_conditionals() ) {
		remove_theme_support( 'infinite-scroll' );
	}
}
add_action( 'template_redirect', '_kucrut_disable_jetpack_infinite_scroll_conditionally', 9 );

Just remember to change my_conditionals() with your actual conditionals and to never add the action callback after priority 9, otherwise it will be too late 😉