PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.2.8
Adminify – White Label, Admin Menu Editor, Login Customizer v4.2.8
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / Inc / Modules / MenuDuplicator / MenuDuplicator.php

MenuDuplicator.php in Adminify – White Label, Admin Menu Editor, Login Customizer 4.2.8, at Inc/Modules/MenuDuplicator/MenuDuplicator.php

282 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PXLBSAdminify\Inc\Modules\MenuDuplicator;
4
5 use PXLBSAdminify\Inc\Utils;
6
7 // no direct access allowed
8 if (!defined('ABSPATH')) {
9 exit;
10 }
11
12 /**
13 * @package WP Adminify
14 * Module: Menu Duplicator
15 *
16 * @author Jewel Theme <support@jeweltheme.com>
17 */
18
19 class MenuDuplicator
20 {
21
22 public function __construct()
23 {
24 add_action('admin_footer', [$this, 'add_duplicate_button'], 11);
25 add_action('admin_footer', [$this, 'creating_menu_duplicate'], 6);
26
27 // Duplicate Nav Menu Item
28 add_action('admin_footer', [$this, 'duplicate_nav_menu_item'], 12);
29 }
30
31 /**
32 * Duplicate Menu Button
33 *
34 * @return void
35 */
36 public function add_duplicate_button()
37 {
38 // Only users who can manage menus may see/use the duplicate action.
39 if ( ! current_user_can( 'edit_theme_options' ) ) {
40 return;
41 }
42
43 $current_screen = get_current_screen();
44 $current_menu = (int) get_user_option('nav_menu_recently_edited');
45 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
46 if ($current_screen->id == 'nav-menus' && isset($_GET['menu']) && sanitize_text_field(wp_unslash($_GET['menu'])) != '0') {
47 // CSRF protection: sign the duplicate action with a nonce tied to the menu id.
48 $duplicate_url = wp_nonce_url(
49 add_query_arg( 'adminify-menu-duplicate', $current_menu, admin_url( 'nav-menus.php' ) ),
50 'adminify_duplicate_menu_' . $current_menu
51 );
52 $return = '';
53 $return .= '<div class="AdminifyDuplicateMenuSpinenr spinner"></div><a class="AdminifyDuplicateMenuClick button button-primary button-large menu-save" href="' . esc_url( $duplicate_url ) . '">' . __('Duplicate Menu', 'adminify') . '</a>';
54 ?>
55 <script type="text/javascript">
56 var update_menu_form = jQuery('#update-nav-menu');
57 update_menu_form.find('.publishing-action').append('<?php echo Utils::kses_custom($return); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- kses_custom() is a wp_kses() wrapper; output already escaped. ?>');
58 jQuery('.AdminifyDuplicateMenuClick').click(function() {
59 jQuery('.AdminifyDuplicateMenuSpinenr').addClass('is-active').show();
60 });
61 </script>
62
63 <?php
64 }
65 }
66
67 /**
68 * Creating Menu Duplication
69 *
70 * @return void
71 */
72 public function creating_menu_duplicate()
73 {
74 $current_screen = get_current_screen();
75 if ($current_screen->id == 'nav-menus') {
76 if (isset($_GET['adminify-menu-duplicate'])) {
77
78 $id = intval(wp_unslash($_GET['adminify-menu-duplicate']));
79
80 // Authorization: only menu managers may duplicate.
81 if ( ! current_user_can( 'edit_theme_options' ) ) {
82 return;
83 }
84
85 // CSRF: verify the nonce that was attached to the duplicate link.
86 $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
87 if ( ! wp_verify_nonce( $nonce, 'adminify_duplicate_menu_' . $id ) ) {
88 wp_die( esc_html__( 'Security check failed.', 'adminify' ) );
89 }
90
91 $source = wp_get_nav_menu_object($id);
92 $duplicate = $this->render_menu_duplicate($id, $source->name . ' ' . __('(Copy)', 'adminify'));
93 if ($duplicate) {
94 ?>
95 <script type="text/javascript">
96 window.location.replace("<?php echo esc_url(admin_url('nav-menus.php?action=edit&menu=' . $duplicate)); ?>");
97 </script>
98 <?php
99 } else {
100 ?>
101 <script type="text/javascript">
102 window.location.replace("<?php echo esc_url(admin_url('nav-menus.php')); ?>");
103 </script>
104 <?php
105 }
106 }
107 }
108 }
109
110
111 /**
112 * Render Menu Duplicate
113 *
114 * @return void
115 */
116 public function render_menu_duplicate($id = null, $name = null)
117 {
118
119 // Sanity check
120 if (empty($id) || empty($name)) {
121 return false;
122 }
123
124 $id = intval($id);
125 $name = sanitize_text_field($name);
126 $source = wp_get_nav_menu_object($id);
127 $source_items = wp_get_nav_menu_items($id);
128
129 $menu_exists = wp_get_nav_menu_object($name);
130
131 if (!$menu_exists) {
132 $new_id = wp_create_nav_menu($name);
133 } else {
134 return $new_id = $this->render_menu_duplicate($id, $name . ' ' . __('(Copy)', 'adminify'));
135 }
136
137 if (!$new_id || is_array($new_id)) {
138 return false;
139 }
140
141 // Key is the original db ID, val is the new
142 $rel = [];
143
144 $i = 1;
145 foreach ($source_items as $menu_item) {
146 $args = [
147 'menu-item-db-id' => $menu_item->db_id,
148 'menu-item-object-id' => $menu_item->object_id,
149 'menu-item-object' => $menu_item->object,
150 'menu-item-position' => $i,
151 'menu-item-type' => $menu_item->type,
152 'menu-item-title' => $menu_item->title,
153 'menu-item-url' => $menu_item->url,
154 'menu-item-description' => $menu_item->description,
155 'menu-item-attr-title' => $menu_item->attr_title,
156 'menu-item-target' => $menu_item->target,
157 'menu-item-classes' => implode(' ', $menu_item->classes),
158 'menu-item-xfn' => $menu_item->xfn,
159 'menu-item-status' => $menu_item->post_status,
160 ];
161
162 $parent_id = wp_update_nav_menu_item($new_id, 0, $args);
163
164 $rel[$menu_item->db_id] = $parent_id;
165
166 // did it have a parent? if so, we need to update with the NEW ID
167 if ($menu_item->menu_item_parent) {
168 $args['menu-item-parent-id'] = $rel[$menu_item->menu_item_parent];
169 $parent_id = wp_update_nav_menu_item($new_id, $parent_id, $args);
170 }
171
172 // allow developers to run any custom functionality they'd like
173 do_action('pxlbsadminify_duplicate_menu_item', $menu_item, $args);
174
175 $i++;
176 }
177
178 return $new_id;
179 }
180
181
182 /**
183 * Duplicate Nav Menu Item
184 *
185 * @return void
186 */
187 public function duplicate_nav_menu_item()
188 {
189 global $pagenow;
190
191 if ($pagenow != 'nav-menus.php' || !current_user_can('edit_theme_options')) {
192 return;
193 }
194
195 ?>
196 <script type="text/javascript">
197 (function($) {
198
199 "use strict";
200
201 function adminifyGetMenuID(el) {
202 return el.attr('id').replace('menu-item-', '') * 1;
203 }
204
205 function adminifyGetMenu(el) {
206 return el.get(0).className.split('menu-item-depth-')[1].split(' ')[0];
207 }
208
209 $(document).on('mouseover', 'li.menu-item:not(.adminify-duplicator-enabled)', function(e) {
210
211 var menu_item_enable = $(this).addClass('adminify-duplicator-enabled');
212
213 menu_item_enable.find('.menu-item-actions').append('<span class="meta-sep hide-if-no-js"> | </span><a class="item-duplicate-this submitcancel hide-if-no-js" href="#">Duplicate</a>');
214
215 });
216
217 $(document).on('click', 'li.menu-item.adminify-duplicator-enabled .item-duplicate-this', function(e) {
218
219 e.preventDefault();
220 var li = $(this).closest('li.menu-item'),
221 depth = 'menu-item-depth-' + adminifyGetMenu(li),
222 availables = $('#menu-to-edit li[id^=menu-item-]'),
223 ids = [],
224 nowId = adminifyGetMenuID(li),
225 newId, newEl, form_data;
226
227 form_data = {
228 action: 'add-menu-item',
229 menu: $('#menu').val(),
230 'menu-settings-column-nonce': $('#menu-settings-column-nonce').val(),
231 'menu-item': {
232 '-1': {
233 'menu-item-db-id': 0,
234 'menu-item-object-id': li.find('input.menu-item-data-object-id').val(),
235 'menu-item-object': li.find('input.menu-item-data-object').val(),
236 'menu-item-parent-id': li.find('input.menu-item-data-parent-id').val(),
237 'menu-item-type': li.find('input.menu-item-data-type').val(),
238 'menu-item-title': li.find('input.edit-menu-item-title').val(),
239 'menu-item-url': li.find('input.edit-menu-item-url').val(),
240 'menu-item-description': li.find('textarea.edit-menu-item-description').val(),
241 'menu-item-attr-title': li.find('input.edit-menu-item-attr-title').val(),
242 'menu-item-target': li.find('.field-link-target input[type=checkbox]').is(':checked') ? '_blank' : '',
243 'menu-item-classes': li.find('input.edit-menu-item-classes').val(),
244 'menu-item-xfn': li.find('input.edit-menu-item-xfn').val()
245 }
246 }
247 };
248
249 $.post(ajaxurl, form_data, function(menuMarkup) {
250 // console.log($(menuMarkup));
251
252 var newElement = $(menuMarkup);
253
254 $('.hide-column-tog').not(':checked').each(function() {
255 newElement.find('.field-' + $(this).val()).addClass('hidden-field');
256 });
257
258 newElement.removeClass('menu-item-depth-0');
259 newElement.addClass(depth);
260
261 newElement = newElement.wrap('<div>').parent().html();
262
263 if (li.next().hasClass(depth) || li.parent().children('li').last().get(0) === li.get(0)) {
264 li.after(newElement);
265 } else if (adminifyGetMenu(li.next()) < adminifyGetMenu(li)) {
266 li.after(newElement);
267 } else {
268 if (adminifyGetMenu(li) != 0) {
269 depth = 'menu-item-depth-' + (adminifyGetMenu(li) - 1);
270 }
271 li.nextUntil('.' + depth).last().after(newElement);
272 }
273 });
274
275 });
276
277 })(jQuery)
278 </script>
279 <?php
280 }
281 }
282