Nested Pages - Version 1.1.1

Version Description

= 1.1 = Several new features have been added in version 1.1, including: saved toggle states, additional menu options, trash functionality, ability to add "link" menu items, and more.

Download this release

Release Info

Developer kylephillips
Plugin Icon 128x128 Nested Pages
Version 1.1.1
Comparing to
See all releases

Code changes from version 1.1 to 1.1.1

assets/banner-772x250.png ADDED
Binary file
assets/icon-128x128.png ADDED
Binary file
assets/js/lib/bs-modal.js ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ========================================================================
2
+ * Bootstrap: modal.js v3.3.0
3
+ * http://getbootstrap.com/javascript/#modals
4
+ * ========================================================================
5
+ * Copyright 2011-2014 Twitter, Inc.
6
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
+ * ======================================================================== */
8
+
9
+
10
+ +function ($) {
11
+ 'use strict';
12
+
13
+ // MODAL CLASS DEFINITION
14
+ // ======================
15
+
16
+ var Modal = function (element, options) {
17
+ this.options = options
18
+ this.$body = $(document.body)
19
+ this.$element = $(element)
20
+ this.$backdrop =
21
+ this.isShown = null
22
+ this.scrollbarWidth = 0
23
+
24
+ if (this.options.remote) {
25
+ this.$element
26
+ .find('.modal-content')
27
+ .load(this.options.remote, $.proxy(function () {
28
+ this.$element.trigger('loaded.bs.modal')
29
+ }, this))
30
+ }
31
+ }
32
+
33
+ Modal.VERSION = '3.3.0'
34
+
35
+ Modal.TRANSITION_DURATION = 300
36
+ Modal.BACKDROP_TRANSITION_DURATION = 150
37
+
38
+ Modal.DEFAULTS = {
39
+ backdrop: true,
40
+ keyboard: true,
41
+ show: true
42
+ }
43
+
44
+ Modal.prototype.toggle = function (_relatedTarget) {
45
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
46
+ }
47
+
48
+ Modal.prototype.show = function (_relatedTarget) {
49
+ var that = this
50
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
51
+
52
+ this.$element.trigger(e)
53
+
54
+ if (this.isShown || e.isDefaultPrevented()) return
55
+
56
+ this.isShown = true
57
+
58
+ this.checkScrollbar()
59
+ this.$body.addClass('modal-open')
60
+
61
+ this.setScrollbar()
62
+ this.escape()
63
+
64
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
65
+
66
+ this.backdrop(function () {
67
+ var transition = $.support.transition && that.$element.hasClass('fade')
68
+
69
+ if (!that.$element.parent().length) {
70
+ that.$element.appendTo(that.$body) // don't move modals dom position
71
+ }
72
+
73
+ that.$element
74
+ .show()
75
+ .scrollTop(0)
76
+
77
+ if (transition) {
78
+ that.$element[0].offsetWidth // force reflow
79
+ }
80
+
81
+ that.$element
82
+ .addClass('in')
83
+ .attr('aria-hidden', false)
84
+
85
+ that.enforceFocus()
86
+
87
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
88
+
89
+ transition ?
90
+ that.$element.find('.modal-dialog') // wait for modal to slide in
91
+ .one('bsTransitionEnd', function () {
92
+ that.$element.trigger('focus').trigger(e)
93
+ })
94
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
95
+ that.$element.trigger('focus').trigger(e)
96
+ })
97
+ }
98
+
99
+ Modal.prototype.hide = function (e) {
100
+ if (e) e.preventDefault()
101
+
102
+ e = $.Event('hide.bs.modal')
103
+
104
+ this.$element.trigger(e)
105
+
106
+ if (!this.isShown || e.isDefaultPrevented()) return
107
+
108
+ this.isShown = false
109
+
110
+ this.escape()
111
+
112
+ $(document).off('focusin.bs.modal')
113
+
114
+ this.$element
115
+ .removeClass('in')
116
+ .attr('aria-hidden', true)
117
+ .off('click.dismiss.bs.modal')
118
+
119
+ $.support.transition && this.$element.hasClass('fade') ?
120
+ this.$element
121
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
122
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
123
+ this.hideModal()
124
+ }
125
+
126
+ Modal.prototype.enforceFocus = function () {
127
+ $(document)
128
+ .off('focusin.bs.modal') // guard against infinite focus loop
129
+ .on('focusin.bs.modal', $.proxy(function (e) {
130
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
131
+ this.$element.trigger('focus')
132
+ }
133
+ }, this))
134
+ }
135
+
136
+ Modal.prototype.escape = function () {
137
+ if (this.isShown && this.options.keyboard) {
138
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
139
+ e.which == 27 && this.hide()
140
+ }, this))
141
+ } else if (!this.isShown) {
142
+ this.$element.off('keydown.dismiss.bs.modal')
143
+ }
144
+ }
145
+
146
+ Modal.prototype.hideModal = function () {
147
+ var that = this
148
+ this.$element.hide()
149
+ this.backdrop(function () {
150
+ that.$body.removeClass('modal-open')
151
+ that.resetScrollbar()
152
+ that.$element.trigger('hidden.bs.modal')
153
+ })
154
+ }
155
+
156
+ Modal.prototype.removeBackdrop = function () {
157
+ this.$backdrop && this.$backdrop.remove()
158
+ this.$backdrop = null
159
+ }
160
+
161
+ Modal.prototype.backdrop = function (callback) {
162
+ var that = this
163
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
164
+
165
+ if (this.isShown && this.options.backdrop) {
166
+ var doAnimate = $.support.transition && animate
167
+
168
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
169
+ .prependTo(this.$element)
170
+ .on('click.dismiss.bs.modal', $.proxy(function (e) {
171
+ if (e.target !== e.currentTarget) return
172
+ this.options.backdrop == 'static'
173
+ ? this.$element[0].focus.call(this.$element[0])
174
+ : this.hide.call(this)
175
+ }, this))
176
+
177
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
178
+
179
+ this.$backdrop.addClass('in')
180
+
181
+ if (!callback) return
182
+
183
+ doAnimate ?
184
+ this.$backdrop
185
+ .one('bsTransitionEnd', callback)
186
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
187
+ callback()
188
+
189
+ } else if (!this.isShown && this.$backdrop) {
190
+ this.$backdrop.removeClass('in')
191
+
192
+ var callbackRemove = function () {
193
+ that.removeBackdrop()
194
+ callback && callback()
195
+ }
196
+ $.support.transition && this.$element.hasClass('fade') ?
197
+ this.$backdrop
198
+ .one('bsTransitionEnd', callbackRemove)
199
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
200
+ callbackRemove()
201
+
202
+ } else if (callback) {
203
+ callback()
204
+ }
205
+ }
206
+
207
+ Modal.prototype.checkScrollbar = function () {
208
+ this.scrollbarWidth = this.measureScrollbar()
209
+ }
210
+
211
+ Modal.prototype.setScrollbar = function () {
212
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
213
+ if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
214
+ }
215
+
216
+ Modal.prototype.resetScrollbar = function () {
217
+ this.$body.css('padding-right', '')
218
+ }
219
+
220
+ Modal.prototype.measureScrollbar = function () { // thx walsh
221
+ if (document.body.clientWidth >= window.innerWidth) return 0
222
+ var scrollDiv = document.createElement('div')
223
+ scrollDiv.className = 'modal-scrollbar-measure'
224
+ this.$body.append(scrollDiv)
225
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
226
+ this.$body[0].removeChild(scrollDiv)
227
+ return scrollbarWidth
228
+ }
229
+
230
+
231
+ // MODAL PLUGIN DEFINITION
232
+ // =======================
233
+
234
+ function Plugin(option, _relatedTarget) {
235
+ return this.each(function () {
236
+ var $this = $(this)
237
+ var data = $this.data('bs.modal')
238
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
239
+
240
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
241
+ if (typeof option == 'string') data[option](_relatedTarget)
242
+ else if (options.show) data.show(_relatedTarget)
243
+ })
244
+ }
245
+
246
+ var old = $.fn.modal
247
+
248
+ $.fn.modal = Plugin
249
+ $.fn.modal.Constructor = Modal
250
+
251
+
252
+ // MODAL NO CONFLICT
253
+ // =================
254
+
255
+ $.fn.modal.noConflict = function () {
256
+ $.fn.modal = old
257
+ return this
258
+ }
259
+
260
+
261
+ // MODAL DATA-API
262
+ // ==============
263
+
264
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
265
+ var $this = $(this)
266
+ var href = $this.attr('href')
267
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
268
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
269
+
270
+ if ($this.is('a')) e.preventDefault()
271
+
272
+ $target.one('show.bs.modal', function (showEvent) {
273
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
274
+ $target.one('hidden.bs.modal', function () {
275
+ $this.is(':visible') && $this.trigger('focus')
276
+ })
277
+ })
278
+ Plugin.call($target, option, this)
279
+ })
280
+
281
+ }(jQuery);
assets/scss/_form-modal.scss ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Modal Forms
3
+ // --------------------------------------------------
4
+ .np-modal-form {
5
+
6
+ .form-interior {
7
+ @include clearfix;
8
+ background: url('../images/border.png') repeat-y;
9
+ background-position: center;
10
+ padding: 5px 0;
11
+ }
12
+
13
+ .form-control {
14
+ @include clearfix;
15
+ margin-bottom: 10px;
16
+ }
17
+
18
+ .checkbox {
19
+ margin-bottom: 10px;
20
+ }
21
+
22
+ .left {
23
+ float: left;
24
+ width: 45%;
25
+ }
26
+
27
+ .right {
28
+ float: right;
29
+ width: 45%;
30
+ padding-top: 18px;
31
+ }
32
+
33
+ label {
34
+ display: block;
35
+ }
36
+
37
+ input[type="text"],
38
+ select {
39
+ width: 100%;
40
+ }
41
+
42
+ .buttons {
43
+ clear: both;
44
+ }
45
+
46
+ } // .np-modal-form
assets/scss/_modals.scss ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Modals
3
+ // --------------------------------------------------
4
+
5
+ .modal-open {
6
+ overflow: hidden;
7
+ }
8
+
9
+ .modal {
10
+ display: none;
11
+ overflow: hidden;
12
+ position: fixed;
13
+ top: 0;
14
+ right: 0;
15
+ bottom: 0;
16
+ left: 0;
17
+ z-index: 99999;
18
+ -webkit-overflow-scrolling: touch;
19
+ outline: 0;
20
+ &.fade .modal-dialog {
21
+ @include translate(0, -25%);
22
+ @include transition-transform(0.3s ease-out);
23
+ }
24
+ &.in .modal-dialog { @include translate(0, 0) }
25
+ }
26
+ .modal-open .modal {
27
+ overflow-x: hidden;
28
+ overflow-y: auto;
29
+ }
30
+
31
+ .modal-dialog {
32
+ position: relative;
33
+ width: auto;
34
+ margin: 10px auto 0px auto;
35
+ max-width: 500px;
36
+ }
37
+
38
+ // Actual modal
39
+ .modal-content {
40
+ position: relative;
41
+ background-color: $white;
42
+ box-shadow: 0 3px 9px rgba(0,0,0,.5);
43
+ background-clip: padding-box;
44
+ outline: 0;
45
+ }
46
+
47
+ // Modal background
48
+ .modal-backdrop {
49
+ position: fixed;
50
+ top: 0;
51
+ right: 0;
52
+ bottom: 0;
53
+ left: 0;
54
+ background-color: #000;
55
+ opacity: .85;
56
+ }
57
+
58
+
59
+ .modal-header {
60
+ padding: 8px;
61
+ background-color: darken($white, 8%);
62
+ .sr-only {
63
+ display: none;
64
+ }
65
+ }
66
+
67
+ .modal-header .close {
68
+ margin-top: -2px;
69
+ }
70
+
71
+ .modal-title {
72
+ margin: 0;
73
+ }
74
+
75
+ .modal-body {
76
+ position: relative;
77
+ padding: 10px;
78
+ }
79
+
80
+ // Footer (for actions)
81
+ .modal-footer {
82
+ padding: 10px;
83
+ text-align: right;
84
+ background-color: #404040;
85
+ @include clearfix;
86
+ .modal-close {
87
+ float: left;
88
+ }
89
+ }
90
+
91
+ // Measure scrollbar width for padding body during modal show/hide
92
+ .modal-scrollbar-measure {
93
+ position: absolute;
94
+ top: -9999px;
95
+ width: 50px;
96
+ height: 50px;
97
+ overflow: scroll;
98
+ }
includes/class-np-confirmation.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Confirmation Messages
4
+ */
5
+ class NP_Confirmation {
6
+
7
+ /**
8
+ * Message Output
9
+ * @var string
10
+ */
11
+ private $message;
12
+
13
+ /**
14
+ * Type of Message
15
+ * @var string
16
+ */
17
+ private $type;
18
+
19
+
20
+ public function __construct()
21
+ {
22
+ $this->setType();
23
+ $this->setMessage();
24
+ }
25
+
26
+
27
+ /**
28
+ * Set the Type of confirmation
29
+ */
30
+ private function setType()
31
+ {
32
+ if ( (isset($_GET['trashed'])) && (intval($_GET['trashed']) > 0) ) $this->type = 'trashConfirm';
33
+ if ( (isset($_GET['untrashed'])) && (intval($_GET['untrashed']) > 0) ) $this->type = 'trashRestored';
34
+ }
35
+
36
+
37
+ /**
38
+ * Set the confirmation message
39
+ */
40
+ private function setMessage()
41
+ {
42
+ if ( $this->type ){
43
+ $type = $this->type;
44
+ $this->$type();
45
+ }
46
+ }
47
+
48
+
49
+ /**
50
+ * Trash Confirmation
51
+ */
52
+ private function trashConfirm()
53
+ {
54
+ $out = '<div id="message" class="updated below-h2"><p>';
55
+ $trashed = ( explode(',', $_GET['ids']) );
56
+ if ( count($trashed) > 1 ){
57
+ $out .= count($trashed) . ' ' . __('pages moved to the Trash', 'nestedpages');
58
+ } else {
59
+ $out .= '<strong>' . get_the_title($trashed[0]) . ' </strong>' . __('page moved to the Trash', 'nestedpages');
60
+
61
+ // Undo Link
62
+ if ( current_user_can('delete_pages') ) {
63
+ $page_obj = get_post_type_object('page');
64
+ $out .= ' <a href="' . wp_nonce_url( admin_url( sprintf( $page_obj->_edit_link . '&amp;action=untrash', $trashed[0] ) ), 'untrash-post_' . $trashed[0] ) . '">' . __( 'Undo' ) . "</a>";
65
+ }
66
+ }
67
+
68
+ $out .= '</p></div>';
69
+ $this->message = $out;
70
+ }
71
+
72
+
73
+ /**
74
+ * Trash Restored (Posts moved out of trash)
75
+ */
76
+ private function trashRestored()
77
+ {
78
+ $out = "";
79
+ $untrashed = sanitize_text_field($_GET['untrashed']);
80
+ $page = ( intval($untrashed) > 1 ) ? __('pages', 'nestedpages') : __('page', 'nestedpages');
81
+ $this->message = '<div id="message" class="updated below-h2"><p>' . $untrashed . ' ' . $page . ' ' . __('restored from trash', 'nestedpages') . '.</p></div>';
82
+ }
83
+
84
+
85
+ /**
86
+ * Get the Message
87
+ */
88
+ public function getMessage()
89
+ {
90
+ return $this->message;
91
+ }
92
+
93
+ }
includes/class-np-handler-nesttoggle.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function nestedpages_nesttoggle_handler()
3
+ {
4
+ new NP_NestToggle_Handler;
5
+ }
6
+ require_once('class-np-handler-base.php');
7
+ /**
8
+ * Syncs User's Visible/Toggled Pages
9
+ */
10
+ class NP_NestToggle_Handler extends NP_BaseHandler {
11
+
12
+ public function __construct()
13
+ {
14
+ parent::__construct();
15
+ $this->updateUserMeta();
16
+ }
17
+
18
+ /**
19
+ * Make sure this is an array of integers
20
+ */
21
+ private function validateIDs()
22
+ {
23
+ if ( !is_array($this->data['ids']) ) $this->sendErrorResponse();
24
+ foreach ($this->data['ids'] as $id){
25
+ if ( !is_numeric($id) ) $this->sendErrorResponse();
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Update the user meta with the array of IDs
31
+ */
32
+ private function updateUserMeta()
33
+ {
34
+ update_user_meta(
35
+ get_current_user_id(),
36
+ 'np_visible_pages',
37
+ serialize($this->data['ids'])
38
+ );
39
+ $this->response = array('status'=>'success', 'data'=>$this->data);
40
+ $this->sendResponse();
41
+ }
42
+
43
+ }
includes/class-np-handler-newredirect.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function nestedpages_new_redirect()
4
+ {
5
+ new NP_NewRedirect;
6
+ }
7
+
8
+ require_once('class-np-handler-base.php');
9
+ require_once('class-np-helpers.php');
10
+
11
+ /**
12
+ * Creates new Redirect/Link
13
+ * @return json response
14
+ */
15
+ class NP_NewRedirect extends NP_BaseHandler {
16
+
17
+
18
+ public function __construct()
19
+ {
20
+ parent::__construct();
21
+ $this->saveRedirect();
22
+ $this->syncMenu();
23
+ $this->sendResponse();
24
+ }
25
+
26
+
27
+ /**
28
+ * Update the Post
29
+ * @todo update taxonomies
30
+ */
31
+ private function saveRedirect()
32
+ {
33
+ $updated = $this->post_repo->saveRedirect($this->data);
34
+ if ( !$updated ) $this->sendErrorResponse();
35
+ $this->data['id'] = $updated;
36
+ $this->addData();
37
+ $this->formatLink();
38
+ $this->response = array(
39
+ 'status' => 'success',
40
+ 'message' => __('Redirect successfully updated'),
41
+ 'post_data' => $this->data
42
+ );
43
+ }
44
+
45
+
46
+ /**
47
+ * Format the new link for AJAX response
48
+ */
49
+ private function formatLink()
50
+ {
51
+ $this->data['np_link_content'] = NP_Helpers::check_url($this->data['np_link_content']);
52
+ }
53
+
54
+
55
+ /**
56
+ * Add additional data to the response object
57
+ */
58
+ private function addData()
59
+ {
60
+ $this->data['nav_status'] = ( isset($this->data['nav_status']) ) ? 'hide' : 'show';
61
+ $this->data['np_status'] = ( isset($this->data['nested_pages_status']) ) ? 'hide' : 'show';
62
+ $this->data['link_target'] = ( isset($this->data['link_target']) ) ? '_blank' : 'none';
63
+ }
64
+
65
+ }
includes/class-np-handler-quickedit-redirect.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function nestedpages_quickedit_redirect_handler()
4
+ {
5
+ new NP_QuickEdit_Handler_Redirect;
6
+ }
7
+
8
+ require_once('class-np-handler-base.php');
9
+
10
+ /**
11
+ * Handles processing the quick edit form for redirects
12
+ * @return json response
13
+ */
14
+ class NP_QuickEdit_Handler_Redirect extends NP_BaseHandler {
15
+
16
+
17
+ public function __construct()
18
+ {
19
+ parent::__construct();
20
+ $this->updatePost();
21
+ $this->syncMenu();
22
+ $this->sendResponse();
23
+ }
24
+
25
+
26
+ /**
27
+ * Update the Post
28
+ */
29
+ private function updatePost()
30
+ {
31
+ $updated = $this->post_repo->updateRedirect($this->data);
32
+ if ( !$updated ) $this->sendErrorResponse();
33
+ $this->addData();
34
+ $this->response = array(
35
+ 'status' => 'success',
36
+ 'message' => __('Redirect successfully updated'),
37
+ 'post_data' => $this->data
38
+ );
39
+ }
40
+
41
+
42
+ /**
43
+ * Add additional data to the response object
44
+ */
45
+ private function addData()
46
+ {
47
+ $this->data['nav_status'] = ( isset($this->data['nav_status']) ) ? 'hide' : 'show';
48
+ $this->data['np_status'] = ( isset($this->data['nested_pages_status']) ) ? 'hide' : 'show';
49
+ $this->data['link_target'] = ( isset($this->data['link_target']) ) ? '_blank' : 'none';
50
+ }
51
+
52
+ }
includes/class-np-helpers.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Helper Functions
4
+ */
5
+ class NP_Helpers {
6
+
7
+ /**
8
+ * Verify URL Format
9
+ * @param string - URL to check
10
+ * @return string - formatted URL
11
+ */
12
+ public static function check_url($url)
13
+ {
14
+ $parsed = parse_url($url);
15
+ if (empty($parsed['scheme'])) $url = 'http://' . ltrim($url, '/');
16
+ return $url;
17
+ }
18
+
19
+ /**
20
+ * Plugin Root Directory
21
+ */
22
+ public static function plugin_url()
23
+ {
24
+ return plugins_url() . '/wp-simple-locator';
25
+ }
26
+
27
+ /**
28
+ * View
29
+ */
30
+ public static function view($file)
31
+ {
32
+ return dirname(dirname(__FILE__)) . '/views/' . $file . '.php';
33
+ }
34
+
35
+ }
includes/class-np-postrepository.php DELETED
@@ -1,164 +0,0 @@
1
- <?php
2
-
3
- require_once('class-np-validation.php');
4
-
5
- class NP_PostRepository {
6
-
7
- /**
8
- * Validation Class
9
- * @var NP_Validation instance
10
- */
11
- protected $validation;
12
-
13
-
14
- public function __construct()
15
- {
16
- $this->validation = new NP_Validation;
17
- }
18
-
19
-
20
- /**
21
- * Update Order
22
- */
23
- public function updateOrder($posts, $parent = 0)
24
- {
25
- $this->validation->validatePostIDs($posts);
26
- foreach( $posts as $key => $post )
27
- {
28
- wp_update_post(array(
29
- 'ID' => $post['id'],
30
- 'menu_order' => $key,
31
- 'post_parent' => $parent
32
- ));
33
-
34
- if ( isset($post['children']) ){
35
- $this->updateOrder($post['children'], $post['id']);
36
- }
37
- }
38
- return true;
39
- }
40
-
41
-
42
- /**
43
- * Update Post
44
- */
45
- public function updatePost($data)
46
- {
47
- $date = $this->validation->validateDate($data);
48
- if ( !isset($_POST['comment_status']) ) $data['comment_status'] = 'closed';
49
-
50
- $updated_post = array(
51
- 'ID' => sanitize_text_field($data['post_id']),
52
- 'post_title' => sanitize_text_field($data['post_title']),
53
- 'post_author' => sanitize_text_field($data['post_author']),
54
- 'post_name' => sanitize_text_field($data['post_name']),
55
- 'post_date' => $date,
56
- 'comment_status' => sanitize_text_field($data['comment_status']),
57
- 'post_status' => sanitize_text_field($data['_status'])
58
- );
59
- wp_update_post($updated_post);
60
-
61
- $this->updateTemplate($data);
62
- $this->updateNavStatus($data);
63
- $this->updateNestedPagesStatus($data);
64
- $this->updateNavTitle($data);
65
- $this->updateCategories($data);
66
- $this->updateHierarchicalTaxonomies($data);
67
-
68
- return true;
69
- }
70
-
71
-
72
- /**
73
- * Update Page Template
74
- */
75
- private function updateTemplate($data)
76
- {
77
- $template = sanitize_text_field($data['page_template']);
78
- update_post_meta(
79
- $data['post_id'],
80
- '_wp_page_template',
81
- $template
82
- );
83
- }
84
-
85
-
86
- /**
87
- * Update Nav Status (show/hide in nav menu)
88
- */
89
- private function updateNavStatus($data)
90
- {
91
- $status = ( isset($data['nav_status']) ) ? 'hide' : 'show';
92
- update_post_meta(
93
- $data['post_id'],
94
- 'np_nav_status',
95
- $status
96
- );
97
- }
98
-
99
-
100
- /**
101
- * Update Nested Pages Visibility (how/hide in Nested Pages interface)
102
- */
103
- private function updateNestedPagesStatus($data)
104
- {
105
- $status = ( isset($data['nested_pages_status']) ) ? 'hide' : 'show';
106
- update_post_meta(
107
- $data['post_id'],
108
- 'nested_pages_status',
109
- $status
110
- );
111
- }
112
-
113
-
114
- /**
115
- * Update Nested Pages Menu Title
116
- */
117
- private function updateNavTitle($data)
118
- {
119
- if ( isset($data['np_nav_title']) ){
120
- $title = sanitize_text_field($data['np_nav_title']);
121
- update_post_meta(
122
- $data['post_id'],
123
- 'np_nav_title',
124
- $title
125
- );
126
- }
127
- }
128
-
129
-
130
- /**
131
- * Update Categories
132
- */
133
- private function updateCategories($data)
134
- {
135
- if ( isset($data['post_category']) )
136
- {
137
- $this->validation->validateIntegerArray($data['post_category']);
138
- $cats = array();
139
- foreach($data['post_category'] as $cat) {
140
- if ( $cat !== 0 ) $cats[] = (int) $cat;
141
- }
142
- wp_set_post_terms($data['post_id'], $cats, 'category');
143
- }
144
- }
145
-
146
-
147
- /**
148
- * Update Hierarchical Taxonomy Terms
149
- */
150
- private function updateHierarchicalTaxonomies($data)
151
- {
152
- if ( isset($data['tax_input']) ) {
153
- foreach ( $data['tax_input'] as $taxonomy => $term_ids ){
154
- $this->validation->validateIntegerArray($term_ids);
155
- $terms = array();
156
- foreach ( $term_ids as $term ){
157
- if ( $term !== 0 ) $terms[] = (int) $term;
158
- }
159
- wp_set_post_terms($data['post_id'], $terms, $taxonomy);
160
- }
161
- }
162
- }
163
-
164
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/class-np-posttypes.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once('class-np-navmenu.php');
3
+ /**
4
+ * Post Types required by Nested Pages
5
+ */
6
+ class NP_PostTypes {
7
+
8
+ public function __construct()
9
+ {
10
+ add_action( 'init', array( $this, 'registerRedirects') );
11
+ add_action( 'trashed_post', array( $this, 'trashHook' ) );
12
+ }
13
+
14
+
15
+ /**
16
+ * Redirects Post Type
17
+ */
18
+ public function registerRedirects()
19
+ {
20
+ $labels = array(
21
+ 'name' => __('Redirects'),
22
+ 'singular_name' => __('Redirect'),
23
+ 'add_new_item'=> 'Add Redirect',
24
+ 'edit_item' => 'Edit Redirect',
25
+ 'view_item' => 'View Redirect'
26
+ );
27
+ $args = array(
28
+ 'labels' => $labels,
29
+ 'public' => false,
30
+ 'show_ui' => false,
31
+ 'menu_position' => 5,
32
+ 'capability_type' => 'post',
33
+ 'hierarchical' => true,
34
+ 'has_archive' => true,
35
+ 'supports' => array('title','editor'),
36
+ 'rewrite' => array('slug' => 'np-redirect', 'with_front' => false)
37
+ );
38
+ register_post_type( 'np-redirect' , $args );
39
+ }
40
+
41
+
42
+
43
+ /**
44
+ * Trash hook - unset parent pages
45
+ */
46
+ public function trashHook($post_id)
47
+ {
48
+ $post_type = get_post_type($post_id);
49
+ if ( $post_type == 'page' ) $this->resetToggles($post_id);
50
+ }
51
+
52
+
53
+ /**
54
+ * Make sure children of trashed pages are viewable in Nested Pages
55
+ */
56
+ private function resetToggles($post_id)
57
+ {
58
+ $visible_pages = unserialize(get_user_meta(get_current_user_id(), 'np_visible_pages', true));
59
+ $child_pages = array();
60
+ $children = new WP_Query(array('post_type'=>'page', 'posts_per_page'=>-1, 'post_parent'=>$post_id));
61
+ if ( $children->have_posts() ) : while ( $children->have_posts() ) : $children->the_post();
62
+ array_push($child_pages, get_the_id());
63
+ endwhile; endif; wp_reset_postdata();
64
+ foreach($child_pages as $child_page){
65
+ if ( !in_array($child_page, $visible_pages) ) array_push($visible_pages, $child_page);
66
+ }
67
+ update_user_meta(get_current_user_id(), 'np_visible_pages', serialize($visible_pages));
68
+ }
69
+
70
+ }
includes/class-np-redirects.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Redirects in admin
4
+ */
5
+ class NP_Redirects {
6
+
7
+
8
+ public function __construct()
9
+ {
10
+ add_action('load-edit.php', array($this, 'pageTrashed'));
11
+ add_action('load-edit.php', array($this, 'pageRestored'));
12
+ add_action('load-edit.php', array($this, 'addNPLink'));
13
+ add_filter( "views_edit-page", array($this, 'addNPLink' ));
14
+ }
15
+
16
+
17
+ /**
18
+ * Redirect back to nested pages after pages moved to trashed
19
+ */
20
+ public function pageTrashed()
21
+ {
22
+ $screen = get_current_screen();
23
+ if ( ($screen->id == 'edit-page') && (isset($_GET['trashed'])) && (intval($_GET['trashed']) >0)){
24
+ $redirect = add_query_arg(array('page'=>'nestedpages', 'trashed' => true, 'ids' => $_GET['ids'] ));
25
+ wp_redirect($redirect);
26
+ exit();
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Redirect to nested pages after page moved out of trash
32
+ */
33
+ public function pageRestored()
34
+ {
35
+ $screen = get_current_screen();
36
+ if ( ($screen->id == 'edit-page') && (isset($_GET['untrashed'])) && (intval($_GET['untrashed']) >0)){
37
+ $redirect = add_query_arg(array('page'=>'nestedpages', 'untrashed' => true, 'untrashed' => $_GET['untrashed'] ));
38
+ wp_redirect($redirect);
39
+ exit();
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Add a nested pages link to the subsub list (WP_List_Table class)
45
+ */
46
+ public function addNPLink($views)
47
+ {
48
+ $screen = get_current_screen();
49
+ if ( $screen->parent_file == 'edit.php?post_type=page' ){
50
+ $link = array('Nested Pages' => '<a href="' . esc_url(admin_url('admin.php?page=nestedpages')) . '">Nested Pages</a>');
51
+ $views = array_merge($views, $link);
52
+ }
53
+ return $views;
54
+ }
55
+
56
+ }
includes/class-np-repository-post.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once('class-np-validation.php');
4
+
5
+ class NP_PostRepository {
6
+
7
+ /**
8
+ * Validation Class
9
+ * @var object NP_Validation
10
+ */
11
+ protected $validation;
12
+
13
+ /**
14
+ * New Post ID
15
+ */
16
+ protected $new_id;
17
+
18
+ public function __construct()
19
+ {
20
+ $this->validation = new NP_Validation;
21
+ }
22
+
23
+
24
+ /**
25
+ * Update Order
26
+ * @param array posts
27
+ * @param int parent
28
+ * @since 1.0
29
+ */
30
+ public function updateOrder($posts, $parent = 0)
31
+ {
32
+ $this->validation->validatePostIDs($posts);
33
+ foreach( $posts as $key => $post )
34
+ {
35
+ wp_update_post(array(
36
+ 'ID' => $post['id'],
37
+ 'menu_order' => $key,
38
+ 'post_parent' => $parent
39
+ ));
40
+
41
+ if ( isset($post['children']) ){
42
+ $this->updateOrder($post['children'], $post['id']);
43
+ }
44
+ }
45
+ return true;
46
+ }
47
+
48
+
49
+ /**
50
+ * Update Post
51
+ * @param array data
52
+ * @since 1.0
53
+ */
54
+ public function updatePost($data)
55
+ {
56
+ $this->validation->checkEmpty($data['post_title'], __('Title', 'nestedpages'));
57
+ $date = $this->validation->validateDate($data);
58
+ if ( !isset($_POST['comment_status']) ) $data['comment_status'] = 'closed';
59
+
60
+ $updated_post = array(
61
+ 'ID' => sanitize_text_field($data['post_id']),
62
+ 'post_title' => sanitize_text_field($data['post_title']),
63
+ 'post_author' => sanitize_text_field($data['post_author']),
64
+ 'post_name' => sanitize_text_field($data['post_name']),
65
+ 'post_date' => $date,
66
+ 'comment_status' => sanitize_text_field($data['comment_status']),
67
+ 'post_status' => sanitize_text_field($data['_status'])
68
+ );
69
+ wp_update_post($updated_post);
70
+
71
+ $this->updateTemplate($data);
72
+ $this->updateNestedPagesStatus($data);
73
+
74
+ // Taxonomies
75
+ $this->updateCategories($data);
76
+ $this->updateHierarchicalTaxonomies($data);
77
+
78
+ // Menu Options
79
+ $this->updateNavStatus($data);
80
+ $this->updateNavTitle($data);
81
+ $this->updateLinkTarget($data);
82
+ $this->updateTitleAttribute($data);
83
+ $this->updateNavCSS($data);
84
+
85
+ return true;
86
+ }
87
+
88
+
89
+ /**
90
+ * Update Page Template
91
+ * @param array data
92
+ * @since 1.0
93
+ */
94
+ private function updateTemplate($data)
95
+ {
96
+ $template = sanitize_text_field($data['page_template']);
97
+ update_post_meta(
98
+ $data['post_id'],
99
+ '_wp_page_template',
100
+ $template
101
+ );
102
+ }
103
+
104
+
105
+ /**
106
+ * Update Nav Status (show/hide in nav menu)
107
+ * @since 1.0
108
+ * @param array data
109
+ */
110
+ private function updateNavStatus($data)
111
+ {
112
+ $status = ( isset($data['nav_status']) ) ? 'hide' : 'show';
113
+ $id = ( isset($data['post_id']) ) ? $data['post_id'] : $this->new_id;
114
+ update_post_meta(
115
+ $id,
116
+ 'np_nav_status',
117
+ $status
118
+ );
119
+ }
120
+
121
+
122
+ /**
123
+ * Update Nested Pages Visibility (how/hide in Nested Pages interface)
124
+ * @since 1.0
125
+ * @param array data
126
+ */
127
+ private function updateNestedPagesStatus($data)
128
+ {
129
+ $status = ( isset($data['nested_pages_status']) ) ? 'hide' : 'show';
130
+ $id = ( isset($data['post_id']) ) ? $data['post_id'] : $this->new_id;
131
+ update_post_meta(
132
+ $id,
133
+ 'nested_pages_status',
134
+ $status
135
+ );
136
+ }
137
+
138
+
139
+ /**
140
+ * Update Nested Pages Menu Navigation Label
141
+ * @since 1.0
142
+ * @param array data
143
+ */
144
+ private function updateNavTitle($data)
145
+ {
146
+ if ( isset($data['np_nav_title']) ){
147
+ $title = sanitize_text_field($data['np_nav_title']);
148
+ update_post_meta(
149
+ $data['post_id'],
150
+ 'np_nav_title',
151
+ $title
152
+ );
153
+ }
154
+ }
155
+
156
+
157
+ /**
158
+ * Update Nested Pages Menu Navigation CSS Classes
159
+ * @since 1.0
160
+ * @param array data
161
+ */
162
+ private function updateNavCSS($data)
163
+ {
164
+ if ( isset($data['np_nav_css_classes']) ){
165
+ $css_classes = sanitize_text_field($data['np_nav_css_classes']);
166
+ update_post_meta(
167
+ $data['post_id'],
168
+ 'np_nav_css_classes',
169
+ $css_classes
170
+ );
171
+ }
172
+ }
173
+
174
+
175
+ /**
176
+ * Update Nested Pages Menu Title Attribute
177
+ * @since 1.0
178
+ * @param array data
179
+ */
180
+ private function updateTitleAttribute($data)
181
+ {
182
+ if ( isset($data['np_title_attribute']) ){
183
+ $title_attr = sanitize_text_field($data['np_title_attribute']);
184
+ update_post_meta(
185
+ $data['post_id'],
186
+ 'np_title_attribute',
187
+ $title_attr
188
+ );
189
+ }
190
+ }
191
+
192
+
193
+ /**
194
+ * Update Categories
195
+ * @since 1.0
196
+ * @param array data
197
+ */
198
+ private function updateCategories($data)
199
+ {
200
+ if ( isset($data['post_category']) )
201
+ {
202
+ $this->validation->validateIntegerArray($data['post_category']);
203
+ $cats = array();
204
+ foreach($data['post_category'] as $cat) {
205
+ if ( $cat !== 0 ) $cats[] = (int) $cat;
206
+ }
207
+ wp_set_post_terms($data['post_id'], $cats, 'category');
208
+ }
209
+ }
210
+
211
+
212
+ /**
213
+ * Update Hierarchical Taxonomy Terms
214
+ * @since 1.0
215
+ * @param array data
216
+ */
217
+ private function updateHierarchicalTaxonomies($data)
218
+ {
219
+ if ( isset($data['tax_input']) ) {
220
+ foreach ( $data['tax_input'] as $taxonomy => $term_ids ){
221
+ $this->validation->validateIntegerArray($term_ids);
222
+ $terms = array();
223
+ foreach ( $term_ids as $term ){
224
+ if ( $term !== 0 ) $terms[] = (int) $term;
225
+ }
226
+ wp_set_post_terms($data['post_id'], $terms, $taxonomy);
227
+ }
228
+ }
229
+ }
230
+
231
+
232
+ /**
233
+ * Update Link Target for Redirects
234
+ * @since 1.1
235
+ * @param array data
236
+ */
237
+ private function updateLinkTarget($data)
238
+ {
239
+ $link_target = ( isset($data['link_target']) ) ? "_blank" : "";
240
+ $id = ( isset($data['post_id']) ) ? $data['post_id'] : $this->new_id;
241
+ update_post_meta(
242
+ $id,
243
+ 'np_link_target',
244
+ $link_target
245
+ );
246
+ }
247
+
248
+
249
+ /**
250
+ * Update a Redirect
251
+ * @since 1.1
252
+ * @param array data
253
+ */
254
+ public function updateRedirect($data)
255
+ {
256
+ $this->validation->checkEmpty($data['post_title'], __('Label', 'nestedpages'));
257
+ $updated_post = array(
258
+ 'ID' => sanitize_text_field($data['post_id']),
259
+ 'post_title' => sanitize_text_field($data['post_title']),
260
+ 'post_status' => sanitize_text_field($data['_status']),
261
+ 'post_content' => sanitize_text_field($data['post_content']),
262
+ 'post_parent' => sanitize_text_field($data['parent_id'])
263
+ );
264
+ wp_update_post($updated_post);
265
+
266
+ $this->updateNavStatus($data);
267
+ $this->updateNestedPagesStatus($data);
268
+ $this->updateLinkTarget($data);
269
+ $this->updateTitleAttribute($data);
270
+ $this->updateNavCSS($data);
271
+
272
+ return true;
273
+ }
274
+
275
+
276
+ /**
277
+ * Save a new Redirect
278
+ * @since 1.1
279
+ * @param array data
280
+ */
281
+ public function saveRedirect($data)
282
+ {
283
+ $this->validation->validateRedirect($data);
284
+ $new_link = array(
285
+ 'post_title' => sanitize_text_field($data['np_link_title']),
286
+ 'post_status' => sanitize_text_field($data['_status']),
287
+ 'post_content' => sanitize_text_field($data['np_link_content']),
288
+ 'post_parent' => sanitize_text_field($data['parent_id']),
289
+ 'post_type' => 'np-redirect'
290
+ );
291
+ $this->new_id = wp_insert_post($new_link);
292
+
293
+ $this->updateNavStatus($data);
294
+ $this->updateNestedPagesStatus($data);
295
+ $this->updateLinkTarget($data);
296
+ return $this->new_id;
297
+ }
298
+
299
+ }
nestedpages.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Nested Pages
4
  Plugin URI: http://nestedpages.com
5
  Description: Provides an intuitive drag and drop interface for managing pages in the Wordpress admin, while maintaining quick edit functionality.
6
- Version: 1.1
7
  Author: Kyle Phillips
8
  Author URI: https://github.com/kylephillips
9
  License: GPLv2 or later.
3
  Plugin Name: Nested Pages
4
  Plugin URI: http://nestedpages.com
5
  Description: Provides an intuitive drag and drop interface for managing pages in the Wordpress admin, while maintaining quick edit functionality.
6
+ Version: 1.1.1
7
  Author: Kyle Phillips
8
  Author URI: https://github.com/kylephillips
9
  License: GPLv2 or later.
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://nestedpages.com/
4
  Tags: pages, admin, nested, tree view, page tree, sort, quick edit
5
  Requires at least: 3.8
6
  Tested up to: 4.0
7
- Stable tag: 1.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
4
  Tags: pages, admin, nested, tree view, page tree, sort, quick edit
5
  Requires at least: 3.8
6
  Tested up to: 4.0
7
+ Stable tag: 1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
views/link-form.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Modal Form for adding a new link
4
+ */
5
+ $post_type_object = get_post_type_object( 'page' );
6
+ $can_publish = current_user_can( $post_type_object->cap->publish_posts );
7
+ ?>
8
+ <div class="modal fade" id="np-link-modal">
9
+ <div class="modal-dialog">
10
+ <div class="modal-content">
11
+ <form method="get" action="" class="np-modal-form np-new-link-form">
12
+ <div class="modal-header">
13
+ <h4 class="modal-title" id="np-add-link-title"><?php _e('Add Link', 'nestedpages'); ?></h4>
14
+ </div>
15
+ <div class="modal-body">
16
+ <div class="form-interior">
17
+
18
+ <div class="np-quickedit-error np-new-link-error" style="clear:both;display:none;"></div>
19
+
20
+ <div class="left">
21
+
22
+ <div class="form-control">
23
+ <label><?php _e( 'Menu Title' ); ?></label>
24
+ <input type="text" name="np_link_title" class="np_link_title" value="" />
25
+ </div>
26
+
27
+ <div class="form-control">
28
+ <label><?php _e( 'URL' ); ?></label>
29
+ <input type="text" name="np_link_content" class="np_link_content" value="" />
30
+ </div>
31
+
32
+ <div class="form-control">
33
+ <label><?php _e( 'Status' ); ?></label>
34
+ <select name="_status" class="np_link_status">
35
+ <?php if ( $can_publish ) : ?>
36
+ <option value="publish"><?php _e( 'Published' ); ?></option>
37
+ <option value="future"><?php _e( 'Scheduled' ); ?></option>
38
+ <?php endif; ?>
39
+ <option value="pending"><?php _e( 'Pending Review' ); ?></option>
40
+ <option value="draft"><?php _e( 'Draft' ); ?></option>
41
+ </select>
42
+ </div>
43
+
44
+ </div><!-- .left -->
45
+
46
+ <div class="right">
47
+
48
+ <?php if ( current_user_can('edit_theme_options') ) : ?>
49
+ <label class="checkbox">
50
+ <input type="checkbox" name="nav_status" class="np_link_nav_status" value="hide" />
51
+ <span class="checkbox-title"><?php _e( 'Hide in Nav Menu', 'nestedpages' ); ?></span>
52
+ </label>
53
+
54
+ <label class="checkbox">
55
+ <input type="checkbox" name="nested_pages_status" class="np_link_status" value="hide" />
56
+ <span class="checkbox-title"><?php _e( 'Hide in Nested Pages', 'nestedpages' ); ?></span>
57
+ </label>
58
+
59
+ <label class="checkbox">
60
+ <input type="checkbox" name="link_target" class="new_link_target" value="_blank" />
61
+ <span class="checkbox-title"><?php _e( 'Open link in new window', 'nestedpages' ); ?></span>
62
+ </label>
63
+ <?php endif; // Edit theme options ?>
64
+
65
+ </div><!-- .right -->
66
+
67
+ </div><!-- .form-interior -->
68
+ </div>
69
+ <div class="modal-footer">
70
+ <input type="hidden" name="parent_id" class="parent_id" value="">
71
+ <button type="button" class="button modal-close" data-dismiss="modal">Close</button>
72
+ <a accesskey="s" class="button-primary np-save-link alignright">
73
+ <?php _e( 'Save Link', 'nestedpages' ); ?>
74
+ </a>
75
+ <span class="np-qe-loading np-link-loading"></span>
76
+ </div>
77
+ </form>
78
+ </div><!-- /.modal-content -->
79
+ </div><!-- /.modal-dialog -->
80
+ </div><!-- /.modal -->
views/quickedit-redirect.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $post_type_object = get_post_type_object( 'np-redirect' );
3
+ $can_publish = current_user_can( $post_type_object->cap->publish_posts );
4
+ ?>
5
+
6
+ <form method="get" action="">
7
+ <div class="form-interior">
8
+ <h3><?php _e('Redirect', 'nestedpages'); ?></h3>
9
+
10
+ <div class="np-quickedit-error" style="clear:both;display:none;"></div>
11
+
12
+ <div class="fields">
13
+
14
+ <div class="left">
15
+
16
+ <div class="form-control">
17
+ <label><?php _e( 'Label', 'nestedpages' ); ?></label>
18
+ <input type="text" name="post_title" class="np_title" value="" />
19
+ </div>
20
+
21
+ <div class="form-control">
22
+ <label><?php _e( 'URL' ); ?></label>
23
+ <input type="text" name="post_content" class="np_content" value="" />
24
+ </div>
25
+
26
+ <div class="form-control">
27
+ <label><?php _e( 'Status' ); ?></label>
28
+ <select name="_status" class="np_status">
29
+ <?php if ( $can_publish ) : ?>
30
+ <option value="publish"><?php _e( 'Published' ); ?></option>
31
+ <option value="future"><?php _e( 'Scheduled' ); ?></option>
32
+ <?php endif; ?>
33
+ <option value="pending"><?php _e( 'Pending Review' ); ?></option>
34
+ <option value="draft"><?php _e( 'Draft' ); ?></option>
35
+ </select>
36
+ </div>
37
+
38
+ </div><!-- .left -->
39
+
40
+ <div class="right">
41
+
42
+ <?php if ( current_user_can('edit_theme_options') ) : ?>
43
+ <div class="form-control">
44
+ <label><?php _e( 'Title Attribute', 'nestedpages' ); ?></label>
45
+ <input type="text" name="np_title_attribute" class="np_title_attribute" value="" />
46
+ </div>
47
+ <div class="form-control">
48
+ <label><?php _e( 'CSS Classes', 'nestedpages' ); ?></label>
49
+ <input type="text" name="np_nav_css_classes" class="np_nav_css_classes" value="" />
50
+ </div>
51
+ <div class="comments">
52
+ <label>
53
+ <input type="checkbox" name="nav_status" class="np_nav_status" value="hide" />
54
+ <span class="checkbox-title"><?php _e( 'Hide in Nav Menu', 'nestedpages' ); ?></span>
55
+ </label>
56
+ </div>
57
+ <div class="comments">
58
+ <label>
59
+ <input type="checkbox" name="nested_pages_status" class="np_status" value="hide" />
60
+ <span class="checkbox-title"><?php _e( 'Hide in Nested Pages', 'nestedpages' ); ?></span>
61
+ </label>
62
+ </div>
63
+ <div class="comments">
64
+ <label>
65
+ <input type="checkbox" name="link_target" class="link_target" value="_blank" />
66
+ <span class="checkbox-title"><?php _e( 'Open link in new window', 'nestedpages' ); ?></span>
67
+ </label>
68
+ </div>
69
+ <?php endif; // Edit theme options?>
70
+
71
+ </div><!-- .right -->
72
+
73
+ </div><!-- .fields -->
74
+
75
+ </div><!-- .form-interior -->
76
+
77
+ <div class="buttons">
78
+ <input type="hidden" name="post_id" class="np_id" value="<?php echo get_the_id(); ?>">
79
+ <input type="hidden" name="parent_id" class="np_parent_id" value="">
80
+ <a accesskey="c" href="#inline-edit" class="button-secondary alignleft np-cancel-quickedit">
81
+ <?php _e( 'Cancel' ); ?>
82
+ </a>
83
+ <a accesskey="s" href="#inline-edit" class="button-primary np-save-quickedit-redirect alignright">
84
+ <?php _e( 'Update' ); ?>
85
+ </a>
86
+ <span class="np-qe-loading"></span>
87
+ </div>
88
+ </form>
views/row-redirect.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Redirect Page
4
+ */
5
+ ?>
6
+ <div class="row">
7
+ <div class="child-toggle"></div>
8
+ <div class="row-inner">
9
+ <i class="np-icon-sub-menu"></i>
10
+ <?php if ( current_user_can('edit_theme_options') ) : ?>
11
+ <i class="handle np-icon-menu"></i>
12
+ <?php endif; ?>
13
+ <a href="<?php echo NP_Helpers::check_url(get_the_content()); ?>" class="page-link page-title" target="_blank">
14
+ <span class="title"><?php the_title(); ?> <i class="np-icon-link"></i></span>
15
+ <?php
16
+
17
+ // Post Status
18
+ if ( $post->post_status !== 'publish' ){
19
+ echo '<span class="status">(' . $post->post_status . ')</span>';
20
+ } else {
21
+ echo '<span class="status"></span>';
22
+ }
23
+
24
+ // Nested Pages Status
25
+ if ( $this->post_data['np_status'] == 'hide' )
26
+ echo '<i class="np-icon-eye-blocked"></i>';
27
+
28
+ // Nav Status
29
+ if ( $this->post_data['nav_status'] == 'hide' ){
30
+ echo '<span class="nav-status">(Hidden)</span>';
31
+ } else {
32
+ echo '<span class="nav-status"></span>';
33
+ }
34
+ ?>
35
+ </a>
36
+
37
+ <a href="#" class="np-toggle-edit"><i class="np-icon-pencil"></i></a>
38
+
39
+ <div class="action-buttons">
40
+
41
+ <a href="#"
42
+ class="np-btn np-quick-edit-redirect"
43
+ data-id="<?php echo get_the_id(); ?>"
44
+ data-parentid="<?php echo $this->post_data['parent_id']; ?>"
45
+ data-title="<?php the_title(); ?>"
46
+ data-url="<?php echo NP_Helpers::check_url(get_the_content()); ?>"
47
+ data-status="<?php echo get_post_status(); ?>"
48
+ data-np-status="<?php echo $this->post_data['np_status']; ?>"
49
+ data-navstatus="<?php echo $this->post_data['nav_status']; ?>"
50
+ data-navtitleattr="<?php echo $this->post_data['nav_title_attr']; ?>"
51
+ data-navcss="<?php echo $this->post_data['nav_css']; ?>"
52
+ data-linktarget="<?php echo $this->post_data['link_target']; ?>">
53
+ <?php _e('Quick Edit', 'nestedpages'); ?>
54
+ </a>
55
+
56
+ <?php if ( current_user_can('delete_pages') ) : ?>
57
+ <a href="<?php echo get_delete_post_link(get_the_id(), '', true); ?>" class="np-btn np-btn-trash">
58
+ <i class="np-icon-remove"></i>
59
+ </a>
60
+ <?php endif; ?>
61
+
62
+ </div><!-- .action-buttons -->
63
+ </div><!-- .row-inner -->
64
+ </div><!-- .row -->