Simple Page Ordering - Version 2.3

Version Description

  • Avoid exceeding PHP's max input variables, which could cause incorrectly assigned page order
  • Fix a malformed URL that would take you to posts instead of pages
  • Use WP_Query instead of get_posts() for better performance
  • Use WordPress core's spinner class
  • Add Grunt-based build process with Sass
  • Remove bundled translations in favor of WordPress.org language packs
  • Fix some PHPDoc and coding standards to align with 10up's Engineering Best Practices
Download this release

Release Info

Developer helen
Plugin Icon 128x128 Simple Page Ordering
Version 2.3
Comparing to
See all releases

Code changes from version 2.2.4 to 2.3

assets/css/scss/simple-page-ordering.scss ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wp-list-table {
2
+ .ui-sortable {
3
+ tr {
4
+ cursor: move;
5
+ &.inline-editor {
6
+ cursor: default;
7
+ }
8
+ }
9
+ }
10
+
11
+ .spo-updating {
12
+ tr {
13
+ cursor: default;
14
+ }
15
+ }
16
+
17
+ .ui-sortable-placeholder {
18
+ outline: 1px dashed #bbb;
19
+ background: #F1F1F1;
20
+ visibility: visible !important;
21
+ }
22
+
23
+ .ui-sortable-helper {
24
+ background-color: #fff;
25
+ outline: 1px solid #e1e1e1;
26
+ }
27
+ }
28
+
29
+ .spo-updating-row {
30
+ .check-column {
31
+ display: table-cell; // reset from core .spinner
32
+ float: none; // reset from core .spinner
33
+ margin: 0; // reset from core .spinner
34
+ background-position: 9px 9px;
35
+
36
+ input {
37
+ visibility: hidden;
38
+ }
39
+ }
40
+ }
assets/css/simple-page-ordering.css ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wp-list-table .ui-sortable tr {
2
+ cursor: move; }
3
+ .wp-list-table .ui-sortable tr.inline-editor {
4
+ cursor: default; }
5
+
6
+ .wp-list-table .spo-updating tr {
7
+ cursor: default; }
8
+
9
+ .wp-list-table .ui-sortable-placeholder {
10
+ outline: 1px dashed #bbb;
11
+ background: #F1F1F1;
12
+ visibility: visible !important; }
13
+
14
+ .wp-list-table .ui-sortable-helper {
15
+ background-color: #fff;
16
+ outline: 1px solid #e1e1e1; }
17
+
18
+ .spo-updating-row .check-column {
19
+ display: table-cell;
20
+ float: none;
21
+ margin: 0;
22
+ background-position: 9px 9px; }
23
+ .spo-updating-row .check-column input {
24
+ visibility: hidden; }
25
+
26
+ /*# sourceMappingURL=simple-page-ordering.css.map */
assets/css/simple-page-ordering.css.map ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "version": 3,
3
+ "file": "simple-page-ordering.css",
4
+ "sources": [
5
+ "scss/simple-page-ordering.scss"
6
+ ],
7
+ "names": [],
8
+ "mappings": "AAAA,AAEE,cAFY,CACb,YAAY,CACX,EAAE,CAAC;EACF,MAAM,EAAE,IAAI,GAIZ;EAPH,AAEE,cAFY,CACb,YAAY,CACX,EAAE,AAED,cAAe,CAAC;IACf,MAAM,EAAE,OAAO,GACf;;AANJ,AAWE,cAXY,CAUb,aAAa,CACZ,EAAE,CAAC;EACF,MAAM,EAAE,OAAO,GACf;;AAbH,AAgBC,cAhBa,CAgBb,wBAAwB,CAAC;EACxB,OAAO,EAAE,eAAe;EACxB,UAAU,EAAE,OAAO;EACnB,UAAU,EAAE,kBAAkB,GAC9B;;AApBF,AAsBC,cAtBa,CAsBb,mBAAmB,CAAC;EACnB,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,iBAAiB,GAC1B;;AAGF,AACC,iBADgB,CAChB,aAAa,CAAC;EACb,OAAO,EAAE,UAAU;EACnB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,CAAC;EACT,mBAAmB,EAAE,OAAO,GAK5B;EAVF,AAOE,iBAPe,CAChB,aAAa,CAMZ,KAAK,CAAC;IACL,UAAU,EAAE,MAAM,GAClB"
9
+ }
assets/js/simple-page-ordering.min.js ADDED
@@ -0,0 +1 @@
 
1
+ function update_simple_ordering_callback(e){if("children"!==e){var t=jQuery.parseJSON(e),r=t.new_pos;for(var n in r)if("next"!==n){var i=document.getElementById("inline_"+n);if(null!==i&&r.hasOwnProperty(n)){var a=i.querySelector(".menu_order");if(void 0!==r[n].menu_order){null!==a&&(a.innerHTML=r[n].menu_order);var l=i.querySelector(".post_parent");null!==l&&(l.innerHTML=r[n].post_parent);var o=null,s=i.querySelector(".post_title");null!==s&&(o=s.innerHTML);for(var d=0;d<r[n].depth;)o="&mdash; "+o,d++;var u=i.parentNode.querySelector(".row-title");null!==u&&null!==o&&(u.innerHTML=o)}else null!==a&&(a.innerHTML=r[n])}}t.next?jQuery.post(ajaxurl,{action:"simple_page_ordering",id:t.next.id,previd:t.next.previd,nextid:t.next.nextid,start:t.next.start,excluded:JSON.stringify(t.next.excluded)},update_simple_ordering_callback):(jQuery(".spo-updating-row").removeClass("spo-updating-row").find(".check-column").removeClass("spinner is-active"),sortable_post_table.removeClass("spo-updating").sortable("enable"))}else window.location.reload()}var sortable_post_table=jQuery(".wp-list-table tbody");sortable_post_table.sortable({items:"> tr",cursor:"move",axis:"y",containment:"table.widefat",cancel:".inline-edit-row",distance:2,opacity:.8,tolerance:"pointer",start:function(e,t){"undefined"!=typeof inlineEditPost&&inlineEditPost.revert(),t.placeholder.height(t.item.height())},helper:function(e,t){for(var r=t.children(),n=0;n<r.length;n++){var i=jQuery(r[n]);i.width(i.width())}return t},stop:function(e,t){t.item.children().css("width","")},update:function(e,t){sortable_post_table.sortable("disable").addClass("spo-updating"),t.item.addClass("spo-updating-row"),t.item.find(".check-column").addClass("spinner is-active");var r=t.item[0].id.substr(5),n=!1,i=t.item.prev();i.length>0&&(n=i.attr("id").substr(5));var a=!1,l=t.item.next();l.length>0&&(a=l.attr("id").substr(5)),jQuery.post(ajaxurl,{action:"simple_page_ordering",id:r,previd:n,nextid:a},update_simple_ordering_callback);for(var o=document.querySelectorAll("tr.iedit"),s=o.length;s--;)0==s%2?jQuery(o[s]).addClass("alternate"):jQuery(o[s]).removeClass("alternate")}});
simple-page-ordering.dev.js → assets/js/src/simple-page-ordering.js RENAMED
@@ -54,10 +54,10 @@ function update_simple_ordering_callback(response) {
54
  previd: changes.next['previd'],
55
  nextid: changes.next['nextid'],
56
  start: changes.next['start'],
57
- excluded: changes.next['excluded']
58
  }, update_simple_ordering_callback );
59
  } else {
60
- jQuery('.spo-updating-row').removeClass('spo-updating-row');
61
  sortable_post_table.removeClass('spo-updating').sortable('enable');
62
  }
63
  }
@@ -93,6 +93,7 @@ sortable_post_table.sortable({
93
  update: function(e, ui) {
94
  sortable_post_table.sortable('disable').addClass('spo-updating');
95
  ui.item.addClass('spo-updating-row');
 
96
 
97
  var postid = ui.item[0].id.substr(5); // post id
98
 
@@ -122,4 +123,4 @@ sortable_post_table.sortable({
122
  }
123
  }
124
  }
125
- });
54
  previd: changes.next['previd'],
55
  nextid: changes.next['nextid'],
56
  start: changes.next['start'],
57
+ excluded: JSON.stringify( changes.next['excluded'] )
58
  }, update_simple_ordering_callback );
59
  } else {
60
+ jQuery('.spo-updating-row').removeClass('spo-updating-row').find('.check-column').removeClass('spinner is-active');
61
  sortable_post_table.removeClass('spo-updating').sortable('enable');
62
  }
63
  }
93
  update: function(e, ui) {
94
  sortable_post_table.sortable('disable').addClass('spo-updating');
95
  ui.item.addClass('spo-updating-row');
96
+ ui.item.find('.check-column').addClass('spinner is-active');
97
 
98
  var postid = ui.item[0].id.substr(5); // post id
99
 
123
  }
124
  }
125
  }
126
+ });
localization/simple-page-ordering-de_DE.mo DELETED
Binary file
localization/simple-page-ordering-de_DE.po DELETED
@@ -1,69 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: Simple Page Ordering v2.2.1\n"
4
- "Report-Msgid-Bugs-To: \n"
5
- "POT-Creation-Date: \n"
6
- "PO-Revision-Date: 2014-07-08 07:20:03+0000\n"
7
- "Last-Translator: glueckpress <caspar@glueckpress.com>\n"
8
- "Language-Team: \n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
- "X-Generator: CSL v1.x\n"
14
- "X-Poedit-Language: German\n"
15
- "X-Poedit-Country: GERMANY\n"
16
- "X-Poedit-SourceCharset: utf-8\n"
17
- "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
18
- "X-Poedit-Basepath: ../\n"
19
- "X-Poedit-Bookmarks: \n"
20
- "X-Poedit-SearchPath-0: .\n"
21
- "X-Textdomain-Support: yes"
22
-
23
- #. translators: plugin header field 'Name'
24
- #: simple-page-ordering.php:0
25
- #@ simple-page-ordering
26
- msgid "Simple Page Ordering"
27
- msgstr "Simple Page Ordering"
28
-
29
- #. translators: plugin header field 'PluginURI'
30
- #: simple-page-ordering.php:0
31
- #@ simple-page-ordering
32
- msgid "http://10up.com/plugins/simple-page-ordering-wordpress/"
33
- msgstr "http://10up.com/plugins/simple-page-ordering-wordpress/"
34
-
35
- #. translators: plugin header field 'Description'
36
- #: simple-page-ordering.php:0
37
- #: simple-page-ordering.php:303
38
- #@ simple-page-ordering
39
- msgid "Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the \"Help\" tab on the Pages screen."
40
- msgstr "Ordne deine Seite und hierarchischen Post Types mittels Drag&Drop in der Seitenliste von WordPress. Für weitere Anleitungen öffne den „Hilfe“-Tab in der Ansicht „Seiten“."
41
-
42
- #. translators: plugin header field 'Author'
43
- #: simple-page-ordering.php:0
44
- #@ simple-page-ordering
45
- msgid "Jake Goldman, 10up"
46
- msgstr "Jake Goldman, 10up"
47
-
48
- #. translators: plugin header field 'AuthorURI'
49
- #: simple-page-ordering.php:0
50
- #@ simple-page-ordering
51
- msgid "http://10up.com"
52
- msgstr "http://10up.com"
53
-
54
- #. translators: plugin header field 'Version'
55
- #: simple-page-ordering.php:0
56
- #@ simple-page-ordering
57
- msgid "2.2.1"
58
- msgstr "2.2.1"
59
-
60
- #: simple-page-ordering.php:98
61
- #@ simple-page-ordering
62
- msgid "To reposition an item, simply drag and drop the row by \"clicking and holding\" it anywhere (outside of the links and form controls) and moving it to its new position."
63
- msgstr "Um ein Element neu zu positionieren, verschiebe die entsprechende Zeile einfach mit Drag&Drop, indem du sie anklickst und angeklickt hältst, sie dann zur neuen Position (außerhalb der Links und Formularelemente) bewegst und los lässt."
64
-
65
- #: simple-page-ordering.php:278
66
- #@ simple-page-ordering
67
- msgid "Sort by Order"
68
- msgstr "Nach Reihenfolge sortieren"
69
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
localization/simple-page-ordering-es_ES.mo DELETED
Binary file
localization/simple-page-ordering-es_ES.po DELETED
@@ -1,49 +0,0 @@
1
- # Copyright (C) 2011 Simple Page Ordering
2
- # This file is distributed under the same license as the Simple Page Ordering package.
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: Simple Page Ordering 1.0\n"
6
- "Report-Msgid-Bugs-To: \n"
7
- "POT-Creation-Date: 2011-07-03 23:41-0500\n"
8
- "PO-Revision-Date: 2012-09-15 16:33-0800\n"
9
- "Last-Translator: Jacob Goldman <jake@10up.com>\n"
10
- "Language-Team: 10up <jake@get10up.com>\n"
11
- "MIME-Version: 1.0\n"
12
- "Content-Type: text/plain; charset=UTF-8\n"
13
- "Content-Transfer-Encoding: 8bit\n"
14
- "Language: es\n"
15
-
16
- #: simple-page-ordering.php:63
17
- #, fuzzy
18
- msgid "is a plug-in by"
19
- msgstr "es un plug-in por"
20
-
21
- #: simple-page-ordering.php:63
22
- #, fuzzy
23
- msgid ""
24
- "that allows you to order pages and other hierarchical post types with drag "
25
- "and drop."
26
- msgstr ""
27
- "que le permite ordenar las páginas y otros tipos de mensaje jerárquica con "
28
- "arrastrar y soltar."
29
-
30
- #: simple-page-ordering.php:64
31
- #, fuzzy
32
- msgid ""
33
- "To reposition an item, simply drag and drop the row by \"clicking and holding"
34
- "\" it anywhere (outside of the links and form controls) and moving it to its "
35
- "new position."
36
- msgstr ""
37
- "Para cambiar la posición de un elemento, basta con arrastrar y soltar en la "
38
- "fila de \"clic y manteniendo\" en cualquier lugar (fuera de los vínculos y "
39
- "formar controles) y moverla a su nueva posición."
40
-
41
- #: simple-page-ordering.php:64
42
- #, fuzzy
43
- msgid ""
44
- "If you have a large number of pages, it may be helpful to adjust the items "
45
- "shown per page by opening the Screen Options tab."
46
- msgstr ""
47
- "Si usted tiene un gran número de páginas, puede ser útil para ajustar los "
48
- "elementos que se muestran por página, abra la pestaña Opciones de la "
49
- "pantalla."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
localization/simple-page-ordering-nl_NL.mo DELETED
Binary file
localization/simple-page-ordering-nl_NL.po DELETED
@@ -1,57 +0,0 @@
1
- # Copyright (C) 2011 Simple Page Ordering
2
- # This file is distributed under the same license as the Simple Page Ordering package.
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: Simple Page Ordering 1.0\n"
6
- "Report-Msgid-Bugs-To: \n"
7
- "POT-Creation-Date: 2011-07-03 23:41-0500\n"
8
- "PO-Revision-Date: 2011-12-14 11:38+0100\n"
9
- "Last-Translator: Moriz <info@moriz.nl>\n"
10
- "Language-Team: 10up <jake@get10up.com>\n"
11
- "MIME-Version: 1.0\n"
12
- "Content-Type: text/plain; charset=UTF-8\n"
13
- "Content-Transfer-Encoding: 8bit\n"
14
- "X-Poedit-Language: Spanish\n"
15
-
16
- #: simple-page-ordering.php:57
17
- msgid ""
18
- "Items can only be repositioned within their current branch in the page tree / hierarchy (next to pages with the same parent).\n"
19
- "\n"
20
- "If you want to move this item into a different part of the page tree, use the Quick Edit feature to change the parent before continuing."
21
- msgstr ""
22
- "Items kunnen alleen verplaatst worden binnen hun huidige niveau (boven of onder pagina's met dezelfde hoofdpagina).\n"
23
- "\n"
24
- "Als u een pagina onder een andere hoofdpagina wilt plaatsen, kies dan eerst de functie Snel bewerken om een andere hoofdpagina te kiezen."
25
-
26
- #: simple-page-ordering.php:71
27
- msgid "Show all"
28
- msgstr "Toon alles"
29
-
30
- #: simple-page-ordering.php:76
31
- msgid "per page"
32
- msgstr "per pagina"
33
-
34
- #: simple-page-ordering.php:86
35
- msgid "Simple Page Ordering"
36
- msgstr "Simple Page Ordering"
37
-
38
- #: simple-page-ordering.php:86
39
- msgid "is a plug-in by"
40
- msgstr "is een plug-in door"
41
-
42
- #: simple-page-ordering.php:86
43
- msgid "that allows you to order pages and other hierarchical post types with drag and drop."
44
- msgstr "welke het mogelijk maakt om pagina's en andere posttypes door drag and drop te verplaatsen."
45
-
46
- #: simple-page-ordering.php:87
47
- msgid "To reposition an item, simply drag and drop the row by \"clicking and holding\" it anywhere (outside of the links and form controls) and moving it to its new position."
48
- msgstr "Om een item te verplaatsen, gebruik eenvoudigweg drag en drop (slepen en loslaten) door klikken en vasthouden (buiten de links en knoppen) en het te verplaatsen naar de nieuwe positie."
49
-
50
- #: simple-page-ordering.php:88
51
- msgid "If you have a large number of pages, it may be helpful to adjust the new \"items per page\" filter located above the table and before the filter button."
52
- msgstr "Als er een groot aantal pagina's zijn, dan kan het handig zijn om het nieuwe Items per pagina filter bovenin de tabel en voor de filter knop aan te passen."
53
-
54
- #: simple-page-ordering.php:89
55
- msgid "To keep things relatively simple, the current version only allows you to reposition items within their current tree / hierarchy (next to pages with the same parent). If you want to move an item into or out of a different part of the page tree, use the \"quick edit\" feature to change the parent."
56
- msgstr "Om alles relatief eenvoudig te houden staat de huidige versie alleen toe om items binnen hun eigen niveau te verplaatsen. Als een item naar een andere hoofdpagina verplaatst moet worden, gebruik dan eerst de Snel bewerken functie om een andere hoofdpagina te kiezen."
57
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
localization/simple-page-ordering-pt_BR.mo DELETED
Binary file
localization/simple-page-ordering-pt_BR.po DELETED
@@ -1,61 +0,0 @@
1
- # Copyright (C) 2011 Simple Page Ordering
2
- # This file is distributed under the same license as the Simple Page Ordering package.
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: Simple Page Ordering 1.0\n"
6
- "Report-Msgid-Bugs-To: \n"
7
- "POT-Creation-Date: 2014-05-29 16:39-0300\n"
8
- "PO-Revision-Date: 2014-05-29 16:41-0300\n"
9
- "Last-Translator: Felds Liscia <dev@felds.com.br>\n"
10
- "Language-Team: 10up <jake@get10up.com>\n"
11
- "Language: pt_BR\n"
12
- "MIME-Version: 1.0\n"
13
- "Content-Type: text/plain; charset=UTF-8\n"
14
- "Content-Transfer-Encoding: 8bit\n"
15
- "Plural-Forms: nplurals=2; plural=(n > 1);\n"
16
- "X-Generator: Poedit 1.6.5\n"
17
- "X-Poedit-SourceCharset: UTF-8\n"
18
- "X-Poedit-Basepath: ../\n"
19
- "X-Poedit-KeywordsList: __;Description:\n"
20
- "X-Poedit-SearchPath-0: .\n"
21
-
22
- #: simple-page-ordering.php:98
23
- msgid ""
24
- "To reposition an item, simply drag and drop the row by \"clicking and holding"
25
- "\" it anywhere (outside of the links and form controls) and moving it to its "
26
- "new position."
27
- msgstr ""
28
- "Para alterar a posição de um elemento, simplesmente clique e segure em "
29
- "qualquer área fora dos links e outros controles, arraste e solte o conteúdo "
30
- "para sua nova posição."
31
-
32
- #: simple-page-ordering.php:278
33
- msgid "Sort by Order"
34
- msgstr "Organizar por ordem"
35
-
36
- #: simple-page-ordering.php:302
37
- msgid ""
38
- "Order your pages and hierarchical post types using drag and drop on the "
39
- "built in page list. For further instructions, open the \"Help\" tab on the "
40
- "Pages screen."
41
- msgstr ""
42
- "Ordene suas páginas e outros tipos de conteúdos hierárquicos usando arrastar-"
43
- "e-soltar na listagem de conteúdos. Para mais instruções, veja a Ajuda, no "
44
- "topo da lista de Páginas."
45
-
46
- #~ msgid "is a plug-in by"
47
- #~ msgstr "é um plug-in de"
48
-
49
- #~ msgid ""
50
- #~ "that allows you to order pages and other hierarchical post types with "
51
- #~ "drag and drop."
52
- #~ msgstr ""
53
- #~ "que permite ordenar páginas e outros conteúdos hierárquicos com arrastar-"
54
- #~ "e-soltar."
55
-
56
- #~ msgid ""
57
- #~ "If you have a large number of pages, it may be helpful to adjust the "
58
- #~ "items shown per page by opening the Screen Options tab."
59
- #~ msgstr ""
60
- #~ "Se você tem um grande número de conteúdos, pode ser útil ajustar o número "
61
- #~ "de itens exibidos por página, abrindo o painel Opções de Tela."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: jakemgold, 10up, thinkoomph
3
  Donate link: http://10up.com/plugins/simple-page-ordering-wordpress/
4
  Tags: order, re-order, ordering, pages, page, manage, menu_order, hierarchical, ajax, drag-and-drop, admin
5
  Requires at least: 3.8
6
- Tested up to: 4.6.1
7
- Stable tag: 2.2.4
8
 
9
  Order your pages and other hierarchical post types with simple drag and drop right from the standard page list.
10
 
@@ -20,6 +20,10 @@ Integrated help is included: just click the "help" tab at the top right of the s
20
 
21
  Please note that the plug-in is not compatible with Internet Explorer 7 and earlier, due to limitations within those browsers.
22
 
 
 
 
 
23
 
24
  == Installation ==
25
 
@@ -75,18 +79,27 @@ This feature is already built into WordPress natively, but a bit tucked away. If
75
  1. Processing indicator
76
 
77
 
78
- == Changelog ==
79
-
80
- = 2.2.4 =
81
- * Fixed redundant URL encoding when sorting in admin page list
82
-
83
- = 2.2.3 =
 
 
 
 
 
 
 
 
 
84
  * Fixed ordering in WordPress 4.0 following core changes to ORDER BY in WP_Query
85
-
86
- = 2.2.2 =
87
- * Column widths no longer change when dragging a row (partial props griffinjt)
88
- * Closed obscure XSS vulnerability related to Sort by Order link (props simon-waters)
89
- * Add German localization (props glueckpress).
90
 
91
  = 2.2.1 =
92
  * Bring back translations / text domain (yikes!)
3
  Donate link: http://10up.com/plugins/simple-page-ordering-wordpress/
4
  Tags: order, re-order, ordering, pages, page, manage, menu_order, hierarchical, ajax, drag-and-drop, admin
5
  Requires at least: 3.8
6
+ Tested up to: 4.9.4
7
+ Stable tag: 2.3
8
 
9
  Order your pages and other hierarchical post types with simple drag and drop right from the standard page list.
10
 
20
 
21
  Please note that the plug-in is not compatible with Internet Explorer 7 and earlier, due to limitations within those browsers.
22
 
23
+ === Contributing ===
24
+
25
+ We'd love to have you join in on development over on [GitHub](https://github.com/10up/simple-page-ordering).
26
+
27
 
28
  == Installation ==
29
 
79
  1. Processing indicator
80
 
81
 
82
+ == Changelog ==
83
+
84
+ = 2.3 =
85
+ * Avoid exceeding PHP's max input variables, which could cause incorrectly assigned page order
86
+ * Fix a malformed URL that would take you to posts instead of pages
87
+ * Use `WP_Query` instead of `get_posts()` for better performance
88
+ * Use WordPress core's spinner class
89
+ * Add Grunt-based build process with Sass
90
+ * Remove bundled translations in favor of WordPress.org language packs
91
+ * Fix some PHPDoc and coding standards to align with 10up's Engineering Best Practices
92
+
93
+ = 2.2.4 =
94
+ * Fixed redundant URL encoding when sorting in admin page list
95
+
96
+ = 2.2.3 =
97
  * Fixed ordering in WordPress 4.0 following core changes to ORDER BY in WP_Query
98
+
99
+ = 2.2.2 =
100
+ * Column widths no longer change when dragging a row (partial props griffinjt)
101
+ * Closed obscure XSS vulnerability related to Sort by Order link (props simon-waters)
102
+ * Add German localization (props glueckpress).
103
 
104
  = 2.2.1 =
105
  * Bring back translations / text domain (yikes!)
simple-page-ordering.css DELETED
@@ -1,33 +0,0 @@
1
- .wp-list-table .ui-sortable tr {
2
- cursor: move;
3
- }
4
-
5
- .wp-list-table .spo-updating tr,
6
- .wp-list-table .ui-sortable tr.inline-editor {
7
- cursor: default;
8
- }
9
-
10
- .wp-list-table .ui-sortable-placeholder {
11
- outline: 1px dashed #bbb;
12
- background: #F1F1F1;
13
- visibility: visible !important;
14
- }
15
- .wp-list-table .ui-sortable-helper {
16
- background-color: #fff;
17
- outline: 1px solid #e1e1e1;
18
- }
19
- .spo-updating-row .check-column {
20
- background: url('../../../wp-admin/images/spinner.gif') 10px 9px no-repeat;
21
- }
22
- @media print,
23
- (-o-min-device-pixel-ratio: 5/4),
24
- (-webkit-min-device-pixel-ratio: 1.25),
25
- (min-resolution: 120dpi) {
26
- .spo-updating-row .check-column {
27
- background-image: url('../../../wp-admin/images/spinner-2x.gif');
28
- background-size: 20px 20px;
29
- }
30
- }
31
- .spo-updating-row .check-column input {
32
- visibility: hidden;
33
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
simple-page-ordering.js DELETED
@@ -1 +0,0 @@
1
- function update_simple_ordering_callback(e){if("children"===e){window.location.reload();return}var t=jQuery.parseJSON(e);var n=t.new_pos;for(var r in n){if("next"===r){continue}var i=document.getElementById("inline_"+r);if(null!==i&&n.hasOwnProperty(r)){var s=i.querySelector(".menu_order");if(undefined!==n[r]["menu_order"]){if(null!==s){s.innerHTML=n[r]["menu_order"]}var o=i.querySelector(".post_parent");if(null!==o){o.innerHTML=n[r]["post_parent"]}var u=null;var a=i.querySelector(".post_title");if(null!==a){u=a.innerHTML}var f=0;while(f<n[r]["depth"]){u="&mdash; "+u;f++}var l=i.parentNode.querySelector(".row-title");if(null!==l&&null!==u){l.innerHTML=u}}else if(null!==s){s.innerHTML=n[r]}}}if(t.next){jQuery.post(ajaxurl,{action:"simple_page_ordering",id:t.next["id"],previd:t.next["previd"],nextid:t.next["nextid"],start:t.next["start"],excluded:t.next["excluded"]},update_simple_ordering_callback)}else{jQuery(".spo-updating-row").removeClass("spo-updating-row");sortable_post_table.removeClass("spo-updating").sortable("enable")}}var sortable_post_table=jQuery(".wp-list-table tbody");sortable_post_table.sortable({items:"> tr",cursor:"move",axis:"y",containment:"table.widefat",cancel:".inline-edit-row",distance:2,opacity:.8,tolerance:"pointer",start:function(e,t){if(typeof inlineEditPost!=="undefined"){inlineEditPost.revert()}t.placeholder.height(t.item.height())},helper:function(e,t){var n=t.children();for(var r=0;r<n.length;r++){var i=jQuery(n[r]);i.width(i.width())}return t},stop:function(e,t){t.item.children().css("width","")},update:function(e,t){sortable_post_table.sortable("disable").addClass("spo-updating");t.item.addClass("spo-updating-row");var n=t.item[0].id.substr(5);var r=false;var i=t.item.prev();if(i.length>0){r=i.attr("id").substr(5)}var s=false;var o=t.item.next();if(o.length>0){s=o.attr("id").substr(5)}jQuery.post(ajaxurl,{action:"simple_page_ordering",id:n,previd:r,nextid:s},update_simple_ordering_callback);var u=document.querySelectorAll("tr.iedit"),a=u.length;while(a--){if(0===a%2){jQuery(u[a]).addClass("alternate")}else{jQuery(u[a]).removeClass("alternate")}}}})
 
simple-page-ordering.php CHANGED
@@ -3,313 +3,321 @@
3
  Plugin Name: Simple Page Ordering
4
  Plugin URI: http://10up.com/plugins/simple-page-ordering-wordpress/
5
  Description: Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the "Help" tab on the Pages screen.
6
- Version: 2.2.4
7
  Author: Jake Goldman, 10up
8
  Author URI: http://10up.com
9
  License: GPLv2 or later
10
  Text Domain: simple-page-ordering
11
- Domain Path: /localization/
12
  */
13
 
14
  if ( ! class_exists( 'Simple_Page_Ordering' ) ) :
15
 
16
- class Simple_Page_Ordering {
17
 
18
- /**
19
- * Handles initializing this class and returning the singleton instance after it's been cached.
20
- *
21
- * @return null|Simple_page_Ordering
22
- */
23
- public static function get_instance() {
24
- // Store the instance locally to avoid private static replication
25
- static $instance = null;
26
 
27
- if ( null === $instance ) {
28
- $instance = new self();
29
- self::_add_actions();
30
- }
31
-
32
- return $instance;
33
- }
34
-
35
- /**
36
- * An empty constructor
37
- */
38
- public function __construct() { /* Purposely do nothing here */ }
39
-
40
- /**
41
- * Handles registering hooks that initialize this plugin.
42
- */
43
- public static function _add_actions() {
44
- add_action( 'load-edit.php', array( __CLASS__, 'load_edit_screen' ) );
45
- add_action( 'wp_ajax_simple_page_ordering', array( __CLASS__, 'ajax_simple_page_ordering' ) );
46
- add_action( 'plugins_loaded', array( __CLASS__, 'load_textdomain' ) );
47
- }
48
-
49
- /**
50
- * Loads the plugin textdomain
51
- */
52
- public static function load_textdomain() {
53
- load_plugin_textdomain( 'simple-page-ordering', false, dirname( plugin_basename( __FILE__ ) ) . '/localization/' );
54
- }
55
 
56
- /**
57
- * Load up page ordering scripts for the edit screen
58
- */
59
- public static function load_edit_screen() {
60
- $screen = get_current_screen();
61
- $post_type = $screen->post_type;
62
-
63
- // is post type sortable?
64
- $sortable = ( post_type_supports( $post_type, 'page-attributes' ) || is_post_type_hierarchical( $post_type ) ); // check permission
65
- if ( ! $sortable = apply_filters( 'simple_page_ordering_is_sortable', $sortable, $post_type ) ) {
66
- return;
67
  }
68
 
69
- // does user have the right to manage these post objects?
70
- if ( ! self::check_edit_others_caps( $post_type ) ) {
71
- return;
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
 
74
- add_filter( 'views_' . $screen->id, array( __CLASS__, 'sort_by_order_link' ) ); // add view by menu order to views
75
- add_action( 'wp', array( __CLASS__, 'wp' ) );
76
- add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
77
- }
78
-
79
- /**
80
- * when we load up our posts query, if we're actually sorting by menu order, initialize sorting scripts
81
- */
82
- public static function wp() {
83
- $orderby = get_query_var('orderby');
84
- if ( ( is_string( $orderby ) && 0 === strpos( $orderby, 'menu_order' ) ) || ( isset( $orderby['menu_order'] ) && $orderby['menu_order'] == 'ASC' ) ) {
85
- $script_name = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? 'simple-page-ordering.dev.js' : 'simple-page-ordering.js';
86
- wp_enqueue_script( 'simple-page-ordering', plugins_url( $script_name, __FILE__ ), array('jquery-ui-sortable'), '2.1', true );
87
- wp_enqueue_style( 'simple-page-ordering', plugins_url( 'simple-page-ordering.css', __FILE__ ) );
88
  }
89
- }
90
 
91
- /**
92
- * Add page ordering help to the help tab
93
- */
94
- public static function admin_head() {
95
- $screen = get_current_screen();
96
- $screen->add_help_tab(array(
97
- 'id' => 'simple_page_ordering_help_tab',
98
- 'title' => 'Simple Page Ordering',
99
- 'content' => '<p>' . __( 'To reposition an item, simply drag and drop the row by "clicking and holding" it anywhere (outside of the links and form controls) and moving it to its new position.', 'simple-page-ordering' ) . '</p>',
100
- ));
101
- }
 
102
 
103
- public static function ajax_simple_page_ordering() {
104
- // check and make sure we have what we need
105
- if ( empty( $_POST['id'] ) || ( !isset( $_POST['previd'] ) && !isset( $_POST['nextid'] ) ) ) {
106
- die(-1);
107
- }
108
 
109
- // real post?
110
- if ( ! $post = get_post( $_POST['id'] ) ) {
111
- die(-1);
 
 
 
112
  }
113
 
114
- // does user have the right to manage these post objects?
115
- if ( ! self::check_edit_others_caps( $post->post_type ) ) {
116
- die(-1);
 
 
 
 
 
 
 
117
  }
118
 
119
- // badly written plug-in hooks for save post can break things
120
- if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
121
- error_reporting( 0 );
 
 
 
 
 
 
 
122
  }
123
 
124
- global $wp_version;
125
-
126
- $previd = empty( $_POST['previd'] ) ? false : (int) $_POST['previd'];
127
- $nextid = empty( $_POST['nextid'] ) ? false : (int) $_POST['nextid'];
128
- $start = empty( $_POST['start'] ) ? 1 : (int) $_POST['start'];
129
- $excluded = empty( $_POST['excluded'] ) ? array( $post->ID ) : array_filter( (array) $_POST['excluded'], 'intval' );
130
 
131
- $new_pos = array(); // store new positions for ajax
132
- $return_data = new stdClass;
 
 
133
 
134
- do_action( 'simple_page_ordering_pre_order_posts', $post, $start );
 
 
 
135
 
136
- // attempt to get the intended parent... if either sibling has a matching parent ID, use that
137
- $parent_id = $post->post_parent;
138
- $next_post_parent = $nextid ? wp_get_post_parent_id( $nextid ) : false;
139
- if ( $previd == $next_post_parent ) { // if the preceding post is the parent of the next post, move it inside
140
- $parent_id = $next_post_parent;
141
- } elseif ( $next_post_parent !== $parent_id ) { // otherwise, if the next post's parent isn't the same as our parent, we need to study
142
- $prev_post_parent = $previd ? wp_get_post_parent_id( $previd ) : false;
143
- if ( $prev_post_parent !== $parent_id ) { // if the previous post is not our parent now, make it so!
144
- $parent_id = ( $prev_post_parent !== false ) ? $prev_post_parent : $next_post_parent;
145
  }
146
- }
147
- // if the next post's parent isn't our parent, it might as well be false (irrelevant to our query)
148
- if ( $next_post_parent !== $parent_id ) {
149
- $nextid = false;
150
- }
151
 
152
- $max_sortable_posts = (int) apply_filters( 'simple_page_ordering_limit', 50 ); // should reliably be able to do about 50 at a time
153
- if ( $max_sortable_posts < 5 ) { // don't be ridiculous!
154
- $max_sortable_posts = 50;
155
- }
156
 
157
- // we need to handle all post stati, except trash (in case of custom stati)
158
- $post_stati = get_post_stati(array(
159
- 'show_in_admin_all_list' => true,
160
- ));
161
-
162
- $siblings_query = array(
163
- 'depth' => 1,
164
- 'posts_per_page' => $max_sortable_posts,
165
- 'post_type' => $post->post_type,
166
- 'post_status' => $post_stati,
167
- 'post_parent' => $parent_id,
168
- 'orderby' => array( 'menu_order' => 'ASC', 'title' => 'ASC' ),
169
- 'post__not_in' => $excluded,
170
- 'update_post_term_cache' => false,
171
- 'update_post_meta_cache' => false,
172
- 'suppress_filters' => true,
173
- 'ignore_sticky_posts' => true,
174
- );
175
- if ( version_compare( $wp_version, '4.0', '<' ) ) {
176
- $siblings_query['orderby'] = 'menu_order title';
177
- $siblings_query['order'] = 'ASC';
178
- }
179
- $siblings = new WP_Query( $siblings_query ); // fetch all the siblings (relative ordering)
180
 
181
- // don't waste overhead of revisions on a menu order change (especially since they can't *all* be rolled back at once)
182
- remove_action( 'pre_post_update', 'wp_save_post_revision' );
183
 
184
- foreach( $siblings->posts as $sibling ) :
185
 
186
- // don't handle the actual post
187
- if ( $sibling->ID === $post->ID ) {
188
- continue;
 
 
 
 
 
 
 
189
  }
190
-
191
- // if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
192
- if ( $nextid === $sibling->ID ) {
193
- wp_update_post(array(
194
- 'ID' => $post->ID,
195
- 'menu_order' => $start,
196
- 'post_parent' => $parent_id,
197
- ));
198
- $ancestors = get_post_ancestors( $post->ID );
199
- $new_pos[$post->ID] = array(
200
- 'menu_order' => $start,
201
- 'post_parent' => $parent_id,
202
- 'depth' => count( $ancestors ),
203
- );
204
- $start++;
205
  }
206
 
207
- // if repositioned post has been set, and new items are already in the right order, we can stop
208
- if ( isset( $new_pos[$post->ID] ) && $sibling->menu_order >= $start ) {
209
- $return_data->next = false;
210
- break;
211
  }
212
 
213
- // set the menu order of the current sibling and increment the menu order
214
- if ( $sibling->menu_order != $start ) {
215
- wp_update_post(array(
216
- 'ID' => $sibling->ID,
217
- 'menu_order' => $start,
218
- ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  }
220
- $new_pos[$sibling->ID] = $start;
221
- $start++;
222
-
223
- if ( !$nextid && $previd == $sibling->ID ) {
224
- wp_update_post(array(
225
- 'ID' => $post->ID,
226
- 'menu_order' => $start,
227
- 'post_parent' => $parent_id
228
- ));
229
- $ancestors = get_post_ancestors( $post->ID );
230
- $new_pos[$post->ID] = array(
231
- 'menu_order' => $start,
232
- 'post_parent' => $parent_id,
233
- 'depth' => count($ancestors) );
234
- $start++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
 
237
- endforeach;
238
-
239
- // max per request
240
- if ( !isset( $return_data->next ) && $siblings->max_num_pages > 1 ) {
241
- $return_data->next = array(
242
- 'id' => $post->ID,
243
- 'previd' => $previd,
244
- 'nextid' => $nextid,
245
- 'start' => $start,
246
- 'excluded' => array_merge( array_keys( $new_pos ), $excluded ),
247
- );
248
- } else {
249
- $return_data->next = false;
250
- }
 
 
 
251
 
252
- do_action( 'simple_page_ordering_ordered_posts', $post, $new_pos );
253
-
254
- if ( ! $return_data->next ) {
255
- // if the moved post has children, we need to refresh the page (unless we're continuing)
256
- $children = get_posts(array(
257
- 'numberposts' => 1,
258
- 'post_type' => $post->post_type,
259
- 'post_status' => $post_stati,
260
- 'post_parent' => $post->ID,
261
- 'fields' => 'ids',
262
- 'update_post_term_cache' => false,
263
- 'update_post_meta_cache' => false,
264
- ));
265
-
266
- if ( ! empty( $children ) ) {
267
- die( 'children' );
268
  }
269
- }
270
 
271
- $return_data->new_pos = $new_pos;
 
 
272
 
273
- die( json_encode( $return_data ) );
274
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
- /**
277
- * Append a sort by order link to the post actions
278
- *
279
- * @param string $views
280
- * @return string
281
- */
282
- public static function sort_by_order_link( $views ) {
283
- $class = ( get_query_var('orderby') == 'menu_order title' ) ? 'current' : '';
284
- $query_string = esc_url( remove_query_arg( array( 'orderby', 'order' ) ) );
285
- if ( ! is_post_type_hierarchical( get_post_type() ) ) {
286
- $query_string = add_query_arg( 'orderby', 'menu_order title', $query_string );
287
- $query_string = add_query_arg( 'order', 'asc', $query_string );
288
  }
289
- $views['byorder'] = sprintf('<a href="%s" class="%s">%s</a>', $query_string, $class, __("Sort by Order", 'simple-page-ordering'));
290
-
291
- return $views;
292
- }
293
 
294
- /**
295
- * Checks to see if the current user has the capability to "edit others" for a post type
296
- *
297
- * @param string $post_type Post type name
298
- * @return bool True or false
299
- */
300
- private static function check_edit_others_caps( $post_type ) {
301
- $post_type_object = get_post_type_object( $post_type );
302
- $edit_others_cap = empty( $post_type_object ) ? 'edit_others_' . $post_type . 's' : $post_type_object->cap->edit_others_posts;
303
- return apply_filters( 'simple_page_ordering_edit_rights', current_user_can( $edit_others_cap ), $post_type );
 
 
 
304
  }
305
- }
306
 
307
- Simple_Page_Ordering::get_instance();
308
 
309
  endif;
310
-
311
- // dummy, to be used by poedit
312
- if (false) {
313
- // Plugin description
314
- __('Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the "Help" tab on the Pages screen.', 'simple-page-ordering');
315
- }
3
  Plugin Name: Simple Page Ordering
4
  Plugin URI: http://10up.com/plugins/simple-page-ordering-wordpress/
5
  Description: Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the "Help" tab on the Pages screen.
6
+ Version: 2.3
7
  Author: Jake Goldman, 10up
8
  Author URI: http://10up.com
9
  License: GPLv2 or later
10
  Text Domain: simple-page-ordering
 
11
  */
12
 
13
  if ( ! class_exists( 'Simple_Page_Ordering' ) ) :
14
 
15
+ class Simple_Page_Ordering {
16
 
17
+ /**
18
+ * Handles initializing this class and returning the singleton instance after it's been cached.
19
+ *
20
+ * @return null|Simple_page_Ordering
21
+ */
22
+ public static function get_instance() {
23
+ // Store the instance locally to avoid private static replication
24
+ static $instance = null;
25
 
26
+ if ( null === $instance ) {
27
+ $instance = new self();
28
+ self::_add_actions();
29
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ return $instance;
 
 
 
 
 
 
 
 
 
 
32
  }
33
 
34
+ /**
35
+ * An empty constructor
36
+ *
37
+ * Purposely do nothing here
38
+ */
39
+ public function __construct() {}
40
+
41
+ /**
42
+ * Handles registering hooks that initialize this plugin.
43
+ */
44
+ public static function _add_actions() {
45
+ add_action( 'load-edit.php', array( __CLASS__, 'load_edit_screen' ) );
46
+ add_action( 'wp_ajax_simple_page_ordering', array( __CLASS__, 'ajax_simple_page_ordering' ) );
47
+ add_action( 'plugins_loaded', array( __CLASS__, 'load_textdomain' ) );
48
  }
49
 
50
+ /**
51
+ * Loads the plugin textdomain
52
+ */
53
+ public static function load_textdomain() {
54
+ load_plugin_textdomain( 'simple-page-ordering', false, dirname( plugin_basename( __FILE__ ) ) . '/localization/' );
 
 
 
 
 
 
 
 
 
55
  }
 
56
 
57
+ /**
58
+ * Load up page ordering scripts for the edit screen
59
+ */
60
+ public static function load_edit_screen() {
61
+ $screen = get_current_screen();
62
+ $post_type = $screen->post_type;
63
+
64
+ // is post type sortable?
65
+ $sortable = ( post_type_supports( $post_type, 'page-attributes' ) || is_post_type_hierarchical( $post_type ) ); // check permission
66
+ if ( ! $sortable = apply_filters( 'simple_page_ordering_is_sortable', $sortable, $post_type ) ) {
67
+ return;
68
+ }
69
 
70
+ // does user have the right to manage these post objects?
71
+ if ( ! self::check_edit_others_caps( $post_type ) ) {
72
+ return;
73
+ }
 
74
 
75
+ add_filter( 'views_' . $screen->id, array(
76
+ __CLASS__,
77
+ 'sort_by_order_link',
78
+ ) ); // add view by menu order to views
79
+ add_action( 'wp', array( __CLASS__, 'wp' ) );
80
+ add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
81
  }
82
 
83
+ /**
84
+ * when we load up our posts query, if we're actually sorting by menu order, initialize sorting scripts
85
+ */
86
+ public static function wp() {
87
+ $orderby = get_query_var( 'orderby' );
88
+ if ( ( is_string( $orderby ) && 0 === strpos( $orderby, 'menu_order' ) ) || ( isset( $orderby['menu_order'] ) && 'ASC' === $orderby['menu_order'] ) ) {
89
+ $script_name = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '/assets/js/src/simple-page-ordering.js' : '/assets/js/simple-page-ordering.min.js';
90
+ wp_enqueue_script( 'simple-page-ordering', plugins_url( $script_name, __FILE__ ), array( 'jquery-ui-sortable' ), '2.1', true );
91
+ wp_enqueue_style( 'simple-page-ordering', plugins_url( '/assets/css/simple-page-ordering.css', __FILE__ ) );
92
+ }
93
  }
94
 
95
+ /**
96
+ * Add page ordering help to the help tab
97
+ */
98
+ public static function admin_head() {
99
+ $screen = get_current_screen();
100
+ $screen->add_help_tab( array(
101
+ 'id' => 'simple_page_ordering_help_tab',
102
+ 'title' => 'Simple Page Ordering',
103
+ 'content' => '<p>' . __( 'To reposition an item, simply drag and drop the row by "clicking and holding" it anywhere (outside of the links and form controls) and moving it to its new position.', 'simple-page-ordering' ) . '</p>',
104
+ ) );
105
  }
106
 
107
+ public static function ajax_simple_page_ordering() {
108
+ // check and make sure we have what we need
109
+ if ( empty( $_POST['id'] ) || ( ! isset( $_POST['previd'] ) && ! isset( $_POST['nextid'] ) ) ) {
110
+ die( - 1 );
111
+ }
 
112
 
113
+ // real post?
114
+ if ( ! $post = get_post( $_POST['id'] ) ) {
115
+ die( - 1 );
116
+ }
117
 
118
+ // does user have the right to manage these post objects?
119
+ if ( ! self::check_edit_others_caps( $post->post_type ) ) {
120
+ die( - 1 );
121
+ }
122
 
123
+ // badly written plug-in hooks for save post can break things
124
+ if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
125
+ error_reporting( 0 );
 
 
 
 
 
 
126
  }
 
 
 
 
 
127
 
128
+ global $wp_version;
 
 
 
129
 
130
+ $previd = empty( $_POST['previd'] ) ? false : (int) $_POST['previd'];
131
+ $nextid = empty( $_POST['nextid'] ) ? false : (int) $_POST['nextid'];
132
+ $start = empty( $_POST['start'] ) ? 1 : (int) $_POST['start'];
133
+ $excluded = empty( $_POST['excluded'] ) ? array( $post->ID ) : array_filter( (array) json_decode( $_POST['excluded'] ), 'intval' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ $new_pos = array(); // store new positions for ajax
136
+ $return_data = new stdClass;
137
 
138
+ do_action( 'simple_page_ordering_pre_order_posts', $post, $start );
139
 
140
+ // attempt to get the intended parent... if either sibling has a matching parent ID, use that
141
+ $parent_id = $post->post_parent;
142
+ $next_post_parent = $nextid ? wp_get_post_parent_id( $nextid ) : false;
143
+ if ( $previd == $next_post_parent ) { // if the preceding post is the parent of the next post, move it inside
144
+ $parent_id = $next_post_parent;
145
+ } elseif ( $next_post_parent !== $parent_id ) { // otherwise, if the next post's parent isn't the same as our parent, we need to study
146
+ $prev_post_parent = $previd ? wp_get_post_parent_id( $previd ) : false;
147
+ if ( $prev_post_parent !== $parent_id ) { // if the previous post is not our parent now, make it so!
148
+ $parent_id = ( false !== $prev_post_parent ) ? $prev_post_parent : $next_post_parent;
149
+ }
150
  }
151
+ // if the next post's parent isn't our parent, it might as well be false (irrelevant to our query)
152
+ if ( $next_post_parent !== $parent_id ) {
153
+ $nextid = false;
 
 
 
 
 
 
 
 
 
 
 
 
154
  }
155
 
156
+ $max_sortable_posts = (int) apply_filters( 'simple_page_ordering_limit', 50 ); // should reliably be able to do about 50 at a time
157
+ if ( $max_sortable_posts < 5 ) { // don't be ridiculous!
158
+ $max_sortable_posts = 50;
 
159
  }
160
 
161
+ // we need to handle all post stati, except trash (in case of custom stati)
162
+ $post_stati = get_post_stati( array(
163
+ 'show_in_admin_all_list' => true,
164
+ ) );
165
+
166
+ $siblings_query = array(
167
+ 'depth' => 1,
168
+ 'posts_per_page' => $max_sortable_posts,
169
+ 'post_type' => $post->post_type,
170
+ 'post_status' => $post_stati,
171
+ 'post_parent' => $parent_id,
172
+ 'orderby' => array(
173
+ 'menu_order' => 'ASC',
174
+ 'title' => 'ASC',
175
+ ),
176
+ 'post__not_in' => $excluded,
177
+ 'update_post_term_cache' => false,
178
+ 'update_post_meta_cache' => false,
179
+ 'suppress_filters' => true,
180
+ 'ignore_sticky_posts' => true,
181
+ );
182
+ if ( version_compare( $wp_version, '4.0', '<' ) ) {
183
+ $siblings_query['orderby'] = 'menu_order title';
184
+ $siblings_query['order'] = 'ASC';
185
  }
186
+ $siblings = new WP_Query( $siblings_query ); // fetch all the siblings (relative ordering)
187
+
188
+ // don't waste overhead of revisions on a menu order change (especially since they can't *all* be rolled back at once)
189
+ remove_action( 'pre_post_update', 'wp_save_post_revision' );
190
+
191
+ foreach ( $siblings->posts as $sibling ) :
192
+
193
+ // don't handle the actual post
194
+ if ( $sibling->ID === $post->ID ) {
195
+ continue;
196
+ }
197
+
198
+ // if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
199
+ if ( $nextid === $sibling->ID ) {
200
+ wp_update_post( array(
201
+ 'ID' => $post->ID,
202
+ 'menu_order' => $start,
203
+ 'post_parent' => $parent_id,
204
+ ) );
205
+ $ancestors = get_post_ancestors( $post->ID );
206
+ $new_pos[ $post->ID ] = array(
207
+ 'menu_order' => $start,
208
+ 'post_parent' => $parent_id,
209
+ 'depth' => count( $ancestors ),
210
+ );
211
+ $start ++;
212
+ }
213
+
214
+ // if repositioned post has been set, and new items are already in the right order, we can stop
215
+ if ( isset( $new_pos[ $post->ID ] ) && $sibling->menu_order >= $start ) {
216
+ $return_data->next = false;
217
+ break;
218
+ }
219
+
220
+ // set the menu order of the current sibling and increment the menu order
221
+ if ( $sibling->menu_order != $start ) {
222
+ wp_update_post( array(
223
+ 'ID' => $sibling->ID,
224
+ 'menu_order' => $start,
225
+ ) );
226
+ }
227
+ $new_pos[ $sibling->ID ] = $start;
228
+ $start ++;
229
+
230
+ if ( ! $nextid && $previd == $sibling->ID ) {
231
+ wp_update_post( array(
232
+ 'ID' => $post->ID,
233
+ 'menu_order' => $start,
234
+ 'post_parent' => $parent_id,
235
+ ) );
236
+ $ancestors = get_post_ancestors( $post->ID );
237
+ $new_pos[ $post->ID ] = array(
238
+ 'menu_order' => $start,
239
+ 'post_parent' => $parent_id,
240
+ 'depth' => count( $ancestors ),
241
+ );
242
+ $start ++;
243
+ }
244
+
245
+ endforeach;
246
+
247
+ // max per request
248
+ if ( ! isset( $return_data->next ) && $siblings->max_num_pages > 1 ) {
249
+ $return_data->next = array(
250
+ 'id' => $post->ID,
251
+ 'previd' => $previd,
252
+ 'nextid' => $nextid,
253
+ 'start' => $start,
254
+ 'excluded' => array_merge( array_keys( $new_pos ), $excluded ),
255
+ );
256
+ } else {
257
+ $return_data->next = false;
258
  }
259
 
260
+ do_action( 'simple_page_ordering_ordered_posts', $post, $new_pos );
261
+
262
+ if ( ! $return_data->next ) {
263
+ // if the moved post has children, we need to refresh the page (unless we're continuing)
264
+ $children = new WP_Query(
265
+ array(
266
+ 'posts_per_page' => 1,
267
+ 'post_type' => $post->post_type,
268
+ 'post_status' => $post_stati,
269
+ 'post_parent' => $post->ID,
270
+ 'fields' => 'ids',
271
+ 'update_post_term_cache' => false,
272
+ 'update_post_meta_cache' => false,
273
+ 'ignore_sticky' => true,
274
+ 'no_found_rows' => true,
275
+ )
276
+ );
277
 
278
+ if ( $children->have_posts() ) {
279
+ die( 'children' );
280
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  }
 
282
 
283
+ $return_data->new_pos = $new_pos;
284
+ die( json_encode( $return_data ) );
285
+ }
286
 
287
+ /**
288
+ * Append a sort by order link to the post actions
289
+ *
290
+ * @param array $views
291
+ *
292
+ * @return array
293
+ */
294
+ public static function sort_by_order_link( $views ) {
295
+ $class = ( get_query_var( 'orderby' ) == 'menu_order title' ) ? 'current' : '';
296
+ $query_string = remove_query_arg( array( 'orderby', 'order' ) );
297
+ if ( ! is_post_type_hierarchical( get_post_type() ) ) {
298
+ $query_string = add_query_arg( 'orderby', 'menu_order title', $query_string );
299
+ $query_string = add_query_arg( 'order', 'asc', $query_string );
300
+ }
301
+ $views['byorder'] = sprintf( '<a href="%s" class="%s">%s</a>', esc_url( $query_string ), $class, __( 'Sort by Order', 'simple-page-ordering' ) );
302
 
303
+ return $views;
 
 
 
 
 
 
 
 
 
 
 
304
  }
 
 
 
 
305
 
306
+ /**
307
+ * Checks to see if the current user has the capability to "edit others" for a post type
308
+ *
309
+ * @param string $post_type Post type name
310
+ *
311
+ * @return bool True or false
312
+ */
313
+ private static function check_edit_others_caps( $post_type ) {
314
+ $post_type_object = get_post_type_object( $post_type );
315
+ $edit_others_cap = empty( $post_type_object ) ? 'edit_others_' . $post_type . 's' : $post_type_object->cap->edit_others_posts;
316
+
317
+ return apply_filters( 'simple_page_ordering_edit_rights', current_user_can( $edit_others_cap ), $post_type );
318
+ }
319
  }
 
320
 
321
+ Simple_Page_Ordering::get_instance();
322
 
323
  endif;