<?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>Adam Balée Designs, LLC</title>
	<atom:link href="https://adambalee.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://adambalee.com/</link>
	<description>Freelance WordPress &#38; Front-end Development</description>
	<lastBuildDate>Wed, 22 May 2024 18:59:28 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://adambalee.com/wp-content/uploads/2017/04/cropped-ab-icon-150x150.png</url>
	<title>Adam Balée Designs, LLC</title>
	<link>https://adambalee.com/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">32117821</site>	<item>
		<title>Integrating Sage 10 with Pantheon: A Step-by-Step Guide</title>
		<link>https://adambalee.com/how-to-get-sage-10-working-on-pantheon/</link>
					<comments>https://adambalee.com/how-to-get-sage-10-working-on-pantheon/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Wed, 15 May 2024 21:52:19 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1792</guid>

					<description><![CDATA[<p>Getting Sage 10 to work on Pantheon needs a few tweaks, but don&#8217;t worry—this guide will walk you through it step-by-step. Since Pantheon is a git based hosting solution, we need to ensure that the blade files compiled by Sage 10 and Acorn are stored outside of the repository. Let’s get started. Step 1: Initial [&#8230;]</p>
<p>The post <a href="https://adambalee.com/how-to-get-sage-10-working-on-pantheon/">Integrating Sage 10 with Pantheon: A Step-by-Step Guide</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Getting <a href="https://roots.io/sage/">Sage 10</a> to work on <a href="https://pantheon.io/">Pantheon</a> needs a few tweaks, but don&#8217;t worry—this guide will walk you through it step-by-step. Since Pantheon is a git based hosting solution, we need to ensure that the <a href="https://laravel.com/docs/11.x/blade">blade</a> files compiled by Sage 10 and <a href="https://roots.io/acorn/">Acorn</a> are stored outside of the repository. Let’s get started.</p>
<h2>Step 1: Initial Setup with Acorn</h2>
<p>First, in your theme directory, initialize Sage 10 with Acorn by running these commands:</p>
<pre><code class="language-bash">wp acorn acorn:init
wp acorn vendor:publish --tag=acorn
</code></pre>
<p>These commands create a <code>/config</code> directory in your theme with all the necessary Acorn configuration files, which were part of Sage 9 but removed in Sage 10.</p>
<h2>Step 2: Configuring the View Compilation Path</h2>
<p>Next, update the <code>config/view.php</code> file to set the &#8216;compiled&#8217; path for Blade templates so that they are stored in a writable location for WordPress on Pantheon:</p>
<pre><code class="language-php">'compiled' =&gt; wp_upload_dir()['basedir'].'/storage/framework/views'
</code></pre>
<h2>Step 3: Creating a Symlink for the Storage Directory</h2>
<p>Next, we need to create a symbolic link from the theme directory to the <code>storage/</code> folder within <code>wp-content/uploads</code>. From our theme directory, run the following command:</p>
<pre><code class="language-bash">ln -sfn ../../uploads/storage
</code></pre>
<p>This keeps your theme files separate from uploaded content, making deployments and version control easier.</p>
<h2>Step 4: Updating the Pantheon .gitignore File</h2>
<p>Pantheon’s default .gitignore file excludes the <code>/wp-content/cache</code> directory, which we need to change. Comment out this line in the .gitignore file:</p>
<pre><code class="language-bash"># /wp-content/cache
</code></pre>
<p>This prevents errors from the Acorn package, which requires this directory to exist. If you are working with a repository that you&#8217;ve already pushed to Pantheon, you may need to set your Pantheon environment to SFTP and manually upload the <code>/wp-content/cache</code> directory.</p>
<h2>Step 5: Updating the Sage .gitignore File</h2>
<p>Make sure the <code>/vendor</code> and <code>/public</code> directories are included in your repository, as they contain crucial files for Sage 10. Modify the Sage <code>.gitignore</code> file by commenting out these lines:</p>
<pre><code class="language-bash"># /vendor
# /public
</code></pre>
<h2>Additional Resources</h2>
<p>For more insights, tips, and troubleshooting advice, visit the <a href="https://discourse.roots.io/">Roots Discourse</a>. The community there is a great resource for developers working with Sage 10 on Pantheon.</p>
<p>Check out the primary source for this guide on Roots Discourse: <a href="https://discourse.roots.io/t/sage-10-on-pantheon-a-guide-and-method/19978/5">Sage 10 on Pantheon</a>.</p>
<h2>Conclusion</h2>
<p>Integrating Sage 10 into Pantheon takes some careful setup, but following this guide will help you get everything running smoothly. For the latest information and best practices, always refer to the official Sage documentation and Pantheon’s developer resources.</p>
<p>The post <a href="https://adambalee.com/how-to-get-sage-10-working-on-pantheon/">Integrating Sage 10 with Pantheon: A Step-by-Step Guide</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/how-to-get-sage-10-working-on-pantheon/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1792</post-id>	</item>
		<item>
		<title>How To Customize the WordPress Login Page Without a Plugin</title>
		<link>https://adambalee.com/how-to-customize-the-wordpress-login-page/</link>
					<comments>https://adambalee.com/how-to-customize-the-wordpress-login-page/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Thu, 09 May 2024 15:08:26 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1751</guid>

					<description><![CDATA[<p>Let&#8217;s face it, the default WordPress login screen can be a bit boring and doesn&#8217;t reflect your site&#8217;s unique branding. Customizing the WordPress login page is a simple yet effective way to create a cohesive brand experience for your website. In this guide, I&#8217;ll show you how to customize the WordPress login page without using [&#8230;]</p>
<p>The post <a href="https://adambalee.com/how-to-customize-the-wordpress-login-page/">How To Customize the WordPress Login Page Without a Plugin</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Let&#8217;s face it, the default WordPress login screen can be a bit boring and doesn&#8217;t reflect your site&#8217;s unique branding. Customizing the WordPress login page is a simple yet effective way to create a cohesive brand experience for your website. In this guide, I&#8217;ll show you how to customize the WordPress login page without using a plugin.</p>
<h2>Understanding the Login Forms</h2>
<p>The <code>wp-login.php</code> page handles four different forms, each of which can be customized:</p>
<ol>
<li>Login Form</li>
<li>Lost Password Form</li>
<li>Reset Password Form</li>
<li>Register Form</li>
</ol>
<h2>Leveraging WordPress Hooks &amp; Filters</h2>
<p>WordPress offers a variety of hooks, functions, and filters that allow you to customize the login screen extensively. You can explore a comprehensive list of these tools <a href="https://developer.wordpress.org/?s=login_">here</a>.</p>
<h3>Adding Custom CSS &amp; JavaScript</h3>
<p>To change the appearance and behavior of the login page, you can add custom CSS and JavaScript using the <code>login_enqueue_scripts</code> hook. This will enable you to style the login page to match your site&#8217;s theme and add any interactive features you need.</p>
<pre><code class="language-php">add_action('login_enqueue_scripts', function () {
    wp_enqueue_style('custom-login', get_stylesheet_directory_uri() . '/css/custom-login.css');
    wp_enqueue_script('custom-login', get_stylesheet_directory_uri() . '/js/custom-login.js');
});
</code></pre>
<h3>Changing the Login Url</h3>
<p>By default, the logo on the login page redirects to wordpress.org. You can change this URL to redirect users to your homepage or any other URL that fits your needs.</p>
<pre><code class="language-php">add_filter('login_headerurl', function () {
    return home_url();
});
</code></pre>
<h3>Customizing the Login Text</h3>
<p>To modify the text that appears when users hover over the login logo, use the <code>login_headertext</code> filter. This is a great way to add a personal touch or include a call to action.</p>
<pre><code class="language-php">add_filter('login_headertext', function () {
    return 'Welcome to My Website';
});
</code></pre>
<h3>Modifying the Login Page Title</h3>
<p>You can also customize the meta title of the login page to better reflect your brand. This can be done using the &#8216;login_title&#8217; filter.</p>
<pre><code class="language-php">add_filter('login_title', function ($login_title) {
    return 'Login to My Awesome Site';
});
</code></pre>
<h3>Securing Login Error Messages</h3>
<p>Default login form error messages can reveal whether a username exists in the system, which poses a security risk. To improve security, you can make the error messages more generic, preventing potential attackers from gathering information about your users.</p>
<pre><code class="language-php">/**
 * Customizing the login error message
 * 
 * @link https://developer.wordpress.org/reference/hooks/login_errors/
 * 
 * @return string
 */
add_filter('login_errors', function ($error) {
    $error = 'Invalid username or password.';
    return $error;
});
</code></pre>
<h2>Additional Customizations</h2>
<p>Beyond the basics, there are numerous other customizations you can implement to enhance the login experience:</p>
<h3>Custom Background and Logo</h3>
<p>Add a custom background and logo to the login page to align it with your site&#8217;s branding.</p>
<pre><code class="language-php">add_action('login_enqueue_scripts', function () {
    echo '
    &lt;style type="text/css"&gt;
        body.login {
            background-image: url(' . get_stylesheet_directory_uri() . '/images/custom-background.jpg);
            background-size: cover;
        }
        .login h1 a {
            background-image: url(' . get_stylesheet_directory_uri() . '/images/custom-logo.png);
            background-size: contain;
            width: 320px;
            height: 80px;
        }
    &lt;/style&gt;';
});
</code></pre>
<h3>Custom Login Button</h3>
<p>Style the login button to match your site&#8217;s theme.</p>
<pre><code class="language-php">add_action('login_enqueue_scripts', function () {
    echo '
    &lt;style type="text/css"&gt;
        .login .button-primary {
            background-color: #0073aa;
            border-color: #006799;
            color: #fff;
            text-shadow: none;
            box-shadow: none;
        }
        .login .button-primary:hover {
            background-color: #005a8e;
            border-color: #004f7a;
        }
    &lt;/style&gt;';
});
</code></pre>
<h3>Custom Footer Text</h3>
<p>Add a custom message or copyright notice in the footer of the login page.</p>
<pre><code class="language-php">add_action('login_footer', function () {
    echo '&lt;div style="text-align: center; margin-top: 20px;"&gt;© ' . date('Y') . ' Your Website. All rights reserved.&lt;/div&gt;';
});
</code></pre>
<h2>Conclusion</h2>
<p>Customizing the WordPress login page is a powerful way to enhance your site&#8217;s branding and improve security. By leveraging WordPress hooks and filters, you can modify the login page without relying on external plugins. Start customizing your login page today to create a more personalized and secure experience for your users.</p>
<p>Whether you&#8217;re adding custom styles, modifying error messages, or changing the login URL, these tweaks will help your site make a great first impression from the moment users log in. Embrace these customizations to ensure your WordPress site is as unique and professional as your brand.</p>
<p>The post <a href="https://adambalee.com/how-to-customize-the-wordpress-login-page/">How To Customize the WordPress Login Page Without a Plugin</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/how-to-customize-the-wordpress-login-page/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1751</post-id>	</item>
		<item>
		<title>How To Add Inline SVG Menu Icons to WordPress Custom Post Types</title>
		<link>https://adambalee.com/how-to-add-inline-svg-menu-icons-to-wordpress-custom-post-types/</link>
					<comments>https://adambalee.com/how-to-add-inline-svg-menu-icons-to-wordpress-custom-post-types/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Wed, 01 May 2024 21:39:11 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1657</guid>

					<description><![CDATA[<p>Custom post types are a powerful feature in WordPress. When you create a new custom post type, the same thumbtack menu icon seen next to &#8216;Posts&#8217; is inserted by default. This can be overridden with any Dashicon you like, but the selection of Dashicons is fairly limited. Let&#8217;s get fancy and add our own custom [&#8230;]</p>
<p>The post <a href="https://adambalee.com/how-to-add-inline-svg-menu-icons-to-wordpress-custom-post-types/">How To Add Inline SVG Menu Icons to WordPress Custom Post Types</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Custom post types are a powerful feature in WordPress. When you create a new custom post type, the same thumbtack menu icon seen next to &#8216;Posts&#8217; is inserted by default. This can be overridden with any Dashicon you like, but the selection of <a href="https://developer.wordpress.org/resource/dashicons/">Dashicons</a> is fairly limited. Let&#8217;s get fancy and add our own custom svg icon.</p>
<p>As always, when it comes to WordPress, there are multiple ways to achieve the same goal.</p>
<h3>Method 1: <code>register_post_type</code></h3>
<p>First, let&#8217;s suppose you have registered a custom post type in your theme or plugin. If that is the case, you can simply update the <code>menu_icon</code> parameter in the <a href="https://developer.wordpress.org/reference/functions/register_post_type/"><code>register_post_type</code></a> arguments.</p>
<blockquote><p>
Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme — this should begin with &#8216;data:image/svg+xml;base64,&#8217;.</p>
<footer>
<cite style="font-size: 14px; font-weight: 700;">WordPress Developer Resources</cite><br />
</footer>
</blockquote>
<p>I&#8217;m using a free <a href="https://fontawesome.com/icons/people-group?f=classic&#038;s=solid">FontAwesome</a> icon in this case, and you can copy the svg code directly from their website. That said, not all icons are created equal, and you may have to tweak them a bit to get it to display correctly. In the case of FontAwesome icons, I had to add a <code>fill="currentColor"</code> to the icon to make it work.</p>
<pre><code class="language-php">/**
 * Register custom post type
 *
 * @see https://developer.wordpress.org/reference/functions/register_post_type/
 *
 * @return void
 */
register_post_type( 'people', array(
    'labels' => array(
	'name' => 'People',
	'singular_name' => 'People',
	'all_items' => 'All People',
    ),
    'menu_icon' => 'data:image/svg+xml;base64,' . base64_encode('&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 640 512&quot; fill=&quot;currentColor&quot;&gt;&lt;!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--&gt;&lt;path d=&quot;M72 88a56 56 0 1 1 112 0A56 56 0 1 1 72 88zM64 245.7C54 256.9 48 271.8 48 288s6 31.1 16 42.3V245.7zm144.4-49.3C178.7 222.7 160 261.2 160 304c0 34.3 12 65.8 32 90.5V416c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V389.2C26.2 371.2 0 332.7 0 288c0-61.9 50.1-112 112-112h32c24 0 46.2 7.5 64.4 20.3zM448 416V394.5c20-24.7 32-56.2 32-90.5c0-42.8-18.7-81.3-48.4-107.7C449.8 183.5 472 176 496 176h32c61.9 0 112 50.1 112 112c0 44.7-26.2 83.2-64 101.2V416c0 17.7-14.3 32-32 32H480c-17.7 0-32-14.3-32-32zm8-328a56 56 0 1 1 112 0A56 56 0 1 1 456 88zM576 245.7v84.7c10-11.3 16-26.1 16-42.3s-6-31.1-16-42.3zM320 32a64 64 0 1 1 0 128 64 64 0 1 1 0-128zM240 304c0 16.2 6 31 16 42.3V261.7c-10 11.3-16 26.1-16 42.3zm144-42.3v84.7c10-11.3 16-26.1 16-42.3s-6-31.1-16-42.3zM448 304c0 44.7-26.2 83.2-64 101.2V448c0 17.7-14.3 32-32 32H288c-17.7 0-32-14.3-32-32V405.2c-37.8-18-64-56.5-64-101.2c0-61.9 50.1-112 112-112h32c61.9 0 112 50.1 112 112z&quot;/&gt;&lt;/svg&gt;'),
    'public' => true,
    'show_in_rest' => true,
    'supports' => array(
	0 => 'title',
	1 => 'editor',
	2 => 'thumbnail',
    ),
    'delete_with_user' => false,
));
</code></pre>
<h3>Method 2: <code>registered_post_type</code></h3>
<p>In the case where your custom post type has been registered by a third-party plugin, and you don&#8217;t want to alter the code, you can use the <code>registered_post_type</code> hook to update the <code>menu_icon</code> parameter like so. Keep in mind, this method can also be used to replace any of the default registered post types as well (ie. Posts, Media, Pages, etc&#8230;)</p>
<pre><code class="language-php">/**
 * Add custom post type icon
 * 
 * @see https://developer.wordpress.org/reference/hooks/registered_post_type/
 * 
 * @param string $post_type
 * @param object $post_type_object
 * 
 * @return void
 */
add_action('registered_post_type', function ($post_type, $post_type_object) {
    if ($post_type === 'people') {
        $post_type_object->menu_icon = 'data:image/svg+xml;base64,' . base64_encode('&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 640 512&quot; fill=&quot;currentColor&quot;&gt;&lt;!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--&gt;&lt;path d=&quot;M72 88a56 56 0 1 1 112 0A56 56 0 1 1 72 88zM64 245.7C54 256.9 48 271.8 48 288s6 31.1 16 42.3V245.7zm144.4-49.3C178.7 222.7 160 261.2 160 304c0 34.3 12 65.8 32 90.5V416c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V389.2C26.2 371.2 0 332.7 0 288c0-61.9 50.1-112 112-112h32c24 0 46.2 7.5 64.4 20.3zM448 416V394.5c20-24.7 32-56.2 32-90.5c0-42.8-18.7-81.3-48.4-107.7C449.8 183.5 472 176 496 176h32c61.9 0 112 50.1 112 112c0 44.7-26.2 83.2-64 101.2V416c0 17.7-14.3 32-32 32H480c-17.7 0-32-14.3-32-32zm8-328a56 56 0 1 1 112 0A56 56 0 1 1 456 88zM576 245.7v84.7c10-11.3 16-26.1 16-42.3s-6-31.1-16-42.3zM320 32a64 64 0 1 1 0 128 64 64 0 1 1 0-128zM240 304c0 16.2 6 31 16 42.3V261.7c-10 11.3-16 26.1-16 42.3zm144-42.3v84.7c10-11.3 16-26.1 16-42.3s-6-31.1-16-42.3zM448 304c0 44.7-26.2 83.2-64 101.2V448c0 17.7-14.3 32-32 32H288c-17.7 0-32-14.3-32-32V405.2c-37.8-18-64-56.5-64-101.2c0-61.9 50.1-112 112-112h32c61.9 0 112 50.1 112 112z&quot;/&gt;&lt;/svg&gt;');
    }
}, 10, 2);
</code></pre>
<h3>Method 3: Using CSS</h3>
<p>Instead of adding an inline svg, we have a third option available to us. We can simply leave the <code>menu_icon</code> parameter empty, and then add our own with CSS. This method requires two steps. </p>
<p>1. Make sure the <code>menu_icon</code> parameter is empty in the <code>register_post_type</code> or <code>registered_post_type</code> functions respectively.<br />
2. Add custom CSS to the WordPress admin with the following code.</p>
<p>We can either create our own stylesheet and enqueue it in the admin.</p>
<pre><code class="language-php">/**
 * Add styles to admin
 * 
 * @see https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/
 * 
 * @return void
 */
add_action( 'admin_enqueue_scripts', function () {
    wp_enqueue_style( 'admin-custom', get_stylesheet_directory_uri() . '/admin-custom.css');
});
</pre>
<p></code></p>
<p>Or, we can add inline styles directly to the <a href="https://developer.wordpress.org/reference/hooks/admin_head/"><code>admin_head</code></a>. Emojis are still <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" />, right?</p>
<pre><code class="language-php">/**
 * Add styles to admin menu
 * 
 * @see https://developer.wordpress.org/reference/hooks/admin_head/
 * 
 * @return void
 */
add_action( 'admin_head', function () {
    echo '
        &lt;style&gt;
		#adminmenu #menu-posts-people div.wp-menu-image:before {
			content: &quot;&#x1f47d;&quot;;
		}
	&lt;/style&gt;
    ';
});
</pre>
<p></code></p>
<p>The post <a href="https://adambalee.com/how-to-add-inline-svg-menu-icons-to-wordpress-custom-post-types/">How To Add Inline SVG Menu Icons to WordPress Custom Post Types</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/how-to-add-inline-svg-menu-icons-to-wordpress-custom-post-types/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1657</post-id>	</item>
		<item>
		<title>Add a Formatted Date to the WordPress REST API JSON Response</title>
		<link>https://adambalee.com/add-a-formatted-date-to-the-wordpress-rest-api-json-response/</link>
					<comments>https://adambalee.com/add-a-formatted-date-to-the-wordpress-rest-api-json-response/#comments</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Sat, 04 Jan 2020 21:05:07 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[REST API]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1547</guid>

					<description><![CDATA[<p>By default, the WordPress REST API returns the post date in date time format. This is not ideal when we want to display a formatted date using a Javascript framework like Vue or React. We could reach for the popular Moment.js library to parse our date, but why add the unnecessary bloat to our Javascript, [&#8230;]</p>
<p>The post <a href="https://adambalee.com/add-a-formatted-date-to-the-wordpress-rest-api-json-response/">Add a Formatted Date to the WordPress REST API JSON Response</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>By default, the <a href="https://developer.wordpress.org/rest-api/" rel="noopener noreferrer" target="_blank">WordPress REST API</a> returns the post date in date time format. This is not ideal when we want to display a formatted date using a Javascript framework like Vue or React. We could reach for the popular <a href="https://momentjs.com/" rel="noopener noreferrer" target="_blank">Moment.js</a> library to parse our date, but why add the unnecessary bloat to our Javascript, when we can just add the formatted date directly to the JSON response.</p>
<p>Fortunately, the WordPress REST API provides us with the <a href="https://developer.wordpress.org/reference/functions/register_rest_field/" rel="noopener noreferrer" target="_blank">register_rest_field</a> function, which we can use to add custom properties to the JSON response. Let&#8217;s add a formatted date to the post object response by hooking into the <a href="https://developer.wordpress.org/reference/functions/rest_api_init/" rel="noopener noreferrer" target="_blank">rest_api_init</a> function and registering our new field.</p>
<pre><code class="language-php">/**
 * Add a Formatted Date to the WordPress REST API JSON Post Object
 *
 * https://adambalee.com/?p=1547
 */
add_action('rest_api_init', function() {
    register_rest_field(
        array('post'),
        'formatted_date',
        array(
            'get_callback'    =&gt; function() {
                return get_the_date();
            },
            'update_callback' =&gt; null,
            'schema'          =&gt; null,
        )
    );
});
</code></pre>
<p>Adding the code above to functions.php will return the following result in the JSON post object returned by the WordPress REST API.</p>
<pre><code class="language-json">{
    "formatted_date": "December 24, 2019"
}
</code></pre>
<p>The post <a href="https://adambalee.com/add-a-formatted-date-to-the-wordpress-rest-api-json-response/">Add a Formatted Date to the WordPress REST API JSON Response</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/add-a-formatted-date-to-the-wordpress-rest-api-json-response/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1547</post-id>	</item>
		<item>
		<title>Lazy Loading Responsive Images in WordPress Without a Plugin</title>
		<link>https://adambalee.com/lazy-loading-responsive-images-in-wordpress-without-a-plugin/</link>
					<comments>https://adambalee.com/lazy-loading-responsive-images-in-wordpress-without-a-plugin/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Fri, 20 Dec 2019 00:40:43 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1542</guid>

					<description><![CDATA[<p>If content is king, then performance is a close second. Lazy loading is a technique used to defer the downloading of resources by the browser before they are needed. As a user scrolls down the page, images will come into view as they enter the window. Not only will lazy loading images improve the performance [&#8230;]</p>
<p>The post <a href="https://adambalee.com/lazy-loading-responsive-images-in-wordpress-without-a-plugin/">Lazy Loading Responsive Images in WordPress Without a Plugin</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>If content is king, then performance is a close second.</p>
<p>Lazy loading is a technique used to defer the downloading of resources by the browser before they are needed. As a user scrolls down the page, images will come into view as they enter the window. Not only will lazy loading images improve the performance of your site, it also helps to create a smoother experience for your users.</p>
<h3>The Javascript</h3>
<p>In this example, we&#8217;ll be using <a href="https://github.com/aFarkas/lazysizes" rel="noopener noreferrer" target="_blank">lazysizes</a> to handle the javascript. Check out the Github repo for detailed installation and usage instructions.</p>
<h3>The PHP</h3>
<p>Assuming you have lazysizes installed, let&#8217;s get to the code we need to start lazy loading our images in WordPress.</p>
<p>The <a href="https://developer.wordpress.org/reference/functions/wp_get_attachment_image/" rel="noopener noreferrer" target="_blank">wp_get_attachment_image</a> function is how we create an HTML img element representing an image attachment in WordPress. It provides us with a number of properties that allow us to modify the output we need to start lazy loading our images.</p>
<pre><code class="language-php">// getting the featured image id as an example
$attachment_id = get_post_thumbnail_id( $post-&gt;ID );
$size = 'large';
echo wp_get_attachment_image( $attachment_id, $size, false, [
    'class' =&gt; 'lazyload',
    'src' =&gt; '#',
    'srcset' =&gt; '#',
    'data-src' =&gt; wp_get_attachment_image_url( $attachment_id, $size ),
    'data-srcset' =&gt; wp_get_attachment_image_srcset( $attachment_id, $size )
]);
</code></pre>
<p>Now you could just place the code above in your templates and call it a day, but we can do better. Let&#8217;s wrap our code in a neat little function that we can call instead.</p>
<pre><code>function lazy_attachment($attachment_id, $size)
{
    echo wp_get_attachment_image( $attachment_id, $size, false, [
        'class' =&gt; 'lazyload',
        'src' =&gt; '#',
        'srcset' =&gt; '#',
        'data-src' =&gt; wp_get_attachment_image_url( $attachment_id, $size ),
        'data-srcset' =&gt; wp_get_attachment_image_srcset( $attachment_id, $size )
    ]);
}
</code></pre>
<p>Place the code above in your functions.php file and you can now call your lazy loading images with a single line of code.</p>
<pre><code>lazy_attachment($attachment_id, $size);
</code></pre>
<p>Remember to replace $attachment_id and $size with the their appropriate values. The following example pulls in the &#8216;large&#8217; version of a featured image.</p>
<pre><code>lazy_attachment(get_the_post_thumbnail($post-&gt;ID, 'large');
</code></pre>
<p>The post <a href="https://adambalee.com/lazy-loading-responsive-images-in-wordpress-without-a-plugin/">Lazy Loading Responsive Images in WordPress Without a Plugin</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/lazy-loading-responsive-images-in-wordpress-without-a-plugin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1542</post-id>	</item>
		<item>
		<title>Copy SSH Public Key to Clipboard</title>
		<link>https://adambalee.com/copy-ssh-public-key-to-clipboard/</link>
					<comments>https://adambalee.com/copy-ssh-public-key-to-clipboard/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Mon, 11 Jun 2018 02:38:19 +0000</pubDate>
				<category><![CDATA[Snippets]]></category>
		<category><![CDATA[SSH]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1483</guid>

					<description><![CDATA[<p>Use the following command in terminal to copy your SSH public key to your clipboard on Mac or Linux. Be sure to swap out the path and file name with your own if necessary. cat ~/.ssh/id_rsa.pub &#124; pbcopy</p>
<p>The post <a href="https://adambalee.com/copy-ssh-public-key-to-clipboard/">Copy SSH Public Key to Clipboard</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Use the following command in terminal to copy your SSH public key to your clipboard on Mac or Linux. Be sure to swap out the path and file name with your own if necessary.</p>
<pre><code class="language-shell">cat ~/.ssh/id_rsa.pub | pbcopy
</code></pre>
<p>The post <a href="https://adambalee.com/copy-ssh-public-key-to-clipboard/">Copy SSH Public Key to Clipboard</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/copy-ssh-public-key-to-clipboard/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1483</post-id>	</item>
		<item>
		<title>How to Offset WordPress Queries without Breaking Pagination</title>
		<link>https://adambalee.com/offset-wordpress-queries-without-breaking-pagination/</link>
					<comments>https://adambalee.com/offset-wordpress-queries-without-breaking-pagination/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Sat, 28 Oct 2017 04:16:03 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[advanced custom fields]]></category>
		<category><![CDATA[found_posts]]></category>
		<category><![CDATA[offset]]></category>
		<category><![CDATA[pre_get_posts]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1428</guid>

					<description><![CDATA[<p>While designing this blog, I discovered that using the offset argument in a WordPress query can and will break pagination. I wanted to display the latest blog post in a hero section on my blog&#8217;s home page, and then all of the remaining posts in a grid below. Sounds easy, right? Indeed it is, until [&#8230;]</p>
<p>The post <a href="https://adambalee.com/offset-wordpress-queries-without-breaking-pagination/">How to Offset WordPress Queries without Breaking Pagination</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>While designing this blog, I discovered that using the offset argument in a WordPress query can and will break pagination. I wanted to display the latest blog post in a hero section on my blog&#8217;s home page, and then all of the remaining posts in a grid below. Sounds easy, right? Indeed it is, until I realized that my pagination was no longer working.</p>
<h3>The Problem</h3>
<p>Apparently, this is a really common issue, and there is some fantastic documentation in the <a href="https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination" rel="noopener" target="_blank">WordPress Codex</a> that deals with this exact problem. The following is a direct quote that explains the problem in a nutshell.</p>
<blockquote><p>
&#8230; the offset argument is actually the value WordPress uses to handle pagination itself. If a developer sets a manual offset value, pagination will not function because that value will override WordPress&#8217;s automatic adjustment of the offset for a given page.
</p></blockquote>
<p>I&#8217;m not going to go over everything in the Codex, but I highly suggest you give it a read. Basically, it outlines how to use the <a href="https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts" rel="noopener" target="_blank"><i>pre_get_posts</i></a> hook, in combination with the <a href="https://codex.wordpress.org/Plugin_API/Filter_Reference/found_posts" rel="noopener" target="_blank"><i>found_posts</i></a> filter, to offset a specific page and/or query, and then adjust the <em>found_posts</em> calculation needed to fix our pagination problem. Unfortunately, the suggested code wasn&#8217;t working for me, and I needed to make a minor adjustment to the conditional statements in order for it to work.</p>
<p>The Codex suggests the following conditional statement in the <i>pre_get_posts</i> hook.</p>
<pre><code>// Before anything else, make sure this is the right query...
if ( ! $query-&gt;is_home() ) {
    return;
}
</code></pre>
<p>This conditional merely checks whether or not the query object is on the home page. In my case, additional calls to the WP_Query object were causing this code to fail. The <em>pre_get_posts</em> hook was being applied to every query on the page and the results were less than desirable.</p>
<h3>The Solution</h3>
<p>It&#8217;s highly likely that you have more than one query on your blog&#8217;s home page. If that&#8217;s the case, we need to be a bit more explicit with our conditional statements. We need to make sure that the query is not only on our blog&#8217;s home page, but that we&#8217;re only targeting the <a href="https://codex.wordpress.org/Function_Reference/is_main_query" rel="noopener" target="_blank">main query</a> on that page.</p>
<pre><code>&lt;?php   
/**
 *
 * Offset the main query on our blog's home page
 *
 */
function myprefix_query_offset(&amp;$query) {

    // Before anything else, make sure this query is on our
    // blog's home page, and that it's the main query...
    if ( $query-&gt;is_home() &amp;&amp; $query-&gt;is_main_query() ) {

        // First, define your desired offset...
        $offset = 1;

        // Next, determine how many posts per page you want (we'll use WordPress's settings)
        $ppp = get_option('posts_per_page');

        // Next, detect and handle pagination...
        if ( $query-&gt;is_paged ) {

            // Manually determine page query offset (offset + current page (minus one) x posts per page)
            $page_offset = $offset + ( ($query-&gt;query_vars['paged']-1) * $ppp );

            // Apply adjust page offset
            $query-&gt;set('offset', $page_offset );

        }
        else {

            // This is the first page. Just use the offset...
            $query-&gt;set('offset',$offset);

        }

    } else {

        return;

    }
}
add_action('pre_get_posts', 'myprefix_query_offset', 1 );

/**
 *
 * Adjust the found_posts according to our offset.
 * Used for our pagination calculation.
 *
 */
function myprefix_adjust_offset_pagination($found_posts, $query) {

    // Define our offset again...
    $offset = 1;

    // Ensure we're modifying the right query object...
    if ( $query-&gt;is_home() &amp;&amp; $query-&gt;is_main_query() ) {
        // Reduce WordPress's found_posts count by the offset... 
        return $found_posts - $offset;
    }
    return $found_posts;
}
add_filter('found_posts', 'myprefix_adjust_offset_pagination', 1, 2 );
</code></pre>
<p>The post <a href="https://adambalee.com/offset-wordpress-queries-without-breaking-pagination/">How to Offset WordPress Queries without Breaking Pagination</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/offset-wordpress-queries-without-breaking-pagination/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1428</post-id>	</item>
		<item>
		<title>How to Create Custom Widgets with Advanced Custom Fields</title>
		<link>https://adambalee.com/create-custom-widgets-advanced-custom-fields/</link>
					<comments>https://adambalee.com/create-custom-widgets-advanced-custom-fields/#comments</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Wed, 18 Oct 2017 17:21:54 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[advanced custom fields]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1416</guid>

					<description><![CDATA[<p>In this tutorial, we&#8217;ll cover how to leverage the power of Advanced Custom Fields Pro to create complex custom widgets. If you would like to learn more about creating custom widgets, have a look at the Widgets API in the WordPress Codex. Create a Custom Widget First we need to create a new file for [&#8230;]</p>
<p>The post <a href="https://adambalee.com/create-custom-widgets-advanced-custom-fields/">How to Create Custom Widgets with Advanced Custom Fields</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In this tutorial, we&#8217;ll cover how to leverage the power of <a href="https://www.advancedcustomfields.com/pro/" rel="noopener" target="_blank">Advanced Custom Fields Pro</a> to create complex custom widgets. If you would like to learn more about creating custom widgets, have a look at the <a href="https://codex.wordpress.org/Widgets_API" rel="noopener" target="_blank">Widgets API</a> in the WordPress Codex.</p>
<h3>Create a Custom Widget</h3>
<p>First we need to create a new file for our custom widget. Let&#8217;s name it <em>acf-custom-widget.php</em> and add it in a new directory to keep things nice and tidy. I recommend the following directory structure, but feel free to place the file anywhere you like:</p>
<pre><code>-- theme
---- inc
------ plugins
-------- acf
---------- acf-custom-widget.php
</code></pre>
<p>Next let&#8217;s include our new file in our <em>functions.php</em> file. Open up <em>functions.php</em> and add the following code:</p>
<pre><code>include_once( get_stylesheet_directory() . '/inc/plugins/acf/acf-custom-widget.php');
</code></pre>
<p>Now we&#8217;re ready to add the custom widget code to our new file. Open <em>acf-custom-widget.php</em> and add the following code:</p>
<pre><code>&lt;?php

/**
 * A custom ACF widget.
 */
class ACF_Custom_Widget extends WP_Widget {

    /**
    * Register widget with WordPress.
    */
    function __construct() {
        parent::__construct(
            'acf_custom_widget', // Base ID
            __('ACF Custom Widget', 'text_domain'), // Name
            array( 'description' =&gt; __( 'A custom ACF widget', 'text_domain' ), 'classname' =&gt; 'acf-custom-widget' ) // Args
        );
    }

    /**
    * Front-end display of widget.
    *
    * @see WP_Widget::widget()
    *
    * @param array $args     Widget arguments.
    * @param array $instance Saved values from database.
    */
    public function widget( $args, $instance ) {
        echo $args['before_widget'];
        if ( !empty($instance['title']) ) {
            echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ). $args['after_title'];
        }

        echo get_field('title', 'widget_' . $args['widget_id']);


        // Place your ACF code here


        echo $args['after_widget'];
    }

    /**
    * Back-end widget form.
    *
    * @see WP_Widget::form()
    *
    * @param array $instance Previously saved values from database.
    */
    public function form( $instance ) {
        if ( isset($instance['title']) ) {
            $title = $instance['title'];
        }
    ?&gt;
    &lt;p&gt;
      &lt;label for="&lt;?php echo $this-&gt;get_field_id( 'title' ); ?&gt;"&gt;&lt;?php _e( 'Title' ); ?&gt;&lt;/label&gt;
      &lt;input class="widefat" id="&lt;?php echo $this-&gt;get_field_id( 'title' ); ?&gt;" name="&lt;?php echo $this-&gt;get_field_name( 'title' ); ?&gt;" type="text" value="&lt;?php echo esc_attr( $title ); ?&gt;"&gt;
    &lt;/p&gt;
    &lt;?php
    }

    /**
    * Sanitize widget form values as they are saved.
    *
    * @see WP_Widget::update()
    *
    * @param array $new_instance Values just sent to be saved.
    * @param array $old_instance Previously saved values from database.
    *
    * @return array Updated safe values to be saved.
    */
    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';

        return $instance;
    }

} // class ACF_Custom_Widget

// register ACF_Custom_Widget widget
add_action( 'widgets_init', function(){
  register_widget( 'ACF_Custom_Widget' );
});
</code></pre>
<p>Let&#8217;s make sure everything is working properly. Log in to your dashboard and navigate to Appearance > Widgets. You should now see our new ACF Custom Widget listed among the available widgets.</p>
<p><img fetchpriority="high" decoding="async" src="https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM-1024x753.png" alt="" width="840" height="618" class="alignnone size-large wp-image-1418" srcset="https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM-1024x753.png 1024w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM-300x220.png 300w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM-768x565.png 768w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM-820x603.png 820w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM-640x471.png 640w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-15-at-5.23.46-PM.png 1594w" sizes="(max-width: 840px) 100vw, 840px" /></p>
<h3>Create an ACF Field Group</h3>
<p>Now it&#8217;s time to create a new field group for our widget using Advanced Custom Fields. I&#8217;m going to name mine &#8216;Custom Widget&#8217; and add a simple &#8216;textarea&#8217; field to the group. Make sure to select &#8216;Widget&#8217; in the locations menu and then set it equal to our new custom widget.</p>
<p><img decoding="async" src="https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM-1024x258.png" alt="" width="840" height="212" class="alignnone size-large wp-image-1419" srcset="https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM-1024x258.png 1024w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM-300x76.png 300w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM-768x194.png 768w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM-820x207.png 820w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM-640x161.png 640w, https://adambalee.com/wp-content/uploads/2017/10/Screen-Shot-2017-10-18-at-10.41.40-AM.png 1792w" sizes="(max-width: 840px) 100vw, 840px" /></p>
<p>All custom fields that you add to this new group should now appear in your widget. The last thing we need to do is add the custom field code to our widget.</p>
<h3>Add Custom Fields Code</h3>
<p>It&#8217;s time for the good part. Open up the <em>acf-custom-widget.php</em> file we created earlier and add the custom field code.</p>
<pre><code>&lt;?php

/**
 * A custom ACF widget.
 */
class ACF_Custom_Widget extends WP_Widget {

    /**
    * Register widget with WordPress.
    */
    function __construct() {
        parent::__construct(
            'acf_custom_widget', // Base ID
            __('ACF Custom Widget', 'text_domain'), // Name
            array( 'description' =&gt; __( 'A custom ACF widget', 'text_domain' ), 'classname' =&gt; 'acf-custom-widget' ) // Args
        );
    }

    /**
    * Front-end display of widget.
    *
    * @see WP_Widget::widget()
    *
    * @param array $args     Widget arguments.
    * @param array $instance Saved values from database.
    */
    public function widget( $args, $instance ) {
        echo $args['before_widget'];
        if ( !empty($instance['title']) ) {
            echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ). $args['after_title'];
        }

        echo get_field('title', 'widget_' . $args['widget_id']);


        // BEGIN ACF CODE
        if ( get_field('content') ) {
            echo '&lt;div class="content"&gt;'
                . get_field('content') . 
            '&lt;/div&gt;';
        }
        // END ACF CODE


        echo $args['after_widget'];
    }

    /**
    * Back-end widget form.
    *
    * @see WP_Widget::form()
    *
    * @param array $instance Previously saved values from database.
    */
    public function form( $instance ) {
        if ( isset($instance['title']) ) {
            $title = $instance['title'];
        }
    ?&gt;
    &lt;p&gt;
      &lt;label for="&lt;?php echo $this-&gt;get_field_id( 'title' ); ?&gt;"&gt;&lt;?php _e( 'Title' ); ?&gt;&lt;/label&gt;
      &lt;input class="widefat" id="&lt;?php echo $this-&gt;get_field_id( 'title' ); ?&gt;" name="&lt;?php echo $this-&gt;get_field_name( 'title' ); ?&gt;" type="text" value="&lt;?php echo esc_attr( $title ); ?&gt;"&gt;
    &lt;/p&gt;
    &lt;?php
    }

    /**
    * Sanitize widget form values as they are saved.
    *
    * @see WP_Widget::update()
    *
    * @param array $new_instance Values just sent to be saved.
    * @param array $old_instance Previously saved values from database.
    *
    * @return array Updated safe values to be saved.
    */
    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';

        return $instance;
    }

} // class ACF_Custom_Widget

// register ACF_Custom_Widget widget
add_action( 'widgets_init', function(){
  register_widget( 'ACF_Custom_Widget' );
});
</code></pre>
<h3>Conclusion</h3>
<p>That&#8217;s pretty much it! With the basic structure for our widget in place, we now have the ability to create complex widgets using any number or combination of ACF field types.</p>
<p>The post <a href="https://adambalee.com/create-custom-widgets-advanced-custom-fields/">How to Create Custom Widgets with Advanced Custom Fields</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/create-custom-widgets-advanced-custom-fields/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1416</post-id>	</item>
		<item>
		<title>Create an Alias to Download and Unzip WordPress via the Command Line</title>
		<link>https://adambalee.com/install-wordpress-with-a-single-command/</link>
					<comments>https://adambalee.com/install-wordpress-with-a-single-command/#respond</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Thu, 28 Jan 2016 06:32:47 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1063</guid>

					<description><![CDATA[<p>A while back I decided to start delving into the using the command line. At first it was scary experience. I was sure that one wrong key stroke and I was going to fry my motherboard. After I got over my initial fear, it immediately became clear how powerful the command line can be. One [&#8230;]</p>
<p>The post <a href="https://adambalee.com/install-wordpress-with-a-single-command/">Create an Alias to Download and Unzip WordPress via the Command Line</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>A while back I decided to start delving into the using the command line. At first it was scary experience. I was sure that one wrong key stroke and I was going to fry my motherboard. After I got over my initial fear, it immediately became clear how powerful the command line can be.</p>
<p>One of the first things I started doing was to download and install WordPress via the command line. I bookmarked an article with the code and referred back to it regularly. Eventually I discovered how to create aliases and realized I didn&#8217;t have to remember the code at all. I only had to create an alias and remember the one word command I assigned to it.</p>
<p>There are a few different ways to create an alias, but I prefer to create my own .aliases file so I can keep everything nice and tidy. I&#8217;m doing this on a mac, but I&#8217;m sure the process is somewhat similar on Windows.</p>
<p>First, create the .aliases file in your user directory.</p>
<pre><code>$ cd ~
$ touch .aliases
</code></pre>
<p>Next, in the same directory, we need to add the .aliases file to our .bashrc or .bash_profile. If you don&#8217;t see this file, go ahead and create one, and add the following using your editor.</p>
<pre><code>. ~/.aliases
</code></pre>
<p>Now open the .aliases file in your favorite editor and add the following.</p>
<pre><code># WordPress
alias wordpress='wget https://wordpress.org/latest.tar.gz; tar xfz latest.tar.gz; mv wordpress/* ./; rmdir ./wordpress/; rm -f latest.tar.gz;'
</code></pre>
<p>That&#8217;s it! From now on, all you need to do to download and install WordPress is to type one word&#8230;</p>
<pre><code>$ wordpress
</code></pre>
<p>The post <a href="https://adambalee.com/install-wordpress-with-a-single-command/">Create an Alias to Download and Unzip WordPress via the Command Line</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/install-wordpress-with-a-single-command/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1063</post-id>	</item>
		<item>
		<title>Search WordPress by Custom Fields without a Plugin</title>
		<link>https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/</link>
					<comments>https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/#comments</comments>
		
		<dc:creator><![CDATA[Adam J. Balée]]></dc:creator>
		<pubDate>Wed, 25 Feb 2015 00:32:20 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[custom fields]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://adambalee.com/?p=1018</guid>

					<description><![CDATA[<p>Custom fields are one of the more powerful features available in WordPress. They are particularly useful when extending WordPress via the use of custom post types. I create custom post types all the time for things like products, portfolios, or galleries when developing WordPress themes for clients. Custom fields are extremely handy when it comes [&#8230;]</p>
<p>The post <a href="https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/">Search WordPress by Custom Fields without a Plugin</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="http://codex.wordpress.org/Custom_Fields" title="Custom Fields - WordPress Codex" target="_blank" rel="noopener noreferrer">Custom fields</a> are one of the more powerful features available in WordPress. They are particularly useful when extending WordPress via the use of <a href="http://codex.wordpress.org/Post_Types" title="Custom Post Types - WordPress Codex" target="_blank" rel="noopener noreferrer">custom post types</a>. I create custom post types all the time for things like products, portfolios, or galleries when developing WordPress themes for clients. Custom fields are extremely handy when it comes to adding product details, such as item numbers or prices. Unfortunately, it&#8217;s not possible to search WordPress by custom fields out of the box. In order to fix that, we need to modify the WordPress search query to include custom fields.</p>
<h3>Left Join</h3>
<p>The &#8216;postmeta&#8217; table is where all the custom field data is stored in the database. By default, the WordPress search functionality is set to search the &#8216;posts&#8217; table only. In order to include the custom fields data in our search, we first need to perform a left join on the &#8216;posts&#8217; and &#8216;postmeta&#8217; tables in the database.</p>
<pre><code class="language-php">/**
 * Join posts and postmeta tables
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
 */
function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb-&gt;postmeta. ' ON '. $wpdb-&gt;posts . '.ID = ' . $wpdb-&gt;postmeta . '.post_id ';
    }

    return $join;
}
add_filter('posts_join', 'cf_search_join' );
</code></pre>
<h3>Modify the Query</h3>
<p>Next we need to modify the WordPress search query to include custom fields.</p>
<pre><code class="language-php">/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;

    if ( is_search() ) {
        $where = preg_replace(
            "/\(\s*".$wpdb-&gt;posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(".$wpdb-&gt;posts.".post_title LIKE $1) OR (".$wpdb-&gt;postmeta.".meta_value LIKE $1)", $where );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );
</code></pre>
<h3>Prevent Duplicates</h3>
<p>Finally, we need to add the DISTINCT keyword to the SQL query in order to prevent returning duplicates.</p>
<pre><code class="language-php">/**
 * Prevent duplicates
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
 */
function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );
</code></pre>
<h3>Wrapping It Up</h3>
<p>Add the following to functions.php to start searching WordPress by custom fields. Not only will this code modify the search on the front-end, but you&#8217;ll also be able to search the edit screens in the admin by custom fields as well.</p>
<pre><code class="language-php">&lt;?php
/**
 * Extend WordPress search to include custom fields
 *
 * https://adambalee.com
 */

/**
 * Join posts and postmeta tables
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
 */
function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb-&gt;postmeta. ' ON '. $wpdb-&gt;posts . '.ID = ' . $wpdb-&gt;postmeta . '.post_id ';
    }

    return $join;
}
add_filter('posts_join', 'cf_search_join' );

/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;

    if ( is_search() ) {
        $where = preg_replace(
            "/\(\s*".$wpdb-&gt;posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(".$wpdb-&gt;posts.".post_title LIKE $1) OR (".$wpdb-&gt;postmeta.".meta_value LIKE $1)", $where );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

/**
 * Prevent duplicates
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
 */
function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );
</code></pre>
<p>The post <a href="https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/">Search WordPress by Custom Fields without a Plugin</a> appeared first on <a href="https://adambalee.com">Adam Balée Designs, LLC</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/feed/</wfw:commentRss>
			<slash:comments>32</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1018</post-id>	</item>
	</channel>
</rss>
