Using Laravel Valet with WordPress

In case you missed the release of Laravel Valet last week, allow me to introduce you.

WHAT. A. RUSH.

Pretty awesome right?  It’s not just for Laravel though.  In fact, out of the box, Valet supports almost a dozen different php platforms as well as static sites, including WordPress.

But WordPress doesn’t have a one-command installer like Laravel.  It requires a database, it’s more/less tied to a specific domain, and even then you need to go through the “Famous 5 Minute Install” before you can do anything with the site.

So out of the box, the Valet experience for WordPress is a bit lackluster since you still have to go through all that extra setup.  Much of the initial install for WordPress can be done pretty easily using WP-CLI, but there’s still no single command — until now.

Introducing the valet command for WP-CLI

A new WP-CLI command you can pull in as a package, and is available right now on the official package index.

There are a few prerequisites before you can use it, but if you already have Valet and WP-CLI installed, that’s pretty much it.

Here’s how it works.  From your terminal, change to a directory where you keep your projects.  Here I’m assuming that directory is called Sites in your home directory.

You can now have a new WordPress install, ready to use right now in your browser at https://my-project.dev.  By use I mean, you can view the homepage, login, etc.  It’s completely installed.

Most of the magic I have to give credit to Valet for, but the end result is a one command, ready to use WordPress install.

But wait… there’s more

Have you ever wanted to work with WordPress locally, but didn’t want or need a MySQL database running just to make it work?   Unfortunately, database abstraction isn’t exactly .. robust .. in WordPress as it is tightly coupled to SQL.  However, it is possible to run WordPress using SQLite instead.

SQLite is a fast, server-less, user-less, zero-configuration, file-based database system. It’s also used more than any other database system there is.

The WP-CLI Valet command supports installing a new WordPress instance, ready to use with SQLite instead of MySQL with a single option.

The command accepts many more options for fine-grained control.

Check it out on GitHub

Hacking, Musings & Aspirations

Lots of cool stuff going on lately.  Where to begin?  I have released several new projects lately which are in various stages of development.

After working with so many projects which are completely installed with Composer, it’s hard to think of the “dark ages” of what development was like before that.

On a (big) side note, if you are a developer who works with PHP, you should take a minute and extend your gratitude to Jordi Boggiano and Nils Adermann — the authors leading the development of Composer.  Earlier this month, these guys celebrated the v1.0.0 release of Composer after 5 years of development.

In the WordPress ecosystem, WP-CLI recently released v0.23 which packed a long anticipated feature – the package command.  This is the command which leverages Composer to install Community WP-CLI Packages.  You can head over to the official package index to browse around, or if you already have this version of WP-CLI or newer, you can just run wp package browse to view all available packages!

If you actually did either of those things right now, you would probably see a few of my packages right there at the top (almost).

The dotenv command for WP-CLI

For those who are unfamiliar with what a .env file is or what it would be used for, take a quick second to read up on that on the phpdotenv project page.  It’s not anything new, or even php-specific.  The one sentence TL;DR is that it is a simple key-value format for defining environment variables – usually for storing sensitive information (like passwords or api keys) or other environment-specific configuration which doesn’t belong in a project’s source.

This project is a WP-CLI api for interacting with that file.  It has several handy features, like displaying the keys & values in a nice cli table, creating a new environment file interactively from a template, or even (re)generating entries for WordPress authentication salts.

A member of the package index, you can install this package by running:
wp package install aaemnnosttv/wp-cli-dotenv-command

Check it out on GitHub

The http Command for WP-CLI

The newest command I have added to the package index is the http command.  This is very much inspired by httpie, which is a really nice cli wrapper for cURL.  The http command is a wrapper for using the WordPress HTTP API.

WordPress supports a number of different methods to make HTTP requests.  This is because WordPress needs to be flexible enough to work on a wide range of hosts with different flavors of host OS, and binaries available to it.  For that reason, testing one action on your server with cURL may provide inconsistent results because WordPress may be using a different method.

The main use case for the command is that it gives you the ability to “see things through the eyes of WordPress” in the context of http requests.

I won’t rehash the whole ins-outs of the plugin here but one of the coolest features (I think) is the ability to impersonate a given user for the request you are making.

Here’s some food for thought to start playing with it.  Compare the output of these two commands:

wp http get / --realm=admin
wp http get / --realm=admin --as=1

If you’re on https, you may need to add the --scheme=https flag as well.

Install the package with:
wp package install aaemnnosttv/wp-cli-http-command

Check it out on GitHub

WordPress Tests Core

Testing is something that does not get nearly as much attention in the world of WordPress as its peers in the sphere of web development.  Some information is available regarding writing unit tests for plugins and themes with PHPUnit, but that’s about it.  I found this leaving a lot to be desired.

A WordPress site is much more than a some plugins and theme.  The fact is that even if all of the individual components have 100% test coverage and passing builds, that does not guarantee that they work together — which is unquestionably more important.  So how do you test that with WordPress?  As far as I know, nothing has been written about that — yet.

There is a wide range of (often inconsistent) vocabulary around the terms people use to talk about testing but generally speaking, when testing to make sure everything is working together, this is referred to as “integration testing”.

If you look at a mature web application framework like Laravel, writing these kinds of tests is ridiculously easy.  It’s so nice.  I wish I could say the same for WordPress, but it’s a pain just to install the test library!  By test library, I mean the WordPress core testing files which are what PHPUnit test cases and test suites are built on.  Until now, the most efficient way to install these has been via svn checkout.

Why can’t we install this like any other library with Composer?  (Reasonable question, right?)  It’s not impossible, but one reason is because the WordPress files require a specific location relative to your wp-tests-config.php file.  (the equivalent of wp-config.php but for the test suite).  That means we would need to get our tests config file into the vendor directory, or we should choose a more appropriate location to install the library to.

Enter the WordPress Tests Core library Composer package

Similar to installing WordPress core via Composer, to install the WordPress core test library, it uses a custom installer to be to install the package to a location of our choosing within the project.

Add the install path to the extra: {...}  config in your composer.json, require the package in your dev dependencies and you’re ready to rock!

See the project readme for more information.  More on this to come soon.

That leads me to my last project which is currently in the works.

It’s no secret; I’m a pretty big fan of Laravel.  When you look through the Laravel source, you can tell that a lot of thought and care was put into it.  The whole thing oozes with clean and expressive object-oriented design. Naturally, I wanted to have the same thing with WordPress.

Most people would probably just stop there and say “Why not just use Laravel?”, and the reality is that sometimes that just isn’t an option or even the best choice for different reasons.  I believe that the values which Laravel stands for are universal, and WordPress has a lot of room to grow in that regard.

Many projects have been created to fuse these two entities together in some way, but they all come with their compromises.  Most commonly, developers seem to really want to be able to use the expressive syntax of Eloquent, Laravel’s ORM. Eloquent can be made to work with a WordPress database — but not really with WordPress.

What does that mean exactly?  It means that Eloquent can be configured to work with a WordPress database, query it, etc, but it is not compatible with WP_Query or any other code which may require modifying the query at runtime.  And there very well may be cases where that may be exactly what you want.  Especially for sites with massive databases, WP_Query can be sub-optimal.

For me, a solution like this is a deal-breaker for most sites though.  Most people aren’t developing sites that get the kind of traffic to warrant that.  I want my code to be consistent and there are going to be cases you need to use WP_Query, so why mess with two?

Furthermore, there are other aspects of Laravel which make it a joy to work with, like its prolific use of Collections.  There’s really nothing Laravel-specific about collections.  If you’ve used jQuery, you’ve used collections.  Collections are like arrays with methods.  Learning to use these can seriously transform the way you write code in PHP.

Enter: Silk

A few months ago, I broke ground on a new project called Silk, which aims to provide an implementation of a very Laravel-esque API around WordPress.  Although it is heavily influenced by Laravel and will even leverage some Laravel packages, it will not be an exact API match. Silk aims to embody the values of Laravel — a clean, expressive, object-oriented layer on top of WordPress rather than around it.  Under the hook, Silk will use the same WordPress functions and classes you’ve grown to know and … Because of this key difference, Silk will remain fully-compatible with reasonably current versions of WordPress (with the exception of its PHP version requirement, and maybe some other things).

Silk is designed to be a library of powerful tools and building blocks rather than a framework which requires you to do things a certain way.

Check it out on GitHub


fin

Simple Callbacks in WordPress

Callbacks are the core of WordPress.  The Plugin API functions rely on them directly, as do shortcodes!  In WordPress core, we commonly see these referred to with strings which refer to function names:

Another common usage is to reference a method

Sometimes the return value is so trivial that creating a function or method just to return it is almost silly.  The most common cases have been given their own full-fledged functions as part of WordPress core since v3.0:

  • __return_true
  • __return_false
  • __return_zero
  • __return_empty_array
  • __return_null (since 3.4)
  • __return_empty_string (since 3.7)

But what if you wanted to return something else without creating a named function or class method?

The next option would be an anonymous function.  These are possible even in PHP 4 using create_function() but it uses eval() internally and the usage is totally disgusting, so I would recommend never using that.  However, unless your host is running PHP 5.2 (the bare minimum for WordPress – in which case you should run away or upgrade IMMEDIATELY), you can use a real anonymous function, like so:

Pretty nice, eh?  Not a good solution if you want your callback to be able to be removed using remove_action or remove_filter but we’re assuming this is something you’re in control of here, and we wouldn’t need to do that.  Read: if you are distributing a plugin/theme to be used by others, you shouldn’t do that.

Moving on.

So that’s really nice and all, but still more characters than necessary, especially if you want to do this kind of thing several times.

Let’s DRY all that up with a simple __return helper function!

Just as shown before, we can pass a closure directly to the action or filter callback we are adding.  The only difference here is we’re abstracting the creation of the closure within our little higher order function that simply returns whatever we gave it.  The function isn’t called until the hook is fired.

Now we can write a single, expressive line of code to return whatever we want:

This will return “cool stuff”.  Since we’re using a function to create our callback, we can pass any valid expression to it that we want to use to pass the result.

A practical example might be a simple shortcode for rendering the current year:

 

 

 

 

Post Link Shortcodes 0.4

Today, Post Link Shortcodes marked it’s fourth release – v0.4.0 – the best version yet.

The documentation for the plugin has all been completely rewritten, and is already pushing 11 pages. You can find it at it’s new home on the project’s GitHub Wiki.

After writing all of that, I’m going to keep things short here.

Notable features of this release

  • Overhauled codebase – lots of improvements, including inline documentation and overall readability
  • Better support for attachments
  • Image support – including image sizes
  • Post Thumbnail support – aka Featured Image
  • All new documentation

Post Link Shortcodes on GitHub

Reviews on WordPress.org

Shortcode Aliases: The Plugin – Coming Soon to a Plugin Repository Near You!

Inspired by the original concept introduced in Post Link Shortcodes v0.3, I realized that the ability to create shortcode aliases was something that should available for any shortcode. I broke ground on the shortcode-aliases-api plugin several months ago, but it’s been on the back burner ever since.  Despite the delay, the initial release is finally coming!

So What Is A Shortcode Alias?

In a nutshell, it’s a shortcode that kind of behaves as a “shortcut” to another shortcode.  Conceptually, it’s very close to a symbolic link, for those who are hip to that kind of thing.

More specifically, it is a real shortcode, which resolves to an existing callback for another shortcode.

In PHP, we could make a very primitive alias like so:

This would register a new [gall3ry] shortcode, to work exactly the same as the built-in WordPress [gallery] shortcode.

All we’re doing here is registering a new shortcode to share the same callback as another existing shortcode.

While this may work fine in some cases, there may be cases where it will not work as expected.  One problem comes when shortcode callbacks utilize the parameter for the called shortcode $tag which is passed as the 3rd argument to a shortcode callback.  I should mention that there’s nothing wrong with using this argument — in fact it can be quite helpful when writing shortcodes!

Consider this simple example using a new div shortcode:

This would give us a shortcode that would produce some simple output like this:

If we aliased this shortcode using the method above, whatever shortcode name we chose, would affect the output.

Using our primitive method would be no different than this:

Such a shortcode would produce this:

While that may be desirable in some cases, that’s not what we’re trying to achieve here.  We want our alias to behave – by default – exactly the same as if we had used the original.

A shortcode by any other name should be just as sweet, or more.

So… why?

Just being able to call a shortcode by a different name, doesn’t offer a whole lot of utility.  The SAA is not nearly as primitive as our example, so things will work as expected.  Even still, let’s explore some of the possible use cases.

Abstraction – Shortcodes as an Interface

Many plugins use namespaced shortcodes to avoid possible tag collisions.  Unlike function or class names, which produce a fatal error in the case of a name collision, if two shortcodes are registered with the same name, it’s a simple game of “last one wins”.  There can be only one callback for a given tag, so the last one registered with the same tag name is the one that “owns” it.

Instead of using the concrete namespaced implementations (eg: xzy_responsive_column), the target shortcodes could be aliased into semantic/expressive references to them (eg: column).  Later if you so desired, a different implementation could be swapped in by changing the target of the alias, without having to make any change in the usage of the shortcode within the database.

But how then would we reconcile the differences in the shortcode attribute names between implementations, you ask?  Filters.

This leads me to another feature/use-case:

Extensibility

Not all shortcodes follow a particular convention.  If you ever found yourself wanting to be able to filter the attributes ($atts) or the $content or even the returned output of a given shortcode, only to find that it wasn’t made available to you by the developer, you were out of luck — until now.  All of those things are made possible via the Shortcode Alias API!

Going back to the previous use case of abstraction: using the filters which are made available for every shortcode alias, it would be possible to use a filter as a kind of an adapter of sorts between the attributes used (the interface), and the API of the shortcode’s implementation.

Perhaps that sounds silly, but imagine changing the usage on site with thousands of posts?  Now imagine, making that work — without changing the database.  As mentioned, changing implementations or “target shortcodes” will almost certainly not be as simple as just changing the shortcode name.  Some “translation” would be required, and Aliases make that possible.

So simply by registering an alias, it’s attributes, content, and output are all filterable!

Defaults

One of the core features of a shortcode-alias-api alias is the ability to register defaults for the shortcode’s attributes and content.

This is especially useful for target shortcodes which are very versatile.

If you notice yourself repeating a lot of the same attributes with the same shortcode, this is probably a good use case for an alias!

For example, if you had an events shortcode, which had many attributes for filtering and displaying its output, these could be pre-set by an alias with defaults.

Eg:

might be aliased with defaults to produce the same result with:

These are in fact defaults so nothing is set in stone*.  The alias would be able to override any set default simply by using the same attribute normally like so:

Where the range attribute might control the number of weeks/months of events to show.

* – Alias defaults can be registered to optionally force a defined value, regardless of the shortcode-passed value.

Enter the Shortcode Alias API

I’m referring to this plugin as an API, because it simply offers the functionality; no UI or options.

The plugin introduces a few new functions which aim to follow the existing Shortcode API as closely as possible.

For more information, read the documentation.

View the source or contribute on GitHub!

Essential Resources for WordPress Developers

A few months ago, I was drafted by my friends over at Tuna Traffic as the team’s WordPress Master General.  So far everything has been really great and they’ve been a fantastic group of people to work with.

The team is growing at what seems to be a near exponential rate as we will be welcoming our newest member next week!  Tasked with the responsibility of making sure our new bundle of joy is able to hit the ground running, I decided to compile a list of my most valuable resources and references that I use every day, available for all, right here.

The List

#1 The Codex – the online manual for WordPress and a living repository for WordPress information and documentation.

The Codex has documentation that covers pretty much everything and then some, which is great, but if you’re new to WP, digging through the documentation by yourself could be a bit intimidating, so I’m going to highlight some of the most important/useful bits.

  • Plugin API – The core of the Plugin API outlines actions and filters, the two kinds of hooks that WordPress provides to extend and modify its behavior.  This is more of a one time read and will only be useful for beginners and those that are new to WP.  Once you get the basics of hooks in WordPress, you won’t really need to revisit it.  It’s kind of like riding a bike. 🙂
  • Function Reference – A comprehensive list of just about every function in WordPress, with links to the function’s own Codex page for those that have one.  For each function, it’s respective page contains information about each accepted parameter, the possible return values, and many have several code examples as well.  As part of the Codex, it is an evolving documentation that has lots of useful notes and important things to keep in mind, such as execution timing, and common problems/solutions.
  • Action Reference – Part of the Plugin API reference, if I had a nickel for all the times I’ve referred to the top half of this page, I’d have a shit load of nickels.
    In all seriousness though, this one reference is so important because it lays out all of the core actions, in order, with additional information available for most of them.
  • WP_Query Reference – Just about everything you need to know about one of the most important and fundamental aspects of working with WordPress.

#2 Developer Code Reference – one of the newest additions to the core developer resources, it provides quick access via search to all core functions, actions/filters, classes, and methods!  This is a great resource if you’re looking for more information about a particular [any of those things].  Compared to the codex, this one is geared towards more experienced developers and is more of a window into the source code itself, than a how-to.  All-in-all, a fantastic resource.
Note:  I have noticed that there are some inconsistencies/inaccuracies within the documentation here regarding function signatures in the descriptions.  Double check the source!

#3 QueryPosts – very similar to the Developer Code Reference (and possibly even the inspiration for it), QueryPosts was released long before the DCR was available but currently only serves as a function reference.  Built by WordPress Stack Exchange moderator and well-known WP expert Andrey “Rarst” Savchenko (rarst.net).  I really like this site for it’s elegant design and it’s all around well-doneness (for lack of a better term).

A few features that set QP apart are:

  • Non-user manual-esque design
  • Real-time search suggestions
  • Links to related functions on function pages.
  • Links to placement in source on both WordPress Github repository & WP Trac code browser.

#4 WordPress/WordPress – The WordPress git mirror of the core SVN repository, synced every 15 minutes.  Great for searching across the entire codebase.  Nuff’ said.

#5 WordPress on StackExchange – The dedicated WordPress forum on StackExchange. Have a problem that has yet to be answered?  Not likely!  A lot of great answers here, and no better place to ask if you still need an answer.

#6 Rarst’s “Making Sense of __” Infographics – Ok, we’re starting to develop a pattern here, but seriously, these are fantastic.  A great resource especially for the new to WordPress.

#7 Solid Debugging Tools – Tripping over yourself is a natural part of growing as a developer. We learn by failing.  The quality of your debugging tools greatly determines how much hair you’re likely to retain long-term.

  • Debugging in WordPress – The Codex’s overview on debugging and related constants.
  • Debug Bar – The “Mothership” of debugging plugins.  Quite a versatile tool, there are many extensions for this plugin alone (including my own below), allowing you to add what you need.
  • Dev Debug – My own hand-rolled debugging tool that has evolved over many years of working with WordPress.  It’s by no means a one-stop-shop for debugging tools, but it’s something I use everyday to analyze the data I’m working with.

Miscellaneous other helpful resources

  • WordPress Coding Standards – Information about how to code “The WordPress Way”.  Useful for those who are interested in contributing to core, or are a new developer looking to make a solid start.
  • WordPress Database Search & Replace by interconnect/it – A great utility for doing safe search/replace in your database.
  • WP Constants Reference – There are quite a few constants used in WordPress.  Some can be changed and others are just good to know.  This site puts together a nice reference for them.
  • The Anatomy of a Theme by Yoast – Great crash course in the basic parts of a theme.
  • WP Salt Generator – Make sure any new install always has unique security keys & salts or you’re asking to be hacked!
  • Dashicons – the official icon font of the WordPress admin as of 3.8.  Icon fonts are all the rage these days, and for good reason!  Why not leverage the ones that are already built-in for your plugin/theme?

 

Did I miss something?

Do you have a great resource that has been an invaluable asset for you or your team?  Drop it in the comments below!

Aliases! Post Link Shortcodes 0.3

When I first started what would eventually become this plugin a few years ago, it was very basic; I never though it would turn into something like this.  I’m happy to say that I’m glad it did.

If this is your first time here, or you’re already totally confused and have no idea what Post Link shortcodes is or does, take a minute and get yourself up to speed here.

Today with the release of version 0.3 – which will be hitting the plugin repository shortly – I’m really excited to introduce aliases.

Aliases are new shortcodes that can be added (by you) that “forward” or reference a dynamic PLS shortcode.

Why Aliases?

I thought you’d never ask!

Compatibility

You may already have an existing shortcode by the same name that does something a little differently and you don’t want to go through your whole website to change it.

PLS respects existing shortcodes and will not overwrite them (which happens by default when adding new shortcodes).
(ie: you already have a shortcode named page_link)

In this case, you could easily setup a new shortcode, say: article or blog to reference post_link.  This is what PLS refers to as an alias.

Aliases are kind of like a shortcut for PLS shortcodes.

Convenience / Awesomeness

This is where things get freaking cool.

Aliases allow you to optionally define default shortcode attribute values.  And if that isn’t cool enough, not only can they the defined as simple default values (which can be overriden by the passed shortcode value), they can also be defined as additive values that are either prepended or appended to the passed shortcode value.

Wow.  In Apu’s words:

…Such a thing has never been done.

 Let’s Recap

  • An alias is like a shortcut between a new shortcode to a PLS shortcode
  • Aliases can be setup with default values for shortcode attributes
  • Default values can be prepended or appended to the passed shortcode value.

Practical Use

Now that we know what the features are, let’s see how we could use them in real world applications to make our lives easier.

Let’s say that we have a PLS that we want to reuse over and over throughout our site that links to our Contact page.

As a page, the PLS shortcode would be: [[page_link contact]]
This would create an anchor that links to the contact page (assuming the slug for the page is ‘contact’, but with that title it would default to that).  The inner text of the anchor would also default to the page title, “Contact”.

Let’s say we want to give it some special styling to bring more attention to it.

We could add a class to the link that we would then use to add some custom highlighting style like so: [[page_link contact class="call-to-action"]]

Cool, not bad!  Getting a little bit big though..  And what if we wanted to change the link text too..  [[page_link contact class="call-to-action" text="Contact us for a free consultation"]]

This is quickly turning into quite a large shortcode.  And if we’re using this across many pages, it can make changing them all later a bit of a headache.

Setup The Alias

PLS provides a function pls_add_shortcode_alias() for registering a new alias which will then add our new shortcode for us and handle all the heavy lifting.

This function can be called anytime after the plugin is loaded and accepts 3 arguments:

  1. the new shortcode name ( ie: consult or blog, similar to add_shortcode )
  2. the shortcode name of the PLS shortcode to reference ( page_link, post_link, etc. )
  3. (optional) array of defaults – see below

In our theme’s functions.php (hopefully you’re using a child theme) we can add this code to setup our new alias:

This will add a new shortcode [consult] that is already setup with all of those shortcode attributes as default values.

In a nutshell:  Now using [consult] is the same as[[page_link contact text="Contact us for a free consultation"]].

What isn’t obvious is that [consult] is still a Post Link Shortcode.  That means that if you want to add a html id to the link, it’s simply [consult id="my_ID"] or use a different link text, simply override it [consult text="Contact Us Today"].  The limitation is only that the PLS shortcode tag that is aliased – in this case page_link – is not changeable on a per-use basis.  That is, [consult] will always refer to page_link unless defined otherwise.

Additive Attributes

So if default values weren’t cool enough, what if you wanted to define an alias with a base set of defaults, some of which you would want to be able to add to rather than override?

Let’s say we want to add a cool bootstrap icon inside our link to our contact page.  We want it to always show up before our link text, but we still want to be able to control that text without reentering the code for the icon every time.

Back to our (slightly modified) alias definition:

The text attribute which controls the inner text of the anchor has changed to +text.
The + on the left side of the attribute name indicates that we want to prepend the default to the shortcode-passed value, or if it isn’t passed, use it as the default value.

If we wanted to append instead to the end of the shortcode-passed value, the attribute would be text+ respectively. The position of the + indicates where the prepended/appended content will go relative to the shortcode-passed value.

This syntax and ability applies to all attributes!

Note: in the new alias definition above that I changed the 'slug' => 'contact' to 'post_id' => 15.  Using the post_id will save a query the first time.  It’s probably not at all noticeable from a performance standpoint.  I generally prefer to use the post slug with PLS shortcodes for it’s semantic value, so you can see what page/post it’s actually linking to, where if you’re using the ID, it’s not obvious at all.

More importantly, it protects the integrity of the link as post slugs can be changed, whereas the post_id will always be the same.

Basically, there’s really no reason to use the slug to establish the target for an alias, as the target can simply be added as a comment above if it’s not obvious from the shortcode name.

Closing Arguments

That’s it.  I hope y’all dig it –  with 2 shovels.

Post Link Shortcodes

A new plugin is coming soon!  How soon you ask?  Well, that all depends on how fast the folks over at WP Plugin Review HQ have their drinking bird toy pecking the Y key.   But if you stay tuned to this website that has only existed for a matter of minutes, you’ll be the first to know when it hits the WP Plugin Repository!

Aptly titled, Post Link Shortcodes, the plugin dynamically creates .. shortcodes .. for each registered post type.  These ..shortcodes.. can be used to create …links… that is (crudely) <a href="blah">blah</a> to the post, post type archive OR just return the URL for either.

Each post type will have 4 shortcodes created for it where posttype is the name of the post type. Eg: post or page

The shortcodes themselves are also quite powerful and very flexible allowing you to add as many attributes as you which that will be turned into html attributes of the link.

That’s all for now.  There’s much more to say about it, but it’s not even approved yet!

For those who can’t wait, check it out on GitHub!