diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a4edf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.project diff --git a/.project b/.project new file mode 100644 index 0000000..96e8a1d --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + post-types-order + + + + + + + + diff --git a/css/cpt-archive-dd.css b/css/cpt-archive-dd.css new file mode 100644 index 0000000..ccf2daf --- /dev/null +++ b/css/cpt-archive-dd.css @@ -0,0 +1,3 @@ +#the-list.ui-sortable tr:hover { cursor: move;} +#the-list.ui-sortable tr.alternate { background-color: #F9F9F9; } +#the-list.ui-sortable tr.ui-sortable-helper { background-color: #ffffff; outline: 1px solid #dfdfdf;} \ No newline at end of file diff --git a/css/cpt.css b/css/cpt.css index b3b3c45..840921c 100644 --- a/css/cpt.css +++ b/css/cpt.css @@ -1,25 +1,26 @@ #order-post-type #sortable { list-style-type: none; margin: 10px 0 0; padding: 0; width: 100%; } #order-post-type #sortable ul { margin-left:20px; list-style: none; } -#order-post-type #sortable li { padding: 2px 0px; margin: 4px 0px; border: 1px solid #DDDDDD; cursor: move; -moz-border-radius:6px; background-color: #f9f9f9;} +#order-post-type #sortable li { padding: 7px 10px; margin: 4px 0px; border: 1px solid #DDDDDD; cursor: move; -moz-border-radius:6px; background-color: #f9f9f9;} #order-post-type #sortable li:nth-child(2n+1) { background-color: #fff !important;} -#order-post-type #sortable li span { display: block; padding: 5px 10px; color:#555; font-size:13px;} -#order-post-type #sortable li.placeholder{border: dashed 2px #ccc;height:25px; background-color: #FFF;} +#order-post-type #sortable li span { display: block; color:#555; font-size:13px;} +#order-post-type #sortable li.placeholder{border: dashed 2px #ccc;height:18px; background-color: #FFF;} #icon-settings {background-image:url("../images/admin-icon-settings.gif");background-repeat:no-repeat;} -h2.subtitle {font-size: 15px; font-style: italic; font-weight: bold} +#cpto h2.subtitle {font-size: 15px; font-style: italic; font-weight: bold; padding-left: 0px} .wrap .example { color: #666666; font-size: 11px; font-weight: bold} -#cpt_info_box {padding: 0 10px; border: 1px dashed #6aadcc; background-color: #FFF; margin-top: 10px; +#cpto #cpt_info_box {padding: 0 10px; border: 1px dashed #6aadcc; background-color: #FFF; margin-top: 10px; -webkit-box-shadow: 1px 1px 7px rgba(50, 50, 50, 0.17); -moz-box-shadow: 1px 1px 7px rgba(50, 50, 50, 0.17); box-shadow: 1px 1px 7px rgba(50, 50, 50, 0.17);} -#cpt_info_box p {font-size: 12px} -#cpt_info_box a {text-decoration: none} -#cpt_info_box #donate_form {float: right; padding: 10px 0 17px; text-align: center; width: 100%;} +#cpto #cpt_info_box a {text-decoration: none} +#cpto #p_socialize {padding: 20px 0px 20px 0} +#cpto #cpt_info_box #donate_form { padding: 20px 0 17px; text-align: center; width: 100%;} .menu_pto {margin-right: 4px; display: inline; vertical-align: middle; margin-top: -1px;} -#p_right {float: right; width: 210px; background-color:#f5f5f5; border-left: 1px dashed #dedede; border-right: 1px dashed #dedede} -.p_s_item {float: right; padding: 0px 5px; margin-top: 15px; margin-bottom: 5px; } -.p_s_item.s_gp {padding-top: 2px; margin-left: 5px} +#cpto #p_right {float: right; width: 230px; background-color:#f5f5f5; border-left: 1px dashed #dedede; border-right: 1px dashed #dedede; margin-left: 10px; text-align: center;} +#cpto .p_s_item {float: none; padding: 0px 5px; margin: 0px; display: inline-block; vertical-align: middle;} +#cpto .p_s_item > iframe, #cpto .p_s_item > div {display: block} +#cpto .p_s_item.s_gp {padding-top: 0px; margin-left: 0px} .clear {clear: both} \ No newline at end of file diff --git a/include/class.cpto.php b/include/class.cpto.php new file mode 100644 index 0000000..0b979e8 --- /dev/null +++ b/include/class.cpto.php @@ -0,0 +1,599 @@ +functions = new CptoFunctions(); + + $is_configured = get_option('CPT_configured'); + if ($is_configured == '') + add_action( 'admin_notices', array($this, 'admin_configure_notices')); + + + add_filter('init', array($this, 'on_init')); + + + add_filter('pre_get_posts', array($this, 'pre_get_posts')); + add_filter('posts_orderby', array($this, 'posts_orderby'), 99, 2); + + + } + + + function init() + { + + include_once(CPTPATH . '/include/class.walkers.php'); + + add_action( 'admin_init', array(&$this, 'registerFiles'), 11 ); + add_action( 'admin_init', array(&$this, 'checkPost'), 10 ); + add_action( 'admin_menu', array(&$this, 'addMenu') ); + + add_action('admin_menu', array(&$this, 'plugin_options_menu')); + + //load archive drag&drop sorting dependencies + add_action( 'admin_enqueue_scripts', array(&$this, 'archiveDragDrop'), 10 ); + + add_action( 'wp_ajax_update-custom-type-order', array(&$this, 'saveAjaxOrder') ); + add_action( 'wp_ajax_update-custom-type-order-archive', array(&$this, 'saveArchiveAjaxOrder') ); + + + } + + + /** + * On WordPress Init hook + * This is being used to set the navigational links + * + */ + function on_init() + { + + if(is_admin()) + return; + + + //check the navigation_sort_apply option + $options = $this->functions->get_options(); + + $navigation_sort_apply = ($options['navigation_sort_apply'] == "1") ? TRUE : FALSE; + $navigation_sort_apply = apply_filters('cpto/navigation_sort_apply', $navigation_sort_apply); + + if( ! $navigation_sort_apply) + return; + + add_filter('get_previous_post_where', array($this->functions, 'cpto_get_previous_post_where'), 99, 3); + add_filter('get_previous_post_sort', array($this->functions, 'cpto_get_previous_post_sort') ); + add_filter('get_next_post_where', array($this->functions, 'cpto_get_next_post_where'), 99, 3); + add_filter('get_next_post_sort', array($this->functions, 'cpto_get_next_post_sort') ); + + } + + + + function pre_get_posts($query) + { + + //no need if it's admin interface + if (is_admin()) + return $query; + + //check for ignore_custom_sort + if (isset($query->query_vars['ignore_custom_sort']) && $query->query_vars['ignore_custom_sort'] === TRUE) + return $query; + + //ignore if "nav_menu_item" + if(isset($query->query_vars) && isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == "nav_menu_item") + return $query; + + $options = $this->functions->get_options(); + + //if auto sort + if ($options['autosort'] == "1") + { + //remove the supresed filters; + if (isset($query->query['suppress_filters'])) + $query->query['suppress_filters'] = FALSE; + + + if (isset($query->query_vars['suppress_filters'])) + $query->query_vars['suppress_filters'] = FALSE; + + } + + return $query; + } + + + + function posts_orderby($orderBy, $query) + { + global $wpdb; + + $options = $this->functions->get_options(); + + //check for ignore_custom_sort + if (isset($query->query_vars['ignore_custom_sort']) && $query->query_vars['ignore_custom_sort'] === TRUE) + return $orderBy; + + //ignore the bbpress + if (isset($query->query_vars['post_type']) && ((is_array($query->query_vars['post_type']) && in_array("reply", $query->query_vars['post_type'])) || ($query->query_vars['post_type'] == "reply"))) + return $orderBy; + if (isset($query->query_vars['post_type']) && ((is_array($query->query_vars['post_type']) && in_array("topic", $query->query_vars['post_type'])) || ($query->query_vars['post_type'] == "topic"))) + return $orderBy; + + //check for orderby GET paramether in which case return default data + if (isset($_GET['orderby']) && $_GET['orderby'] != 'menu_order') + return $orderBy; + + //check to ignore + /** + * Deprecated filter + * do not rely on this anymore + */ + if(apply_filters('pto/posts_orderby', $orderBy, $query) === FALSE) + return $orderBy; + + $ignore = apply_filters('pto/posts_orderby/ignore', FALSE, $orderBy, $query); + if($ignore === TRUE) + return $orderBy; + + if (is_admin()) + { + + if ( $options['adminsort'] == "1" || (defined('DOING_AJAX') && isset($_REQUEST['action']) && $_REQUEST['action'] == 'query-attachments') ) + { + + global $post; + + //temporary ignore ACF group and admin ajax calls, should be fixed within ACF plugin sometime later + if (is_object($post) && $post->post_type == "acf-field-group" + || (defined('DOING_AJAX') && isset($_REQUEST['action']) && strpos($_REQUEST['action'], 'acf/') === 0)) + return $orderBy; + + if(isset($_POST['query']) && isset($_POST['query']['post__in']) && is_array($_POST['query']['post__in']) && count($_POST['query']['post__in']) > 0) + return $orderBy; + + $orderBy = "{$wpdb->posts}.menu_order, {$wpdb->posts}.post_date DESC"; + } + } + else + { + //ignore search + if($query->is_search()) + return($orderBy); + + if ($options['autosort'] == "1") + { + if(trim($orderBy) == '') + $orderBy = "{$wpdb->posts}.menu_order "; + else + $orderBy = "{$wpdb->posts}.menu_order, " . $orderBy; + } + } + + return($orderBy); + } + + + + /** + * Show not configured notive + * + */ + function admin_configure_notices() + { + if (isset($_POST['form_submit'])) + return; + + ?> +
+

+
+ check_options_update(); + + add_options_page('Post Types Order', 'Post Types Order', 'manage_options', 'cpto-options', array($options_interface, 'plugin_options_interface')); + + } + + + + /** + * Load archive drag&drop sorting dependencies + * + * Since version 1.8.8 + */ + function archiveDragDrop() + { + $options = $this->functions->get_options(); + + //if functionality turned off, continue + if( $options['archive_drag_drop'] != '1') + return; + + //if adminsort turned off no need to continue + if( $options['adminsort'] != '1') + return; + + $screen = get_current_screen(); + + //check if the right interface + if(!isset($screen->post_type) || empty($screen->post_type)) + return; + + //check if post type is sortable + if(isset($options['show_reorder_interfaces'][$screen->post_type]) && $options['show_reorder_interfaces'][$screen->post_type] != 'show') + return; + + //if is taxonomy term filter return + if(is_category() || is_tax()) + return; + + //return if use orderby columns + if (isset($_GET['orderby']) && $_GET['orderby'] != 'menu_order') + return false; + + //return if post status filtering + if (isset($_GET['post_status'])) + return false; + + //return if post author filtering + if (isset($_GET['author'])) + return false; + + //load required dependencies + wp_enqueue_style('cpt-archive-dd', CPTURL . '/css/cpt-archive-dd.css'); + + wp_enqueue_script('jquery'); + wp_enqueue_script('jquery-ui-sortable'); + wp_register_script('cpto', CPTURL . '/js/cpt.js', array('jquery')); + + global $userdata; + + // Localize the script with new data + $CPTO_variables = array( + 'archive_sort_nonce' => wp_create_nonce( 'CPTO_archive_sort_nonce_' . $userdata->ID) + ); + wp_localize_script( 'cpto', 'CPTO', $CPTO_variables ); + + // Enqueued script with localized data. + wp_enqueue_script( 'cpto' ); + + } + + function registerFiles() + { + if ( $this->current_post_type != null ) + { + wp_enqueue_script('jQuery'); + wp_enqueue_script('jquery-ui-sortable'); + } + + wp_register_style('CPTStyleSheets', CPTURL . '/css/cpt.css'); + wp_enqueue_style( 'CPTStyleSheets'); + } + + function checkPost() + { + if ( isset($_GET['page']) && substr($_GET['page'], 0, 17) == 'order-post-types-' ) + { + $this->current_post_type = get_post_type_object(str_replace( 'order-post-types-', '', $_GET['page'] )); + if ( $this->current_post_type == null) + { + wp_die('Invalid post type'); + } + } + } + + + /** + * Save the order set through separate interface + * + */ + function saveAjaxOrder() + { + + set_time_limit(600); + + global $wpdb; + + $nonce = $_POST['interface_sort_nonce']; + + //verify the nonce + if (! wp_verify_nonce( $nonce, 'interface_sort_nonce') ) + die(); + + parse_str($_POST['order'], $data); + + if (is_array($data)) + foreach($data as $key => $values ) + { + if ( $key == 'item' ) + { + foreach( $values as $position => $id ) + { + + //sanitize + $id = (int)$id; + + $data = array('menu_order' => $position); + $data = apply_filters('post-types-order_save-ajax-order', $data, $key, $id); + + $wpdb->update( $wpdb->posts, $data, array('ID' => $id) ); + } + } + else + { + foreach( $values as $position => $id ) + { + + //sanitize + $id = (int)$id; + + $data = array('menu_order' => $position, 'post_parent' => str_replace('item_', '', $key)); + $data = apply_filters('post-types-order_save-ajax-order', $data, $key, $id); + + $wpdb->update( $wpdb->posts, $data, array('ID' => $id) ); + } + } + } + } + + + /** + * Save the order set throgh the Archive + * + */ + function saveArchiveAjaxOrder() + { + + set_time_limit(600); + + global $wpdb, $userdata; + + $post_type = filter_var ( $_POST['post_type'], FILTER_SANITIZE_STRING); + $paged = filter_var ( $_POST['paged'], FILTER_SANITIZE_NUMBER_INT); + $nonce = $_POST['archive_sort_nonce']; + + //verify the nonce + if (! wp_verify_nonce( $nonce, 'CPTO_archive_sort_nonce_' . $userdata->ID ) ) + die(); + + parse_str($_POST['order'], $data); + + if (!is_array($data) || count($data) < 1) + die(); + + //retrieve a list of all objects + $mysql_query = $wpdb->prepare("SELECT ID FROM ". $wpdb->posts ." + WHERE post_type = %s AND post_status IN ('publish', 'pending', 'draft', 'private', 'future') + ORDER BY menu_order, post_date DESC", $post_type); + $results = $wpdb->get_results($mysql_query); + + if (!is_array($results) || count($results) < 1) + die(); + + //create the list of ID's + $objects_ids = array(); + foreach($results as $result) + { + $objects_ids[] = (int)$result->ID; + } + + global $userdata; + $objects_per_page = get_user_meta($userdata->ID ,'edit_' . $post_type .'_per_page', TRUE); + if(empty($objects_per_page)) + $objects_per_page = 20; + + $edit_start_at = $paged * $objects_per_page - $objects_per_page; + $index = 0; + for($i = $edit_start_at; $i < ($edit_start_at + $objects_per_page); $i++) + { + if(!isset($objects_ids[$i])) + break; + + $objects_ids[$i] = (int)$data['post'][$index]; + $index++; + } + + //update the menu_order within database + foreach( $objects_ids as $menu_order => $id ) + { + $data = array( + 'menu_order' => $menu_order + ); + $data = apply_filters('post-types-order_save-ajax-order', $data, $menu_order, $id); + + $wpdb->update( $wpdb->posts, $data, array('ID' => $id) ); + } + + } + + + function addMenu() + { + global $userdata; + //put a menu for all custom_type + $post_types = get_post_types(); + + $options = $this->functions->get_options(); + //get the required user capability + $capability = ''; + if(isset($options['capability']) && !empty($options['capability'])) + { + $capability = $options['capability']; + } + else if (is_numeric($options['level'])) + { + $capability = $this->functions->userdata_get_user_level(); + } + else + { + $capability = 'install_plugins'; + } + + foreach( $post_types as $post_type_name ) + { + if ($post_type_name == 'page') + continue; + + //ignore bbpress + if ($post_type_name == 'reply' || $post_type_name == 'topic') + continue; + + if(is_post_type_hierarchical($post_type_name)) + continue; + + $post_type_data = get_post_type_object( $post_type_name ); + if($post_type_data->show_ui === FALSE) + continue; + + if(isset($options['show_reorder_interfaces'][$post_type_name]) && $options['show_reorder_interfaces'][$post_type_name] != 'show') + continue; + + if ($post_type_name == 'post') + add_submenu_page('edit.php', __('Re-Order', 'post-types-order'), __('Re-Order', 'post-types-order'), $capability, 'order-post-types-'.$post_type_name, array(&$this, 'SortPage') ); + elseif ($post_type_name == 'attachment') + add_submenu_page('upload.php', __('Re-Order', 'post-types-order'), __('Re-Order', 'post-types-order'), $capability, 'order-post-types-'.$post_type_name, array(&$this, 'SortPage') ); + else + { + add_submenu_page('edit.php?post_type='.$post_type_name, __('Re-Order', 'post-types-order'), __('Re-Order', 'post-types-order'), $capability, 'order-post-types-'.$post_type_name, array(&$this, 'SortPage') ); + } + } + } + + + function SortPage() + { + ?> +
+

+

current_post_type->labels->singular_name . ' - '. __('Re-Order', 'post-types-order') ?>

+ + functions->cpt_info_box(); ?> + +
+ + + +
+ + +
+
+ +

+ +

+ + + + + +
+ -1, + 'date_format' => get_option('date_format'), + 'child_of' => 0, + 'sort_column' => 'menu_order', + 'post_status' => 'any' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + $output = ''; + + $r['exclude'] = implode( ',', apply_filters('wp_list_pages_excludes', array()) ); + + // Query pages. + $r['hierarchical'] = 0; + $args = array( + 'sort_column' => 'menu_order', + 'post_type' => $post_type, + 'posts_per_page' => -1, + 'post_status' => 'any', + 'orderby' => array( + 'menu_order' => 'ASC', + 'post_date' => 'DESC' + ) + ); + + $the_query = new WP_Query($args); + $pages = $the_query->posts; + + if ( !empty($pages) ) + { + $output .= $this->walkTree($pages, $r['depth'], $r); + } + + $output = apply_filters('wp_list_pages', $output, $r); + + echo $output; + } + + function walkTree($pages, $depth, $r) + { + $walker = new Post_Types_Order_Walker; + + $args = array($pages, $depth, $r); + return call_user_func_array(array(&$walker, 'walk'), $args); + } + } + + + + +?> \ No newline at end of file diff --git a/include/class.functions.php b/include/class.functions.php new file mode 100644 index 0000000..cb0b575 --- /dev/null +++ b/include/class.functions.php @@ -0,0 +1,279 @@ += 0;$i--) + { + if (current_user_can('level_' . $i) === TRUE) + { + $user_level = $i; + if ($return_as_numeric === FALSE) + $user_level = 'level_'.$i; + break; + } + } + return ($user_level); + } + + + /** + * Retrieve the plugin options + * + */ + function get_options() + { + //make sure the vars are set as default + $options = get_option('cpto_options'); + + $defaults = array ( + 'show_reorder_interfaces' => array(), + 'autosort' => 1, + 'adminsort' => 1, + 'archive_drag_drop' => 1, + 'capability' => 'install_plugins', + 'navigation_sort_apply' => 1, + + ); + $options = wp_parse_args( $options, $defaults ); + + $options = apply_filters('pto/get_options', $options); + + return $options; + } + + + /** + * General messages box + * + */ + function cpt_info_box() + { + ?> +
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+ +
+ + + + +
+
+ +
+
+ +
+ +

http://www.nsp-code.com/.

+

+

Category Order - Taxonomy Terms Order

+

  WP Hide & Security Enhancer .

+ +
+
+ + term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id"; + $_where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); + + if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) + { + // back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and " + if ( false !== strpos( $excluded_terms, ' and ' ) ) + { + _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) ); + $excluded_terms = explode( ' and ', $excluded_terms ); + } + else + { + $excluded_terms = explode( ',', $excluded_terms ); + } + + $excluded_terms = array_map( 'intval', $excluded_terms ); + } + + if ( $in_same_term ) + { + $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) ); + + // Remove any exclusions from the term array to include. + $term_array = array_diff( $term_array, (array) $excluded_terms ); + $term_array = array_map( 'intval', $term_array ); + + $_where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")"; + } + + if ( ! empty( $excluded_terms ) ) { + $_where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( $excluded_terms, ',' ) . ') )'; + } + } + + $current_menu_order = $post->menu_order; + + $query = $wpdb->prepare( "SELECT p.* FROM $wpdb->posts AS p + $_join + WHERE p.post_date < %s AND p.menu_order = %d AND p.post_type = %s AND p.post_status = 'publish' $_where" , $post->post_date, $current_menu_order, $post->post_type); + $results = $wpdb->get_results($query); + + if (count($results) > 0) + { + $where .= $wpdb->prepare( " AND p.menu_order = %d", $current_menu_order ); + } + else + { + $where = str_replace("p.post_date < '". $post->post_date ."'", "p.menu_order > '$current_menu_order'", $where); + } + + return $where; + } + + function cpto_get_previous_post_sort($sort) + { + global $post, $wpdb; + + $sort = 'ORDER BY p.menu_order ASC, p.post_date DESC LIMIT 1'; + + return $sort; + } + + function cpto_get_next_post_where($where, $in_same_term, $excluded_terms) + { + global $post, $wpdb; + + if ( empty( $post ) ) + return $where; + + $taxonomy = 'category'; + if(preg_match('/ tt.taxonomy = \'([^\']+)\'/i',$where, $match)) + $taxonomy = $match[1]; + + $_join = ''; + $_where = ''; + + if ( $in_same_term || ! empty( $excluded_terms ) ) + { + $_join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id"; + $_where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); + + if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) + { + // back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and " + if ( false !== strpos( $excluded_terms, ' and ' ) ) + { + _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) ); + $excluded_terms = explode( ' and ', $excluded_terms ); + } + else + { + $excluded_terms = explode( ',', $excluded_terms ); + } + + $excluded_terms = array_map( 'intval', $excluded_terms ); + } + + if ( $in_same_term ) + { + $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) ); + + // Remove any exclusions from the term array to include. + $term_array = array_diff( $term_array, (array) $excluded_terms ); + $term_array = array_map( 'intval', $term_array ); + + $_where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")"; + } + + if ( ! empty( $excluded_terms ) ) { + $_where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( $excluded_terms, ',' ) . ') )'; + } + } + + $current_menu_order = $post->menu_order; + + //check if there are more posts with lower menu_order + $query = $wpdb->prepare( "SELECT p.* FROM $wpdb->posts AS p + $_join + WHERE p.post_date > %s AND p.menu_order = %d AND p.post_type = %s AND p.post_status = 'publish' $_where", $post->post_date, $current_menu_order, $post->post_type ); + $results = $wpdb->get_results($query); + + if (count($results) > 0) + { + $where .= $wpdb->prepare(" AND p.menu_order = %d", $current_menu_order ); + } + else + { + $where = str_replace("p.post_date > '". $post->post_date ."'", "p.menu_order < '$current_menu_order'", $where); + } + + return $where; + } + + function cpto_get_next_post_sort($sort) + { + global $post, $wpdb; + + $sort = 'ORDER BY p.menu_order DESC, p.post_date ASC LIMIT 1'; + + return $sort; + } + + + + } + +?> \ No newline at end of file diff --git a/include/class.options.php b/include/class.options.php new file mode 100644 index 0000000..a36035c --- /dev/null +++ b/include/class.options.php @@ -0,0 +1,171 @@ +CPTO = $CPTO; + + } + + function check_options_update() + { + + $options = $this->CPTO->functions->get_options(); + + if (isset($_POST['form_submit']) && wp_verify_nonce($_POST['cpto_form_nonce'],'cpto_form_submit')) + { + + $options['show_reorder_interfaces'] = (array) $_POST['show_reorder_interfaces']; + $options['show_reorder_interfaces'] = array_map( 'sanitize_key', $options['show_reorder_interfaces'] ); + + $options['capability'] = sanitize_key($_POST['capability']); + + $options['autosort'] = isset($_POST['autosort']) ? intval($_POST['autosort']) : ''; + $options['adminsort'] = isset($_POST['adminsort']) ? intval($_POST['adminsort']) : ''; + $options['archive_drag_drop'] = isset($_POST['archive_drag_drop']) ? intval($_POST['archive_drag_drop']) : ''; + + $options['navigation_sort_apply'] = isset($_POST['navigation_sort_apply']) ? intval($_POST['navigation_sort_apply']) : ''; + + echo '

' . __('Settings Saved', 'post-types-order') . '

'; + + update_option('cpto_options', $options); + update_option('CPT_configured', 'TRUE'); + + } + + } + + + function plugin_options_interface() + { + $options = $this->CPTO->functions->get_options(); + + ?> +
+
+

+ + CPTO->functions->cpt_info_box(); ?> + +
+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ show_ui === FALSE) + continue; + ?> +


 

+ +
+ +
+

id="autosort" value="1" name="autosort"> No code update is necessarily)", 'post-types-order'); ?>

+

'menu_order' into query parameters", 'post-types-order') ?>. +
+

+ +
+

+ id="adminsort" value="1" name="adminsort"> + .

+
+

+ id="archive_drag_drop" value="1" name="archive_drag_drop"> + .

+
+

+ id="navigation_sort_apply" value="1" name="navigation_sort_apply"> +

+
+ +

+ +

+ + + + + +
+ +
+ \ No newline at end of file diff --git a/include/class.walkers.php b/include/class.walkers.php new file mode 100644 index 0000000..beea323 --- /dev/null +++ b/include/class.walkers.php @@ -0,0 +1,54 @@ + 'post_parent', + 'id' => 'ID' + ); + + + function start_lvl(&$output, $depth = 0, $args = array()) + { + $indent = str_repeat("\t", $depth); + $output .= "\n$indent\n"; + } + + + function start_el(&$output, $page, $depth = 0, $args = array(), $id = 0) + { + if ( $depth ) + $indent = str_repeat("\t", $depth); + else + $indent = ''; + + extract($args, EXTR_SKIP); + + $item_details = apply_filters( 'the_title', $page->post_title, $page->ID ); + $item_details = apply_filters('cpto/interface_itme_data', $item_details, $page); + + $output .= $indent . '
  • '. $item_details .''; + + + + } + + + function end_el(&$output, $page, $depth = 0, $args = array()) + { + $output .= "
  • \n"; + } + + } + + + +?> \ No newline at end of file diff --git a/js/cpt.js b/js/cpt.js new file mode 100644 index 0000000..8d58b11 --- /dev/null +++ b/js/cpt.js @@ -0,0 +1,54 @@ + + + var getUrlParameter = function getUrlParameter(sParam) + { + var sPageURL = decodeURIComponent(window.location.search.substring(1)), + sURLVariables = sPageURL.split('&'), + sParameterName, + i; + + for (i = 0; i < sURLVariables.length; i++) { + sParameterName = sURLVariables[i].split('='); + + if (sParameterName[0] === sParam) { + return sParameterName[1] === undefined ? true : sParameterName[1]; + } + } + }; + + jQuery(document).ready(function() + { + + jQuery('table.posts #the-list').sortable({ + 'items': 'tr', + 'axis': 'y', + 'update' : function(e, ui) { + + var post_type = jQuery('input[name="post_type"]').val(); + var order = jQuery('#the-list').sortable('serialize'); + + var paged = getUrlParameter('paged'); + if(typeof paged === 'undefined') + paged = 1; + + var queryString = { "action": "update-custom-type-order-archive", "post_type" : post_type, "order" : order ,"paged": paged, "archive_sort_nonce" : CPTO.archive_sort_nonce}; + //send the data through ajax + jQuery.ajax({ + type: 'POST', + url: ajaxurl, + data: queryString, + cache: false, + dataType: "html", + success: function(data){ + + }, + error: function(html){ + + } + }); + + } + }); + + + }); diff --git a/post-types-order.php b/post-types-order.php index bd8f35f..d69073b 100644 --- a/post-types-order.php +++ b/post-types-order.php @@ -1,372 +1,79 @@ -ID) && $post->ID < 1) - { return $query; } // Stop running the function if this is a virtual page - //-- - - //no need if it's admin interface - if (is_admin()) - return $query; - - //check for ignore_custom_sort - if (isset($query->query_vars['ignore_custom_sort']) && $query->query_vars['ignore_custom_sort'] === TRUE) - return $query; - - //ignore if "nav_menu_item" - if(isset($query->query_vars) && isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == "nav_menu_item") - return $query; - - $options = cpt_get_options(); - - //if auto sort - if ($options['autosort'] == "1") - { - //remove the supresed filters; - if (isset($query->query['suppress_filters'])) - $query->query['suppress_filters'] = FALSE; - - - if (isset($query->query_vars['suppress_filters'])) - $query->query_vars['suppress_filters'] = FALSE; - - } - - return $query; - } - - add_filter('posts_orderby', 'CPTOrderPosts', 99, 2); - function CPTOrderPosts($orderBy, $query) - { - global $wpdb; - - $options = cpt_get_options(); - - //check for ignore_custom_sort - if (isset($query->query_vars['ignore_custom_sort']) && $query->query_vars['ignore_custom_sort'] === TRUE) - return $orderBy; - - //ignore the bbpress - if (isset($query->query_vars['post_type']) && ((is_array($query->query_vars['post_type']) && in_array("reply", $query->query_vars['post_type'])) || ($query->query_vars['post_type'] == "reply"))) - return $orderBy; - if (isset($query->query_vars['post_type']) && ((is_array($query->query_vars['post_type']) && in_array("topic", $query->query_vars['post_type'])) || ($query->query_vars['post_type'] == "topic"))) - return $orderBy; - - //check for orderby GET paramether in which case return default data - if (isset($_GET['orderby']) && $_GET['orderby'] != 'menu_order') - return $orderBy; - - if (is_admin()) - { - - if ($options['adminsort'] == "1" || - //ignore when ajax Gallery Edit default functionality - (defined('DOING_AJAX') && isset($_REQUEST['action']) && $_REQUEST['action'] == 'query-attachments') - ) - { - - global $post; - - //temporary ignore ACF group and admin ajax calls, should be fixed within ACF plugin sometime later - if (is_object($post) && $post->post_type == "acf-field-group" - || (defined('DOING_AJAX') && isset($_REQUEST['action']) && strpos($_REQUEST['action'], 'acf/') < 1)) - return $orderBy; - - $orderBy = "{$wpdb->posts}.menu_order, {$wpdb->posts}.post_date DESC"; - } - } - else - { - //ignore search - if($query->is_search()) - return($orderBy); - - if ($options['autosort'] == "1") - { - if(trim($orderBy) == '') - $orderBy = "{$wpdb->posts}.menu_order "; - else - $orderBy = "{$wpdb->posts}.menu_order, " . $orderBy; - } - } - - return($orderBy); - } - - $is_configured = get_option('CPT_configured'); - if ($is_configured == '') - add_action( 'admin_notices', 'CPTO_admin_notices'); - - function CPTO_admin_notices() - { - if (isset($_POST['form_submit'])) - return; - ?> -
    -

    -
    - Post Types Order', 'manage_options', 'cpto-options', 'cpt_plugin_options'); - } - - - add_action('wp_loaded', 'initCPTO' ); - function initCPTO() - { - global $custom_post_type_order, $userdata; - - $options = cpt_get_options(); - - if (is_admin()) - { - if(isset($options['capability']) && !empty($options['capability'])) - { - if(current_user_can($options['capability'])) - $custom_post_type_order = new CPTO(); - } - else if (is_numeric($options['level'])) - { - if (userdata_get_user_level(true) >= $options['level']) - $custom_post_type_order = new CPTO(); - } - else - { - $custom_post_type_order = new CPTO(); - } - } - } - - - add_filter('init', 'cpto_setup_theme'); - function cpto_setup_theme() - { - if(is_admin()) - return; - - //check the navigation_sort_apply option - $options = cpt_get_options(); - - $navigation_sort_apply = ($options['navigation_sort_apply'] == "1") ? TRUE : FALSE; - $navigation_sort_apply = apply_filters('cpto/navigation_sort_apply', $navigation_sort_apply); - - if( ! $navigation_sort_apply) - return; - - add_filter('get_previous_post_where', 'cpto_get_previous_post_where', 99, 3); - add_filter('get_previous_post_sort', 'cpto_get_previous_post_sort'); - add_filter('get_next_post_where', 'cpto_get_next_post_where', 99, 3); - add_filter('get_next_post_sort', 'cpto_get_next_post_sort'); - } - - function cpto_get_previous_post_where($where, $in_same_term, $excluded_terms) - { - global $post, $wpdb; - - if ( empty( $post ) ) - return $where; - - //?? WordPress does not pass through this varialbe, so we presume it's category.. - $taxonomy = 'category'; - if(preg_match('/ tt.taxonomy = \'([^\']+)\'/i',$where, $match)) - $taxonomy = $match[1]; - - $_join = ''; - $_where = ''; - - if ( $in_same_term || ! empty( $excluded_terms ) ) - { - $_join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id"; - $_where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); - - if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) - { - // back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and " - if ( false !== strpos( $excluded_terms, ' and ' ) ) - { - _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) ); - $excluded_terms = explode( ' and ', $excluded_terms ); - } - else - { - $excluded_terms = explode( ',', $excluded_terms ); - } - - $excluded_terms = array_map( 'intval', $excluded_terms ); - } - - if ( $in_same_term ) - { - $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) ); - - // Remove any exclusions from the term array to include. - $term_array = array_diff( $term_array, (array) $excluded_terms ); - $term_array = array_map( 'intval', $term_array ); - - $_where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")"; - } - - if ( ! empty( $excluded_terms ) ) { - $_where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( $excluded_terms, ',' ) . ') )'; - } - } - - $current_menu_order = $post->menu_order; - - $query = "SELECT p.* FROM $wpdb->posts AS p - $_join - WHERE p.post_date < '". $post->post_date ."' AND p.menu_order = '".$current_menu_order."' AND p.post_type = '". $post->post_type ."' AND p.post_status = 'publish' $_where"; - $results = $wpdb->get_results($query); - - if (count($results) > 0) - { - $where .= " AND p.menu_order = '".$current_menu_order."'"; - } - else - { - $where = str_replace("p.post_date < '". $post->post_date ."'", "p.menu_order > '$current_menu_order'", $where); - } - - return $where; - } - - function cpto_get_previous_post_sort($sort) - { - global $post, $wpdb; - - $sort = 'ORDER BY p.menu_order ASC, p.post_date DESC LIMIT 1'; - - return $sort; - } - - function cpto_get_next_post_where($where, $in_same_term, $excluded_terms) - { - global $post, $wpdb; - - if ( empty( $post ) ) - return $where; - - $taxonomy = 'category'; - if(preg_match('/ tt.taxonomy = \'([^\']+)\'/i',$where, $match)) - $taxonomy = $match[1]; - - $_join = ''; - $_where = ''; - - if ( $in_same_term || ! empty( $excluded_terms ) ) - { - $_join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id"; - $_where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); - - if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) - { - // back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and " - if ( false !== strpos( $excluded_terms, ' and ' ) ) - { - _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) ); - $excluded_terms = explode( ' and ', $excluded_terms ); - } - else - { - $excluded_terms = explode( ',', $excluded_terms ); - } - - $excluded_terms = array_map( 'intval', $excluded_terms ); - } - - if ( $in_same_term ) - { - $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) ); - - // Remove any exclusions from the term array to include. - $term_array = array_diff( $term_array, (array) $excluded_terms ); - $term_array = array_map( 'intval', $term_array ); - - $_where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")"; - } - - if ( ! empty( $excluded_terms ) ) { - $_where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( $excluded_terms, ',' ) . ') )'; - } - } - - $current_menu_order = $post->menu_order; - - //check if there are more posts with lower menu_order - $query = "SELECT p.* FROM $wpdb->posts AS p - $_join - WHERE p.post_date > '". $post->post_date ."' AND p.menu_order = '".$current_menu_order."' AND p.post_type = '". $post->post_type ."' AND p.post_status = 'publish' $_where"; - $results = $wpdb->get_results($query); - - if (count($results) > 0) - { - $where .= " AND p.menu_order = '".$current_menu_order."'"; - } - else - { - $where = str_replace("p.post_date > '". $post->post_date ."'", "p.menu_order < '$current_menu_order'", $where); - } - - return $where; - } - - function cpto_get_next_post_sort($sort) - { - global $post, $wpdb; - - $sort = 'ORDER BY p.menu_order DESC, p.post_date ASC LIMIT 1'; - - return $sort; - } - - +functions->get_options(); + + if (is_admin()) + { + if(isset($options['capability']) && !empty($options['capability'])) + { + if( current_user_can($options['capability']) ) + $CPTO->init(); + } + else if (is_numeric($options['level'])) + { + if ( $CPTO->functions->userdata_get_user_level(true) >= $options['level'] ) + $CPTO->init(); + } + else + { + $CPTO->init(); + } + } + } + + + ?> \ No newline at end of file diff --git a/readme.txt b/readme.txt index 19f8ec8..210bbb0 100644 --- a/readme.txt +++ b/readme.txt @@ -1,18 +1,22 @@ === Post Types Order === -Contributors: Nsp Code +Contributors: nsp-code, tdgu Donate link: http://www.nsp-code.com/donate.php Tags: post order, posts order, sort, post sort, posts sort, post type order, custom order, admin posts order Requires at least: 2.8 -Tested up to: 4.3.1 -Stable tag: 1.8.5 +Tested up to: 4.7.2 +Stable tag: 1.9.3 +. +License: GPLv2 or later -Post Order and custom Post Type Objects (posts, any custom post types) using a Drag and Drop Sortable JavaScript AJAX interface. +Post Order and custom Post Type Objects (custom post types) using a Drag and Drop Sortable JavaScript AJAX interface or default WordPress dashboard. == Description == -Over 1.200.000 DOWNLOADS and near PERFECT ratting out of 150 REVIEWS.
    -A powerful plugin, Order Posts and Post Types Objects using a Drag and Drop Sortable JavaScript capability. -It allow to reorder the posts for any custom post types you defined, including the default Posts. Also you can have the admin posts interface sorted per your new sort. Post Order has never been easier. +Over 2 MILLIONS DOWNLOADS and near PERFECT rating out of 150 REVIEWS.
    +A powerful plugin, Order Posts and Post Types Objects using a Drag and Drop Sortable JavaScript capability. + +The order can be customized within **default WordPress post type archive list page** or **a separate Re-Order interface** which display all objects. +It allow to reorder the posts for any custom post types you defined, including the default Posts. Also you can display the posts within admin interface sorted per your new sort. Post Order has never been easier. = Usage = This was built considering for everyone to be able to use no matter the WordPress experience, so it's very easy: @@ -22,6 +26,7 @@ This was built considering for everyone to be able to use no matter the WordPres * A new setting page will be created within Settings > Post Types Order, you should check with that, and make a first options save. * Using the AutoSort option as ON you don't need to worry about any code changes, the plugin will do the post order update on fly. * Use the Re-Order interface which appear to every custom post type (non-hierarchical) to change the post order to a new one. +* If prefer sort apply through the code, include 'orderby' =>'menu_order' within custom query arguments, more details at http://www.nsp-code.com/sample-code-on-how-to-apply-the-sort-for-post-types-order-plugin/ = Example of Usage = [youtube http://www.youtube.com/watch?v=VEbNKFSfhCc] @@ -31,7 +36,7 @@ If for some reason the post order does not update on your front side, you either
    Something is wrong with this plugin on your site? Just use the forum or get in touch with us at Contact and we'll check it out. -
    Check out the advanced version of this plugin at Advanced Post Types Order +
    Need More? Check out the advanced version of this plugin at Advanced Post Types Order which include Hierarchically post types order, Manual / Automatic Sorting, Individual Categories Order, Conditionals to apply, Paginations for large list, Mobile ready, Enhanced Interface, Plugins compatibility (MultiSite Network Support, WPML, Polylang, WooCommerce, WP E-Commerce, Platform Pro, Genesis etc), font side re-order interface, ... and many more !!

    This plugin is developed by Nsp-Code @@ -48,13 +53,20 @@ If for some reason the post order does not update on your front side, you either 1. The ReOrder interface through which the sort can be created. +2. Sort can be managed within default WordPress post type interface. + + == Frequently Asked Questions == -Feel free to contact me at electronice_delphi@yahoo.com +Feel free to contact us at electronice_delphi@yahoo.com = I have no PHP knowledge at all, i will still be able to use this plugin? = -Absolutely you can! Unlike many other plugins, you don't have to do any code changes to make your post order to change accordingly to custom defined post order. There is an option to autoupdate the WordPress queries so the posts order will be returned in the required order. Anyway this can be turned off to allow customized code usage. +Absolutely you can! Unlike many other plugins, you don't have to do any code changes to make your post order to change accordingly to custom defined post order. There is an option to autoupdate the WordPress queries so the posts order will be returned in the required order. Anyway this can be turned off (Autosort) to allow customized code usage. + += How to manually apply the sort on queries = + +Include a 'orderby' => 'menu_order' property within your custom query. = What kind of posts/pages this plugin allow me to sort? = @@ -70,11 +82,54 @@ All ideas are welcome and i put them on my list to be implemented into the new v = Can i make certain queries to ignore the custom sort when Autosort is turned On? = -This can be doe by including the ignore_custom_sort within custom query arguments. An example can be found at http://www.nsp-code.com/advanced-post-types-order-api/sample-usage/ +This can be done by including the ignore_custom_sort within custom query arguments. An example can be found at http://www.nsp-code.com/advanced-post-types-order-api/sample-usage/ + += How can i force sort apply for certain queries when Autosort is turned On? = + +A filter can be used to achieve that pto/posts_orderby. An example can be found at http://www.nsp-code.com/ignore-sort-apply-for-certain-query-on-post-types-order/ + += I still need more features like front sorting interface, shortcodes, filters, conditionals, advanced queries, taxonomy/ category sorting etc = + +Consider upgrading to our advanced version of this plugin at a very resonable price Advanced Post Types Order == Change Log == += 1.9.3 = + - Fix for custom post type objects per page when using default archive interface drag & drop sort + - Plugin code redo and re-structure + - Improved compatibility with other plugins + - Security improvments for AJAX order updates + += 1.9 = + - Remove translations from the package + - Remove link for donate + - Wp Hide plugin availability notification + - New Filter pto/get_options to allow to chaneg default options; Custom capability can be set for 'capability' + - New Filter pto/admin/plugin_options/capability to allow custom capability option to be inserted within html + += 1.8.9.2 = + - WPDB Prepare argument fix + - User preferance objects per page set to default if empty + += 1.8.9 = + - Add Nonce for admin settings + - Update queries to use prepare + - Drag & Drop Sortable within Post Type archive interface + - Code cleanup + - Set time limit for ajax calls to attempt a code execution extend + += 1.8.7 = + - Admin Post / Page Gallery items order fix + - New filter pto/posts_orderby to ignore sort apply + += 1.8.6 = + - PHP 7 deprecated nottice fix Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; + - Fix: $_REQUEST['action'] comparison evaluate as Identical instead equal + - New filter cpto/interface_itme_data to append additional data for items within sortable interface + - Slight style updates + - Replaced Socialize FB like page + = 1.8.5 = - Text domain change to post-types-order to allow translations at https://translate.wordpress.org/projects/wp-plugins/post-types-order - New query argument ignore_custom_sort , to be used with Autosort. Ignore any customised sort and return posts in default order. @@ -213,6 +268,5 @@ Make sure you get the latest version. == Localization == -Available in English, Brazilian Portuguese, Spanish, Romanian, Italian, Dusth, Hebrew, German, Norwegian (norsk), Turkish (t?rk?e), Swedish, Hungarian, Portuguese, Chinese, Czech -Want to contribute with a translation to your language? Please contact us at electronice_delphi@yahoo.com +Want to contribute with a translation to your language? Please check at https://translate.wordpress.org/projects/wp-plugins/post-types-order http://www.nsp-code.com diff --git a/screenshot-1.png b/screenshot-1.png index 92f3254..743dbf0 100644 Binary files a/screenshot-1.png and b/screenshot-1.png differ diff --git a/screenshot-2.png b/screenshot-2.png new file mode 100644 index 0000000..d6e3a1d Binary files /dev/null and b/screenshot-2.png differ