summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class-draggable-post-order.php175
-rw-r--r--src/index.js49
-rw-r--r--src/index.scss23
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;
+ }
+ }
+}