All posts by Ben Kaplan

SFCC SFRA page designer tools

I’ve been quite busy learning all sorts of technologies since 2019, but one of my main focuses has been on Salesforce Commerce Cloud and their page designer framework.

One of the developers that I was working with, the amazing Jacob Swain, had a set of HTML files that could parse an SFCC content asset export for page designer pages, and return results. He also introduced me to custom editors, which take page designer to an entirely new level.

Here’s a link to a repo that has my active collection:

https://github.com/zotsf/sfra-page-designer-tools

Here’s a link to my repo of custom page designer editors:

https://github.com/zotsf/sfcc-page-designer-custom-editors

Gutenberg or not to Gutenberg with ACF

The Gutenberg editor is pretty fantastic, and you can do all sorts of things. I personally love it.

However, if you want to use ACF to manage the content on a particular page template, you can’t really rely on ACF’s ‘Hide on Screen’ functionality in the field group editor.

Here’s a simple function you can use to turn off the Gutenberg editor on pages with those specific templates.

add_action('init', 'my_disable_editor');
function my_disable_editor() {

	// get the current post ID
	$post_id = $_GET['post'] ? $_GET['post'] : $_POST['post_ID'] ;

	// if it's not set, ignore the function
	if( !isset( $post_id ) ) return;

	// find the page template of the current post
	$template_file = get_post_meta($post_id, '_wp_page_template', true);

	// hide the gutenberg editor if one of these page types
	// edit the following to suite your page templates
	if(
	    $template_file == 'page-templates/page-this.php' ||
	    $template_file == 'page-templates/page-that.php' ||
            $template_file == 'page-templates/page-other.php' 
	) {
	    remove_post_type_support('page', 'editor');
	}
}

WordPress wants to update my custom theme

I build custom themes all day long all year long. Recently I created a theme with the word Diamond in the name. Once it was installed in WordPress, WordPress wanted to offer an update for it. It was offering an update to some random theme named Diamond. I tried changing the name in the style.css file to have other words in it, but it seems just having the name diamond triggered it. Then I changed the version number to 100. Since that’s way above any likely version number in the WP database, WordPress stopped offering an update! Alternatively, you could just remove the version number. That works as well.

Pagination for Custom Post Types

Getting pagination for your custom post type indexes isn’t too hard.

Set the variable $paged:


$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

Be sure that ‘paged’ is in your args for your WP_Query:


'paged' => $paged,

Output the links:


$output .= paginate_links( array(
'base' => str_replace( $big, '%#%', get_pagenum_link( $big ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $query_name->max_num_pages
) );

SSL for your local development server

So, some of you may have gotten MAMP to work happily with self-generated SSL certificates. It’s a bit tricky and I’ll assume you’ve got that working.

… a quick tip on getting OS X to shut down the default installed apache so Mamp can run on port 80 and 443:
(found here… https://gist.github.com/jfloff/5138826 )

First of all you need to be able to run MAMP in port 80. This is a “heat check” if you don’t have any process jamming http ports. You can check it like this:

sudo lsof | grep LISTEN

If you do happen to have any process with something like this *:http (LISTEN), you are in trouble. Before with adventure check if it isn’t MAMP itself (yeah, you should close that beforehand)

ps If you don't see MAMP, you are in good hands, I have just the thing for you:
# I've forced the removal of the job
$ launchctl remove org.apache.httpd

# and load it again
$ launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

# and unload it again
$ launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist

Now you should be able to use port 80 (and almost any other) in MAMP. Just go to MAMP > Preferences > Ports Tab and click the Set to default Apache and MySQL ports.

….now back to SSL certs

However, there’s a new wrinkle. Chrome and FF both have decided that self-signed certificates need to be of the Version 3 variety, rather than the plain old ones generated by MAMP. I ran into an issue where chrome was complaining about a missing subjectAltName in the certificate that I had set up.

So, here’s the article I used to get my stuff sort of working:

https://alexanderzeitler.com/articles/Fixing-Chrome-missing_subjectAltName-selfsigned-cert-openssl/

Here’s another version of that:

Create Your Own SSL Certificate Authority for Local HTTPS Development

OMG, you say, that’s like waaaaaaa? No worries, I’ll help break it down here and do it a little differently.

They have you create all sorts of scripts. I’m not sure why, probably because it’s the right way to do it, but here’s the straight forward way to set up.

What you are doing is creating your own CA certificate (aka a certificate authority), then using that to create a certificate for your site that needs ssl.

In the following directions, you need to replace YOURLOCALSITEDOMAIN with the domain your are setting up on your MAMP server. You know, like mysite.dev, or sams-site.dev, etc…

Go to the directory, where you store your ssl certificates for MAMP and do the following:

STEP 1
On the command line type out the following:

openssl genrsa -des3 -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

– this sets your server up to be a CA certificate issuer
– it’s going to ask you a bunch of questions about the country, state, city, and other things. Just answer them with your own info 🙂 The questions will be similar to the parameters you see in the [dn] section in the code below.

STEP 2
Create a file called YOURLOCALSITEDOMAIN.csr.cnf with the following:

[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=US
ST=New York
L=Rochester
O=End Point
OU=Testing Domain
emailAddress=your-administrative-address@your-awesome-existing-domain.com
CN = YOURLOCALSITEDOMAIN

– This is a configuration file that will be used when generating your specific site certificates. Change the ST, L, email parameters to whatever you want. I’d go ahead and use your own email.

STEP 3
Then, create a file called v3.ext with the following:

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
DNS.2 = YOURLOCALSITEDOMAIN

– This is the file that is used by the CA issuer to ensure your cert is version 3 and offers up the named domain as you see in the parameter DNS.2.

STEP 4
Then generate the certificates with this!!! On the command line type out the following (don’t forget to replace the YOURLOCALSITEDOMAIN with whatever development domain you are using:

openssl req -new -sha256 -nodes -out YOURLOCALSITEDOMAIN.csr -newkey rsa:2048 -keyout YOURLOCALSITEDOMAIN.key -config <( cat YOURLOCALSITEDOMAIN.csr.cnf )

openssl x509 -req -in YOURLOCALSITEDOMAIN.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out YOURLOCALSITEDOMAIN.crt -days 5000 -sha256 -extfile v3.ext

Now, when you need to get a second site working, you'll repeat steps 2 through 4. HOWEVER, you won't recreate the v3.ext file. You'll just add a new DNS parameter with your new domain. So, in the above example, I'd be adding DNS.3 = NEWSITEDOMAIN. You'd add a new DNS parameter for each new secure site you do.

STEP 5
Now, open your keychain access app in OS X and add your new certs, then set them to always be trusted. That way your mac will stop throwing warnings. Also, if you are looking at your site in the CodeKit Bonjour URL, then you'll need to add the Temp SSL certificate Codekit creates. You'll find that in the My Certificates section of the Keychain Access app.

I also ran into a thing with iThemes Security. The .htaccess rules were causing redirect loops for the SSL. You could get to the home page, but no secondary pages. Secondary pages resulted in a 500 error. Replacing the iThemes Security SSL feature with the plugin, 'really simple ssl', then clearing out the config that iThemes put in the .htaccess file cleared that right up.

OMG, that made your brain hurt, right? It made mine hurt for a bit too, but hopefully all is working for you now.

The countdown timer and possible redirect

Hey folks, here’s a nifty script that you can use to have a countdown timer. It’s also useful if you want a page to redirect at a specific time of day. For instance, if the sales of a client’s program ends at midnight, you can use this script to countdown to midnight and redirect to a different page after that time.

Got it from here…

https://gist.github.com/nbrombal/63923dda778c67f43ffa

Here’s the code:

<script>
(function($) {

// If target date is specific to one timezone, set to true and specify it
var absoluteTarget = true;
// this number is the number of hours behind Greenwich Mean Time you are setting your clock to.
// In this example, it's set to Pacific time, which is 7 hours behind GMT.
var targetTimeZone = -7;

// You set the target date/time with var targetDateUTC.
//Use this documentation to get an understanding of the numbers below: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC
var targetDateUTC = new Date(Date.UTC(2017,04,24,21,0)).getTime();
var currentDate = new Date();
var timeZoneOffset = (absoluteTarget ? targetTimeZone * -60 : currentDate.getTimezoneOffset()) * 60 * 1000;
var targetDate = targetDateUTC + timeZoneOffset;

var getCountdown = function() {
var totalSeconds = (targetDate - Date.now())/1000;
var days = Math.floor(totalSeconds / (60 * 60 * 24));
var hours = Math.floor(totalSeconds / (60 * 60)) % 24;
var minutes = Math.floor(totalSeconds / 60) % 60;
var seconds = Math.floor(totalSeconds) % 60;

if ( currentDate > targetDate ) {
// Redirect to specific URL
window.location.replace("http://jennjoycoaching.com/");
} else {
// I've commented the below out to NOT show the actual timer.
// if you want to show the timer, see the HTML markup below
// Display the remaining time
//$('.clock .days').html(days);
//$('.clock .hours').html(hours);
//$('.clock .minutes').html(minutes);
//$('.clock .seconds').html(seconds);
}
};

setInterval(getCountdown, 1000);

getCountdown();

})(jQuery);
</script>

HTML Markup for timer


<div class="clock">
<span class="days"></span>
<span class="hours"></span>
<span class="minutes"></span>
<span class="seconds"></span>
</div>

 

Custom Taxonomy Archive Template Paginiation Notes

Five things you need for custom taxonomy archive page pagination working perfectly :

( 1 ) Don’t put exclude_from_search parameter key as register_post_type argument parameter or if mention set it ‘exclude_from_search’ => false. By default it is set false if not mentioned.

( 2 ) The taxonomy that will be use with the custom post type set
‘taxonomies’ => ‘custom_taxonomy_name’ as register_post_type argument parameter or
use register_taxonomy_for_object_type() directly.
Custom taxonomies still need to be registered with register_taxonomy().

( 3 ) While querying within new WP_Query ($args)
i ) If not set in admin static front page use before new WP_Query($args)
$paged = ( get_query_var(‘paged’) ) ? get_query_var(‘paged’) : 1;
and use $query = new WP_Query( array( ‘paged’ => $paged ) );

ii ) If set in admin static front page use before new WP_Query($args)
$paged = ( get_query_var(‘page’) ) ? get_query_var(‘page’) : 1;
and use $query = new WP_Query( array( ‘page’ => $paged ) );
Remember to use ‘posts_per_page’ and ‘paged’ parameter in new WP_Query($arg) argument array.
If not set static front page then you should use ‘page’ parameter in new WP_Query ($arg) argument array

( 4 ) Use WordPress paginate_links( $args ) function like the example below to render pagination in archive template file.

$big = 999999999; // need an unlikely integer
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%', or '/paged=%#%', // if using pretty permalink
'current' => max( 1, get_query_var('paged') ),
'total' => $query->max_num_pages ) );
// Here $max_num_pages is the properties of new WP_Query() object . It is total number of pages. Is the result of $found_posts / $posts_per_page

( 5 ) The paginate_links() function output the html.

  • .......

If you use bootstrap inject “pagination” class to the

    with the help of javascript or jquery and a nice fancy pagination will be output.