In this interview, Javier gives advice for junior developers who are hoping to grow professionally as backend developers and shares his programming style, his favorite books, and how he deals with the unexpected as a backend developer.
WPScan is on track to post a record-breaking year for WordPress plugin vulnerabilities submitted to its database, according to a collaborative mid-year security report the company published with Wordfence. In the first half of 2021, WPScan has recorded 602 new vulnerabilities, quickly surpassing the 514 reported during all of 2020.
The report is based on attack data from Wordfence’s platform and data from WPScan’s vulnerability database, providing a more comprehensive picture of the current state of WordPress security than either company could present alone.
One of the trends highlighted in the report is the increase in password attacks. Wordfence blocked more than 86 billion password attack attempts in the first half of 2021. Attackers use a variety of methods to gain access to WordPress sites, including testing sites against lists of compromised passwords, dictionary attacks, and more resource intensive brute force attacks.
Wordfence found the standard login to be the primary password attack target for 40.4% of attempts, followed by XML-RPC (37.7%). Since these attacks seem to be increasing, the report recommends that site owners use 2-factor authentication on all available accounts, use strong secure passwords unique to each account, disable XML-RPC when not in use, and put brute force protection in place.
Data from Wordfence’s Web Application Firewall shows more than 4 billion blocked requests due to vulnerability exploits and blocked IP addresses. The report includes a breakdown of the percentage of requests blocked by firewall per firewall rule. Directory Traversal accounts for 27.1% of requests. This is when an attacker attempts to access files without being authorized and perform an action such as reading or deleting a site’s /wp-config.php file, for example. This breakdown also highlights the fact that certain older vulnerabilities are still frequently targeted by attackers.
The vast majority of the vulnerabilities you hear about in the WordPress ecosystem come from plugins, with themes making up a much smaller portion. The report notes that only three of the 602 vulnerabilities catalogued by WPScan in the first half of this year were found within WordPress core.
In analyzing vulnerabilities by type, WPScan found that Cross-Site Scripting (XSS) vulnerabilities accounted for more than half of all them (52%), followed by Cross-Site Request Forgery (CSRF) at 16%, SQL Injection (13%), Access Control issues (12%), and File Upload issues (7%). Using scores from the Common Vulnerability Scoring System (CVSS), WPScan found that 17% of reported vulnerabilities were critical, 31% high, and 50% medium in severity.
Both Wordfence and WPScan claim that the greater number of vulnerabilities reported this year is indicative of the growth of the WordPress ecosystem and a maturing, healthy interest in security. Themes and plugins aren’t getting more insecure over time but rather there are more people interested in discovering and reporting vulnerabilities.
“First and foremost, we aren’t seeing a lot of newly introduced vulnerabilities in plugins and themes but rather we are seeing a lot of older vulnerabilities in older plugins and themes being reported/fixed that just weren’t detected until now,” Wordfence Threat Analyst Chloe Chamberland said.
“Vulnerabilities aren’t being introduced as frequently and more vulnerabilities are being detected simply due to the higher activity of researchers which is in turn positively impacting the security of the WordPress ecosystem. Considering it isn’t newly introduced vulnerabilities that are being frequently discovered, I feel confident in saying that the increase in discoveries doesn’t indicate that the ecosystem is getting less secure at all but rather getting more secure.”
Chamberland also said she believes there is a domino effect when vulnerabilities are disclosed to vendors and they learn from their accidents, causing them to develop more secure products in the future.
“Speaking from experience as I spend a lot of my time looking for vulnerabilities in WordPress plugins, things have definitely been getting more secure from my perspective,” she said. “Today, I frequently find capability checks and nonce checks in all the right places along with proper file upload validation measures in place, and all the good stuff. It’s become harder to find easily exploitable vulnerabilities in plugins and themes that are being actively maintained which is a great thing!”
The mid-year report is available as a PDF to download for free from the WPScan website. WPScan founder and CEO Ryan Dewhurst said he expects there will be an end of the year report for 2021. He has not yet discussed it with Wordfence but the companies are brainstorming about other ways they can collaborate.
The most obvious solution is to start with a Brute Force approach. In this approach, you can compare each number with the rest of the numbers in the array. In case you find a duplicate proceed to the next number and in case you don’t find a duplicate you return the current number as a Single Number.
Technology forms the major backbone of our society today. However — not all technology is accessible to people with disabilities, which comprise around 15% of the world’s population. According to the 2021 WebAIM study, "97% of the top one million home pages had accessibility issues." Moreover, according to an analysis from UsableNet Inc., the number of web accessibility lawsuits is expected to reach a total of a whopping 4,195 in 2021. These statistics reveal that we, in the software community, can do a lot better to make our technology more accessible. Software engineers can contribute by baking accessibility in their development process instead of waiting until accessibility auditing or fixing bugs at the end. Here are a few ways on how to get started:
These are an extensive set of guidelines on how to make your web application accessible to not just users who use screen-readers, but also other types of disabilities such as Deaf/Hard of Hearing, cognitive or motor disabilities. Many of these guidelines and principles also apply to Desktop based applications or really any technical product you can think of. For software engineers focused on web development and who want to learn more the accessibility infrastructure of the web, I recommend reading up on Accessible Rich Internet Applications (ARIA) and the Accessibility Tree.
Are you looking out to explore some best WordPress security plugins? Well to have all your queries sorted we have brought you an article that will highlight the key elements of two of the most famous WP security plugins that are capable of delivering excellent services when it comes to web security and administration Sucuri […]
Recently I had the opportunity to build a small application that needed to authenticate and authorize a user using Google’s sign-in mechanism, and requests on their behalf data from a Google API.
I choose to implement this as a Cloudflare Worker as a serverless compute service leveraging Cloudflare key-value storage (KV) for session storage. The tooling from Cloudflare (wrangler) has evolved nicely since my first attempt at Cloudflare Workers, so I thought it was high time that I gave it another try.
Serverless architecture has already become an efficient solution to align overprovisioning and underprovisioning resources (e.g., CPU, memory, disk, networking) with actual workloads regardless of physical servers, virtual machines, and cloud environments. Yet, there is a concern for Java developers when choosing new programming languages to develop serverless applications. The Java framework seems too heavyweight and slow for serverless deployment on the cloud, especially Kubernetes.
What if you, Java developer, could keep using the Java framework to build traditional cloud-native microservices as well as new serverless functions at the same time? This approach should be exciting since you don’t have to worry about a steep learning curve for new serverless application frameworks.
When Document Generation API launched a few months ago, we included a Microsoft Word add-in to make it simpler for folks to design their Word templates for use within the API. To use the add-in, you needed to provide data in JSON format, either pasted in or uploaded via an existing file:
This worked perfectly fine if you had your data ready to go, but that wouldn’t always be possible, especially if you’re starting a new project and need to start prototyping quickly. Luckily, our latest update adds a few features to simplify this. Let’s take a quick look at what’s changed. Note — for folks who’ve already installed the Word add-in, it should update automatically for you. Suppose you haven’t installed this add-in yet; head over to our documentation for instructions on how to do it.
Arctype is a high-performance SQL client that lets you manage your database with a simple user interface. It also enables you to build visualizations straight from queries, modify databases in the same way that you would spreadsheets, and share frequently used SQL queries with your team.
What are Arctype Dashboards?
Arctype dashboards allow you to generate charts and tables to examine your data. You can also use them to create tools that modify and visualize data from your database and automate technical and tedious activities.
Every day, the ProgrammableWeb team is busy, updating its three primary directories for APIs, clients (language-specific libraries or SDKs for consuming or providing APIs), and source code samples.
A few days ago, Chris wrote up his thoughts about how alert(), confirm(), and prompt() were being deprecated by Chrome and collected a bunch of thoughts from developers. If certain features can essentially be turned off by a major browser, a lot of folks started to worry about the predictability of the web.
We can’t normalise the attitude that collateral damage is the price of progress, even if we accept the premise — which I don’t — that removing APIs like alert represents progress. For all its flaws, the web is generally agreed to be a stable platform, where investments made today will stand the test of time. A world in which websites are treated as inherently transient objects, where APIs we commonly rely on today could be cast aside as unwanted baggage by tomorrow’s spec wranglers, is a world in which the web has already lost.
This specific bit of drama isn’t of much interest to me, I must admit. But! I think it brings up a super important distinction between software and the web. Here’s a story.
The other day I was faffing about with Astro (which I like a lot). I was rebuilding my personal site with it and I decided — in a spark of punk rock-ness — to update to the latest version of it. I thought perhaps it might make my build process a bit quicker and give me a chance to explore new features. But alas — everything broke. APIs had been deprecated! My build process broke! Everything crumbled down around me.
This isn’t me dunking on Astro. I love it, still. But it’s important to remember that Astro isn’t the web. Neither is React or any other framework, really. Those teams can feel free to deprecate things, improve things as much as they want. They can burn it all to the ground and start again. But stuff like alert(), old CSS features, and HTML elements aren’t in the same category. They can’t be deprecated in the same way because, as Jeremy said, the web needs to be predictable. And we can’t treat the web like plain ol’ software because no one team or individual owns those features.
Here’s the gist of my rant: alert() and confirm() aren’t features of Chrome, but of the web. But I fear that’s how a lot of folks might think about them.
This is also why standards are so important! Talking about new features in public lets us fix all the bugs and answer all the questions before a new feature ships onto this platform where you can’t just delete it when you realize you goofed up. I’m not even really dunking on Chrome here either, but this distinction between software and the open web is an important one to make. Right?
Based on the 2020 Java Ecosystem survey from Jetbrains, 75% of Java developers are still using JDK 8. JDK 11 introduces HttpClient, which replaces the legacy HttpURLConnection API. For this tutorial, we will build a HttpClient that consumes the free Cat Facts API.
Goals
At the end of this tutorial, you would have learned:
How to use the HttpClient to consume REST APIs.
Prerequisite Knowledge
Basic Java.
Good understanding of HTTP protocols.
Tools Required
Any Java IDE that supports JDK 11 and above.
The Application Entry Point
Our App does not need any special build tool. Follow the steps below to create the main method:
Create an empty Java project with support for JDK 11+.
Create a package called com.example.client.
Inside the client package, create a class called Entry.
Add the main method inside Entry.
Your Entry.java file should now look like this:
package com.example.client;
public class Entry {
public static void main(String[] args){
}
}
The CatFactsService Class
Next, we need to create a class for grouping all of the logics for our HttpClient.
Inside the same Entry.java file, create another top level class called CatFactsService with package visibility (empty modifier).
Add a private final instance variable with type HttpClient(from java.net.http) and identifier httpClient.
Add an empty constructor and initialize httpClient using the static method newHttpClient() from the HttpClient class. This will initialize a HttpClient with default settings, which is sufficient for this tutorial. If you want to obtain an instance of HttpClient with custom settings, you can use the static method newBuilder() from HttpClient instead.
The CatFactsService class should now look like this:
class CatFactsService {
private final HttpClient httpClient;
CatFactsService() {
this.httpClient = HttpClient.newHttpClient();
}
}
Preparing for Requests
There are a couple of steps that we will have to follow before sending a simple request:
Build the request: setting headers, parameters, body content, uri, etc. We will use HttpRequest.Builder for this.
Decides whether we want an async or synchronous request, so we can handle the response properly.
a. If the request is synchronous, we would use the send() method and assign the response to HttpResponse.
b. If the request is async, we would use the sendAsync() method and assign the response to CompletableFuture.
Whether we want to use a default HttpResponse.BodyHandler implementation or a custom implementation.
Retrieving a Random Cat Fact
The first request that we will build is a synchronous GET request.
Add a private static final String randomFactURI variable into CatFactsService. Initialize it with https://catfact.ninja/fact?max_length=%d. This variable serves as a constant for other methods in the class. Hard-coded URIs can change and is not a good practice, so loading String constants from an external source such as the .properties file is preferred. I am only using hard-coded String objects to keep the tutorial simple to understand.
private static final String randomFactURI = "https://catfact.ninja/fact?max_length=%d";
Add the getRandomCatFact method to the CatFactsService.
public String getRandomCatFact(int maxLength) throws IOException, InterruptedException {
//Creates a new request for sending
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(String.format(randomFactURI, maxLength)))
.build();
//Gets response with the body as String
HttpResponse<String> res = this.httpClient.send(req, HttpResponse.BodyHandlers.ofString());
return res.body();
}
Here are the explanation for the method above:
The cat fact API has an endpoint to get a random cat fact, and the only customization we can make is the max length of the cat fact String. The max length is set as a request parameter. Our method takes a parameter of int, which is the max length that callers can set.
In the String constant that you added in the previous step, there is a placeholder %d String. Based on Java Formatter rules, this allows us to insert an integral type into the placeholder String. The int parameter would replace %d.
The first statement that declares req and initializes an HttpRequest object is where we build our request. Since we only need to modify the URI parameters, we would call the uri() method to set our custom URI.
The second statement is where we send a synchronous request and assigns the response to the HttpResponse object.
Because the API returns the cat fact as a json object in the body of the response, we need to return the body of the response to our caller.
Use the CatFactsService
In the main method, we need to initialize a CatFactsService instance, and then use the getRandomCatFact method to get random cat fact. Here is the content of the main method:
var service = new CatFactsService();
String jsonCatFact1 = service.getRandomCatFact(70);
String jsonCatFact2 = service.getRandomCatFact(140);
System.out.println(jsonCatFact1);
System.out.println(jsonCatFact2);
After running main, you will receive two json objects (as String). Here are what I received:
{"fact":"Neutering a cat extends its life span by two or three years.","length":60}
{"fact":"Many cats love having their forehead gently stroked.","length":52}
Solution Code
package com.example.client;
import java.io.IOException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.URI;
import java.net.http.HttpResponse;
public class Entry {
public static void main(String[] args) throws IOException, InterruptedException {
var service = new CatFactsService();
String jsonCatFact1 = service.getRandomCatFact(70);
String jsonCatFact2 = service.getRandomCatFact(140);
System.out.println(jsonCatFact1);
System.out.println(jsonCatFact2);
}
}
class CatFactsService {
private final HttpClient httpClient;
private static final String randomFactURI = "https://catfact.ninja/fact?max_length=%d";
CatFactsService() {
this.httpClient = HttpClient.newHttpClient();
}
public String getRandomCatFact(int maxLength) throws IOException, InterruptedException {
//Creates a new request for sending
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(String.format(randomFactURI, maxLength)))
.build();
//Gets response with the body as String
HttpResponse<String> res = this.httpClient.send(req, HttpResponse.BodyHandlers.ofString());
return res.body();
}
}
Summary
The project that we created is a good starting point if you want to create an HTTP client to consume REST APIs. As for why HttpClient was introduced in JDK 11, you can check out JEP 110 and JEP 321.
Earlier today, Yoast CEO Marieke van de Rakt announced the company had been acquired by NewFold Digital. Yoast and its SEO-related business are expected to continue operating as usual with its current team and maintaining its product line.
Newfold Digital is a global web solutions provider that serves small-to-medium businesses. The company has many brands under its umbrella, such as Network Solutions, Bluehost, and more.
“Yoast never had any funding before, it grew organically into a company with 140 employees maintaining a plugin with over 12 million active installs,” wrote van de Rakt in the announcement. “We don’t want to stop there! We’re planning to grow and improve even further! Joining Newfold Digital provides us with the freedom to build and iterate on ideas to further our mission.”
There are no plans to change the team or the culture around Yoast. One of the goals during the acquisition was to keep everyone in place, continuing work on their product line.
“Of course, some things change,” said Yoast founder and CPO Joost de Valk. “We’ll integrate into their systems (HR and finance). We’ll work on special offers for customers from Newfold. Our company changed so much over the five years, so it will change no matter what. I do feel that this opens up more security for growth and for developing new ideas.”
While Yoast does not plan to change its 140-person team, it is still bringing in fresh talent. The company has been hiring a lot lately and expects that trend to continue with 19 current job openings.
As host Nathan Wrigley and guest Cory Miller discussed on the latest episode of the Jukebox, acquisitions can be a welcome change for all parties. It can provide more financial stability and backing for the acquired company. It may allow the team to explore new features or new products that were not possible before. This can also work in the user’s favor in the long term.
“Marieke and I felt ever since this Covid pandemic hit that we needed a partner or some more financial backing,” said Joost de Valk. “Being totally bootstrapped was getting to us. We worried about the exchange rate of the dollar, for instance. We got risk-averse, and all around us other companies got financial injections.”
The husband-and-wife duo thought about selling part of their stock for additional funding but was worried about potential consequences. One such downside may have been the need to grow fast to keep investors happy.
“We wanted to find a place to keep Yoast SEO growing and to keep working on WordPress,” said de Valk. “We had help from RBC, a company that helps with these types of acquisitions. They introduced us to Newfold, and we had a really good connection right from the start.”
He remained tight-lipped about any new products or features in the pipeline, only saying that a lot is coming and things will speed up.
Newfold is the owner of several high-profile hosting brands, including Bluehost and HostGator — both offer a managed WordPress service. It would not be unheard of to see a company mix and match its various products to draw in more customers. Nor would it be surprising to eventually see Yoast SEO or even some of the commercial Yoast offerings as part of packaged hosting deals. WP Engine fully integrates StudioPress products, for example, into its packages. However, de Valk said they have yet to discuss anything on that front.
“You’re absolutely right that the things you’re proposing here make perfect sense,” he said. “So, I think we’ll work on those deals and, at the same time, team Yoast will work independently on their products.”
Eden AI has launched what the company terms an “AI management platform,” which is intended to provide developers with a unified source for machine learning APIs across myriad vendors. Rather than working directly with AI service providers, Eden AI provides a streamlined entry point for access to machine learning resources.
The recent pandemic has forced many businesses to go online. This has created a boom for Shopify, a popular eCommerce platform that makes it easy to open up your online store.
With hundreds of beautiful themes and apps that enhance your shoppers’ experience, Shopify has everything you need to shift your operation online and create a digital storefront for your business.
But to get started, you’ll need a solid Shopify theme and that’s what this post is all about. We’ll cover the best free and premium Shopify themes for 2021 that will allow you to launch your store as quickly as possible.
Your Web Designer Toolbox
Unlimited Downloads: 500,000+ Web Templates, Icon Sets, Themes & Design Assets
Starting at only $16.50/month!
18 Best Free And Premium Shopify Themes
Below, you’ll find an overview of the 18 best Shopify themes along with their features.
The Helas theme has a clean and minimal design. It would work well for a fashion store and has a product-centered layout which makes it easy for your customers to see what you have to offer. Notable features include product carousels and labels, plenty of customization options, built-in customer reviews, wishlist support, and more.
The Vintage theme is a free Shopify theme that would work well with home and garden, entertainment or arts and crafts stores. The theme has a minimal design and includes features such as recommended products, stock counter, in store pickup availability indicator, and more. In addition to that, the theme is responsive and easy to use.
Here’s a versatile and responsive Shopify theme that can be used for any type of store. It features a minimal design and has a built-in mega menu. Notable features include automatic price changes, products’ quick view, powerful customization options, product labels, built-in product zoom, and more.
The Narrative is a free Shopify theme that would work well for stores selling only one or two products. The theme has a simple design and includes features such as hero video, customizable image blocks, quote slides, customizable navigation, wide layout, and more. On top of this, the theme looks stunning on both mobile and desktop devices.
If you have a store that sells hiking, camping, and trekking gear, the Hikez theme is a great choice. It has a stunning grid based layout which makes it easy to organize and display your products. The theme is fully responsive and comes with awesome features such as product carousel and product comparison, 5 types of mega menus, Ajax filters, multi-currency support, and more.
If you’re looking for a free theme that was designed with apparel stores in mind, the Brooklyn theme has you covered. This theme features a modern and elegant design and has plenty of customization options. You’ll also find all the necessary features for a powerful eCommerce store such as dynamic product grid, header slideshow, slideout cart, support for video on the homepage, and more.
The Daxone theme is a great choice for any type of store since it has a versatile and modern design. The theme is packed with features to help you sell more, including: various page layouts, prebuilt sections, plenty of customization options, popup cart, built-in newsletter form, product quick view, and more. The theme is also responsive and optimized for SEO.
As the name implies, the Simple theme has a clean and simple layout that makes it easy to showcase your products in a modern grid layout. The theme has a sidebar menu which offers easy navigation and you’ll also find features such as product image zoom, image animations, product recommendations, and customization options. The theme is also responsive.
The Ella theme is a premium multipurpose Shopify theme that works well with any type of store. The theme looks stunning on both desktop and mobile devices thanks to its responsive design. It has plenty of customization options and includes important eCommerce features such as dynamic product filters, pre-built page sections, quick shop, quick edit cart, recommended products, product bundles, and more.
The Supply theme is perfect for any store that has a large inventory. You can easily showcase products, feature best-sellers, and more. The theme is responsive, easy to customize, and comes with features such as collection filtering in the sidebar, product slideshow, featured collections, and more. In addition to that, the theme comes with two color schemes.
If you’re looking for a theme that gives you plenty of control over the design of your store, the Wookie theme is a great choice. Not only does it have plenty of customization options but it also offers a number of premade sections to make it easy to design and build your store. You’ll also find features such as numerous layout variations, mega menu, dynamic checkout buttons, product filters, and sticky add to cart button.
The Boundless theme has a minimal and lightweight design that puts your product photography front and center. The theme is easy to use and has a responsive design. It includes features such as slideshows with a fading effect, full width collection images, sticky navigation, homepage video, and more. The theme is also fully responsive and optimized for large images.
The Avone theme has been optimized to load fast. It has a versatile design that works well for any type of store. The theme also includes features such as powerful customization options, mega menu, wishlist support, product countdown, quick view, product filters, product recommendations, and more. The theme is responsive and has several demo layouts to choose from.
The Venture Shopify theme is another free theme designed with stores that have a large inventory in mind. The theme features a multi-column menu that makes it easy to browse your store. You’ll find features such as product filtering, product slideshow, single featured product, promotional banner, and more. The theme is also responsive, optimized to load fast, and has a clean design.
The August theme comes with 8 different demos and it’s a great choice for a fashion, apparel or swimwear store. The theme has a modern design and comes with features such as product style variations, multiple header and footer layouts, product filters, built-in product compare and wishlist, countdown timers, product labels, and more. On top of that, the theme is also responsive.
The Express theme was designed to get you online fast. It doesn’t have a lot of customization options but it makes up for it with its ease of use and quick setup. The theme has a modern design and comes with features such as quick buy, responsive design, slideout cart, featured collections, and more. This theme is a great choice for one page stores that have a small product catalog.
If you sell car parts, the Aero theme is a perfect fit. It has a modern and bold design that’s fully responsive. The theme has 10+ premade layouts and a mega menu that makes it easy to browse your store. Notable features include product slider module, Ajax add to cart, Ajax layered navigation, product quick view, and more.
As you can see, there is no shortage of amazing free and premium themes for Shopify. The only thing left to do now is to pick a theme that suits your style and get started with your Shopify store. Good luck! Be sure to check out our other Shopify articles while you’re at it.
With the demand for sustainable solar energy now on the rise, more solar installation companies are looking for exclusive, high-conversion appointments for their businesses. This means as a solar installer; you need an ideal solar appointment system in place. Even better, this system should be capable of linking you to solar appointments that are not shared with other installers for best conversion chances. Finding exclusive solar appointments is now the new way of going about the solar installation business. These appointments offer you the opportunity to work with prequalified clients who are genuinely interested in solar panel installations. Currently, reputable companies like Solar Exclusive(https://solarexclusive.com) make this process even easier by leveraging their technology to match you with clients who appreciate your offering.
Company Name: Solar Exclusive
Address: 331 Newman Springs Rd. Bldg. 1, 4th Flr, Suite 143 - Red Bank, NJ 07701
Phone Number: 732-784-2396
Email: rich@solarexclusive.com
Now that we’ve seen that web components and interactive web components are both easier than you think, let’s take a look at adding them to a content management system, namely WordPress.
There are three major ways we can add them. First, through manual input into the site—putting them directly into widgets or text blocks, basically anywhere we can place other HTML. Second, we can add them as the output of a theme in a theme file. And, finally, we can add them as the output of a custom block.
Loading the web component files
Now whichever way we end up adding web components, there’s a few things we have to ensure:
our custom element’s template is available when we need it,
Let’s hit that first point. Once we have the template it’s easy enough to add that to the WordPress theme’s footer.php file, but rather than adding it directly in the theme, it’d be better to hook into wp_footer so that the component is loaded independent of the footer.php file and independent of the overall theme— assuming that the theme uses wp_footer, which most do. If the template doesn’t appear in your theme when you try it, double check that wp_footer is called in your theme’s footer.php template file.
<?php function diy_ezwebcomp_footer() { ?>
<!-- print/echo Zombie profile template code. -->
<!-- It's available at https://codepen.io/undeadinstitute/pen/KKNLGRg -->
<?php }
add_action( 'wp_footer', 'diy_ezwebcomp_footer');
Next is to enqueue our component’s JavaScript. We can add the JavaScript via wp_footer as well, but enqueueing is the recommended way to link JavaScript to WordPress. So let’s put our JavaScript in a file called ezwebcomp.js (that name is totally arbitrary), stick that file in the theme’s JavaScript directory (if there is one), and enqueue it (in the functions.php file).
We’ll want to make sure that last parameter is set to true , i.e. it loads the JavaScript before the closing body tag. If we load it in the head instead, it won’t find our HTML template and will get super cranky (throw a bunch of errors.)
If you can fully encapsulate your web component, then you can skip this next step. But if you (like me) are unable to do it, you’ll need to enqueue those un-encapsulated styles so that they’re available wherever the web component is used. (Similar to JavaScript, we could add this directly to the footer, but enqueuing the styles is the recommended way to do it). So we’ll enqueue our CSS file:
That wasn’t too tough, right? And if you don’t plan to have any users other than Administrators use it, you should be all set for adding these wherever you want them. But that’s not always the case, so we’ll keep moving ahead!
Don’t filter out your web component
WordPress has a few different ways to both help users create valid HTML and prevent your Uncle Eddie from pasting that “hilarious” picture he got from Shady Al directly into the editor (complete with scripts to pwn every one of your visitors).
So when adding web-components directly into blocks or widgets, we’ll need to be careful about WordPress’s built-in code filtering . Disabling it all together would let Uncle Eddie (and, by extension, Shady Al) run wild, but we can modify it to let our awesome web component through the gate that (thankfully) keeps Uncle Eddie out.
First, we can use the wp_kses_allowed filter to add our web component to the list of elements not to filter out. It’s sort of like we’re whitelisting the component, and we do that by adding it to the the allowed tags array that’s passed to the filter function.
We’re adding an empty array to the <zombie-profile> component because WordPress filters out attributes in addition to elements—which brings us to another problem: the slot attribute (as well as part and any other web-component-ish attribute you might use) are not allowed by default. So, we have to explitcly allow them on every element on which you anticipate using them, and, by extension, any element your user might decide to add them to. (Wait, those element lists aren’t the same even though you went over it six times with each user… who knew?) Thus, below I have set slot to true on <span>, <img> and <ul>, the three elements I’m putting into slots in the <zombie-profile> component. (I also set part to true on span elements so that I could let that attribute through too.)
Sadly, there is one more possible wrinkle with this. You may not run into this if all the elements you’re putting in your slots are inline/phrase elements, but if you have a block level element to put into your web component, you’ll probably get into a fistfight with the block parser in the Code Editor. You may be a better fist fighter than I am, but I always lost.
For reasons I can’t fully explain, the client-side parser assumes that the web component should only have inline elements within it, and if you put a <ul> or <div>, <h1> or some other block-level element in there, it’ll move the closing web component tag to just after the last inline/phrase element. Worse yet, according to a note in the WordPress Developer Handbook, it’s currently “not possible to replace the client-side parser.”
While this is frustrating and something you’ll have to train your web editors on, there is a workaround. If we put the web component in a Custom HTML block directly in the Block Editor, the client-side parser won’t leave us weeping on the sidewalk, rocking back and forth, and questioning our ability to code… Not that that’s ever happened to anyone… particularly not people who write articles…
Component up the theme
Outputting our fancy web component in our theme file is straightforward as long as it isn’t updated outside the HTML block. We add it the way we would add it in any other context, and, assuming we have the template, scripts and styles in place, things will just work.
But let’s say we want to output the contents of a WordPress post or custom post type in a web component. You know, write a post and that post is the content for the component. This allows us to use the WordPress editor to pump out an archive of <zombie-profile> elements. This is great because the WordPress editor already has most of the UI we need to enter the content for one of the <zombie-profile> components:
The post title can be the zombie’s name.
A regular paragraph block in the post content can be used for the zombie’s statement.
The featured image can be used for the zombie’s profile picture.
That’s most of it! But we’ll still need fields for the zombie’s age, infection date, and interests. We’ll create these with WordPress’s built in Custom Fields feature.
We’ll use the template part that handles printing each post, e.g. content.php, to output the web component. First, we’ll print out the opening <zombie-profile> tag followed by the post thumbnail (if it exists).
<zombie-profile>
<?php
// If the post featured image exists...
if (has_post_thumbnail()) {
$src = wp_get_attachment_image_url(get_post_thumbnail_id()); ?>
<img src="<?php echo $src; ?>" slot="profile-image">
<?php
}
?>
Next we’ll print the title for the name
<?php
// If the post title field exits...
if (get_the_title()) { ?>
<span slot="zombie-name"><?php echo get_the_title(); ?></span>
<?php
}
?>
In my code, I have tested whether these fields exist before printing them for two reasons:
It’s just good programming practice (in most cases) to hide the labels and elements around empty fields.
If we end up outputting an empty <span> for the name (e.g. <span slot="zombie-name"></span>), then the field will show as empty in the final profile rather than use our web component’s built-in default text, image, etc. (If you want, for instance, the text fields to be empty if they have no content, you can either put in a space in the custom field or skip the if statement in the code).
Next, we will grab the custom fields and place them into the slots they belong to. Again, this goes into the theme template that outputs the post content.
One of the downsides of using the WordPress custom fields is that you can’t do any special formatting, A non-technical web editor who’s filling this out would need to write out the HTML for the list items (<li>) for each and every interest in the list. (You can probably get around this interface limitation by using a more robust custom field plugin, like Advanced Custom Fields, Pods, or similar.)
Lastly. we add the zombie’s statement and the closing <zombie-profile> tag.
Because we’re using the body of the post for our statement, we’ll get a little extra code in the bargain, like paragraph tags around the content. Putting the profile statement in a custom field will mitigate this, but depending on your purposes, it may also be intended/desired behavior.
You can then add as many posts/zombie profiles as you need simply by publishing each one as a post!
Block party: web components in a custom block
Creating a custom block is a great way to add a web component. Your users will be able to fill out the required fields and get that web component magic without needing any code or technical knowledge. Plus, blocks are completely independent of themes, so really, we could use this block on one site and then install it on other WordPress sites—sort of like how we’d expect a web component to work!
There are the two main parts of a custom block: PHP and JavaScript. We’ll also add a little CSS to improve the editing experience.
First, the PHP:
function ez_webcomp_register_block() {
// Enqueues the JavaScript needed to build the custom block
wp_register_script(
'ez-webcomp',
plugins_url('block.js', __FILE__),
array('wp-blocks', 'wp-element', 'wp-editor'),
filemtime(plugin_dir_path(__FILE__) . 'block.js')
);
// Enqueues the component's CSS file
wp_register_style(
'ez-webcomp',
plugins_url('ezwebcomp-style.css', __FILE__),
array(),
filemtime(plugin_dir_path(__FILE__) . 'ezwebcomp-style.css')
);
// Registers the custom block within the ez-webcomp namespace
register_block_type('ez-webcomp/zombie-profile', array(
// We already have the external styles; these are only for when we are in the WordPress editor
'editor_style' => 'ez-webcomp',
'editor_script' => 'ez-webcomp',
));
}
add_action('init', 'ez_webcomp_register_block');
The CSS isn’t necessary, it does help prevent the zombie’s profile image from overlapping the content in the WordPress editor.
/* Sets the width and height of the image.
* Your mileage will likely vary, so adjust as needed.
* "pic" is a class we'll add to the editor in block.js
*/
#editor .pic img {
width: 300px;
height: 300px;
}
/* This CSS ensures that the correct space is allocated for the image,
* while also preventing the button from resizing before an image is selected.
*/
#editor .pic button.components-button {
overflow: visible;
height: auto;
}
The JavaScript we need is a bit more involved. I’ve endeavored to simplify it as much as possible and make it as accessible as possible to everyone, so I’ve written it in ES5 to remove the need to compile anything.
Show code
(function (blocks, editor, element, components) {
// The function that creates elements
var el = element.createElement;
// Handles text input for block fields
var RichText = editor.RichText;
// Handles uploading images/media
var MediaUpload = editor.MediaUpload;
// Harkens back to register_block_type in the PHP
blocks.registerBlockType('ez-webcomp/zombie-profile', {
title: 'Zombie Profile', //User friendly name shown in the block selector
icon: 'id-alt', //the icon to usein the block selector
category: 'layout',
// The attributes are all the different fields we'll use.
// We're defining what they are and how the block editor grabs data from them.
attributes: {
name: {
// The content type
type: 'string',
// Where the info is available to grab
source: 'text',
// Selectors are how the block editor selects and grabs the content.
// These should be unique within an instance of a block.
// If you only have one img or one <ul> etc, you can use element selectors.
selector: '.zname',
},
mediaID: {
type: 'number',
},
mediaURL: {
type: 'string',
source: 'attribute',
selector: 'img',
attribute: 'src',
},
age: {
type: 'string',
source: 'text',
selector: '.age',
},
infectdate: {
type: 'date',
source: 'text',
selector: '.infection-date'
},
interests: {
type: 'array',
source: 'children',
selector: 'ul',
},
statement: {
type: 'array',
source: 'children',
selector: '.statement',
},
},
// The edit function handles how things are displayed in the block editor.
edit: function (props) {
var attributes = props.attributes;
var onSelectImage = function (media) {
return props.setAttributes({
mediaURL: media.url,
mediaID: media.id,
});
};
// The return statement is what will be shown in the editor.
// el() creates an element and sets the different attributes of it.
return el(
// Using a div here instead of the zombie-profile web component for simplicity.
'div', {
className: props.className
},
// The zombie's name
el(RichText, {
tagName: 'h2',
inline: true,
className: 'zname',
placeholder: 'Zombie Name…',
value: attributes.name,
onChange: function (value) {
props.setAttributes({
name: value
});
},
}),
el(
// Zombie profile picture
'div', {
className: 'pic'
},
el(MediaUpload, {
onSelect: onSelectImage,
allowedTypes: 'image',
value: attributes.mediaID,
render: function (obj) {
return el(
components.Button, {
className: attributes.mediaID ?
'image-button' : 'button button-large',
onClick: obj.open,
},
!attributes.mediaID ?
'Upload Image' :
el('img', {
src: attributes.mediaURL
})
);
},
})
),
// We'll include a heading for the zombie's age in the block editor
el('h3', {}, 'Age'),
// The age field
el(RichText, {
tagName: 'div',
className: 'age',
placeholder: 'Zombie\'s Age…',
value: attributes.age,
onChange: function (value) {
props.setAttributes({
age: value
});
},
}),
// Infection date heading
el('h3', {}, 'Infection Date'),
// Infection date field
el(RichText, {
tagName: 'div',
className: 'infection-date',
placeholder: 'Zombie\'s Infection Date…',
value: attributes.infectdate,
onChange: function (value) {
props.setAttributes({
infectdate: value
});
},
}),
// Interests heading
el('h3', {}, 'Interests'),
// Interests field
el(RichText, {
tagName: 'ul',
// Creates a new <li> every time `Enter` is pressed
multiline: 'li',
placeholder: 'Write a list of interests…',
value: attributes.interests,
onChange: function (value) {
props.setAttributes({
interests: value
});
},
className: 'interests',
}),
// Zombie statement heading
el('h3', {}, 'Statement'),
// Zombie statement field
el(RichText, {
tagName: 'div',
className: "statement",
placeholder: 'Write statement…',
value: attributes.statement,
onChange: function (value) {
props.setAttributes({
statement: value
});
},
})
);
},
// Stores content in the database and what is shown on the front end.
// This is where we have to make sure the web component is used.
save: function (props) {
var attributes = props.attributes;
return el(
// The <zombie-profile web component
'zombie-profile',
// This is empty because the web component does not need any HTML attributes
{},
// Ensure a URL exists before it prints
attributes.mediaURL &&
// Print the image
el('img', {
src: attributes.mediaURL,
slot: 'profile-image'
}),
attributes.name &&
// Print the name
el(RichText.Content, {
tagName: 'span',
slot: 'zombie-name',
className: 'zname',
value: attributes.name,
}),
attributes.age &&
// Print the zombie's age
el(RichText.Content, {
tagName: 'span',
slot: 'z-age',
className: 'age',
value: attributes.age,
}),
attributes.infectdate &&
// Print the infection date
el(RichText.Content, {
tagName: 'span',
slot: 'idate',
className: 'infection-date',
value: attributes.infectdate,
}),
// Need to verify something is in the first element since the interests's type is array
attributes.interests[0] &&
// Pint the interests
el(RichText.Content, {
tagName: 'ul',
slot: 'z-interests',
value: attributes.interests,
}),
attributes.statement[0] &&
// Print the statement
el(RichText.Content, {
tagName: 'span',
slot: 'statement',
className: 'statement',
value: attributes.statement,
})
);
},
});
})(
//import the dependencies
window.wp.blocks,
window.wp.blockEditor,
window.wp.element,
window.wp.components
);
Plugging in to web components
Now, wouldn’t it be great if some kind-hearted, article-writing, and totally-awesome person created a template that you could just plug your web component into and use on your site? Well that guy wasn’t available (he was off helping charity or something) so I did it. It’s up on github:
The plugin is a coding template that registers your custom web component, enqueues the scripts and styles the component needs, provides examples of the custom block fields you might need, and even makes sure things are styled nicely in the editor. Put this in a new folder in /wp-content/plugins like you would manually install any other WordPress plugin, make sure to update it with your particular web component, then activate it in WordPress on the “Installed Plugins” screen.
Not that bad, right?
Even though it looks like a lot of code, we’re really doing a few pretty standard WordPress things to register and render a custom web component. And, since we packaged it up as a plugin, we can drop this into any WordPress site and start publishing zombie profiles to our heart’s content.
I’d say that the balancing act is trying to make the component work as nicely in the WordPress block editor as it does on the front end. We would have been able to knock this out with a lot less code without that consideration.
Still, we managed to get the exact same component we made in my previous articles into a CMS, which allows us to plop as many zombie profiles on the site. We combined our knowledge of web components with WordPress blocks to develop a reusable block for our reusable web component.
What sort of components will you build for your WordPress site? I imagine there are lots of possibilities here and I’m interested to see what you wind up making.
“I have to say that the new live builder is an absolute masterpiece. So far I used elementor, but switching to your new builder will definitely affect the speed of my work and greater customer satisfaction. Love it!” – DinoMaron