PluginProbe
Menu Duplicator / trunk
Menu Duplicator vtrunk
trunk 0.2 0.4 0.5 0.6 0.7 0.8
menu-duplicator / menu-duplicator.php

menu-duplicator.php in Menu Duplicator trunk, at menu-duplicator.php

281 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Menu Duplicator
4 * Plugin URI: http://jereross.com/menu-duplicator/
5 * Description: Quickly duplicate WordPress menus
6 * Version: 0.8
7 * Author: Jeremy Ross
8 * Author URI: http://jereross.com
9 * Requires at least: 4.0
10 *
11 * Menu Duplicator is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * any later version.
15 *
16 * Menu Duplicator is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Menu Duplicator. If not, see http://www.gnu.org/licenses/.
23 *
24 * @package MenuDuplicator
25 */
26
27 // Exit if accessed directly.
28 if (! defined('ABSPATH')) {
29 exit;
30 }
31
32 // Only execute inside the dashboard.
33 if (! is_admin()) {
34 return;
35 }
36
37 define('MD_VERSION', '0.5');
38 define('MD_TOOLS_PAGE', esc_url(admin_url('tools.php')).'?page=menu-duplicator');
39 define('MD_PLUGIN_URL', plugin_dir_url(__FILE__));
40
41
42 /**
43 * Create Menu & Page for Menu Duplicator
44 *
45 * Add a menu item and page for Menu Duplicator
46 *
47 * @since Menu Duplicator 0.1
48 */
49 function menu_duplicator_create_page()
50 {
51 add_management_page('Menu Duplicator', 'Menu Duplicator', 'edit_theme_options', 'menu-duplicator', 'menu_duplicator_settings_page');
52 }
53 add_action('admin_menu', 'menu_duplicator_create_page');
54
55
56 /**
57 * Process Menu Duplicator Form
58 *
59 * Check capabilities and nonce then process the form.
60 *
61 * @since Menu Duplicator 0.1
62 */
63 function menu_duplicator_process_form()
64 {
65
66 // Allow only users with edit_theme_options capabilities.
67 if (! current_user_can('edit_theme_options')) {
68 return;
69 }
70
71 // Check for POST and wpnonce.
72 if (isset($_POST['type']) && 'menu-duplicator' === $_POST['type'] && check_admin_referer('menu-duplicator', 'menu-duplicator-nonce')) {
73 if (! isset($_POST['menu-to-duplicate'])) { // Input var okay.
74 menu_duplicator_admin_message('error', 'Menu to duplicate was not supplied. Please select a menu from the list below.');
75 return;
76 }
77
78 if (! isset($_POST['new-menu-name'])) { // Input var okay.
79 menu_duplicator_admin_message('error', 'Name for the new menu was not supplied. Please input a name for the menu below.');
80 return;
81 }
82
83 menu_duplicator_settings_update($_POST['menu-to-duplicate'], $_POST['new-menu-name']);
84 }
85 }
86 add_action('init', 'menu_duplicator_process_form');
87
88
89 /**
90 * Menu Page Tab
91 * Add a tab to existing menu.php page for a better user experience
92 * A bit "hacky" but it works, this will need to be tested with each WordPress release
93 *
94 * @since Menu Duplicator 0.1
95 */
96 function menu_duplicator_screen_check()
97 {
98
99 // Allow only users with edit_theme_options capabilities.
100 if (! current_user_can('edit_theme_options')) {
101 return;
102 }
103
104 $current_screen = get_current_screen();
105 $menu_count = count(wp_get_nav_menus());
106
107 if ($current_screen->id === 'nav-menus' and $menu_count) {
108 wp_enqueue_script('menu_duplicator_script', MD_PLUGIN_URL . '/scripts/menu-duplicator.js', false, '1.0');
109 // Output jQuery to create a new tab within the Menus dashboard page.
110 add_action('admin_head', 'menu_duplicator_admin_head_js');
111 }
112 }
113 add_action('current_screen', 'menu_duplicator_screen_check');
114
115
116 /**
117 * Menu Page Tab
118 * Add a tab to existing menu.php page for a better user experience
119 * A bit "hacky" but it works, this will need to be tested with each WordPress release
120 *
121 * @since Menu Duplicator 0.2
122 */
123 function menu_duplicator_admin_head_js()
124 {
125 ?>
126 <script type="text/javascript">var MD_TOOLS_PAGE = "<?php echo esc_url(MD_TOOLS_PAGE); ?>";</script>
127 <?php
128 }
129
130
131 /**
132 * Menu Duplicator Settings Page
133 *
134 * Creates HTML output for the Menu Duplicator page.
135 *
136 * @since Menu Duplicator 0.1
137 */
138 function menu_duplicator_settings_page()
139 {
140 $nav_menus = wp_get_nav_menus(); ?>
141 <div class="wrap">
142
143 <h1>Menu Duplicator</h1>
144
145 <div id="menu-duplicator-wrap">
146 <form method="post" action="<?php echo esc_attr(MD_TOOLS_PAGE); ?>">
147 <table class="form-table">
148 <tbody>
149 <tr>
150 <th>
151 <label for="menu-to-duplicate">Existing Menu <span class="description">(required)</span></label>
152 </th>
153 <td>
154 <select id="menu-to-duplicate" name="menu-to-duplicate" required>
155 <option value="">&mdash; Select a Menu &mdash;</option>
156 <?php foreach ($nav_menus as $menu) : ?>
157 <option value="<?php echo esc_attr($menu->term_id); ?>">
158 <?php echo esc_html(wp_html_excerpt($menu->name, 40, '&hellip;')); ?>
159 </option>
160 <?php endforeach; ?>
161 </select>
162 </td>
163 </tr>
164 <tr>
165 <th>
166 <label for="new-menu-name">New Menu Name <span class="description">(required)</span></label>
167 </th>
168 <td>
169 <input type="text" type="text" name="new-menu-name" id="new-menu-name" class="regular-text" required>
170 </td>
171 </tr>
172 </tbody>
173 </table>
174 <input type="hidden" name="type" value="menu-duplicator">
175 <?php submit_button('Duplicate', 'primary', 'submit', true); ?>
176 <?php wp_nonce_field('menu-duplicator', 'menu-duplicator-nonce'); ?>
177 </form>
178 </div>
179
180 </div>
181 <?php
182 }
183
184
185 /**
186 * Duplicate Menu
187 *
188 * Function to duplicate menus
189 *
190 * @param string $menu_to_duplicate Type of message to dipaly. Default error.
191 * @param string $new_menu_name Message to display.
192 *
193 * @since Menu Duplicator 0.1
194 */
195 function menu_duplicator_settings_update($menu_to_duplicate, $new_menu_name)
196 {
197 if (! isset($menu_to_duplicate)) { // Input var okay.
198 menu_duplicator_admin_message('error', 'Menu to duplicate was not supplied. Please select a menu from the list below.');
199 return;
200 }
201
202 if (! isset($new_menu_name)) { // Input var okay.
203 menu_duplicator_admin_message('error', 'Name for the new menu was not supplied. Please input a name for the menu below.');
204 return;
205 }
206
207 $existing_menu_id = intval($menu_to_duplicate); // Input var okay.
208 $new_menu_name = sanitize_text_field($new_menu_name); // Input var okay.
209 $new_menu_id = wp_create_nav_menu($new_menu_name);
210 $existing_menu_items = wp_get_nav_menu_items($existing_menu_id);
211
212 if (is_wp_error($new_menu_id)) {
213 menu_duplicator_admin_message('error', 'Menu <strong>'.$new_menu_name.'</strong> already exists, please select a different name.');
214 return;
215 }
216
217 // [Loop each existing menu item, to create a new menu item with the new menu id.
218 foreach ($existing_menu_items as $key => $value) {
219
220 // Create new menu item to get the id.
221 $new_menu_item_id = wp_update_nav_menu_item($new_menu_id, 0, null);
222
223 // Store all parent child relationships in an array.
224 $parent_child[ $value->db_id ] = $new_menu_item_id;
225
226 if (isset($parent_child[ $value->menu_item_parent ])) {
227 $menu_item_parent_id = $parent_child[ $value->menu_item_parent ];
228 } else {
229 $menu_item_parent_id = 0;
230 }
231
232 $args = array(
233 'menu-item-db-id' => $value->db_id,
234 'menu-item-object-id' => $value->object_id,
235 'menu-item-object' => $value->object,
236 'menu-item-parent-id' => intval($menu_item_parent_id),
237 'menu-item-position' => $value->menu_order,
238 'menu-item-type' => $value->type,
239 'menu-item-title' => $value->title,
240 'menu-item-url' => $value->url,
241 'menu-item-description' => $value->description,
242 'menu-item-attr-title' => $value->attr_title,
243 'menu-item-target' => $value->target,
244 'menu-item-classes' => implode(' ', $value->classes),
245 'menu-item-xfn' => $value->xfn,
246 'menu-item-status' => $value->post_status,
247 );
248
249 // Update the menu nav item with all information.
250 wp_update_nav_menu_item($new_menu_id, $new_menu_item_id, $args);
251 }
252
253 menu_duplicator_admin_message('success', '<strong>' . esc_html($new_menu_name) . '</strong> menu has been created. <a href="' . esc_url(admin_url('nav-menus.php')) . '?action=edit&menu=' . $new_menu_id . '">Edit Menu</a>');
254 }
255
256
257 /**
258 * Admin Messages
259 *
260 * Function to create nice looking admin notices inside the WordPress dashboard
261 *
262 * @since Menu Duplicator 0.1
263 *
264 * @param string $status Type of message to dipaly. Default error.
265 * @param string $message Message to display.
266 */
267 function menu_duplicator_admin_message($status, $message)
268 {
269 add_action(
270 'admin_notices', function () use ($status, $message) {
271 if (! in_array($status, array( 'error', 'warning', 'success', 'info' ), true)) {
272 $class = 'error';
273 } else {
274 $class = $status;
275 }
276
277 echo '<div class="notice notice-' . esc_attr($class) . ' is-dismissible"><p>' . $message . '</p></div>'; // WPCS: xss ok.
278 }
279 );
280 }
281