📜 ⬆️ ⬇️

Single page wordpress plugin

Why do people love wordpress? Because it's easy to work with him. It does not have the flexibility of great CMS like Joomla and Drupal, which means you won’t get confused. And it is also very popular - which means you can find plug-ins for all occasions.

Not for nothing, despite the condemnation of Lurkmore.ru , Wordpress is used by the Coat of Arms of Sutter , Mark Shuttleworth , and many more. For example me.

I often refer to other blogs in my posts. And I got the idea - why not show next to the nickname of the person to whom I refer, also the icon of his service? For example, a bird from Twitter or a letter B from blogspot? Similar functionality exists, for example, on Wikipedia, and many blog hosting sites allow it (for example, Dreamwidth).
')
This is how the wordpress plugin for Rikki's WP Social Icons was born. Allows for one click to add a link to an account in any service, from a social network to GitHub.

What for?


There are many articles on how to write plugins for Wordpress correctly, but not one of them contained a word about the bugs I encountered in the process. Therefore, I write down my impressions - all of a sudden someone will face the same thing, but he does not know how to decide. And I point out all the improvements that are usually omitted in the training examples.

During the work, I used quite a lot of source codes of other plug-ins, as well as Jenyay developments (references to his series of articles are given in the appendix). But the "artisanal" implementation was not enough. Plugin is so convenient that every end user can modify it himself. So, you need to do so to add to it the support of a new service was a matter of five minutes and one reinstallation.

Especially it helped that I was going to use this plugin myself (i.e., eat dog food , as our American colleagues say). And it was my agony with the first sketches that prompted me where and what could be improved.

We program


We design


To begin with, writing wordpress plugins is not easy , but very simple . You do not need to create any classes from something inherited from there, nor to subjugate with the formats, nor follow any tricky specifications. “Events” are rendered into special objects that work approximately as event-s in “large” applications.

First you need to think carefully about what we need. And we need a way to mark individual words, which would be visible when editing, and was automatically converted into a link in posts, pages and RSS.

Shortcode works very well - a special tag surrounded by square brackets and specially sharpened for processing by plugins. They also appeared in version 2.5, which was released back in 2008, so there are no special compatibility problems.

What format should we accept from the user? Because the final HTML code will differ only in the icon and url th, it would be logical to have one shortcode and one function that would process it. Additional information can be passed through the parameters, which is very convenient. In addition, the less shortcodes we create, the less chance that we will come into conflict with some other plugin.

My shortcode looked like this:

[userid]

Its parameters are:

'id' is an optional parameter. id, under which our hero is registered on the service. For example. torvalds-family.

'type'- service

'url' is an optional parameter. the url we want to refer to (for example, a profile or some kind of separate blog post).

And use it like this:

[userid type="blogspot" id="torvalds-family"]Linus Torvalds[/userid]


or so:

[userid type="blogspot" url="http://blogspot.com"]blogspot[/userid]


We write the core



Now we create the structure for our plugin (see on GitHub ) and throw in our miniature kernel in rikkis-wp-social-icons.php:

 class socialusers { var $options = array( "blogspot" => "http://%s.blogspot.com/", "ljuser" => "http://%s.livejournal.com/", "ljcomm" => "http://livejournal.com/community/%s", "liruboy" => "http://www.liveinternet.ru/users/%s/", "lirugirl" => "http://www.liveinternet.ru/users/%s/", "vk" => "http://vk.com/%s", "twitter" => "http://twitter.com/#!/%s/", "facebook" => "http://www.facebook.com/%s", "google_plus" => "https://plus.google.com/%s", "wordpress" => "http://%s.wordpress.com/", "habrahabr" => "http://%s.habrahabr.ru/", "github" => "http://github.com/users/%s/" ); function socialusers(){ if (!function_exists ('add_shortcode') ) return; add_shortcode('userid', array (&$this, 'icon_func') ); } function icon_func($atts, $content="") { if (!$content) return ""; extract( shortcode_atts ( array('id' => null, 'type' => null, 'url' => null), $atts ) ); if (!$type || !array_key_exists($type, $this->options) ) return $content; if (!$id) $id = $content; $userinfo_url = esc_url(($url) ? $url : sprintf($this->options[$type], trim($id))); $userpic_url = esc_url(plugins_url( "js/img/$type.gif" , __FILE__ )); return "<span style='white-space: nowrap; display: inline !important;'><a href='$userinfo_url' ref='nofollow'><img src='$userpic_url' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;vertical-align:middle; margin-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0;' /></a><a href='$userinfo_url' ref='nofollow'><b>$content</b></a></span>"; } } $socialusers = new socialusers(); 


To avoid the conflict of variable names, we put all our challenges in one class socialusers. The options variable stores the id and URLs of the services we are going to refer to, replacing the username with% s. In the js / img folder we put gif-ki with the corresponding icons.

In the constructor, we check if Wordpress supports shortcode, and, if not, we don’t do anything. It is not good for a user to fall down Wordpress just because he uses the old version.

If everything is in order, we add a new shortcode, indicating the function icon_func from the same class instance as a handler.

icon_func - it is very short and very interesting. It comes with 2 parameters:

$ atts - an array of attributes
$ content - text between tags

The user will see instead of shortcode what this function returns. It is here (in the last return) that the final code of our block is formed.

According to the advice from the comments, all the incoming “lines” are checked via esc_url so that there are no security holes.

Two lines are noteworthy:
 extract( shortcode_atts ( array('id' => null, 'type' => null, 'url' => null), $atts ) ); </<source>     $atts       <source lang="php"> plugins_url( "js/img/$type.gif" , __FILE__ ); 


Gets url icons by type, relative to the current directory. This is what the __FILE__ attribute is for. If it does not exist (and the authors of some plugins and examples have clearly not heard of it), then you have to insert the name of the plug-in directory and still it may not work.

Equally important is trim () for $ id. The fact is that if you double-click on a word in the Wordpress editor, it will highlight the word along with the space after it . As a result, we will get the name of the account with a completely inappropriate space and the link will not work.

In principle, already in this form (17 lines of code + 14 lines of settings) our plugin can be installed and used. A real hacker despises window interfaces :). You can try to pack php and pictures in zip and install them in wordpress, as a regular plugin installs.

I highly recommend setting up local Apache + PHP + mySQL for such experiments, and Wordpress in addition to them. Debugging will go much more fun - for example, instead of installing-reinstalling, you can simply replace the files in the appropriate directory.

Add buttons



A separate component tinyMCE is responsible for editing posts and pages in Wordpress. To pull it from the main PHP, you need to slightly expand our original form:

 class socialusers { var $options = array( "blogspot" => "http://%s.blogspot.com/", "ljuser" => "http://%s.livejournal.com/", "ljcomm" => "http://livejournal.com/community/%s", "liruboy" => "http://www.liveinternet.ru/users/%s/", "lirugirl" => "http://www.liveinternet.ru/users/%s/", "vk" => "http://vk.com/%s", "twitter" => "http://twitter.com/#!/%s/", "facebook" => "http://www.facebook.com/%s", "google_plus" => "https://plus.google.com/%s", "wordpress" => "http://%s.wordpress.com/", "habrahabr" => "http://%s.habrahabr.ru/", "github" => "http://github.com/users/%s/" ); function socialusers(){ if (!function_exists ('add_shortcode') ) return; add_shortcode('userid', array (&$this, 'icon_func') ); add_filter( 'mce_buttons_3', array(&$this, 'mce_buttons') ); add_filter( 'mce_external_plugins', array(&$this, 'mce_external_plugins') ); } function icon_func($atts, $content="") { if (!$content) return ""; extract( shortcode_atts ( array('id' => null, 'type' => null, 'url' => null), $atts ) ); if (!$type || !array_key_exists($type, $this->options) ) return $content; if (!$id) $id = $content; $userinfo_url = esc_url(($url) ? $url : sprintf($this->options[$type], trim($id))); $userpic_url = esc_url(plugins_url( "js/img/$type.gif" , __FILE__ )); return "<span style='white-space: nowrap; display: inline !important;'><a href='$userinfo_url' ref='nofollow'><img src='$userpic_url' alt='[info]' width='17' height='17' style='vertical-align: bottom; border: 0; padding-right: 1px;vertical-align:middle; margin-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0;' /></a><a href='$userinfo_url' ref='nofollow'><b>$content</b></a></span>"; } function mce_external_plugins($plugin_array) { $plugin_array['rikkisocialicons'] = plugins_url ('js/rikkis-wp-social-icons-editor_plugin.js', __FILE__ ); return $plugin_array; } function mce_buttons($buttons) { return array_merge($buttons, array_keys($this->options)); } } $socialusers = new socialusers(); 


Everything is simple here - mce_external_plugins loads JavaScript, in which it will generate buttons, and mce_buttons puts all the keys from the options dictionary there.

Now we have to write JavaScript for the buttons. Alas, tinyMCE is embedded in Wordpress so firmly that the standard way to transfer parameters from PHP to JavaScript for Wordpress plugins will not work here. Of course, one could try to get them through JSon and make sure that the correction needs to be made really only in one place . But this is the case when a minor convenience can cause significant problems.

The framing of the tinyMCE plugin is pretty standard:

 (function() { tinymce.create('tinymce.plugins.RikkiSocialIconsPlugin', { init : function(ed, url) { //   } }, getInfo : function() { return { //   ,     }; } }); tinymce.PluginManager.add('rikkisocialicons', tinymce.plugins.RikkiSocialIconsPlugin); })(); 


Adding one button that frames a selected text fragment with some kind of our shortcode tag looks like this:

 ed.addCommand('mce-blogspot', function() { var newcontent = '[userid type="blogspot"]' + tinyMCE.activeEditor.selection.getContent({format : 'raw'}) + '[/userid]'; tinyMCE.activeEditor.selection.setContent(newcontent); }); ed.addButton('blogspot', { title : 'blogspot', md : 'mce-blogspot', image : url + '/img/blogspot.gif' }); 


Of course, a user who has become accustomed to the fact that our plugin is setting itself up will want to try to generate buttons in a loop:
 (function() { tinymce.create('tinymce.plugins.RikkiSocialIconsPlugin', { var newButtons = ["ljuser", "ljcomm", "liruman", "lirugirl", "ljr", "vk", "twitter"]; tinymce.create('tinymce.plugins.LjusersPlugin', { init : function(ed, url) { var newButtonsLength = newButtons.length, i = 0; while(i < newButtonsLength){ var itemTitle = newButtons[i]; var itemCommand = 'mce'+itemTitle; ed.addCommand(itemCommand, function() { var newcontent = '[userid type="'+itemTitle+'"]' + tinyMCE.activeEditor.selection.getContent({format : 'raw'}) + '[/userid]'; tinyMCE.activeEditor.selection.setContent(newcontent); }); ed.addButton(itemTitle, { title : itemTitle, cmd : itemCommand, image : url + '/img/'+itemTitle+'.gif' }); i++; } }, getInfo : function() { return { longname : 'Rikki\'s WP Social Icons', author : 'Rikki Mongoose', authorurl : 'http://rikkimongoose.ru', infourl : 'http://rikkimongoose.ru/projects/rikkis-wp-social-icons/', version : "1.0" }; } }); tinymce.PluginManager.add('rikkisocialicons', tinymce.plugins.RikkiSocialIconsPlugin); })(); 


And that's right - shouldn't robots work for a programmer?

If you generate the buttons in this way, and then go to the editor, you will immediately feel pride in your skill. The buttons indicated in the array are lined up in a row, and on each one is the same icon that the site visitor or RSS feed reader will see. Very comfortably!

This code looks great, but it has only one drawback - it does not work . This is the first bug that traps you in tinyMCE. At first glance, the buttons look very ordinary - but if you click on them, it turns out that each of them inserts a shortcode with the last element - in our case, with twitter.

We'll have to write everything by hand through the circuit, as suggested in the comments. Like this:

 (function() { var newButtons = ["ljuser", "google_plus", "wordpress", "habrahabr", "github"]; tinymce.create('tinymce.plugins.RikkiSocialIconsPlugin', { init : function(ed, url) { for ( i in newButtons) { var itemTitle = newButtons[i]; (function(itemTitle) { var itemCommand = 'mce'+itemTitle; ed.addCommand(itemCommand, function() { var newcontent = '[userid type="'+itemTitle+'"]' + tinyMCE.activeEditor.selection.getContent({format : 'raw'}) + '[/userid]'; tinyMCE.activeEditor.selection.setContent(newcontent); }); ed.addButton(itemTitle, { title : itemTitle, cmd : itemCommand, image : url + '/img/'+itemTitle+'.gif' }); })(itemTitle); } }, getInfo : function() { return { longname : 'Rikki\'s WP Social Icons', author : 'Rikki Mongoose', authorurl : 'http://rikkimongoose.ru', infourl : 'http://rikkimongoose.ru/projects/rikkis-wp-social-icons/', version : "1.0" }; } }); tinymce.PluginManager.add('rikkisocialicons', tinymce.plugins.RikkiSocialIconsPlugin); })(); 


Testing has shown that this option works fine. Glory to the commentators!

This option is already much better - each button knows its place and works as it should.

Finally, there is a second bug that depends solely on you. And, although Wordpress, tinyMCE and even Internet Explorer are to blame except for not very convenient error handling, it can spoil a lot of blood for you.

A possible error concerns the function tinymce.PluginManager.add (param1, param2). Please write it very carefully .

param1 must match the key to which we added the id array of new buttons in our php file. In my case there should be ' rikkisocialicons ' (because in PHP we have $ plugin_array [' rikkisocialicons ']).
param2 must match what is being created via tinymce.create (). In my case, it is tinymce.plugins.RikkiSocialIconsPlugin, (because we have written in the script tinymce.create (' tinymce.plugins.RikkiSocialIconsPlugin ')

If any of this doesn’t match, your editor’s panel will have a panel with buttons, and the console will report the error ' k is undefined ' that occurred ... of course, in compressed jQuery.min.js, so neither debugging nor watch call will not be the slightest opportunity.

How to add an icon for service X?


First, it's a good idea to go to GitHub and see - has suddenly appeared a fork with the desired icon? If not, then we save ourselves.
  1. Save it in gif format in the same directory as the rest of the icons
  2. We add one more parameter to $ options, where the key matches the name of gif, and the URL is with the url that needs to be substituted, and the user name is replaced with% s (taking this opportunity, send my regards to all C ++ programmers who are in this place sure to experience nostalgia).
  3. If you want a button to go to JavaScript, add an element with the same id to the array newButtons
  4. Pack everything in ZIP
  5. Disable and remove the old version of the plugin. Do not worry, shortcode in your posts will not be affected.
  6. Download the updated version, activate it and enjoy


The order of the buttons depends on the order in the PHP file.

That's all!



The plugin is in the Wordpress directory . In the same place, or on GitHub , you can please the author, having informed that now your stand-alone blog is also decorated with fashionable icons. And you can also add a project with icons of dreamwidth or some other xanga.

Add to catalog



The last step is to add the plugin to the Wordpress directory so that it can be found by a standard search.

Of course, you need to remember to add pre-readme.txt and standard comments in the header of the plugin. Otherwise, the user will not be able to find out what he puts.

The whole procedure is described in detail in a large English manual .

And for those who can not wait - here is a short step by step guide:

  1. Go to wordpress.org and create an account there
  2. Get the password. Go under it and go to the add plugin page . Throw a link to the ZIP there, write the name and description, and send Post.
  3. Now you have to wait. The plug-in from the manual was reviewed at 18 o'clock, with my time was set at 4:00. When the review was over and everything turned out, an empty SVN-directory will appear on the server in which you will need to upload your project
  4. Create a folder locally, checkout there and copy our plug-in to trunc. Compressing the ZIP is not necessary - after a commit, the trunc script on the server will compress everything automatically.
  5. We commit.
  6. Go to the page http://wordpress.org/extend/plugins/rikkis-wp-social-icons/ . Instead of rikkis-wp-social-icons, substitute the name of your plugin.
  7. Go to the page http://wordpress.org/extend/plugins/ and look carefully at the list of Newest Plugins. Here it is, our handsome!


If something is not working - refer to the large manual. Everything is very detailed there.

see also


  1. In the wordpress directory
  2. Official representation on GitHub
  3. Download from GitHub
  4. Original article from Jenyay - part 1 , part 2 , part 3 .


The author will be grateful to everyone who takes patronage over the github version of the project and will develop it further.

Source: https://habr.com/ru/post/147699/


All Articles