May 3rd, 2012
You’ve probably seen the small notification bubble that shows up in the Dashboard menu when a new update is available. Here’s how you can add a menu bubble to your own custom menu:
function add_menu_with_notification_bubble() {
$bubble = sprintf(
' <span class="update-plugins"><span class="update-count">%d</span></span>',
42 //bubble contents
);
add_dashboard_page(
'Example Menu',
'Example Menu' . $bubble,
'read',
'example-menu-item'
);
}
add_action('admin_menu', 'add_menu_with_notification_bubble');
The resulting menu will look like this:

No Comments »
|
WordPress Development
|
Permalink
Posted by Jānis Elsts
April 27th, 2012
Plugins are usually loaded and executed along with the rest of WordPress. However, since each plugin is physically just set of .php, .css and .js files, it is also possible for someone to bypass the normal load order and execute the plugin files directly. They just need to type the right URL in the address bar.
Security-wise, this is dangerous for two reasons:
- Most plugins are not designed to be accessed in this way and will simply crash. The error message, if any, can disclose sensitive information about your site.
- Most plugin developers don’t expect anyone to access the plugin .php files directly. Doing so may trigger a dangerous bug or vulnerability that they haven’t tested for.
While the chances of either happening are admittedly fairly slim, it doesn’t hurt to safe-guard your site from this type of attack. Luckily, disabling direct browser access plugin .php files is very easy. Just create a text file named “.htaccess” in your /wp-content/plugins directory and place this code in the file:
<FilesMatch "\.php$">
Order deny,allow
Deny from all
</FilesMatch>
Now anyone who tries to load a plugin PHP file in their browser will now get a “Forbidden” error.
A word of warning
This will break some plugins. While most plugins only need their CSS, JS and image files to be accessible via the web browser, a handful also rely on .php files being directly accessible (e.g. for AJAX or dynamically generated CSS).
If you find out that one of your plugins doesn’t work, create a .htaccess file in that plugin’s directory and place the following code in the file:
<FilesMatch "\.php$">
Order deny,allow
Allow from all
</FilesMatch>
This will re-enable browser access to .php files for just that directory.
2 Comments
|
Blogging, WordPress Development
|
Permalink
Posted by Jānis Elsts
April 17th, 2012
WordPress transients are very similar to DB options but they also support expiration times. The Transients API documentation states:
Our transient will die naturally of old age once $expiration seconds have passed since we last ran set_transient()
What you might not know if you haven’t explored the source code of the transients API is that transients stored in the database* will not actually “die of old age”. Instead, a stale transient will stick around until someone tries to access it. Only then will WordPress notice that the transient has expired and delete it. If no-one ever attempts to read a stale transient – e.g. because the plugin that created it has been uninstalled – it will stay in your database forever.
* If you have a suitable caching plugin installed, transients can be stored in a fast in-memory cache like APC or Memcached instead of the database.
Fortunately, since the expiration time of each transient is also stored in the database, we can easily clean up stale transients with a little bit of SQL magic. Run the two queries below to delete all stale transients. You can use either phpMyAdmin or a plugin like WP-DBManager to execute SQL queries.
DELETE a, b
FROM
wp_options a, wp_options b
WHERE
a.option_name LIKE "_transient_%" AND
a.option_name NOT LIKE "_transient_timeout_%" AND
b.option_name = CONCAT(
"_transient_timeout_",
SUBSTRING(
a.option_name,
CHAR_LENGTH("_transient_") + 1
)
)
AND b.option_value < UNIX_TIMESTAMP()
DELETE a, b
FROM
wp_options a, wp_options b
WHERE
a.option_name LIKE "_site_transient_%" AND
a.option_name NOT LIKE "_site_transient_timeout_%" AND
b.option_name = CONCAT(
"_site_transient_timeout_",
SUBSTRING(
a.option_name,
CHAR_LENGTH("_site_transient_") + 1
)
)
AND b.option_value < UNIX_TIMESTAMP()
2 Comments
|
WordPress Development
|
Permalink
Posted by Jānis Elsts
April 10th, 2012
Now that spring has arrived (at least in the Northern Hemisphere), it is an excellent time to clean up and decruft your WordPress site. In this post I will show you a number of plugins and techniques that you can use to do just that.
Note: Back up your database [...] Continue Reading…
4 Comments
|
Blogging
|
Permalink
Posted by Jānis Elsts