Shortcode in Menus - Version 2.0

Version Description

  • Added new Shortcode box to Menu Editor
  • Added html support.
  • Deprecated Links box basis.
  • Added screenshots
  • Updated readme and instructions
Download this release

Release Info

Developer gagan0123
Plugin Icon 128x128 Shortcode in Menus
Version 2.0
Comparing to
See all releases

Code changes from version 1.2 to 2.0

Files changed (4) hide show
  1. index.php +274 -47
  2. js/admin.js +79 -0
  3. js/admin.min.js +1 -0
  4. readme.txt +29 -6
index.php CHANGED
@@ -1,10 +1,9 @@
1
  <?php
2
-
3
  /*
4
  Plugin Name: Shortcodes in Menus
5
  Description: Allows you to add shortcodes in WordPress Navigation Menus
6
  Plugin URI: http://wordpress.org/plugins/shortcode-in-menus/
7
- Version: 1.2
8
  Author URI: http://gagan.pro
9
  Author: Gagan Deep Singh
10
  */
@@ -12,61 +11,289 @@
12
  if (!defined('ABSPATH'))
13
  exit; // Exit if accessed directly
14
 
15
- /**
16
- * Allows shortcode to be saved in database
17
- */
18
 
19
- function gs_sim_allow_saving_shortcode_custom_links($url, $orig_url, $context) {
20
- if ($context == 'db') {
21
- return $orig_url;
22
- }
23
- return $url;
24
- }
25
 
26
- function gs_sim_security_check() {
27
- if (current_user_can('activate_plugins')) {
28
- //Conditionally adding the function for database context for
29
- add_filter('clean_url', 'gs_sim_allow_saving_shortcode_custom_links', 99, 3);
30
- }
31
- }
32
 
33
- add_action('wp_loaded', 'gs_sim_security_check');
 
34
 
35
- /**
36
- * Allows shortcode to be processed and displayed
37
- */
38
- function gs_sim_allow_display_shortcode_custom_links($url, $orig_url, $context) {
39
- if ($context == 'display') {
40
- return do_shortcode($orig_url);
41
- }
42
- return $url;
43
- }
44
 
45
- add_filter('clean_url', 'gs_sim_allow_display_shortcode_custom_links', 1, 3);
 
46
 
47
- /**
48
- * Adding a test shortcode for testing this plugin
49
- * */
50
- add_shortcode('gs_test_shortcode', 'gs_sim_test_shortcode');
51
 
52
- /**
53
- * Returns "Hello World" for testing the shortcode
54
- */
55
- function gs_sim_test_shortcode($data) {
56
- return "http://gagan.pro";
57
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
- if (!function_exists('gs_sim_menu_item')) {
60
 
61
- /**
62
- * Allows adding of full HTML supported shortcodes instead of just URL's
63
- */
64
- function gs_sim_menu_item($item_output, $item) {
65
- if ($item->post_title == 'FULL HTML OUTPUT') {
66
- $item_output = do_shortcode($item->url);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
- return $item_output;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
 
71
  }
72
- add_filter('walker_nav_menu_start_el', 'gs_sim_menu_item', 10, 2);
 
 
1
  <?php
 
2
  /*
3
  Plugin Name: Shortcodes in Menus
4
  Description: Allows you to add shortcodes in WordPress Navigation Menus
5
  Plugin URI: http://wordpress.org/plugins/shortcode-in-menus/
6
+ Version: 2.0
7
  Author URI: http://gagan.pro
8
  Author: Gagan Deep Singh
9
  */
11
  if (!defined('ABSPATH'))
12
  exit; // Exit if accessed directly
13
 
14
+ if (!class_exists('gsShortCodeInMenu')) {
 
 
15
 
16
+ class gsShortCodeInMenu {
 
 
 
 
 
17
 
18
+ /**
19
+ * Hooks, filters and registers everything appropriately
20
+ */
21
+ public function init() {
 
 
22
 
23
+ // register a test shortcode for testing
24
+ add_shortcode('gs_test_shortcode', array($this, 'shortcode'));
25
 
26
+ // setup the meta box
27
+ add_action('admin_init', array($this, 'setup_meta_box'));
 
 
 
 
 
 
 
28
 
29
+ // filter the menu item output on frontend
30
+ add_filter('walker_nav_menu_start_el', array($this, 'start_el'), 10, 2);
31
 
32
+ // filter the menu item before display in admin
33
+ add_filter('wp_setup_nav_menu_item', array($this, 'setup_item'), 10, 1);
 
 
34
 
35
+ // enqueue custom js
36
+ add_action('admin_enqueue_scripts', array($this, 'enqueue'));
37
+
38
+ // add an ajax hack to save the html content
39
+ add_action('wp_ajax_gs_sim_description_hack', array($this, 'description_hack'));
40
+
41
+ // hook to allow saving of shortcode in custom link metabox for legacy support
42
+ add_action('wp_loaded', array($this, 'security_check'));
43
+
44
+ // filter the output when shortcode is saved using custom links, for legacy support
45
+ add_filter('clean_url', array($this, 'display_shortcode'), 1, 3);
46
+ }
47
+
48
+ /**
49
+ * Test shortcode. Output's the developer's url
50
+ *
51
+ * @return string
52
+ */
53
+ public function shortcode() {
54
+ return "http://gagan.pro";
55
+ }
56
+
57
+ /**
58
+ * Gets a new object id,given the current one
59
+ *
60
+ * @param int $last_object_id The current/last object id
61
+ * @return int
62
+ */
63
+ public function new_object_id($last_object_id) {
64
+
65
+ // make sure it's an integer
66
+ $object_id = (int) $last_object_id;
67
+
68
+ // increment it
69
+ $object_id++;
70
+
71
+ // if object_id was 0 to start off with, make it 1
72
+ $object_id = ($object_id < 1) ? 1 : $object_id;
73
+
74
+ // save into the options table
75
+ update_option('gs_sim_last_object_id', $object_id);
76
+
77
+ return $object_id;
78
+ }
79
+
80
+ /**
81
+ * Register our custom meta box
82
+ */
83
+ public function setup_meta_box() {
84
+ add_meta_box('add-shortcode-section', __('Shortcode'), array($this, 'meta_box'), 'nav-menus', 'side', 'default');
85
+ }
86
+
87
+ /**
88
+ * Display our custom meta box
89
+ * @global int $_nav_menu_placeholder A placeholder index for the menu item
90
+ * @global int|string $nav_menu_selected_id (id, name or slug) of the currently-selected menu
91
+ */
92
+ public function meta_box() {
93
+ global $_nav_menu_placeholder, $nav_menu_selected_id;
94
+
95
+ $_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1;
96
+
97
+ $last_object_id = get_option('gs_sim_last_object_id', 0);
98
+ $object_id = $this->new_object_id($last_object_id);
99
+ ?>
100
+ <div class="gs-sim-div" id="gs-sim-div">
101
+ <input type="hidden" class="menu-item-db-id" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-db-id]" value="0" />
102
+ <input type="hidden" class="menu-item-object-id" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-object-id]" value="<?php echo $object_id; ?>" />
103
+ <input type="hidden" class="menu-item-object" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-object]" value="gs_sim" />
104
+ <input type="hidden" class="menu-item-type" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-type]" value="gs_sim" />
105
+ <input type="hidden" id="gs-sim-description-nonce" value="<?php echo wp_create_nonce('gs-sim-description-nonce') ?>" />
106
+ <p id="menu-item-title-wrap">
107
+ <label for="gs-sim-title"><?php _e('Title'); ?></label>
108
+ <input id="gs-sim-title" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-title]" type="text" class="regular-text menu-item-textbox" title="<?php esc_attr_e('Title'); ?>" style="width:100%" />
109
+ </p>
110
+
111
+ <p id="menu-item-html-wrap">
112
+ <textarea style="width:100%;" rows="9" id="gs-sim-html" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-description]" class="code menu-item-textbox" title="<?php esc_attr_e('Text/html/shortcode here!'); ?>"></textarea>
113
+ </p>
114
+
115
+ <p class="button-controls">
116
+ <span class="add-to-menu">
117
+ <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e('Add to Menu'); ?>" name="add-gs-sim-menu-item" id="submit-gs-sim" />
118
+ <span class="spinner"></span>
119
+ </span>
120
+ </p>
121
+
122
+ </div>
123
+ <?php
124
+ }
125
+
126
+ /**
127
+ * Check if the passed content has any shortcode. Inspired from the core's has_shortcode
128
+ *
129
+ * @param string $content The content to check for shortcode
130
+ * @return boolean
131
+ */
132
+ function has_shortcode($content) {
133
 
134
+ if (false != strpos($content, '[')) {
135
 
136
+ preg_match_all('/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER);
137
+
138
+ if (!empty($matches)) {
139
+ return true;
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+
145
+ /**
146
+ * Modifies the menu item display on frontend
147
+ *
148
+ * @param string $item_output The original html.
149
+ * @param object $item The menu item being displayed.
150
+ * @return object
151
+ */
152
+ public function start_el($item_output, $item) {
153
+ // if it isn't our custom object
154
+ if ($item->object != 'gs_sim') {
155
+
156
+ // check the legacy hack
157
+ if ($item->post_title == 'FULL HTML OUTPUT' || $this->has_shortcode($item->url)) {
158
+
159
+ // trigger notice for deprecation
160
+ trigger_error('Using Custom Links is deprecated.'
161
+ . ' Use the new Shortcode box on the Menu Editor.');
162
+
163
+ // then just process as we used to
164
+ $item_output = do_shortcode($item->url);
165
+ }
166
+
167
+ // if it is our object
168
+ } else {
169
+ // just process it
170
+ $item_output = stripslashes(do_shortcode($item->description));
171
+
172
+ }
173
+
174
+ return $item_output;
175
+ }
176
+
177
+ /**
178
+ * Modify the menu item before display on Menu editor
179
+ *
180
+ * @param object $item The menu item
181
+ * @return object
182
+ */
183
+ public function setup_item($item) {
184
+
185
+ // only if it is our object
186
+ if ($item->object == 'gs_sim') {
187
+
188
+ // setup our label
189
+ $item->type_label = __('Shortcode', 'gs_sim');
190
+
191
+ if($item->post_content!= ''){
192
+ $item->description = $item->post_content;
193
+ }else{
194
+
195
+ // set up the description from the transient
196
+ $item->description = get_transient('gs_sim_description_hack_' . $item->object_id);
197
+
198
+ // discard the transient
199
+ delete_transient('gs_sim_description_hack_' . $item->object_id);
200
+ }
201
+ }
202
+ return $item;
203
+ }
204
+
205
+ /**
206
+ * Enqueue our custom js
207
+ *
208
+ * @param string $hook The current screen
209
+ * @return null
210
+ */
211
+ public function enqueue($hook) {
212
+
213
+ // don't enqueue if it isn't the menu editor
214
+ if ('nav-menus.php' != $hook)
215
+ return;
216
+
217
+ // otherwise enqueue with nav-menu.js as a dependency so that our script is loaded after it
218
+ wp_enqueue_script(
219
+ 'gs-sim-admin', plugins_url('/js/admin.min.js', __FILE__), array('nav-menu')
220
+ );
221
  }
222
+
223
+ /**
224
+ * An ajax based workaround to save descriptions without using the custom object type
225
+ */
226
+ public function description_hack() {
227
+ // verify the nonce
228
+ $nonce = $_POST['description-nonce'];
229
+ if (!wp_verify_nonce($nonce, 'gs-sim-description-nonce')) {
230
+ die();
231
+ }
232
+
233
+ // get the menu item
234
+ $item = $_POST['menu-item'];
235
+
236
+ // save the description in a transient. This is what we'll use in setup_item()
237
+ set_transient('gs_sim_description_hack_' . $item['menu-item-object-id'], $item['menu-item-description']);
238
+
239
+ // increment the object id, so it can be used by js
240
+ $object_id = $this->new_object_id($item['menu-item-object-id']);
241
+
242
+ echo $object_id;
243
+
244
+ die();
245
+ }
246
+
247
+ /**
248
+ * Legacy method to allow saving of shortcodes in custom_link url
249
+ *
250
+ * @deprecated since 2.0
251
+ *
252
+ * @param string $url The processed url for displaying/saving
253
+ * @param string $orig_url The url that was submitted, retreived
254
+ * @param string $context Whether saving or displaying
255
+ * @return string
256
+ */
257
+ public function save_shortcode($url, $orig_url, $context) {
258
+
259
+ if ($context == 'db') {
260
+ return $orig_url;
261
+ }
262
+ return $url;
263
+ }
264
+
265
+ /**
266
+ * Allows shortcodes into the custom link url field
267
+ *
268
+ * @deprecated since 2.0
269
+ */
270
+ public function security_check() {
271
+ if (current_user_can('activate_plugins')) {
272
+ //Conditionally adding the function for database context for
273
+ add_filter('clean_url', array($this, 'save_shortcode'), 99, 3);
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Allows shortcode to be processed and displayed
279
+ *
280
+ * @deprecated since 2.0
281
+ *
282
+ * @param string $url The processed url for displaying/saving
283
+ * @param string $orig_url The url that was submitted, retreived
284
+ * @param string $context Whether saving or displaying
285
+ * @return string
286
+ */
287
+ public function display_shortcode($url, $orig_url, $context) {
288
+ if ($context == 'display') {
289
+ return do_shortcode($orig_url);
290
+ }
291
+ return $url;
292
+ }
293
+
294
  }
295
 
296
  }
297
+
298
+ $gs_sim = new gsShortCodeInMenu();
299
+ $gs_sim_init = $gs_sim->init();
js/admin.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery('document').ready(function() {
2
+
3
+ jQuery('#submit-gs-sim').on('click', function(e) {
4
+ // call registerChange like any add
5
+ wpNavMenu.registerChange();
6
+
7
+ // call our custom function
8
+ gsSimAddWidgettoMenu();
9
+ });
10
+
11
+ /**
12
+ * Add our custom Shortcode object to Menu
13
+ *
14
+ * @returns {Boolean}
15
+ */
16
+ function gsSimAddWidgettoMenu( ) {
17
+
18
+ // get the description
19
+ description = jQuery('#gs-sim-html').val();
20
+
21
+ // initialise object
22
+ menuItems = {};
23
+
24
+ // the usual method for ading menu Item
25
+ processMethod = wpNavMenu.addMenuItemToBottom;
26
+
27
+ var t = jQuery('.gs-sim-div');
28
+
29
+ // Show the ajax spinner
30
+ t.find('.spinner').show();
31
+
32
+ // regex to get the index
33
+ re = /menu-item\[([^\]]*)/;
34
+
35
+ m = t.find('.menu-item-db-id');
36
+ // match and get the index
37
+ listItemDBIDMatch = re.exec(m.attr('name')),
38
+ listItemDBID = 'undefined' == typeof listItemDBIDMatch[1] ? 0 : parseInt(listItemDBIDMatch[1], 10);
39
+
40
+ // assign data
41
+ menuItems[listItemDBID] = t.getItemData('add-menu-item', listItemDBID);
42
+ menuItems[listItemDBID]['menu-item-description'] = description;
43
+
44
+ if(menuItems[listItemDBID]['menu-item-title'] === ''){
45
+ menuItems[listItemDBID]['menu-item-title'] = '(Untitled)';
46
+ }
47
+
48
+ // get our custom nonce
49
+ nonce = jQuery('#gs-sim-description-nonce').val();
50
+
51
+ // set up params for our ajax hack
52
+ params = {
53
+ 'action': 'gs_sim_description_hack',
54
+ 'description-nonce': nonce,
55
+ 'menu-item': menuItems[listItemDBID]
56
+ };
57
+
58
+ // call it
59
+ jQuery.post(ajaxurl, params, function(objectId) {
60
+
61
+ // returns the incremented object id, add to ui
62
+ jQuery('#gs-sim-div .menu-item-object-id').val(objectId);
63
+
64
+ // now call the ususl addItemToMenu
65
+ wpNavMenu.addItemToMenu(menuItems, processMethod, function() {
66
+ // Deselect the items and hide the ajax spinner
67
+ t.find('.spinner').hide();
68
+ // Set form back to defaults
69
+ jQuery('#gs-sim-title').val('').blur();
70
+ jQuery('#gs-sim-html').val('');
71
+
72
+ });
73
+
74
+ });
75
+
76
+
77
+ }
78
+
79
+ });
js/admin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery("document").ready(function(){jQuery("#submit-gs-sim").on("click",function(b){wpNavMenu.registerChange();a()});function a(){description=jQuery("#gs-sim-html").val();menuItems={};processMethod=wpNavMenu.addMenuItemToBottom;var b=jQuery(".gs-sim-div");b.find(".spinner").show();re=/menu-item\[([^\]]*)/;m=b.find(".menu-item-db-id");listItemDBIDMatch=re.exec(m.attr("name")),listItemDBID="undefined"==typeof listItemDBIDMatch[1]?0:parseInt(listItemDBIDMatch[1],10);menuItems[listItemDBID]=b.getItemData("add-menu-item",listItemDBID);menuItems[listItemDBID]["menu-item-description"]=description;if(menuItems[listItemDBID]["menu-item-title"]===""){menuItems[listItemDBID]["menu-item-title"]="(Untitled)"}nonce=jQuery("#gs-sim-description-nonce").val();params={action:"gs_sim_description_hack","description-nonce":nonce,"menu-item":menuItems[listItemDBID]};jQuery.post(ajaxurl,params,function(c){jQuery("#gs-sim-div .menu-item-object-id").val(c);wpNavMenu.addItemToMenu(menuItems,processMethod,function(){b.find(".spinner").hide();jQuery("#gs-sim-title").val("").blur();jQuery("#gs-sim-html").val("")})})}});
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Shortcodes in Menus ===
2
- Contributors: gagan0123
3
  Tags: Shortcode, Menus, Custom Link
4
  Requires at least: 3.5
5
  Tested up to: 4.0
6
- Stable tag: 1.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -11,12 +11,28 @@ Allows you to add shortcodes in WordPress Navigation Menus
11
 
12
  == Description ==
13
 
14
- Allows you to add shortcodes in WordPress Navigation Menus so that you can
15
- generate the links dynamically.
16
 
17
- To test this, you can add a custom link with a ShortCode [gs_test_shortcode] as link URL, if it points to http://gagan.pro, plugin is working, if not(even any other ShortCode), then please write a new support ticket with ticket with the ShortCode you used and from which plugin/function that ShortCode is from, so that I'll be able to help you better.
 
 
18
 
19
- PLEASE NOTE: If you want to use a ShortCode that outputs not just the URL, but complete HTML sections, put "FULL HTML OUTPUT" in the "Link Text" option for that link and it will output the complete HTML without breaking your site.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  == Installation ==
22
 
@@ -39,3 +55,10 @@ PLEASE NOTE: If you want to use a ShortCode that outputs not just the URL, but c
39
 
40
  = 1.2 =
41
  * Added ability to echo complete HTML output instead of just URL by using ShortCode
 
 
 
 
 
 
 
1
  === Shortcodes in Menus ===
2
+ Contributors: gagan0123, saurabhshukla
3
  Tags: Shortcode, Menus, Custom Link
4
  Requires at least: 3.5
5
  Tested up to: 4.0
6
+ Stable tag: 2.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
11
 
12
  == Description ==
13
 
14
+ Allows you to add shortcodes in WordPress Navigation Menus so that you can generate links dynamically. Also allows you to add full fledged html sections to navigation menus.
 
15
 
16
+ > *Note*
17
+ >
18
+ > This new version adds a *Shortcode* box on the Nav Menus screen. The earlier functionality using the *Links* box will be deprecated over the next few versions. Please switch to this new box, asap.
19
 
20
+ **Usage**
21
+
22
+ See the [screenshots](https://wordpress.org/plugins/shortcode-in-menus/).
23
+
24
+ Also, see a [great tutorial](https://wordpress.org/support/topic/how-does-it-work-24?replies=22#post-6160111) by Aurovrata Venet
25
+
26
+ == Screenshots ==
27
+
28
+ 1. Check the screen options, if you don't see the *Shortcode* box.
29
+ 1. Check the Shortcode option to see the new Shortcode box.
30
+ 1. Add your shortcode/html to the text area (not a link, in the screenshot). Optionally, add a title.
31
+ 1. The menu item is saved.
32
+ 1. The html is displayed.
33
+ 1. Old Method: In the *Links* box, add your shortcode in the URL field.
34
+ 1. Old Method: If you want to use a shortcode that outputs not just the URL, but complete HTML sections, write *FULL HTML OUTPUT* in the *Link Text* option for that link and it will output the complete HTML without breaking your site.
35
+ 1. Old Method: The menu item is saved.
36
 
37
  == Installation ==
38
 
55
 
56
  = 1.2 =
57
  * Added ability to echo complete HTML output instead of just URL by using ShortCode
58
+
59
+ = 2.0 =
60
+ * Added new Shortcode box to Menu Editor
61
+ * Added html support.
62
+ * Deprecated Links box basis.
63
+ * Added screenshots
64
+ * Updated readme and instructions