<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>W-Shadow.com</title>
	<atom:link href="https://w-shadow.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://w-shadow.com</link>
	<description>A blog about web development, software business, and WordPress</description>
	<lastBuildDate>Fri, 17 Feb 2023 18:01:35 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">5745274</site>	<item>
		<title>How To Add the “Add Media” Button When Using wp.editor.initialize()</title>
		<link>https://w-shadow.com/blog/2023/02/17/how-to-add-media-button-using-wp-editor-initialize/</link>
					<comments>https://w-shadow.com/blog/2023/02/17/how-to-add-media-button-using-wp-editor-initialize/#respond</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Fri, 17 Feb 2023 18:01:35 +0000</pubDate>
				<category><![CDATA[WordPress Development]]></category>
		<guid isPermaLink="false">https://w-shadow.com/?p=3809</guid>

					<description><![CDATA[<p>This is just a quick note for anyone who runs into the same issue. If you use wp.editor.initialize() to dynamically create an instance of the WordPress visual editor, the editor will be missing the &#8220;Add Media&#8221; button by default. To fix that, you need to do two things: 1. Add mediaButtons: true to the setting [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2023/02/17/how-to-add-media-button-using-wp-editor-initialize/">How To Add the “Add Media” Button When Using wp.editor.initialize()</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>This is just a quick note for anyone who runs into the same issue. If you use <a href="https://codex.wordpress.org/Javascript_Reference/wp.editor"><code>wp.editor.initialize()</code></a> to dynamically create an instance of the WordPress visual editor, the editor will be missing the &#8220;Add Media&#8221; button by default. To fix that, you need to do two things:</p>
<p><strong>1.</strong> Add <code>mediaButtons: true</code> to the setting object that you pass to the function:</p>
<pre class="brush: jscript; title: ; notranslate">
wp.editor.initialize('textarea-id', {
	tinymce: { /* ... */ },
	quicktags: true,
	mediaButtons: true // &lt;---
});
</pre>
<p><strong>2.</strong> Call <a href="https://developer.wordpress.org/reference/functions/wp_enqueue_media/"><code>wp_enqueue_media()</code></a> somewhere, like from the <a href="https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/">admin_enqueue_scripts</a> hook.</p>
<p>This should make the &#8220;Add Media&#8221; button appear above the editor.</p>The post <a href="https://w-shadow.com/blog/2023/02/17/how-to-add-media-button-using-wp-editor-initialize/">How To Add the “Add Media” Button When Using wp.editor.initialize()</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2023/02/17/how-to-add-media-button-using-wp-editor-initialize/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3809</post-id>	</item>
		<item>
		<title>WordPress Hook Order</title>
		<link>https://w-shadow.com/blog/2022/11/11/wordpress-hook-order/</link>
					<comments>https://w-shadow.com/blog/2022/11/11/wordpress-hook-order/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Fri, 11 Nov 2022 15:28:26 +0000</pubDate>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[WordPress Tools]]></category>
		<guid isPermaLink="false">https://w-shadow.com/?p=3791</guid>

					<description><![CDATA[<p>I&#8217;ve made a site that shows actions and filters executed during different WordPress requests. Why? When I&#8217;m writing a plugin, I sometimes need to know not just what a hook does, but also when it runs in relation to other hooks. The official WordPress documentation has a list of common actions, but it&#8217;s out of [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2022/11/11/wordpress-hook-order/">WordPress Hook Order</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve made a site that shows actions and filters executed during different WordPress requests.</p>
<p><a href="https://hookorder.com"><img data-recalc-dims="1" fetchpriority="high" decoding="async" data-attachment-id="3792" data-permalink="https://w-shadow.com/blog/2022/11/11/wordpress-hook-order/firefox_2022-11-10_21-08-19/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?fit=1051%2C740&amp;ssl=1" data-orig-size="1051,740" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screenshot of the WordPress Hook Execution Order site" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?fit=300%2C211&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?fit=490%2C345&amp;ssl=1" class="alignnone size-large wp-image-3792" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?resize=490%2C345&#038;ssl=1" alt="Screenshot of hookorder.com" width="490" height="345" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?resize=490%2C345&amp;ssl=1 490w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?resize=300%2C211&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?resize=768%2C541&amp;ssl=1 768w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2022/11/firefox_2022-11-10_21-08-19.png?w=1051&amp;ssl=1 1051w" sizes="(max-width: 490px) 100vw, 490px" /></a></p>
<h3>Why?</h3>
<p>When I&#8217;m writing a plugin, I sometimes need to know not just <em>what</em> a hook does, but also <em>when</em> it runs in relation to other hooks. The official WordPress documentation has <a href="https://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request">a list of common actions</a>, but it&#8217;s out of date and far from complete. There have been <a href="http://rachievee.com/the-wordpress-hooks-firing-sequence/">other</a> <a href="https://lance.bio/2017/10/11/wordpress-hooks-and-filters-order-of-precedence/">attempts</a> to document the hook execution order, but those are also a few years old now and not comprehensive.</p>
<p>This is not entirely surprising. WordPress comes with hundreds of unique actions and filters, and some of them are called dozens of times per page. Manually collating and maintaining an ordered list of all hooks would require a huge amount of work. Fortunately, it&#8217;s possible to automate some of that work, which is what I&#8217;ve done for this project.</p>
<h3>What is it?</h3>
<p><a href="https://hookorder.com/">HookOrder.com</a> is a documentation/reference site that shows the execution order of all unique WordPress hooks that are fired on common pages. Notable features include:</p>
<ul>
<li>Up to date with WordPress 6.1 (as of this writing).</li>
<li>Shows both actions and filters. You can hide filters if you&#8217;re only interested in actions.</li>
<li>Hook documentation in the sidebar.</li>
<li>Shows active callbacks, if any.</li>
<li>Shows hook arguments. The actual values will be different on each site, of course, but it can be handy to see some practical examples.</li>
</ul>
<h3>How does it work?</h3>
<p>The hook lists are generated by setting up a basic WordPress site and logging every <code>do_action()</code>, <code>apply_filters()</code>, etc call that happens during a request.  A bunch of post-processing is necessary to normalize and format the results and make the database fast enough to be usable.</p>
<p>For anyone curious, here are some of the tools I used:</p>
<ul>
<li>The <code>all</code> hook makes it possible to catch every action and filter. The hook itself appears to be undocumented, but see <a href="https://developer.wordpress.org/reference/functions/_wp_call_all_hook/">_wp_call_all_hook</a>.</li>
<li><a href="https://pptr.dev/">Puppeteer</a> &#8211; to control headless Chrome.</li>
<li><a href="https://wp-cli.org/">WP-CLI</a> &#8211; to install and configure WordPress, activate plugins, create or import sample data, and so on.</li>
<li><a href="https://github.com/WPTT/theme-test-data">Theme Test Data</a> &#8211; to fill out the site and hopefully make the results more realistic.</li>
<li>SQLite &#8211; for temporary log storage.</li>
<li><a href="https://github.com/YahnisElsts/mini-wp-hook-parser">Hook documentation parser</a> &#8211; to extract hook documentation from WordPress source code.</li>
<li>Miscellaneous <a href="https://symfony.com/components">Symfony Components</a>.</li>
</ul>
<p>&nbsp;</p>The post <a href="https://w-shadow.com/blog/2022/11/11/wordpress-hook-order/">WordPress Hook Order</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2022/11/11/wordpress-hook-order/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3791</post-id>	</item>
		<item>
		<title>Plugin Updates: Securing Download Links</title>
		<link>https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/</link>
					<comments>https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 19 Mar 2013 08:20:06 +0000</pubDate>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin Update Checker]]></category>
		<category><![CDATA[WP Update Server]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3266</guid>

					<description><![CDATA[<p>Ever since the release of the Plugin Update Checker library, one of the most common questions asked has been this: &#8220;How can I secure my download links so that only users who have purchased my plugin can download an update?&#8221; In this post I&#8217;ll try to answer that question in the context of using WP [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/">Plugin Updates: Securing Download Links</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>Ever since the release of the <a href="//w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/">Plugin Update Checker</a> library, one of the most common questions asked has been this: &#8220;How can I secure my download links so that only users who have purchased my plugin can download an update?&#8221;</p>
<p>In this post I&#8217;ll try to answer that question in the context of using <a href="https://github.com/YahnisElsts/wp-update-server">WP Update Server</a> to serve plugin updates. I will also provide a couple of practical examples from one of my commercial plugins.</p>
<p>Lets get started. There are many ways to secure update downloads, but most of them boil down to this:</p>
<ol>
<li>Give some kind of security token to each user. This could be a login + password to a membership site, a license key, or something more esoteric.</li>
<li>Whenever someone installs your plugin on their site, ask them to enter the key/log in/whatever.</li>
<li>Modify the plugin to append the token to each update request.</li>
<li>Write a server script that verifies the token before it allows download.</li>
</ol>
<h3>Choose a Security Token</h3>
<p>How you implement the first two steps will vary greatly depending on your plugin UI and what online store, cart software, or membership plugin you use. You might already have some kind of customer authentication mechanism in place that just needs a bit of tweaking to be used for updates, or you might need to build your own from scratch. There&#8217;s no &#8220;one size fits all&#8221; solution here.</p>
<p>Personally, I prefer to use license keys. Whenever someone buys my <a href="https://adminmenueditor.com/">Admin Menu Editor Pro</a> plugin, the order processing script generates a random key, stores it in the database, and sends the key and a download link to the customer&#8217;s email. Then, when they install the plugin, there&#8217;s a link to enter the license key.</p>
<p>I won&#8217;t include the license management code here because it&#8217;s beyond the scope of this post and built for that specific plugin, but the user interface looks something like this (click to enlarge):</p>
<p style="text-align: center;"><a href="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png"><img data-recalc-dims="1" style=' display: block; margin-right: auto; margin-left: auto;'  decoding="async" data-attachment-id="3274" data-permalink="https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/ame-license-link/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png?fit=647%2C119&amp;ssl=1" data-orig-size="647,119" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Admin Menu Editor Pro entry on the &amp;#8220;Plugins&amp;#8221; page" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png?fit=300%2C55&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png?fit=490%2C90&amp;ssl=1" class="size-large wp-image-3274 aligncenter" title="The &quot;Enter License Key&quot; link is displayed on the &quot;Plugins&quot; page" alt="Admin Menu Editor Pro entry on the &quot;Plugins&quot; page" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link-490x90.png?resize=490%2C90" width="490" height="90" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png?resize=490%2C90&amp;ssl=1 490w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png?resize=300%2C55&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-link.png?w=647&amp;ssl=1 647w" sizes="(max-width: 490px) 100vw, 490px" /></a></p>
<p style="text-align: center;"><a href="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png"><img data-recalc-dims="1" style=' display: block; margin-right: auto; margin-left: auto;'  decoding="async" data-attachment-id="3273" data-permalink="https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/ame-license-window/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png?fit=678%2C486&amp;ssl=1" data-orig-size="678,486" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="ame-license-window" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png?fit=300%2C215&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png?fit=490%2C351&amp;ssl=1" class="size-large wp-image-3273 aligncenter" title="Licensing information window" alt="" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window-490x351.png?resize=490%2C351" width="490" height="351" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png?resize=490%2C351&amp;ssl=1 490w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png?resize=300%2C215&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2013/03/ame-license-window.png?w=678&amp;ssl=1 678w" sizes="(max-width: 490px) 100vw, 490px" /></a></p>
<h3>Add the Token To Update Requests</h3>
<p>Now, how do we add our security token to each update request? You can do that by using the <code>addQueryArgFilter($callback)</code> method of the update checker. The callback function will receive an associative array of query arguments. Just add the token to the list and return the modified array.</p>
<p>Here&#8217;s an example:</p>
<pre class="brush: php; title: ; notranslate">
/* ... Code that initializes the update checker ... */

//Add the license key to query arguments.
$updateChecker-&gt;addQueryArgFilter('wsh_filter_update_checks');
function wsh_filter_update_checks($queryArgs) {
	$settings = get_option('my_plugin_settings');
	if ( !empty($settings&#x5B;'license_key']) ) {
		$queryArgs&#x5B;'license_key'] = $settings&#x5B;'license_key'];
	}
	return $queryArgs;
}
</pre>
<h3>Use the Token To Authorize Downloads</h3>
<p>Finally, let&#8217;s make <a href="https://github.com/YahnisElsts/wp-update-server">the update server</a> verify the security token before it lets the user download an update. To do that, you&#8217;ll need to create a custom server class (see <em><a href="https://github.com/YahnisElsts/wp-update-server#extending-the-server">Extending the server</a></em>) and override <em>at least</em> the <code>Wpup_UpdateServer::checkAuthorization($request)</code> method. Here&#8217;s what you should do in this method:</p>
<ol>
<li>Retrieve the query argument(s) that contains the token by using <code>$request-&gt;param('arg_name')</code>.</li>
<li>Verify the token. Again, this part is up to you. You could look it up in a database, use a checksum to validate it, or something else.</li>
<li>If the token is good, you don&#8217;t need to do anything special.</li>
<li>If the token is invalid, call <code>$this-&gt;exitWithError('Error message')</code> to output an error and stop script execution.</li>
</ol>
<p>Below is a simplified version of the script I use to implement secure updates for  <em>Admin Menu Editor Pro</em>. It is slightly more advanced than the above outline, but the general idea is the same.</p>
<p><em>(Again, license management is beyond the scope of this post, so I&#8217;ve omitted most of the code that deals with loading and validating licenses. Just treat verifyLicenseExists() and other licensing functions as pseudo-code.)</em></p>
<pre class="brush: php; title: ; notranslate">
class SecureUpdateServer extends Wpup_UpdateServer {
	protected $licenseServer;

	public function __construct($serverUrl, $licenseServer) {
		parent::__construct($serverUrl);
		$this-&gt;licenseServer = $licenseServer;
	}

	protected function initRequest($query = null, $headers = null) {
		$request = parent::initRequest($query, $headers);

		//Load the license, if any.
		$license = null;
		if ( $request-&gt;param('license_key') ) {
			$result = $this-&gt;licenseServer-&gt;verifyLicenseExists(
				$request-&gt;slug,
				$request-&gt;param('license_key')
			);
			if ( is_wp_error($result) ) {
				//If the license doesn't exist, we'll output an invalid dummy license.
				$license = new Wslm_ProductLicense(array(
					'status' =&gt; $result-&gt;get_error_code(),
					'error' =&gt; array(
						'code' =&gt; $result-&gt;get_error_code(),
						'message' =&gt; $result-&gt;get_error_message(),
					),
				));
			} else {
				$license = $result;
			}
		}

		$request-&gt;license = $license;
		return $request;
	}

	protected function filterMetadata($meta, $request) {
		$meta = parent::filterMetadata($meta, $request);

		//Include license information in the update metadata. This saves an HTTP request
		//or two since the plugin doesn't need to explicitly fetch license details.
		$license = $request-&gt;license;
		if ( $license !== null ) {
			$meta&#x5B;'license'] = $this-&gt;licenseServer-&gt;prepareLicenseForOutput($license);
		}

		//Only include the download URL if the license is valid.
		if ( $license &amp;&amp; $license-&gt;isValid() ) {
			//Append the license key or to the download URL.
			$args = array( 'license_key' =&gt; $request-&gt;param('license_key') );
			$meta&#x5B;'download_url'] = self::addQueryArg($args, $meta&#x5B;'download_url']);
		} else {
			//No license = no download link.
			unset($meta&#x5B;'download_url']);
		}

		return $meta;
	}

	protected function checkAuthorization($request) {
		parent::checkAuthorization($request);

		//Prevent download if the user doesn't have a valid license.
		$license = $request-&gt;license;
		if ( $request-&gt;action === 'download' &amp;&amp; ! ($license &amp;&amp; $license-&gt;isValid()) ) {
			if ( !isset($license) ) {
				$message = 'You must provide a license key to download this plugin.';
			} else {
				$error = $license-&gt;get('error');
				$message = isset($error) ? $error : 'Sorry, your license is not valid.';
			}
			$this-&gt;exitWithError($message, 403);
		}
	}
}
</pre>
<p>If you have any questions, feel free to leave a comment.</p>The post <a href="https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/">Plugin Updates: Securing Download Links</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/feed/</wfw:commentRss>
			<slash:comments>38</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3266</post-id>	</item>
		<item>
		<title>WordPress Update Server</title>
		<link>https://w-shadow.com/blog/2013/03/12/wordpress-update-server/</link>
					<comments>https://w-shadow.com/blog/2013/03/12/wordpress-update-server/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 12 Mar 2013 10:05:56 +0000</pubDate>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[updates]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3255</guid>

					<description><![CDATA[<p>It&#8217;s been a long time coming, but I&#8217;ve finally released an external update API server for WordPress plugins and themes. Check it out on GitHub. This is the server component to my plugin update checker and theme update checker client libraries. Features Provide updates for private or commercial plugins and themes. From the users&#8217; perspective, the [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2013/03/12/wordpress-update-server/">WordPress Update Server</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>It&#8217;s been a long time coming, but I&#8217;ve finally released an external update API server for WordPress plugins and themes. <a href="https://github.com/YahnisElsts/wp-update-server">Check it out on GitHub</a>. This is the server component to my <a href="http://w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/">plugin update checker</a> and <a href="http://w-shadow.com/blog/2011/06/02/automatic-updates-for-commercial-themes/">theme update checker</a> client libraries.</p>
<h3>Features</h3>
<ul>
<li><strong>Provide updates for private or commercial plugins and themes.<br />
</strong>From the users&#8217; perspective, the updates work just like they do with plugins and themes listed in the official WordPress.org directory.<strong><br />
</strong></li>
<li><strong>Easy to set up.</strong><br />
Just upload the script to your site and drop a plugin or theme Zip in the &#8220;packages&#8221; subdirectory.</li>
<li><strong>Easy to integrate with existing plugins and themes.</strong><br />
All it takes is about 5 lines of code.</li>
<li><strong>Minimal server requirements.</strong><br />
The server component requires PHP 5.3+ and the Zip extension. The update checker component only requires PHP 5.2 &#8211; same as the current version of WordPress.</li>
<li><strong>Extensible.</strong><br />
Want to secure your upgrade download links? Or use a custom logger or cache? Maybe you &#8216;d like to load the change log and other update meta from the database instead of parsing it from a Zip file? Create your own, customized update server by extending the <code>Wpup_UpdateServer</code> class.</li>
</ul>
<h3>What&#8217;s Next?</h3>
<p>See the <a href="https://github.com/YahnisElsts/wp-update-server">GitHub repository</a> for download links and usage instructions. The documentation still needs work, but it should be good enough to get you up and running.</p>The post <a href="https://w-shadow.com/blog/2013/03/12/wordpress-update-server/">WordPress Update Server</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2013/03/12/wordpress-update-server/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3255</post-id>	</item>
		<item>
		<title>Plugin Compatibility Reporter</title>
		<link>https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/</link>
					<comments>https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 04 Dec 2012 10:45:44 +0000</pubDate>
				<category><![CDATA[WordPress Plugins]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3216</guid>

					<description><![CDATA[<p>Plugin Compatibility Reporter is a WordPress plugin that enables you report if the plugins that you&#8217;re using are working properly. It integrates with the compatibility reporting features of the official WordPress.org plugin directory, and lets you mark plugins as &#8220;working&#8221; or &#8220;broken&#8221; from within your WordPress dashboard. It also tracks how long each plugin has [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/">Plugin Compatibility Reporter</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p><em>Plugin Compatibility Reporter</em> is a WordPress plugin that enables you report if the plugins that you&#8217;re using are working properly. It integrates with the compatibility reporting features of the official WordPress.org plugin directory, and lets you mark plugins as &#8220;working&#8221; or &#8220;broken&#8221; from within your WordPress dashboard.</p>
<p>It also tracks how long each plugin has been active on your site and automatically reports plugins that have been active for a while (1 week by default) as compatible &#8211; unless, of course, you&#8217;ve already marked them as broken. This way you won&#8217;t need to waste time on reporting that some plugins work fine.</p>
<p><em>See also: <a href="#why-use-it">Why use this plugin?</a></em></p>
<h3>Screenshots</h3>
<div id="attachment_3228" style="width: 490px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding: 4px; margin: 10px; text-align:center;" class="wp-caption alignnone"><a href="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1.png"><img data-recalc-dims="1" loading="lazy" decoding="async" aria-describedby="caption-attachment-3228" data-attachment-id="3228" data-permalink="https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/screenshot-1-small/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1-small.png?fit=480%2C274&amp;ssl=1" data-orig-size="480,274" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Plugin settings page" data-image-description="" data-image-caption="&lt;p&gt;Plugin settings page&lt;/p&gt;
" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1-small.png?fit=300%2C171&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1-small.png?fit=480%2C274&amp;ssl=1" class="size-full wp-image-3228" title="Plugin settings page" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1-small.png?resize=480%2C274" alt="" width="480" height="274" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1-small.png?w=480&amp;ssl=1 480w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-1-small.png?resize=300%2C171&amp;ssl=1 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a><p style=' padding: 0 4px 5px; margin: 0;'  id="caption-attachment-3228" class="wp-caption-text">Plugin settings page</p></div>
<div id="attachment_3229" style="width: 490px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding: 4px; margin: 10px; text-align:center;" class="wp-caption alignnone"><a href="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2.png"><img data-recalc-dims="1" loading="lazy" decoding="async" aria-describedby="caption-attachment-3229" data-attachment-id="3229" data-permalink="https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/screenshot-2-small/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2-small.png?fit=480%2C301&amp;ssl=1" data-orig-size="480,301" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="You can use these &amp;#8220;works&amp;#8221; and &amp;#8220;broken&amp;#8221; links to report if a plugin is working properly with your WP version" data-image-description="" data-image-caption="&lt;p&gt;You can use these &amp;#8220;works&amp;#8221; and &amp;#8220;broken&amp;#8221; links to report if a plugin is working properly with your WP version&lt;/p&gt;
" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2-small.png?fit=300%2C188&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2-small.png?fit=480%2C301&amp;ssl=1" class="size-full wp-image-3229" title="You can use these &quot;works&quot; and &quot;broken&quot; links to report if a plugin is working properly with your WP version" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2-small.png?resize=480%2C301" alt="" width="480" height="301" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2-small.png?w=480&amp;ssl=1 480w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/screenshot-2-small.png?resize=300%2C188&amp;ssl=1 300w" sizes="auto, (max-width: 480px) 100vw, 480px" /></a><p style=' padding: 0 4px 5px; margin: 0;'  id="caption-attachment-3229" class="wp-caption-text">You can use these &#8220;works&#8221; and &#8220;broken&#8221; links to report if a plugin is working properly with your WP version</p></div>
<h3>Download</h3>
<ul>
<li><a href="http://w-shadow.com/files/plugin-compatibility-reporter.zip"><strong>Download plugin</strong></a></li>
<li><a href="https://github.com/YahnisElsts/plugin-compatibility-reporter">GitHub repository</a></li>
</ul>
<p>Requires WordPress 3.4 or later.</p>
<h3>Installation</h3>
<ol>
<li>Go to <em>Plugins -&gt; Add New -&gt; Upload</em> and upload the plugin archive to your site.</li>
<li>Activate the plugin via the &#8220;Plugins&#8221; page.</li>
<li>Go to <em>Plugins -&gt; Compatibility Reporter</em> and enter your WordPress.org credentials in the appropriate fields. If you don&#8217;t have a WordPress.org account yet, you can <a href="http://wordpress.org/support/register.php">get one here</a>.</li>
<li><em>(Optional)</em> Change how long a plugin needs to be active before it gets marked as working. The default is 1 week.</li>
<li>The plugin will now download your existing compatibility votes. This happens in the background and can take up to 10 minutes.</li>
<li>You should see &#8220;Works&#8221; and &#8220;Broken&#8221; links on your &#8220;Plugins&#8221; page. Click them to report your plugins as compatible or incompatible with your WordPress version. Your current vote (if any) will be displayed in <strong>bold</strong>.</li>
</ol>
<h3 id="why-use-it">Why Use It?</h3>
<p>The main goal of this plugin is to make the compatibility reports that WordPress.org displays for each plugin more useful. Right now, most plugins only have a handful of votes &#8211; not enough to reliably determine if they&#8217;re compatible with this or that WordPress version.</p>
<div id="attachment_3220" style="width: 234px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding: 4px; margin: 10px; text-align:center; display: block; margin-right: auto; margin-left: auto;" class="wp-caption aligncenter"><img data-recalc-dims="1" loading="lazy" decoding="async" aria-describedby="caption-attachment-3220" data-attachment-id="3220" data-permalink="https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/compatibility-widget/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/compatibility-widget.png?fit=224%2C171&amp;ssl=1" data-orig-size="224,171" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="compatibility-widget" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/compatibility-widget.png?fit=224%2C171&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/compatibility-widget.png?fit=224%2C171&amp;ssl=1" class="size-full wp-image-3220 " title="compatibility-widget" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/12/compatibility-widget.png?resize=224%2C171&#038;ssl=1" alt="" width="224" height="171" /><p style=' padding: 0 4px 5px; margin: 0;'  id="caption-attachment-3220" class="wp-caption-text">Exhibit A</p></div>
<p>Even plugins that have been downloaded millions of times usually have only a couple dozen of compatibility reports for the current version, at best. Why is that, and how does this plugin help the situation? <strong></strong></p>
<h4>1. Reporting plugin compatibility is inconvenient.</h4>
<p>To be able to vote, you first have to sign up for a WordPress.org account. That&#8217;s easy enough and you only need to do it once. Then, when you actually want to report a plugin as working or broken, you need to:</p>
<ol>
<li>Go to WordPress.org.</li>
<li>Remember your username and password.</li>
<li>Find the plugin you want to vote on. There might be a &#8220;Visit plugin homepage&#8221; link on the &#8220;Plugins&#8221; page, but that usually leads to the author&#8217;s site, not the WordPress.org listing.</li>
<li>Find your plugin version in the drop-down list.</li>
<li>Find your WordPress version in the second list.</li>
<li>Click &#8220;Works&#8221; or &#8220;Broken&#8221;.</li>
</ol>
<p>Multiply this by the number of plugins you have installed and the number of plugin and WordPress updates, and you&#8217;ll see why most people don&#8217;t bother with it. This plugin simplifies the process down to clicking a &#8220;Works&#8221; or &#8220;Broken&#8221; link on your &#8220;Plugins&#8221; page. You only have to enter your WordPress.org account details once: when setting up the plugin.</p>
<h4>2.There&#8217;s little incentive to mark plugins as working.</h4>
<p><strong></strong>Of those users who <em>do</em> send compatibility reports, many do it only when a plugin doesn&#8217;t work. Even if you deliberately try to avoid this and always report compatible plugins as working, it can get tiresome quickly since new plugin versions are released all the time.</p>
<p>One side-effect of this is that compatibility figures tend to be unfairly biased towards &#8220;broken&#8221;. For example, take <a href="http://wordpress.org/extend/plugins/jetpack/">Jetpack</a> which currently has 29 &#8220;works&#8221; and 8 &#8220;broken&#8221; votes. I seriously doubt that a plugin that was made by the same folk who run WordPress.com is broken on 8/37 = 22% of sites. <em></em></p>
<p><em>Plugin Compatibility Reporter</em> solves this by automatically marking plugins that have been active for a long time as working. This is based on the assumption that the user wouldn&#8217;t leave a plugin active if it was incompatible with their site. Of course, you can always change your vote to &#8220;broken&#8221; if it turns out that the plugin had a subtle bug that you didn&#8217;t notice at first.  This plugin will not overwrite your existing reports. <strong></strong></p>
<h4>Benefits</h4>
<ul>
<li>Users get a better idea of how well any given plugin works with the latest version of WordPress.</li>
<li>Developers get a more accurate impression of what fraction of users are having problems with their plugin.</li>
<li>Less time is wasted on reporting plugins that work properly.</li>
</ul>The post <a href="https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/">Plugin Compatibility Reporter</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2012/12/04/plugin-compatibility-reporter/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3216</post-id>	</item>
		<item>
		<title>How to Pre-Select a Category for a New Post</title>
		<link>https://w-shadow.com/blog/2012/11/20/pre-select-category-for-new-post/</link>
					<comments>https://w-shadow.com/blog/2012/11/20/pre-select-category-for-new-post/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 20 Nov 2012 08:21:41 +0000</pubDate>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[category]]></category>
		<category><![CDATA[taxonomies]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3198</guid>

					<description><![CDATA[<p>Lets say you have a category called &#8220;X&#8221;, and you want to create a link which when clicked will take the user to the &#8220;Add New Post&#8221; screen with the &#8220;X&#8221; category already selected. This could be used to simplify posting for non-technical users, or even as a way to implement &#8220;poor-man&#8217;s custom post types&#8221; [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2012/11/20/pre-select-category-for-new-post/">How to Pre-Select a Category for a New Post</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>Lets say you have a category called &#8220;X&#8221;, and you want to create a link which when clicked will take the user to the &#8220;Add New Post&#8221; screen with the &#8220;X&#8221; category already selected. This could be used to simplify posting for non-technical users, or even as a way to implement &#8220;poor-man&#8217;s custom post types&#8221; of sorts, with categories instead of true CPTs.</p>
<p>To make this possible, you&#8217;ll need a way to set the post category via the URL. The following snippet lets you do just that. Simply append a <code>category_id=123</code> parameter to the post editor URL, and it will automatically select the specified category in the &#8220;Categories&#8221; widget.</p>
<p>Place this code in your <code>functions.php</code> or <a href="http://wpcandy.com/teaches/how-to-create-a-functionality-plugin/">a functionality plugin</a>:</p>
<pre class="brush: php; title: ; notranslate">
function ws_preselect_post_category() {
	if ( isset($_GET&#x5B;'category_id']) &amp;&amp; is_numeric($_GET&#x5B;'category_id']) ) {
		$catId = intval($_GET&#x5B;'category_id']);
		?&gt;
		&lt;script type=&quot;text/javascript&quot;&gt;
			jQuery(function() {
				var catId = &lt;?php echo json_encode($catId); ?&gt;;
				jQuery('#in-category-' + catId).click();
			});
		&lt;/script&gt;
		&lt;?php
	}
}
add_action('admin_footer-post-new.php', 'ws_preselect_post_category');
</pre>
<p>Now you can pass in the category ID like this: <code>/wp-admin/post-new.php?category_id=123</code>. </p>
<p>For example, suppose you have a web development blog that has a &#8220;JavaScript&#8221; category with the ID = 15. You could use this snippet to add a <em>Posts -> Add New JS Article</em> link to the admin menu. When you click it, the &#8220;JavaScript&#8221; category will be selected automatically:</p>
<pre class="brush: php; title: ; notranslate">
function ws_add_new_post_link() {
	add_posts_page(
		'Add New JS Article',
		'Add New JS Article',
		'edit_posts',
		'post-new.php?category_id=15'
	);
}
add_action('admin_menu', 'ws_add_new_post_link');
</pre>The post <a href="https://w-shadow.com/blog/2012/11/20/pre-select-category-for-new-post/">How to Pre-Select a Category for a New Post</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2012/11/20/pre-select-category-for-new-post/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3198</post-id>	</item>
		<item>
		<title>Magic Quotes in WordPress, and How To Get Rid of Them</title>
		<link>https://w-shadow.com/blog/2012/11/13/wordpress-magic-quotes/</link>
					<comments>https://w-shadow.com/blog/2012/11/13/wordpress-magic-quotes/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 13 Nov 2012 09:16:56 +0000</pubDate>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[backwards compatibility]]></category>
		<category><![CDATA[magic quotes]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3185</guid>

					<description><![CDATA[<p>One thing that many developers are not aware of is that WordPress automatically adds magic quotes to request variables. This means that all quotes, backslashes and null-byte characters will be escaped with a backslash. Even if you disable magic quotes in php.ini, WordPress will apply them to $_GET, $_POST, $_COOKIE and other superglobals anyway. If [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2012/11/13/wordpress-magic-quotes/">Magic Quotes in WordPress, and How To Get Rid of Them</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>One thing that many developers are not aware of is that WordPress automatically adds <a href="http://www.php.net/manual/en/security.magicquotes.what.php">magic quotes</a> to request variables. This means that all quotes, backslashes and null-byte characters will be escaped with a backslash.</p>
<p>Even if you disable magic quotes in php.ini, WordPress will apply them to $_GET, $_POST, $_COOKIE and other superglobals anyway. If you ever notice unexpected slashes showing up in your input data, this is why.</p>
<p>The function that enables magic quotes is called <code>wp_magic_quotes()</code>. It is declared in <code>/wp-includes/load.php</code> and called in <code>/wp-settings.php</code>, shortly after WordPress finishes loading plugins.</p>
<pre class="brush: php; title: ; notranslate">
/**
 * Add magic quotes to $_GET, $_POST, $_COOKIE, and $_SERVER.
 *
 * Also forces $_REQUEST to be $_GET + $_POST. If $_SERVER, $_COOKIE,
 * or $_ENV are needed, use those superglobals directly.
 *
 * @access private
 * @since 3.0.0
 */
function wp_magic_quotes() {
	// If already slashed, strip.
	if ( get_magic_quotes_gpc() ) {
		$_GET    = stripslashes_deep( $_GET    );
		$_POST   = stripslashes_deep( $_POST   );
		$_COOKIE = stripslashes_deep( $_COOKIE );
	}

	// Escape with wpdb.
	$_GET    = add_magic_quotes( $_GET    );
	$_POST   = add_magic_quotes( $_POST   );
	$_COOKIE = add_magic_quotes( $_COOKIE );
	$_SERVER = add_magic_quotes( $_SERVER );

	// Force REQUEST to be GET + POST.
	$_REQUEST = array_merge( $_GET, $_POST );
}</pre>
<p>So how do you access the clean, un-escaped data?  Unfortunately, it is not possible to completely turn off WordPress magic quotes without editing core files. However, since WordPress adds magic quotes <em>after</em> all plugins have been loaded, you can simply grab the unmodified variables while your plugin is loading (or in the &#8220;plugins_loaded&#8221; action) and store a local copy for your own use. Here&#8217;s an example:</p>
<pre class="brush: php; title: ; notranslate">
class MyExamplePlugin {
	//Local copies of the PHP superglobals.
	private $get;
	private $post;
	private $cookie;

	public function __construct() {
		/* ... Other plugin code ... */

		add_action('plugins_loaded', array($this, 'captureRequestVars'));
	}

	public function captureRequestVars() {
		//Store the original GET and POST data + cookies.
		$this-&gt;get = $_GET;
		$this-&gt;post = $_POST;
		$this-&gt;cookie = $_COOKIE;

		//If magic quotes are actually enabled in PHP,
		//we'll need to remove the slashes.
		if ( get_magic_quotes_gpc() ) {
			$this-&gt;get    = stripslashes_deep($this-&gt;get);
			$this-&gt;post   = stripslashes_deep($this-&gt;post);
			$this-&gt;cookie = stripslashes_deep($this-&gt;cookie);
		}
	}

	public function doSomethingWithInput() {
		/* ... */

		//Use the internal copy of $_GET.
		$something = $this-&gt;get&#x5B;'something'];

		/* ... */
	}
}

$myExamplePlugin = new MyExamplePlugin();
</pre>
<p>Now you might be wondering: why go to all this trouble with copying built-in PHP variables when you could continue using them as normal and just run <code>stripslashes()</code> on any input data? There are several reasons:</p>
<ul>
<li>Sooner or later, you&#8217;re going to forget to call <code>stripslashes()</code>somewhere. This can lead to hard-to-find bugs.</li>
<li>Code duplication. Why spread the backslash-stripping code through-out your entire codebase when you could put it in one place?</li>
<li>Forward compatibility. If the WordPress team ever decides to stop emulating this deprecated PHP misfeature, plugins and themes that indiscriminately apply <code>stripslashes()</code> to all input data will suddenly break.</li>
</ul>
<p>That said, I wouldn&#8217;t count on WordPress dropping this &#8220;feature&#8221; any time soon. It&#8217;s a matter of backwards compatibility, and sometimes it seems WordPress considers compatibility more important than encouraging good programming practices.</p>The post <a href="https://w-shadow.com/blog/2012/11/13/wordpress-magic-quotes/">Magic Quotes in WordPress, and How To Get Rid of Them</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2012/11/13/wordpress-magic-quotes/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3185</post-id>	</item>
		<item>
		<title>8 Great Tools For Working With JSON</title>
		<link>https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/</link>
					<comments>https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/#respond</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 06 Nov 2012 08:20:50 +0000</pubDate>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[lists]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3157</guid>

					<description><![CDATA[<p>JSONLint &#8211; Validate Your JSON JSONLint is an online JSON validator and formatter. It will check your JSON for syntax errors and format it with proper indentation and line breaks to make it more human-readable (this can be very handy when analysing complex JSON documents). You can either paste your JSON data in the form [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/">8 Great Tools For Working With JSON</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<h3><a href="http://jsonlint.com/">JSONLint &#8211; Validate Your JSON</a></h3>
<p><a href="http://jsonlint.com/"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3162" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/jsonlint/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonlint.png?fit=488%2C300&amp;ssl=1" data-orig-size="488,300" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="JSONLint" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonlint.png?fit=300%2C184&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonlint.png?fit=488%2C300&amp;ssl=1" class="alignnone size-full wp-image-3162" title="JSONLint" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonlint.png?resize=488%2C300&#038;ssl=1" alt="" width="488" height="300" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonlint.png?w=488&amp;ssl=1 488w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonlint.png?resize=300%2C184&amp;ssl=1 300w" sizes="auto, (max-width: 488px) 100vw, 488px" /></a></p>
<p>JSONLint is an online JSON validator and formatter. It will check your JSON for syntax errors and format it with proper indentation and line breaks to make it more human-readable (this can be very handy when analysing complex JSON documents). You can either paste your JSON data in the form or enter a URL and have JSONLint fetch it automatically.</p>
<h3><a href="http://jsoneditoronline.org/">Online JSON Editor</a></h3>
<p><a href="http://jsoneditoronline.org/"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3161" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/json-editor-online/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-editor-online.png?fit=458%2C300&amp;ssl=1" data-orig-size="458,300" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Online JSON Editor" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-editor-online.png?fit=300%2C196&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-editor-online.png?fit=458%2C300&amp;ssl=1" class="alignnone size-full wp-image-3161" title="Online JSON Editor" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-editor-online.png?resize=458%2C300&#038;ssl=1" alt="" width="458" height="300" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-editor-online.png?w=458&amp;ssl=1 458w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-editor-online.png?resize=300%2C196&amp;ssl=1 300w" sizes="auto, (max-width: 458px) 100vw, 458px" /></a></p>
<p>There&#8217;s a whole bunch of different JSON editors available, but <a href="http://jsoneditoronline.org/">JsonEditorOnline.org</a> is easily the best one I&#8217;ve seen. It displays JSON as a hierarchical tree and lets you add, remove and duplicate fields, re-arrange them via drag &amp; drop, change field type, and so on. The interface is intuitive and well thought out.</p>
<h3><a href="https://addons.mozilla.org/en-US/firefox/addon/jsonview/">JSON Browser Add-ons</a></h3>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/jsonview/"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3166" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/jsonview-firefox-2/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?fit=500%2C270&amp;ssl=1" data-orig-size="500,270" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="JSONView Add-on for Firefox" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?fit=300%2C162&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?fit=490%2C264&amp;ssl=1" class="alignnone size-full wp-image-3166" title="JSONView Add-on for Firefox" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?resize=500%2C270&#038;ssl=1" alt="" width="500" height="270" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?w=500&amp;ssl=1 500w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?resize=300%2C162&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonview-firefox-2.png?resize=490%2C264&amp;ssl=1 490w" sizes="auto, (max-width: 500px) 100vw, 500px" /></a></p>
<p>When you open a JSON document in the browser, most browsers will either offer to download the file or display it as plain text. To make working with JSON more convenient, you can install a JSON viewer add-on that will display JSON documents with syntax highlighting and proper indentation:</p>
<ul>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/jsonview/">JSONView for Firefox</a></li>
<li><a href="https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc">JSONView for Chrome</a></li>
<li><a href="https://addons.opera.com/en/extensions/details/jsonviewer/?display=en">JSONViewer for Opera</a></li>
</ul>
<h3><a href="https://github.com/WebReflection/JSONH">JSONH &#8211; Compress JSON</a></h3>
<p>JSONH (&#8220;JSON Homogeneous Collections Compressor&#8221;) is a way to compress JSON documents that contain multiple items with the same keys. For example, it can take an array like this:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">&#x5B;{&quot;a&quot;:&quot;A&quot;,&quot;b&quot;:&quot;B&quot;}, {&quot;a&quot;:&quot;C&quot;,&quot;b&quot;:&quot;D&quot;}, {&quot;a&quot;:&quot;E&quot;,&quot;b&quot;:&quot;F&quot;}]</pre>
<p>and pack it into this:</p>
<pre class="brush: jscript; gutter: false; title: ; notranslate">&#x5B;2,&quot;a&quot;,&quot;b&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;,&quot;F&quot;]</pre>
<p>then unpack it into the original collection later.</p>
<p>Using compression saves bandwidth and can improve the performance of applications that download or send large amounts of JSON data. JSONH libraries are available for JavaScript, PHP, Python and Ruby.</p>
<h3><a href="http://json-schema.org/">JSON Schema &#8211; Document And Validate JSON</a></h3>
<p><a href="http://json-schema.org/"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3163" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/json-schema/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?fit=500%2C289&amp;ssl=1" data-orig-size="500,289" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="JSON Schema" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?fit=300%2C173&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?fit=490%2C283&amp;ssl=1" class="alignnone size-full wp-image-3163" title="JSON Schema" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?resize=500%2C289&#038;ssl=1" alt="" width="500" height="289" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?w=500&amp;ssl=1 500w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?resize=300%2C173&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/json-schema.png?resize=490%2C283&amp;ssl=1 490w" sizes="auto, (max-width: 500px) 100vw, 500px" /></a></p>
<p>Have you ever wished JSON was more like XML? Probably not. But if you <em>have</em> &#8211; JSON Schema is for you. It lets you define the structure of your JSON document, specify validation rules, documentation, references (hyperlinks) and so on. Given a JSON document with a schema, you can then use a JSON validator like <a href="https://github.com/garycourt/JSV">JSV</a> to validate it. See also: <a href="https://github.com/justinrainbow/json-schema">JSON Schema validator for PHP</a>.</p>
<h3><a href="http://jsonselect.org/">JSONSelect &#8211; CSS-like Selectors For JSON</a></h3>
<p><a href="http://jsonselect.org/"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3164" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/jsonselect/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?fit=500%2C292&amp;ssl=1" data-orig-size="500,292" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="JSON Selectors" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?fit=300%2C175&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?fit=490%2C286&amp;ssl=1" class="alignnone size-full wp-image-3164" title="JSON Selectors" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?resize=500%2C292&#038;ssl=1" alt="" width="500" height="292" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?w=500&amp;ssl=1 500w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?resize=300%2C175&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jsonselect.png?resize=490%2C286&amp;ssl=1 490w" sizes="auto, (max-width: 500px) 100vw, 500px" /></a></p>
<p>JSONSelect is a powerful CSS-like selector language for JSON documents. You can use it to extract information from complex JSON structures without having to explicitly navigate the object hierarchy. Here are a few example selectors to whet your appetite:</p>
<ul>
<li><code>.foo .bar</code> &#8211; select all nodes with the key <code>bar</code> that have an ancestor with the key <code>foo</code>.</li>
<li><code>.foo :last-child</code> &#8211; select the last child node of the <code>foo</code> object.</li>
<li><code>:has(.lang:val("Spanish")) &gt; .level</code> &#8211; select the <code>level</code> node of all objects that contain a <code>lang</code> field with the value &#8220;Spanish&#8221;.</li>
<li><a href="http://jsonselect.org/#tryit">More examples</a> are available on the project homepage.</li>
</ul>
<h3><a href="http://www.hugoware.net/projects/jlinq">jLinq &#8211; Query JSON</a></h3>
<p><a href="http://www.hugoware.net/projects/jlinq"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3160" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/jlinq2/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?fit=500%2C250&amp;ssl=1" data-orig-size="500,250" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="jLinq" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?fit=300%2C150&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?fit=490%2C245&amp;ssl=1" class="alignnone size-full wp-image-3160" title="jLinq" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?resize=500%2C250&#038;ssl=1" alt="" width="500" height="250" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?w=500&amp;ssl=1 500w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?resize=300%2C150&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/jlinq2.png?resize=490%2C245&amp;ssl=1 490w" sizes="auto, (max-width: 500px) 100vw, 500px" /></a></p>
<p>jLinq is a JavaScript library that lets you run complex queries on JSON arrays. It provides a fluent interface (like jQuery) that you can use to filter your data, extract the fields you need and sort the results. jLinq does have one drawback: the library hasn&#8217;t been updated in a while, and might no longer be maintained.</p>
<h3><a href="https://github.com/ddopson/underscore-cli">Underscore-CLI &#8211; Manipulate JSON On The Command-line</a></h3>
<p><a href="https://github.com/ddopson/underscore-cli"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3168" data-permalink="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/underscore-cli2/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/underscore-cli2.png?fit=489%2C300&amp;ssl=1" data-orig-size="489,300" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Underscore-CLI" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/underscore-cli2.png?fit=300%2C184&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/underscore-cli2.png?fit=489%2C300&amp;ssl=1" class="alignnone size-full wp-image-3168" title="Underscore-CLI" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/underscore-cli2.png?resize=489%2C300&#038;ssl=1" alt="" width="489" height="300" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/underscore-cli2.png?w=489&amp;ssl=1 489w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/11/underscore-cli2.png?resize=300%2C184&amp;ssl=1 300w" sizes="auto, (max-width: 489px) 100vw, 489px" /></a></p>
<p>Underscore-CLI is the swiss-army knife of JSON processing. This command-line tool can do anything from basic pretty-printing to running arbitrary JavaScript or CoffeeScript. You can filter JSON documents, extract specific properties, apply arbitrary transformations to values (map/reduce/reduceRight), fill in missing properties with defaults, and much, much more. Underscore-CLI also supports the JSONSelect selector syntax mentioned above.<style type="text/css">
img.size-full {
	border-radius: 5px;
	box-shadow: 3px 3px 7px 0px #777;
	max-width: 488px;
}
</style></p>The post <a href="https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/">8 Great Tools For Working With JSON</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2012/11/06/json-tools-and-resources/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3157</post-id>	</item>
		<item>
		<title>Plugin Update Checker 1.2 Released</title>
		<link>https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/</link>
					<comments>https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/#comments</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 30 Oct 2012 07:20:14 +0000</pubDate>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[WordPress Tools]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3144</guid>

					<description><![CDATA[<p>After a long delay, a new version of my PluginUpdateChecker library is finally ready for release. Read on to find out what&#8217;s new, or go straight to the download page. For those of you not familiar with this library, here&#8217;s a short summary: You can use it to add automatic update support to any WordPress plugin. Especially [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/">Plugin Update Checker 1.2 Released</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>After a long delay, a new version of my <em>PluginUpdateChecker</em> library is finally ready for release. Read on to find out what&#8217;s new, or go straight to the <a href="//w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/#download">download page</a>.</p>
<p>For those of you not familiar with this library, here&#8217;s a short summary:</p>
<ul>
<li>You can use it to add automatic update support to any WordPress plugin.</li>
<li>Especially useful for commercial plugins that can&#8217;t be hosted on the official WordPress.org repository.</li>
<li>Free and open source.</li>
<li>See <a href="//w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/">the original post</a> for more details.</li>
</ul>
<p>Here&#8217;s what&#8217;s new in this version:</p>
<h3>Added a &#8220;Check For Updates&#8221; Link</h3>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3150" data-permalink="https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/check-for-updates-link/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?fit=500%2C52&amp;ssl=1" data-orig-size="500,52" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="&amp;#8220;Check for updates&amp;#8221; link" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?fit=300%2C31&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?fit=490%2C50&amp;ssl=1" class="alignnone size-full wp-image-3150" title="&quot;Check for updates&quot; link" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?resize=500%2C52" alt="" width="500" height="52" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?w=500&amp;ssl=1 500w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?resize=300%2C31&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/check-for-updates-link.png?resize=490%2C50&amp;ssl=1 490w" sizes="auto, (max-width: 500px) 100vw, 500px" /></p>
<p>This version adds a new &#8220;Check for updates&#8221; link to the associated plugin&#8217;s row in the <em>Plugins</em> page. Clicking the link will trigger an immediate update check. You can change the link text by using the <code>puc_manual_check_link-$slug</code> filter. To disable the link, return an empty string from the filter.</p>
<h3>Debug Bar Integration</h3>
<p><a href="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar.png"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3148" data-permalink="https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/update-checker-debug-bar-thumbnail/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?fit=500%2C257&amp;ssl=1" data-orig-size="500,257" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Update checker Debug Bar panel (click to enlarge)" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?fit=300%2C154&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?fit=490%2C251&amp;ssl=1" class="alignnone size-full wp-image-3148" title="Update checker Debug Bar panel (click to enlarge)" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?resize=500%2C257" alt="" width="500" height="257" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?w=500&amp;ssl=1 500w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?resize=300%2C154&amp;ssl=1 300w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/10/update-checker-debug-bar-thumbnail.png?resize=490%2C251&amp;ssl=1 490w" sizes="auto, (max-width: 500px) 100vw, 500px" /></a></p>
<p><em>(Click to view full size screenshot.) </em></p>
<p>Judging by the comments that the previous version received, one of the things that it was really missing was better error reporting and debugging features. When it worked, it worked well. When it didn&#8217;t, it was ridiculously hard to figure out why.</p>
<p>To make debugging easier, this version adds a new <a href="//wordpress.org/extend/plugins/debug-bar/">Debug Bar</a> panel that displays all kinds of useful information about the update checker, including all of its configuration fields, last check timestamp, cached update information and more. You can also click &#8220;Request Info&#8221; to download and parse the metadata file, which is a good way to make sure the URL and file format are correct. If you have multiple plugins using this library, each plugin gets its own Debug Bar panel.</p>
<h3>New <code>$debugMode</code> Setting</h3>
<p>You can set <code>$updateChecker-&gt;debugMode</code> to <code>true</code> to make the library report errors that it would usually ignore. For example, if it gets an HTTP error while trying to download plugin information, it will usually fail silently and treat it as &#8220;no updates available&#8221;. With debug mode enabled, it will trigger a PHP warning instead. Debug mode will be enabled automatically if <code>WP_DEBUG</code> is enabled.</p>
<h3>New <code>getUpdate()</code> Method</h3>
<p>Previously there was no good way to get information about available updates from the update checker instance. Sure, the updates would show up just fine in the WordPress UI, but if you wanted to get the update details from inside your plugin, you had to jump through quite a few hoops.</p>
<p>In this version, you can just call <code>getUpdate()</code>. It returns an instance of <code>PluginUpdate</code> if there is an update available, or <code>null</code> otherwise. Note that this method uses the internal cache, so use <code>checkForUpdates()</code> instead if you want the most recent information.</p>
<h3>Other Changes</h3>
<ul>
<li>Added a <code>resetUpdateState()</code> method. It clears the update cache, last check timestamp and last checked version number.</li>
<li><code>checkForUpdates()</code> now returns the update details, if any. It didn&#8217;t return anything in the previous version.</li>
<li>You can use the new <code>puc_pre_inject_info-$slug</code> filter to modify the update just before it&#8217;s passed to WordPress.</li>
<li>Store cached updates as generic <code>StdClass</code> objects to prevent the &#8220;Tried to use an incomplete object&#8221; error on sites that use an object cache.</li>
<li>Fixed an incompatibility between this library and WooThemes plugin updater that would cause no updates to show up even if everything was configured correctly. The problem: both libraries use the <code>plugins_api</code> filter, but the WooThemes updater throws away the response returned by other plugins and breaks my update checker.</li>
<li>Minor code clean-up.</li>
</ul>The post <a href="https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/">Plugin Update Checker 1.2 Released</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2012/10/30/plugin-update-checker-v12/feed/</wfw:commentRss>
			<slash:comments>20</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3144</post-id>	</item>
		<item>
		<title>Tell Your Users Where Your Plugin Puts Its Menu Pages</title>
		<link>https://w-shadow.com/blog/2012/10/23/how-to-admin-page-notices/</link>
					<comments>https://w-shadow.com/blog/2012/10/23/how-to-admin-page-notices/#respond</comments>
		
		<dc:creator><![CDATA[Jānis Elsts]]></dc:creator>
		<pubDate>Tue, 23 Oct 2012 07:24:26 +0000</pubDate>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[admin menu]]></category>
		<category><![CDATA[admin notices]]></category>
		<category><![CDATA[dashboard]]></category>
		<guid isPermaLink="false">http://w-shadow.com/?p=3054</guid>

					<description><![CDATA[<p>There&#8217;s one thing that always annoys me when installing new plugins: No matter how popular or obscure the plugin, the first few seconds (or minutes) are usually wasted on trying to figure out where it put its settings page. We&#8217;ve all been there. Trawling the admin menu, looking for that elusive link that will actually [&#8230;]</p>
The post <a href="https://w-shadow.com/blog/2012/10/23/how-to-admin-page-notices/">Tell Your Users Where Your Plugin Puts Its Menu Pages</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></description>
										<content:encoded><![CDATA[<p>There&#8217;s one thing that always annoys me when installing new plugins: No matter how popular or obscure the plugin, the first few seconds (or minutes) are usually wasted on trying to figure out where it put its settings page.</p>
<p>We&#8217;ve all been there. Trawling the admin menu, looking for that elusive link that will actually let us <em>use</em> the awesome new plugin we just installed. Granted, it usually takes only a few moments to find it, but it&#8217;s still annoying and unnecessary. Why not just <em>tell</em> the user how to get to right admin page? (Some plugins do, but in my experience they&#8217;re the exception, not the rule.)</p>
<p>If you&#8217;re a plugin developer, you can make your users&#8217; life a little easier, and the first-run experience a little smoother, by displaying a small notification that explains how to get to the plugin&#8217;s admin page. Example:</p>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="3055" data-permalink="https://w-shadow.com/blog/2012/10/23/how-to-admin-page-notices/new-menu-notice/" data-orig-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/08/new-menu-notice.png?fit=475%2C72&amp;ssl=1" data-orig-size="475,72" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="A Dashboard notification in WordPres" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/08/new-menu-notice.png?fit=300%2C45&amp;ssl=1" data-large-file="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/08/new-menu-notice.png?fit=475%2C72&amp;ssl=1" src="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/08/new-menu-notice.png?resize=475%2C72&#038;ssl=1" alt="" title="A Dashboard notification in WordPres" width="475" height="72" class="alignnone size-full wp-image-3055" srcset="https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/08/new-menu-notice.png?w=475&amp;ssl=1 475w, https://i0.wp.com/w-shadow.com/wp-content/uploads/2012/08/new-menu-notice.png?resize=300%2C45&amp;ssl=1 300w" sizes="auto, (max-width: 475px) 100vw, 475px" /></p>
<p>In this post, I&#8217;ll show you how you can add a notice like that to your plugin. First, I&#8217;ll give you the code, and then I&#8217;ll explain how it works.</p>
<h3>The Code</h3>
<pre class="brush: php; title: ; notranslate">
&lt;?php
function example_display_menu_notice() {
	//Replace these with your plugins' values.
	$pageSlug = 'example-settings-page';
	$parentSlug = 'options-general.php';
	$noticeOption = 'example_show_menu_notice';

	//Only show the notice to users who can access the menu page.
	//Replace 'manage_options' with the appropriate capability.
	if ( !current_user_can('manage_options') ) {
		return;
	}

	$showNotice = get_option($noticeOption, null);

	//Hide the notice when the user first visits the plugin page
	//or when they dismiss it manually.
	$isPluginPage = $GLOBALS&#x5B;'pagenow'] == $parentSlug &amp;&amp; $GLOBALS&#x5B;'plugin_page'] == $pageSlug;
	$isNoticeDismissed = isset($_GET&#x5B;$noticeOption]) &amp;&amp; $_GET&#x5B;$noticeOption] == 'hide';
	if ( ($isPluginPage || $isNoticeDismissed) &amp;&amp; ($showNotice !== false) ) {
		$showNotice = false;
		update_option($noticeOption, false);
	}

	if ( $showNotice ) {
		$dismissUrl = add_query_arg($noticeOption, 'hide');
		$dismissUrl = remove_query_arg(
			array('message', 'settings-updated', 'activate', 'deactivate'), 
			$dismissUrl
		);

		printf(
			'&lt;div class=&quot;updated&quot;&gt;
				&lt;p&gt;
					Tip: Example Plugin\'s admin page is at
					&lt;a href=&quot;%s&quot;&gt;Settings -&gt; Example Settings&lt;/a&gt;.
				&lt;/p&gt;
				&lt;p&gt;&lt;a href=&quot;%s&quot;&gt;Dismiss&lt;/a&gt;&lt;/p&gt;
			 &lt;/div&gt;',
			//Replace this with your admin page URL.
			esc_attr(admin_url('options-general.php?page=example-settings-page')),
			esc_attr($dismissUrl)
		);
	}
}
add_action('admin_notices', 'example_display_menu_notice');

//Enable the notice when the plugin is activated.
function example_enable_menu_notice() {
	//Only enable it not already enabled/disabled.
	if ( get_option('example_show_menu_notice', null) === null ) {
		update_option('example_show_menu_notice', true);
	}
}
register_activation_hook(__FILE__, 'example_enable_menu_notice');

//Clean up the DB option upon uninstallation.
function example_delete_notice_flag() {
	delete_option('example_show_menu_notice');
}
register_uninstall_hook(__FILE__, 'example_delete_notice_flag');
?&gt;
</pre>
<h3>How It Works</h3>
<p>Okay, now lets examine the code.</p>
<p>We&#8217;ll start with <code>example_display_menu_notice()</code>. This is the function that will display the notice. At the top of the function, we have a bunch of variable declarations:</p>
<pre class="brush: php; title: ; notranslate">
//Replace these with your plugins' values.
$pageSlug = 'example-settings-page';
$parentSlug = 'options-general.php';
$noticeOption = 'example_show_menu_notice';
</pre>
<p>Here we just set up some variables that will be used later in the script.</p>
<ul>
<li><code>$pageSlug</code> &#8211; the <em>slug</em> you used when registering your menu page.
<li><code>$parentSlug</code> &#8211; the slug of the parent menu. For example, if your page is part of the the &#8220;Settings&#8221; menu, then the parent slug will &#8220;options-general.php&#8221;, and if it&#8217;s under &#8220;Posts&#8221; then the parent slug will be &#8220;edit.php&#8221;.
<li><code>$noticeOption</code> &#8211; the DB option we&#8217;ll use to store the notice state (visible or hidden).
</ul>
<pre class="brush: php; title: ; notranslate">
if ( !current_user_can('manage_options') ) {
	return;
}
</pre>
<p>Naturally, we only want users who can actually access our menu page to see the notice. So we check if the current user has the necessary capability and bail out of the function if they don&#8217;t.</p>
<pre class="brush: php; title: ; notranslate">
$showNotice = get_option($noticeOption, null);

//Hide the notice when the user first visits the plugin page
//or when they dismiss it manually.
$isPluginPage = $GLOBALS&#x5B;'pagenow'] == $parentSlug &amp;&amp; $GLOBALS&#x5B;'plugin_page'] == $pageSlug;
$isNoticeDismissed = isset($_GET&#x5B;$noticeOption]) &amp;&amp; $_GET&#x5B;$noticeOption] == 'hide';
if ( ($isPluginPage || $isNoticeDismissed) &amp;&amp; ($showNotice !== false) ) {
	$showNotice = false;
	update_option($noticeOption, false);
}
</pre>
<p>This block of code determines whether we should show the notice or not. First, we check the DB option I mentioned later. It can either be <code>true</code> (= show the notice) or <code>false</code> (= don&#8217;t show the notice). If the option doesn&#8217;t exist yet, we&#8217;ll get a <code>null</code> instead. More on that later.</p>
<p>Next, we check if the user is currently viewing our menu page (<code>$isPluginPage</code>). If they are, then they obviously know where the page is and there&#8217;s no need to display the menu notice any more. To determine what the current page is, we check two global variables that are set by WordPress:</p>
<ul>
<li><code>$pagenow</code> &#8211; the current file. For example, this will be &#8220;options-general.php&#8221; if we&#8217;re on the &#8220;Settings -&gt; General&#8221; page or any plugin page that&#8217;s part of the &#8220;Settings&#8221; menu.
<li><code>$plugin_page</code> &#8211; the slug of the currently open plugin page. If the current page was not created by a plugin, this will be <code>null</code> instead.
</ul>
<p>After that, we check if the user has clicked the &#8220;Dismiss&#8221; link. As we&#8217;ll see later, this link has a URL similar to &#8220;current-page-here?example_show_menu_notice=hide&#8221;. So we just check if the right query argument is there and is set to &#8220;hide&#8221;.</p>
<p>Finally, if either of the above conditions is met, we check if the notice isn&#8217;t already disabled (<code>$showNotice !== false</code>) and hide it by setting <code>$showNotice</code> and our DB option to <code>false</code>. </p>
<p>The second half of <code>example_display_menu_notice()</code> is what actually displays the notification message. After making sure that yes, we should show the notice, we build the URL for the &#8220;Dismiss&#8221; link:</p>
<pre class="brush: php; title: ; notranslate">
$dismissUrl = add_query_arg($noticeOption, 'hide');
$dismissUrl = remove_query_arg(array('message', 'settings-updated', 'activate'), $dismissUrl);
</pre>
<p>As I mentioned before, the link is basically the current URL + an extra query argument that we set to &#8220;hide&#8221;. </p>
<p>We also need to <em>remove</em> a couple of arguments from the URL to avoid confusing the user. WordPress uses these arguments throughout the Dashboard to indicate the result of various operations like updating posts, saving settings, activating plugins and so on. If we leave them in and the user clicks the &#8220;Dismiss&#8221; link on a page that&#8217;s currently showing one of those messages, they&#8217;ll get the same message <em>again</em>, which can be misleading.</p>
<p>And finally, there&#8217;s this big <code><a href="http://php.net/manual/en/function.printf.php">printf()</a></code> call:</p>
<pre class="brush: php; title: ; notranslate">
printf(
	'&lt;div class=&quot;updated&quot;&gt;
		&lt;p&gt;
			Tip: Example Plugin\'s admin page is at
			&lt;a href=&quot;%s&quot;&gt;Settings -&gt; Example Settings&lt;/a&gt;.
		&lt;/p&gt;
		&lt;p&gt;&lt;a href=&quot;%s&quot;&gt;Dismiss&lt;/a&gt;&lt;/p&gt;
	 &lt;/div&gt;',
	//Replace this with your admin page URL.
	esc_attr(admin_url('options-general.php?page=example-settings-page')),
	esc_attr($dismissUrl)
);
</pre>
<p>This is what actually outputs the notice. Make sure to customize the message to suit your plugin, and replace <code>options-general.php?page=example-settings-page</code> with the URL of your menu page (relative to <code>/wp-admin/</code>). </p>
<p>To make the message show up in the right place, we&#8217;ll hook the display function to the <code>admin_notices</code> action. This action is run right before the main content of each Dashboard page, and that&#8217;s where WordPress displays most of its notifications and error messages.</p>
<pre class="brush: php; title: ; notranslate">
add_action('admin_notices', 'example_display_menu_notice');
</pre>
<p>Next, we have two considerably simpler functions. The first, <code>example_enable_menu_notice()</code>, enables the notification when the plugin is activated:</p>
<pre class="brush: php; title: ; notranslate">
function example_enable_menu_notice() {
	//Only enable it not already enabled/disabled.
	if ( get_option('example_show_menu_notice', null) === null ) {
		update_option('example_show_menu_notice', true);
	}
}
register_activation_hook(__FILE__, 'example_enable_menu_notice');
</pre>
<p>If the <code>example_show_menu_notice</code> option does not exist, we set it to <code>true</code>.</p>
<p>Now you might ask &#8211; why go to the trouble of explicitly enabling the notice upon activation, instead of just treating it as visible-by-default and hiding it when the user dismisses it or visits our page? The answer is this: we don&#8217;t want to annoy our existing users. </p>
<p>It&#8217;s a good idea to tell <em>new users</em> how to get to your plugin&#8217;s admin page(s). But if we do it to a user who just upgraded from an older version of the plugin, they&#8217;ll probably be annoyed because we&#8217;re telling them stuff they already know.</p>
<p>By enabling the notice on activation, we avoid this problem. The activation hook only runs when a plugin is installed or manually deactivated and re-activated. It does not run when you upgrade a plugin.</p>
<p>Finally, we want our plugin to be a good citizen and clean up after itself. The second short function is <code>example_delete_notice_flag()</code>, and it does just that by removing our DB option when the plugin is uninstalled.</p>
<pre class="brush: php; title: ; notranslate">
function example_delete_notice_flag() {
	delete_option('example_show_menu_notice');
}
register_uninstall_hook(__FILE__, 'example_delete_notice_flag');
?&gt;
</pre>
<p>This concludes today&#8217;s tutorial. If you have any questions or other feedback, leave a comment below.</p>The post <a href="https://w-shadow.com/blog/2012/10/23/how-to-admin-page-notices/">Tell Your Users Where Your Plugin Puts Its Menu Pages</a> first appeared on <a href="https://w-shadow.com">W-Shadow.com</a>.]]></content:encoded>
					
					<wfw:commentRss>https://w-shadow.com/blog/2012/10/23/how-to-admin-page-notices/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3054</post-id>	</item>
	</channel>
</rss>
