The code standard used in Code Potent's ClassicPress plugins is near identical to the code standard used in WordPress plugins, however, there are a handful of notable differences. To ensure your pull requests aren't held up or rejected, please carefully follow the standard.
Things like Yoda conditions? Not allowed. How about extraneous horizontal spacing? Nope. What about PHP/HTML stew? Absolutely not. These are just a few of the things not allowed in Code Potent projects; see the following list for exact differences. If you are thinking about creating a substantial pull request, get in touch first to ensure it is inline with where the plugin is going before doing any work on it.
Extraneous horizontal spacing is not desired. For example, the following code:
if ( ! $condition ) {
some_function( $arg1, $arg2, $arg3 );
}...should be rewritten as:
if (!$condition) {
some_function($arg1, $arg2, $arg3);
}PHP files should tend to have a single, long-form opening <?php tag. A closing PHP tag ?> is omitted. Jumping back and forth from PHP to HTML is not allowed; instead, HTML markup is enclosed in single-quotes and echoed. For example, the following code:
<p><?php esc_html_e($some_value); ?></p>
<p><?php esc_html_e($another_value); ?></p>...should be rewritten as:
echo '<p>'.esc_html($some_value).'</p>';
echo '<p>'.esc_html($another_value).'</p>';If you need pretty source, use \n in double-quotes to create breaks:
echo '<p>'.esc_html($some_value).'</p>'."\n";
echo '<p>'.esc_html($another_value).'</p>'."\n";Single-quotes are preferred for most cases. HTML attributes and escape characters such as \n, \r, and \t are an exception which should always use double quotes. For example, the following code:
echo "<p class='some-class'>Some string of text.</p>";
echo "<p class='some-class'>".$this_value."</p>";
echo "<p class='some-class'>{$that_value}</p>";...should be rewritten as:
echo '<p class="some-class">Some string of text.</p>';
echo '<p class="some-class">'.esc_html($this_value).'</p>';
echo '<p class="some-class">'.esc_html($that_value).'</p>';CSS selectors use hyphens - rather than underscores _. Selectors are prefixed in a consistent way with the plugin's slug to minimize the possibility of CSS collisions with other plugins or the theme. While it is often more convenient to use abbreviations, these are not allowed. For example, the following code:
.some_class_selector,
#some_id_selector {
color:#f00;
}
.tps_some_class_selector,
#tps_some_id_selector {
color:#f00;
}...should be rewritten as:
.the-plugin-slug-some-class-selector,
#the-plugin-slug-some-id-selector {
color:#f00;
}If your pull request is a simple one-line bug-fix or an otherwise small change, it may not be necessary to comment the code. For larger pull requests, comment your work. Good comments not only describe what the code is doing, they also describe why the code is doing it.
Lazy type checking and Yoda conditions are never used. Always use strict type checking to prevent false positives. For example, the following code:
if (true == $the_force) {
use_the_force();
}...should be rewritten as:
if ($the_force === true) {
use_the_force();
}Always prefer === over == to ensure that the data you're testing is of the correct type. Strict checking should also be used for arrays. For example, the following code:
if ($my_var == 'some string') {
// Do something.
}
if ($my_var == true) {
// Do something.
}
$my_array = ['some value', 'another value'];
if (in_array('some string', $my_array)) {
// Do something.
}...should be rewritten as:
if ($my_var === 'some string') {
// Do something.
}
if ($my_var === true) {
// Do something.
}
$my_array = ['some value', 'another value'];
if (in_array('some string', $my_array, true)) {
// Do something.
}Shorthand notation is used for all arrays. Instead of array(), use []. For example, the following code:
$my_array = array($val1, $val2, $val3);...should be rewritten as:
$my_array = [$val1, $val2, $val3];...or...
$my_array = [
$val1,
$val2,
$val3,
];Code is tabbed, not spaced. If values are being aligned vertically, spaces are preferred between items.
All variables must be initialized in some way before use.
Warnings, notices, and errors may not be hidden in any way; this includes the use of @ to supress notices.
The code must be compatible with PHP 7.x.x environments and it must be backward compatible with the lowest version of PHP that ClassicPress currently supports.
Pascal Case
Class names and namespace declarations use Pascal Case in which each word begins with a capital letter and the words are not separated. For example, the following lines depict this case.
namespace MyNamespace;
class MySweetClass{}
new MySweetClass();Snake Case
Constants, variables, functions, methods, and properties use Snake Case in which each word is separated by an underscore. Constants use all uppercase letters only; all others use lowercase letters only. Here are some examples:
const SIMPLE_CONSTANT = 'some value';
define('ANOTHER_CONSTANT', 'some value');
class MySweetClass {
public $my_var = 10;
public function __construct() {
}
public function get_items() {
}
}
function just_some_random_function() {
$my_var = true;
// Do stuff.
}All input must be sanitized early, meaning as soon as it is received. All output must be escaped late, meaning right where it is displayed.
All displayable texts, with the exception of internal slugs, must be run through the appropriate translation functions. If dealing with number-related texts such as 0 items, 1 item, 2 items, etc, correct pluralization must be accounted for.
The plugins provide constants for all the common paths and URLs. Use these constants rather than executing core functions to find the same values.
Classes, methods, and functions should be designed to fail early and fail often. This keeps the code more performant and prevents deep-nesting of conditionals. Consider the following contrived function which is designed to retrieve some sort of items when the user is visiting a dashboard page:
function prefix_display_items() {
$items = get_items();
if (!current_user_can('manage_options')) {
return;
} else {
if (!is_admin()) {
return;
} else {
echo '<ul>';
foreach ($items as $item) {
echo '<li>'.esc_html__($item['title']).'</li>';
}
echo '</ul>';
}
}
}The above code does work, but, it has a couple of issues. First, if the user is not in the dashboard or if the user doesn't have suitable permission, the call to get_items() is needless overhead. Second, if you practice fail early, fail often, all those else clauses become needless, reducing the nesting of code. The following is a rewrite of the above function with fewer lines and more performant code:
function prefix_display_items() {
if (!current_user_can('manage_options')) {
return;
}
if (!is_admin()) {
return;
}
$items = get_items();
echo '<ul>';
foreach ($items as $item) {
echo '<li>'.esc_html__($item['title']).'</li>';
}
echo '</ul>';
}Scripts and styles are only loaded for pages or views in which they are actually used. Scripts and styles are locally stored and non-minified.
When returning a value from a function or method, the line must not contain any logic. Logic must be executed before the return. For example, the following code:
return isset($some_variable);...should be rewritten as:
if (isset($some_variable)) {
$my_value = true;
} else {
$my_value = false;
}
return $my_value;...or...
$my_value = false;
if (isset($some_variable)) {
$my_value = true;
}
return $my_value;...or...
$my_value = (isset($some_variable)) ? true : false;
return $my_value;