diff options
| author | Daniel Weipert <code@drogueronin.de> | 2020-12-21 16:11:17 +0100 | 
|---|---|---|
| committer | Daniel Weipert <code@drogueronin.de> | 2020-12-21 16:11:17 +0100 | 
| commit | 0d1da4356173e926fdcac42462daa4fcb7617109 (patch) | |
| tree | 79535a3dca38b60c1ca93ff351c00e1464b0536b /src | |
Initial commit
Diffstat (limited to 'src')
| -rw-r--r-- | src/class-draggable-post-order.php | 175 | ||||
| -rw-r--r-- | src/index.js | 49 | ||||
| -rw-r--r-- | src/index.scss | 23 | 
3 files changed, 247 insertions, 0 deletions
| diff --git a/src/class-draggable-post-order.php b/src/class-draggable-post-order.php new file mode 100644 index 0000000..ae9b501 --- /dev/null +++ b/src/class-draggable-post-order.php @@ -0,0 +1,175 @@ +<?php +/** + * Entry point class file + * + * @package Draggable_Post_Order + */ + +namespace Draggable_Post_Order; + +/** + * Class DraggablePostOrder + * + * @package Draggable_Post_Order + */ +class Draggable_Post_Order { + +	/** +	 * Initialize. +	 */ +	public static function init() { +		$post_types = get_post_types_by_support( 'draggable-post-order' ); + +		// if there are no post types to order => return. +		if ( empty( $post_types ) ) { +			return; +		} + +		foreach ( $post_types as $post_type ) { +			add_action( "save_post_{$post_type}", [ self::class, 'save_post' ], 10, 2 ); +		} + +		// add meta box. +		add_action( 'add_meta_boxes', [ self::class, 'add_meta_boxes' ] ); + +		// add ajax hook. +		add_action( 'wp_ajax_update-post-order', [ self::class, 'update_post_order' ] ); + +		// load scripts. +		add_action( 'admin_enqueue_scripts', [ self::class, 'enqueue_scripts' ] ); + +		// sort posts by post order. +		add_action( 'pre_get_posts', [ self::class, 'order_posts' ] ); +	} + +	/** +	 * Whether the given post type is allowed to be ordered. +	 * +	 * @param string $post_type The post type to check against. +	 * +	 * @return bool +	 */ +	public static function supports( $post_type = null ) { +		$post_type ??= get_current_screen()->post_type ?? ''; + +		return post_type_supports( $post_type, 'draggable-post-order' ); +	} + +	/** +	 * Callback for "save_post" action. +	 * +	 * @param int      $post_id The post's ID. +	 * @param \WP_Post $post    The post object. +	 */ +	public static function save_post( $post_id, $post ) { +		if ( +			( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || +			! check_admin_referer( 'metaBoxDraggablePostOrder', 'metaBoxDraggablePostOrder' ) || +			( ! isset( $_POST['post_ID'] ) || intval( $_POST['post_ID'] ) !== intval( $post_id ) ) || +			! isset( $_POST['draggable-post-order'] ) +		) { +			return; +		} + +		$post_order = sanitize_text_field( wp_unslash( $_POST['draggable-post-order'] ) ); +		if ( empty( $post_order ) ) { +			$post_order = wp_count_posts( $post->post_type )->publish; +		} + +		update_post_meta( $post_id, 'draggable-post-order', $post_order ); +	} + +	/** +	 * Callback for "add_meta_boxes" action. +	 */ +	public static function add_meta_boxes() { +		if ( ! self::supports() ) { +			return; +		} + +		add_meta_box( 'draggable-post-order', __( 'Post Order', 'draggable-post-order' ), [ self::class, 'add_meta_box' ], '', 'side' ); +	} + +	/** +	 * Callback for "add_meta_box" function. +	 * +	 * @param \WP_Post $post The post object. +	 */ +	public static function add_meta_box( $post ) { +		wp_nonce_field( 'metaBoxDraggablePostOrder', 'metaBoxDraggablePostOrder' ); +		?><input type="number" name="draggable-post-order" value="<?php echo get_post_meta( $post->ID, 'draggable-post-order', true ); ?>"> +		<?php +	} + +	/** +	 * Callback for "wp_ajax" action. +	 */ +	public static function update_post_order() { +		if ( ! isset( $_POST['page'] ) || ! isset( $_POST['perPage'] ) || ! isset( $_POST['postOrder'] ) ) { +			return; +		} + +		$page     = intval( $_POST['page'] ); +		$per_page = intval( $_POST['perPage'] ); +		parse_str( $_POST['postOrder'], $post_order ); + +		foreach ( $post_order['post'] as $order => $post_id ) { +			$order = intval( $order ) + 1; +			update_post_meta( $post_id, 'draggable-post-order', ( ( $page - 1 ) * $per_page ) + $order ); +		} +	} + +	/** +	 * Callback for "admin_enqueue_scripts" action. +	 */ +	public static function enqueue_scripts() { +		$current_screen = get_current_screen(); +		if ( $current_screen->base !== 'edit' || ! self::supports() ) { +			return; +		} + +		list('dependencies' => $dependencies, 'version' => $version) = require draggable_post_order_path() . '/build/index.asset.php'; +		$dependencies[] = 'jquery-ui-sortable'; +		wp_enqueue_script( 'draggable-post-order', draggable_post_order_assets_url( 'index.js' ), $dependencies, $version, true ); +		wp_enqueue_style( 'draggable-post-order', draggable_post_order_assets_url( 'index.css' ), [], $version ); +	} + +	/** +	 * Callback for "pre_get_posts" action. +	 * +	 * @param \WP_Query $query The query object. +	 */ +	public static function order_posts( \WP_Query $query ) { +		$post_type = $query->get( 'post_type' ); +		if ( ! self::supports( $post_type ) ) { +			return; +		} + +		// if no orderby was set previously. +		if ( ! $query->get( 'orderby' ) ) { +			$meta_sub_query = [ +				'relation'                           => 'OR', +				'draggable-post-order-clause'        => [ +					'key'  => 'draggable-post-order', +					'type' => 'NUMERIC', +				], +				// get all posts without the meta as well. +				'draggable-post-order-exists-clause' => [ +					'key'     => 'draggable-post-order', +					'compare' => 'NOT EXISTS', +				], +			]; +			$meta_query   = $query->get( 'meta_query' ) ?: []; +			$meta_query[] = $meta_sub_query; + +			$order   = apply_filters( 'draggable_post_order_order', 'ASC', $post_type, $query ); +			$orderby = [ +				'draggable-post-order-clause'        => $order, +				'draggable-post-order-exists-clause' => $order, +			]; + +			$query->set( 'meta_query', $meta_query ); +			$query->set( 'orderby', $orderby ); +		} +	} +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..eecabf6 --- /dev/null +++ b/src/index.js @@ -0,0 +1,49 @@ +/* global jQuery ajaxurl */ + +import './index.scss'; + +( function ( $ ) { +	const overlay = $( '<div class="post-order-overlay">' ).appendTo( 'body' ); +	$( '#the-list' ).sortable( { +		items: 'tr', +		axis: 'y', +		cursor: 'move', + +		// @see https://stackoverflow.com/a/57611747/6114451 +		start( e, ui ) { +			const $originals = ui.helper.children(); +			ui.placeholder.children().each( function ( index ) { +				$( this ).width( $originals.eq( index ).width() ); +				$( this ).height( $originals.eq( index ).height() ); +			} ); +		}, +		helper( e, tr ) { +			const $helper = tr.clone(); +			const $originals = tr.children(); +			$helper.children().each( function ( index ) { +				$( this ).width( $originals.eq( index ).outerWidth( true ) ); +			} ); +			return $helper; +		}, + +		update() { +			// show overlay +			overlay.addClass( 'post-order-overlay--visible' ); + +			// update posts +			$.post( +				ajaxurl, +				{ +					action: 'update-post-order', +					page: $( '#current-page-selector' ).val(), +					perPage: $( '#edit_post_per_page' ).val(), +					postOrder: $( '#the-list' ).sortable( 'serialize' ), +				}, +				() => { +					// hide overlay after updating +					overlay.removeClass( 'post-order-overlay--visible' ); +				} +			); +		}, +	} ); +} )( jQuery ); diff --git a/src/index.scss b/src/index.scss new file mode 100644 index 0000000..124d799 --- /dev/null +++ b/src/index.scss @@ -0,0 +1,23 @@ +.post-order-overlay { +	position: fixed; +	top: 0; +	left: 0; +	width: 100vw; +	height: 100vh; +	background: rgba(0, 0, 0, 0.8); +	display: none; + +	&--visible { +		display: block; +	} +} + +#the-list { + +	tr { + +		&.ui-sortable-handle { +			cursor: move; +		} +	} +} | 
