├── .editorconfig ├── .github └── workflows │ └── qa.yml ├── LICENSE ├── README.md ├── _typos.toml ├── changelog.md ├── index.md ├── inline-documentation-standards.md ├── inline-documentation-standards ├── javascript.md └── php.md ├── manifest.json ├── styleguide.md ├── wordpress-coding-standards.md └── wordpress-coding-standards ├── accessibility.md ├── css.md ├── html.md ├── javascript.md └── php.md /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # https://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | 16 | [*.yml] 17 | indent_style = space 18 | indent_size = 2 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.github/workflows/qa.yml: -------------------------------------------------------------------------------- 1 | name: Basic QA checks 2 | 3 | on: 4 | push: 5 | pull_request: 6 | # Allow manually triggering the workflow. 7 | workflow_dispatch: 8 | 9 | # Cancels all previous workflow runs for the same branch that have not yet completed. 10 | concurrency: 11 | # The concurrency group contains the workflow name and the branch name. 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | typos-spellcheck: 17 | name: "Find typos" 18 | 19 | runs-on: "ubuntu-latest" 20 | 21 | steps: 22 | - name: "Checkout" 23 | uses: "actions/checkout@v4" 24 | 25 | - name: "Search for misspellings" 26 | uses: "crate-ci/typos@v1" 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WordPress Coding Standards Docs 2 | 3 | This repo contains the source for the [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/) on https://developer.wordpress.org 4 | 5 | When creating new files, these must be added to the [manifest.json](https://github.com/WordPress/wpcs-docs/blob/master/manifest.json) file. 6 | 7 | Removing files also requires updating the [manifest.json](https://github.com/WordPress/wpcs-docs/blob/master/manifest.json) file. After deletion and sync with DevHub, the page also needs to be manually deleted from DevHub. 8 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | ignore-hidden = true 3 | 4 | [default] 5 | locale = "en-us" 6 | check-filename = true 7 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | - 2020-09-25 Update code examples to use Markdown code fence notation instead of shortcodes. 4 | - 2019-12-21 Update `javascript.md` from the [handbook page](https://make.wordpress.org/core/handbook/best-practices/coding-standards/javascript/). 5 | - 2019-12-21 Update `accessibility.md` from the [handbook page](https://make.wordpress.org/core/handbook/best-practices/coding-standards/accessibility-coding-standards/). 6 | - 2018-01-14 Initial import from https://make.wordpress.org/core/handbook/best-practices/ 7 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | # Best Practices 2 | 3 | WordPress is a big project with thousands of contributors. It's important that best practices are followed so that the codebase is consistent and readable, and changes are easy to find and read, whether the code is five days old or five years old. What follows are a series of best practices to help keep WordPress code clean and well documented for years to come. 4 | 21 | -------------------------------------------------------------------------------- /inline-documentation-standards.md: -------------------------------------------------------------------------------- 1 | # Inline Documentation Standards 2 | 3 | Inline documentation provides a good resource for core developers in future development, and other developers when learning about WordPress. It also provides the information necessary to populate the WordPress developer code reference. 4 | 5 |
6 | I don't need to document my code. I wrote all of it - know it like the back of my hand. 7 | 8 | "I would argue that, separately, documentation is also for you, the developer. I've found quite often that my inline documentation can be a very effective breadcrumb trail when establishing one's own intent, particularly with regard to complex function arguments and usage. And it's also helpful to return to a function two years later and find a paragraph in the inline documentation that describes, in meticulous fashion, something that I otherwise would have had to rediscover all over again." - Nacin 9 |
10 | 11 |

Language-specific Standards

12 | 16 | 17 |

Resources

18 | 19 | 22 | -------------------------------------------------------------------------------- /inline-documentation-standards/javascript.md: -------------------------------------------------------------------------------- 1 | # JavaScript Documentation Standards 2 | 3 | WordPress follows the [JSDoc 3 standard](http://jsdoc.app/) for inline JavaScript documentation. 4 | 5 | ## What Should Be Documented 6 | 7 | JavaScript documentation in WordPress takes the form of either formatted blocks of documentation or inline comments. 8 | 9 | The following is a list of what should be documented in WordPress JavaScript files: 10 | 11 | - Functions and class methods 12 | - Objects 13 | - Closures 14 | - Object properties 15 | - Requires 16 | - Events 17 | - File headers 18 | 19 | ## Documenting Tips 20 | 21 | ### Language 22 | 23 | Short descriptions should be clear, simple, and brief. Document "what" and "when" - "why" should rarely need to be included. The "why" can go in the long description if needed. For example: 24 | 25 | Functions and closures are _third-person singular_ elements, meaning _third-person singular verbs_ should be used to describe what each does. 26 | 27 | [tip] 28 | Need help remembering how to conjugate for third-person singular verbs? Imagine prefixing the function, hook, class, or method summary with "It": 29 | 30 | - _Good_: "(It) Does something." 31 | - _Bad:_ "(It) Do something." 32 | 33 | [/tip] 34 | 35 | **Functions**: What does the function do? 36 | 37 | - _Good_: Handles a click on X element. 38 | - _Bad_: Included for back-compat for X element. 39 | 40 | **`@since`**: The recommended tool to use when searching for the version something was added to WordPress is [`svn blame`](https://make.wordpress.org/core/handbook/svn/code-history/#using-subversion-annotate). 41 | 42 | If, after using these tools, the version number cannot be determined, use `@since Unknown`. 43 | 44 | **Code Refactoring**: Do not refactor code in the file when changes to the documentation. 45 | 46 | ### Grammar 47 | 48 | Descriptive elements should be written as complete sentences. The one exception to this standard is file header summaries, which are intended as file "titles" more than sentences. 49 | 50 | The serial (Oxford) comma should be used when listing elements in summaries, descriptions, and parameter or return descriptions. 51 | 52 | ## Formatting Guidelines 53 | 54 | The following guidelines should be followed to ensure that the content of the doc blocks can be parsed properly for inclusion in the code reference. 55 | 56 | **Short descriptions**: 57 | 58 | Short descriptions should be a single sentence and contain no markup of any kind. If the description refers to an HTML element or tag, then it should be written as "link tag", not "<a>". For example: "Fires when printing the link tag in the header". 59 | 60 | **Long descriptions**: 61 | 62 | Markdown can be used, if needed, in a long description. 63 | 64 | **`@param` and `@return` tags**: 65 | 66 | No HTML or markdown is permitted in the descriptions for these tags. HTML elements and tags should be written as "audio element" or "link tag". 67 | 68 | ### Line wrapping 69 | 70 | DocBlock text should wrap to the next line after 80 characters of text. If the DocBlock itself is indented on the left 20 character positions, the wrap could occur at position 100, but should not extend beyond a total of 120 characters wide. 71 | 72 | ### Aligning comments 73 | 74 | Related comments should be spaced so that they align to make them more easily readable. 75 | 76 | For example: 77 | 78 | ```javascript 79 | /** 80 | * @param {very_long_type} name Description. 81 | * @param {type} very_long_name Description. 82 | */ 83 | ``` 84 | 85 | ## Functions 86 | 87 | Functions should be formatted as follows: 88 | 89 | - **Summary**: A brief, one line explanation of the purpose of the function. Use a period at the end. 90 | - **Description**: A supplement to the summary, providing a more detailed description. Use a period at the end. 91 | - **`@deprecated x.x.x`**: Only use for deprecated functions, and provide the version the function was deprecated which should always be 3-digit (e.g. `@deprecated 3.6.0`), and the function to use instead. 92 | - **`@since x.x.x`**: Should be 3-digit for initial introduction (e.g. `@since 3.6.0`). If significant changes are made, additional `@since` tags, versions, and descriptions should be added to serve as a changelog. 93 | - **`@access`**: Only use for functions if private. If the function is private, it is intended for internal use only, and there will be no documentation for it in the code reference. 94 | - **`@class`**: Use for class constructors. 95 | - **`@augments`**: For class constructors, list direct parents. 96 | - **`@mixes`**: List mixins that are mixed into the object. 97 | - **`@alias`**: If this function is first assigned to a temporary variable this allows you to change the name it's documented under. 98 | - **`@memberof`**: Namespace that this function is contained within if JSDoc is unable to resolve this automatically. 99 | - **`@static`**: For classes, used to mark that a function is a static method on the class constructor. 100 | - **`@see`**: A function or class relied on. 101 | - **`@link`**: URL that provides more information. 102 | - **`@fires`**: Event fired by the function. Events tied to a specific class should list the class name. 103 | - **`@listens`**: Events this function listens for. An event must be prefixed with the event namespace. Events tied to a specific class should list the class name. 104 | - **`@global`**: Marks this function as a global function to be included in the global namespace. 105 | - **`@param`**: Give a brief description of the variable; denote particulars (e.g. if the variable is optional, its default) with [JSDoc `@param` syntax](http://jsdoc.app/tags-param.html). Use a period at the end. 106 | - **`@yield`**: For [generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*), a description of the values expected to be yielded from this function. As with other descriptions, include a period at the end. 107 | - **`@return`**: Note the period after the description. 108 | 109 | ```javascript 110 | /** 111 | * Summary. (use period) 112 | * 113 | * Description. (use period) 114 | * 115 | * @since x.x.x 116 | * @deprecated x.x.x Use new_function_name() instead. 117 | * @access private 118 | * 119 | * @class 120 | * @augments parent 121 | * @mixes mixin 122 | * 123 | * @alias realName 124 | * @memberof namespace 125 | * 126 | * @see Function/class relied on 127 | * @link URL 128 | * @global 129 | * 130 | * @fires eventName 131 | * @fires className#eventName 132 | * @listens event:eventName 133 | * @listens className~event:eventName 134 | * 135 | * @param {type} var Description. 136 | * @param {type} [var] Description of optional variable. 137 | * @param {type} [var=default] Description of optional variable with default variable. 138 | * @param {Object} objectVar Description. 139 | * @param {type} objectVar.key Description of a key in the objectVar parameter. 140 | * 141 | * @yield {type} Yielded value description. 142 | * 143 | * @return {type} Return value description. 144 | */ 145 | ``` 146 | 147 | ## Backbone classes 148 | 149 | Backbone's `extend` calls should be formatted as follows: 150 | 151 | - **`@lends`** This tag will allow JSDoc to recognize the `extend` function from Backbone as a class definition. This should be placed right before the Object that contains the class definition. 152 | 153 | Backbone's `initialize` functions should be formatted as follows: 154 | 155 | - **Summary**: A brief, one line explanation of the purpose of the function. Use a period at the end. 156 | - **Description**: A supplement to the summary, providing a more detailed description. Use a period at the end. 157 | - **`@deprecated x.x.x`**: Only use for deprecated classes, and provide the version the class was deprecated which should always be 3-digit (e.g. `@deprecated 3.6.0`), and the class to use instead. 158 | - **`@since x.x.x`**: Should be 3-digit for initial introduction (e.g. `@since 3.6.0`). If significant changes are made, additional `@since` tags, versions, and descriptions should be added to serve as a changelog. 159 | - **`@constructs`**: Marks this function as the constructor of this class. 160 | - **`@augments`**: List direct parents. 161 | - **`@mixes`**: List mixins that are mixed into the class. 162 | - **`@requires`**: Lists modules that this class requires. Multiple `@requires` tags can be used. 163 | - **`@alias`**: If this class is first assigned to a temporary variable this allows you to change the name it's documented under. 164 | - **`@memberof`**: Namespace that this class is contained within if JSDoc is unable to resolve this automatically. 165 | - **`@static`**: For classes, used to mark that a function is a static method on the class constructor. 166 | - **`@see`**: A function or class relied on. 167 | - **`@link`**: URL that provides more information. 168 | - **`@fires`**: Event fired by the constructor. Should list the class name. 169 | - **`@param`**: Document the arguments passed to the constructor even if not explicitly listed in `initialize`. Use a period at the end. 170 | - Backbone Models are passed `attributes` and `options` parameters. 171 | - Backbone Views are passed an `options` parameter. 172 | 173 | ```javascript 174 | Class = Parent.extend( /** @lends namespace.Class.prototype */{ 175 | /** 176 | * Summary. (use period) 177 | * 178 | * Description. (use period) 179 | * 180 | * @since x.x.x 181 | * @deprecated x.x.x Use new_function_name() instead. 182 | * @access private 183 | * 184 | * @constructs namespace.Class 185 | * @augments Parent 186 | * @mixes mixin 187 | * 188 | * @alias realName 189 | * @memberof namespace 190 | * 191 | * @see Function/class relied on 192 | * @link URL 193 | * @fires Class#eventName 194 | * 195 | * @param {Object} attributes The model's attributes. 196 | * @param {type} attributes.key One of the model's attributes. 197 | * @param {Object} [options] The model's options. 198 | * @param {type} options.key One of the model's options. 199 | */ 200 | initialize: function() { 201 | //Do stuff. 202 | } 203 | } ); 204 | ``` 205 | 206 | If a Backbone class does not have an initialize function it should be documented by using `@inheritDoc` as follows: 207 | 208 | ```javascript 209 | /** 210 | * Summary. (use period) 211 | * 212 | * Description. (use period) 213 | * 214 | * @since x.x.x 215 | * @deprecated x.x.x Use new_function_name() instead. 216 | * @access private 217 | * 218 | * @constructs namespace.Class 219 | * @memberOf namespace 220 | * @augments Parent 221 | * @mixes mixin 222 | * @inheritDoc 223 | * 224 | * @alias realName 225 | * @memberof namespace 226 | * 227 | * @see Function/class relied on 228 | * @link URL 229 | */ 230 | Class = Parent.extend( /** @lends namespace.Class.prototype */{ 231 | // Functions and properties. 232 | } ); 233 | ``` 234 | 235 | > Note: This currently doesn't provide the expected functionality due to a bug with JSDoc's inheritDoc tag. See [JSDocs3 issue 1012](https://github.com/jsdoc3/jsdoc/issues/1012). 236 | 237 | ## Local functions 238 | 239 | At times functions will be assigned to a local variable before being assigned as a class member. 240 | Such functions should be marked as inner functions of the namespace that uses them using `~`. 241 | The functions should be formatted as follows: 242 | 243 | ```javascript 244 | /** 245 | * Function description, you can use any JSDoc here as long as the function remains private. 246 | * 247 | * @alias namespace~doStuff 248 | */ 249 | var doStuff = function () { 250 | // Do stuff. 251 | }; 252 | 253 | Class = Parent.extend( /** @lends namespace.Class.prototype */{ 254 | /** 255 | * Class description 256 | * 257 | * @constructs namespace.Class 258 | * 259 | * @borrows namespace~doStuff as prototype.doStuff 260 | */ 261 | initialize: function() { 262 | //Do stuff. 263 | }, 264 | 265 | /* 266 | * This function will automatically have it's documentation copied from above. 267 | * You should make a comment ( not a DocBlock using /**, instead use /* or // ) 268 | * noting that you're describing this function using @borrows. 269 | */ 270 | doStuff: doStuff, 271 | } ); 272 | ``` 273 | 274 | ## Local ancestors 275 | 276 | At times classes will have Ancestors that are only assigned to a local variable. Such classes should be assigned to the namespace their children are and be made inner classes using `~`. 277 | 278 | ## Class members 279 | 280 | Class members should be formatted as follows: 281 | 282 | - **Short description**: Use a period at the end. 283 | - **`@since x.x.x`**: Should be 3-digit for initial introduction (e.g. `@since 3.6.0`). If significant changes are made, additional `@since` tags, versions, and descriptions should be added to serve as a changelog. 284 | - **`@access`**: If the members is private, protected or public. Private members are intended for internal use only. 285 | - **`@type`**: List the type of the class member. 286 | - **`@property`** List all properties this object has in case it's an Object. Use a period at the end. 287 | - **`@member`**: Optionally use this to override JSDoc's member detection in place of `@type` to force a class member. 288 | - **`@memberof`**: Optionally use this to override what class this is a member of. 289 | 290 | ```javascript 291 | /** 292 | * Short description. (use period) 293 | * 294 | * @since x.x.x 295 | * @access (private, protected, or public) 296 | * 297 | * @type {type} 298 | * @property {type} key Description. 299 | * 300 | * @member {type} realName 301 | * @memberof className 302 | */ 303 | ``` 304 | 305 | ## Namespaces 306 | 307 | Namespaces should be formatted as follows: 308 | 309 | - **Short description**: Use a period at the end. 310 | - **`@namespace`**: Marks this symbol as a namespace, optionally provide a name as an override. 311 | - **`@since x.x.x`**: Should be 3-digit for initial introduction (e.g. `@since 3.6.0`). If significant changes are made, additional `@since` tags, versions, and descriptions should be added to serve as a changelog. 312 | - **`@memberof`**: Namespace that this namespace is contained in. 313 | - **`@property`**: Properties that this namespace exposes. Use a period at the end. 314 | 315 | ```javascript 316 | /** 317 | * Short description. (use period) 318 | * 319 | * @namespace realName 320 | * @memberof parentNamespace 321 | * 322 | * @since x.x.x 323 | * 324 | * @property {type} key Description. 325 | */ 326 | ``` 327 | 328 | ## Inline Comments 329 | 330 | Inline comments inside methods and functions should be formatted as follows: 331 | 332 | ### Single line comments 333 | 334 | ```javascript 335 | // Extract the array values. 336 | ``` 337 | 338 | ### Multi-line comments 339 | 340 | ```javascript 341 | /* 342 | * This is a comment that is long enough to warrant being stretched over 343 | * the span of multiple lines. You'll notice this follows basically 344 | * the same format as the JSDoc wrapping and comment block style. 345 | */ 346 | ``` 347 | 348 | **Important note:** Multi-line comments must not begin with `/**` (double asterisk). Use `/*` (single asterisk) instead. 349 | 350 | ## File Headers 351 | 352 | The JSDoc file header block is used to give an overview of what is contained in the file. 353 | 354 | Whenever possible, all WordPress JavaScript files should contain a header block. 355 | 356 | WordPress uses JSHint for general code quality testing. Any inline configuration options should be placed at the end of the header block. 357 | 358 | ```javascript 359 | /** 360 | * Summary. (use period) 361 | * 362 | * Description. (use period) 363 | * 364 | * @link URL 365 | * @file This files defines the MyClass class. 366 | * @author AuthorName. 367 | * @since x.x.x 368 | */ 369 | 370 | /** jshint {inline configuration here} */ 371 | ``` 372 | 373 | ## Supported JSDoc Tags 374 | 375 | | Tag | Description | 376 | |----------------|----------------------------------------------------------------------------------------------| 377 | | `@abstract` | This method can be implemented (or overridden) by the inheritor. | 378 | | `@access` | Specify the access level of this member (private, public, or protected). | 379 | | `@alias` | Treat a member as if it had a different name. | 380 | | `@augments` | This class inherits from a parent class. | 381 | | `@author` | Identify the author of an item. | 382 | | `@borrows` | This object uses something from another object. | 383 | | `@callback` | Document a callback function. | 384 | | `@class` | This function is a class constructor. | 385 | | `@classdesc` | Use the following text to describe the entire class. | 386 | | `@constant` | Document an object as a constant. | 387 | | `@constructs` | This function member will be the constructor for the previous class. | 388 | | `@copyright` | Document some copyright information. | 389 | | `@default` | Document the default value. | 390 | | `@deprecated` | Document that this is no longer the preferred way. | 391 | | `@description` | Describe a symbol. | 392 | | `@enum` | Document a collection of related properties. | 393 | | `@event` | Document an event. | 394 | | `@example` | Provide an example of how to use a documented item. | 395 | | `@exports` | Identify the member that is exported by a JavaScript module. | 396 | | `@external` | Document an external class/namespace/module. | 397 | | `@file` | Describe a file. | 398 | | `@fires` | Describe the events this method may fire. | 399 | | `@function` | Describe a function or method. | 400 | | `@global` | Document a global object. | 401 | | `@ignore` | [todo] Remove this from the final output. | 402 | | `@inner` | Document an inner object. | 403 | | `@instance` | Document an instance member. | 404 | | `@kind` | What kind of symbol is this? | 405 | | `@lends` | Document properties on an object literal as if they belonged to a symbol with a given name. | 406 | | `@license` | [todo] Document the software license that applies to this code. | 407 | | `@link` | Inline tag - create a link. | 408 | | `@member` | Document a member. | 409 | | `@memberof` | This symbol belongs to a parent symbol. | 410 | | `@mixes` | This object mixes in all the members from another object. | 411 | | `@mixin` | Document a mixin object. | 412 | | `@module` | Document a JavaScript module. | 413 | | `@name` | Document the name of an object. | 414 | | `@namespace` | Document a namespace object. | 415 | | `@param` | Document the parameter to a function. | 416 | | `@private` | This symbol is meant to be private. | 417 | | `@property` | Document a property of an object. | 418 | | `@protected` | This member is meant to be protected. | 419 | | `@public` | This symbol is meant to be public. | 420 | | `@readonly` | This symbol is meant to be read-only. | 421 | | `@requires` | This file requires a JavaScript module. | 422 | | `@return` | Document the return value of a function. | 423 | | `@see` | Refer to some other documentation for more information. | 424 | | `@since` | Documents the version at which the function was added, or when significant changes are made. | 425 | | `@static` | Document a static member. | 426 | | `@this` | What does the 'this' keyword refer to here? | 427 | | `@throws` | Describe what errors could be thrown. | 428 | | `@todo` | Document tasks to be completed. | 429 | | `@tutorial` | Insert a link to an included tutorial file. | 430 | | `@type` | Document the type of an object. | 431 | | `@typedef` | Document a custom type. | 432 | | `@variation` | Distinguish different objects with the same name. | 433 | | `@version` | Documents the version number of an item. | 434 | | `@yield` | Document the yielded values of a generator function. | 435 | 436 | ## Unsupported JSDoc Tags 437 | 438 | | Tag | Why it's not supported | 439 | |-----------------|-----------------------------------------------------------------------------------------------| 440 | | `@summary` | Should not be used. See the example of how to separate a summary from the full description. | 441 | | `@virtual` | An unsupported synonym. Use `@abstract` instead. | 442 | | `@extends` | An unsupported synonym. Use `@augments` instead. | 443 | | `@constructor` | An unsupported synonym. Use `@class` instead. | 444 | | `@const` | An unsupported synonym. Use `@constant` instead. | 445 | | `@defaultvalue` | An unsupported synonym. Use `@default` instead. | 446 | | `@desc` | An unsupported synonym. Use `@description` instead. | 447 | | `@host` | An unsupported synonym. Use `@external` instead. | 448 | | `@fileoverview` | An unsupported synonym. Use `@file` instead. | 449 | | `@overview` | An unsupported synonym. Use `@file` instead. | 450 | | `@emits` | An unsupported synonym. Use `@fires` instead. | 451 | | `@func` | An unsupported synonym. Use `@function` instead. | 452 | | `@method` | An unsupported synonym. Use `@function` instead. | 453 | | `@var` | An unsupported synonym. Use `@member` instead. | 454 | | `@emits` | An unsupported synonym. Use `@fires` instead. | 455 | | `@arg` | An unsupported synonym. Use `@param` instead. | 456 | | `@argument` | An unsupported synonym. Use `@param` instead. | 457 | | `@prop` | An unsupported synonym. Use `@property` instead. | 458 | | `@returns` | An unsupported synonym. Use `@return` instead. | 459 | | `@exception` | An unsupported synonym. Use `@throws` instead. | 460 | -------------------------------------------------------------------------------- /inline-documentation-standards/php.md: -------------------------------------------------------------------------------- 1 | # PHP Documentation Standards 2 | 3 | WordPress uses a customized documentation schema that draws inspiration from PHPDoc, an evolving standard for providing documentation to PHP code, which is maintained by [phpDocumentor](http://phpdoc.org/). 4 | 5 | ## What Should Be Documented 6 | 7 | PHP documentation in WordPress mostly takes the form of either formatted blocks of documentation or inline comments. 8 | 9 | The following is a list of what should be documented in WordPress files: 10 | 11 | - Functions and class methods 12 | - Classes 13 | - Class members (including properties and constants) 14 | - Requires and includes 15 | - Hooks (actions and filters) 16 | - Inline comments 17 | - File headers 18 | - Constants 19 | 20 | ### Documenting Tips 21 | 22 | #### Language 23 | 24 | Summaries should be clear, simple, and brief. Avoid describing "why" an element exists, rather, focus on documenting "what" and "when" it does something. 25 | 26 | A function, hook, class, or method is a _third-person singular_ element, meaning that _third-person singular verbs_ should be used to describe what each does. 27 | 28 | [tip] 29 | Need help remembering how to conjugate for third-person singular verbs? Imagine prefixing the function, hook, class, or method summary with "It": 30 | 31 | - _Good_: "(It) Does something." 32 | - _Bad_: "(It) Do something." 33 | 34 | [/tip] 35 | 36 | Summary examples: 37 | 38 | - **Functions**: _What_ does the function do? 39 | - Good: _Displays the last modified date for a post._ 40 | - Bad: _Display the date on which the post was last modified._ 41 | - **Filters**: _What_ is being filtered? 42 | - Good: _Filters the post content._ 43 | - Bad: _Lets you edit the post content that is output in the post template._ 44 | - **Actions:** _When_ does an action fire? 45 | - Good: _Fires after most of core is loaded, and the user is authenticated._ 46 | - Bad: _Allows you to register custom post types, custom taxonomies, and other general housekeeping tasks after a lot of WordPress core has loaded._ 47 | 48 | #### Grammar 49 | 50 | Descriptive elements should be written as complete sentences. The one exception to this standard is file header summaries, which are intended as file "titles" more than sentences. 51 | 52 | The serial (Oxford) comma should be used when listing elements in summaries, descriptions, and parameter or return descriptions. 53 | 54 | #### Miscellaneous 55 | 56 | **`@since`**: The recommended tool to use when searching for the version something was added to WordPress is [`svn blame`](http://make.wordpress.org/core/handbook/svn/code-history/#using-subversion-annotate). An additional resource for older hooks is the [WordPress Hooks Database](http://adambrown.info/p/wp_hooks). 57 | 58 | If the version number cannot be determined after using these tools, use `@since Unknown`. 59 | 60 | Anything ported over from WPMU should use `@since MU (3.0.0)`. Existing `@since MU (3.0.0)` tags should not be changed. 61 | 62 | **Code Refactoring**: It is permissible to space out the specific action or filter lines being documented to meet the coding standards, but do not refactor other code in the file. 63 | 64 | ### Formatting Guidelines 65 | 66 | [info] 67 | WordPress' inline documentation standards for PHP are specifically tailored for optimum output on the [official Code Reference](https://developer.wordpress.org/reference/). As such, following the standards in core and formatting as described below are _extremely_ important to ensure expected output. 68 | [/info] 69 | 70 | #### General 71 | 72 | DocBlocks should directly precede the hook, action, function, method, or class line. There should not be any opening/closing tags or other things between the DocBlock and the declarations to prevent the parser becoming confused. 73 | 74 | #### Summary 75 | 76 | No HTML markup or Markdown of any kind should be used in the summary. If the text refers to an HTML element or tag, then it should be written as "image tag" or "img" element, not "``". For example: 77 | 78 | - Good: _Fires when printing the link tag in the header._ 79 | - Bad: _Fires when printing the `` tag in the header._ 80 | 81 | Inline PHPDoc tags may be used. 82 | 83 | #### Description 84 | 85 | HTML markup should never be used outside of code examples, though Markdown can be used, as needed, in the description. 86 | 87 | 1. Lists: 88 | 89 | Use a hyphen (-) to create an unordered list, with a blank line before and after. 90 | 91 | ```php 92 | * Description which includes an unordered list: 93 | * 94 | * - This is item 1. 95 | * - This is item 2. 96 | * - This is item 3. 97 | * 98 | * The description continues on ... 99 | ``` 100 | 101 | Use numbers to create an ordered list, with a blank line before and after. 102 | 103 | ```php 104 | * Description which includes an ordered list: 105 | * 106 | * 1. This is item 1. 107 | * 2. This is item 2. 108 | * 3. This is item 3. 109 | * 110 | * The description continues on ... 111 | ``` 112 | 113 | 2. Code samples would be created by indenting every line of the code by 4 spaces, with a blank line before and after. Blank lines in code samples also need to be indented by four spaces. Note that examples added in this way will be output in `
` tags and _not_ syntax-highlighted.
114 | 
115 |     ```php
116 |      * Description including a code sample:
117 |      *
118 |      *    $status = array(
119 |      *        'draft'   => __( 'Draft' ),
120 |      *        'pending' => __( 'Pending Review' ),
121 |      *        'private' => __( 'Private' ),
122 |      *        'publish' => __( 'Published' )
123 |      *    );
124 |      *
125 |      * The description continues on ...
126 |     ```
127 | 
128 | 3. Links in the form of URLs, such as related Trac tickets or other documentation, should be added in the appropriate place in the DocBlock using the `@link` tag:
129 | 
130 |     ```php
131 |      * Description text.
132 |      *
133 |      * @link https://core.trac.wordpress.org/ticket/20000
134 |     ```
135 | 
136 | #### `@since` Section (Changelogs)
137 | 
138 | Every function, hook, class, and method should have a corresponding `@since` version associated with it (more on that below).
139 | 
140 | No HTML should be used in the descriptions for `@since` tags, though limited Markdown can be used as necessary, such as for adding backticks around variables, arguments, or parameter names, e.g. `$variable`.
141 | 
142 | Versions should be expressed in the 3-digit `x.x.x` style:
143 | 
144 | ```php
145 |  * @since 4.4.0
146 | ```
147 | 
148 | If significant changes have been made to a function, hook, class, or method, additional `@since` tags, versions, and descriptions should be added to provide a changelog for that function.
149 | 
150 | "Significant changes" include but are not limited to:
151 | 
152 | - Adding new arguments or parameters.
153 | - Required arguments becoming optional.
154 | - Changing default/expected behaviors.
155 | - Functions or methods becoming wrappers for new APIs.
156 | - Parameters which have been renamed (once PHP 8.0 support has been announced).
157 | 
158 | PHPDoc supports multiple `@since` versions in DocBlocks for this explicit reason. When adding changelog entries to the `@since` block, a version should be cited, and a description should be added in sentence case and form and end with a period:
159 | 
160 | ```php
161 |  * @since 3.0.0
162 |  * @since 3.8.0 Added the `post__in` argument.
163 |  * @since 4.1.0 The `$force` parameter is now optional.
164 | ```
165 | 
166 | #### Other Descriptions
167 | 
168 | `@param`, `@type`, `@return`: No HTML should be used in the descriptions for these tags, though limited Markdown can be used as necessary, such as for adding backticks around variables, e.g. `$variable`.
169 | 
170 | - Inline `@see` tags can also be used to auto-link hooks in core:
171 |     - Hooks, e.g. `{@see 'save_post'}`
172 |     - Dynamic hooks, e.g. `{@see '$old_status_to_$new_status'}` (Note that any extra curly braces have been removed inside the quotes)
173 | - Default or available values should use single quotes, e.g. 'draft'. Translatable strings should be identified as such in the description.
174 | - HTML elements and tags should be written as "audio element" or "link tag".
175 | 
176 | #### Line wrapping
177 | 
178 | DocBlock text should wrap to the next line after 80 characters of text. If the DocBlock itself is indented on the left 20 character positions, the wrap could occur at position 100, but should not extend beyond a total of 120 characters wide.
179 | 
180 | ## DocBlock Formatting
181 | 
182 | The examples provided in each section below show the expected DocBlock content and tags, as well as the exact formatting. Use spaces inside the DocBlock, not tabs, and ensure that items in each tag group are aligned according to the examples.
183 | 
184 | ### 1. Functions & Class Methods
185 | 
186 | Functions and class methods should be formatted as follows:
187 | 
188 | - **Summary**: A brief, one sentence explanation of the purpose of the function spanning a maximum of two lines. Use a period at the end.
189 | - **Description**: A supplement to the summary, providing a more detailed description. Use a period at the end of sentences.
190 | - **`@ignore`**: Used when an element is meant only for internal use and should be skipped from parsing.
191 | - **`@since x.x.x`**: Should always be 3-digit (e.g. `@since 3.9.0`). Exception is `@since MU (3.0.0)`.
192 | - **`@access`**: Only used for core-only functions or classes implementing "private" core APIs. If the element is private it will be output with a message stating its intention for internal use.
193 | - **`@see`**: Reference to a function, method, or class that is heavily-relied on within. See the note above about inline `@see` tags for expected formatting.
194 | - **`@link`**: URL that provides more information. This should never be used to reference another function, hook, class, or method, see `@see`.
195 | - **`@global`**: List PHP globals that are used within the function or method, with an optional description of the global. If multiple globals are listed, they should be aligned by type, variable, and description, with each other as a group.
196 | - **`@param`**: Note if the parameter is _Optional_ before the description, and include a period at the end. The description should mention accepted values as well as the default. For example: _Optional. This value does something. Accepts 'post', 'term', or empty. Default empty._
197 | - **`@return`**: Should contain all possible return types and a description for each. Use a period at the end. Note: `@return void` should not be used outside the default bundled themes and the PHP compatibility shims included in WordPress Core.
198 | 
199 | ```php
200 | /**
201 |  * Summary.
202 |  *
203 |  * Description.
204 |  *
205 |  * @since x.x.x
206 |  *
207 |  * @see Function/method/class relied on
208 |  * @link URL
209 |  * @global type $varname Description.
210 |  * @global type $varname Description.
211 |  *
212 |  * @param type $var Description.
213 |  * @param type $var Optional. Description. Default.
214 |  * @return type Description.
215 |  */
216 | ```
217 | 
218 | #### 1.1 Parameters That Are Arrays
219 | 
220 | Parameters that are an array of arguments should be documented in the "originating" function only, and cross-referenced via an `@see` tag in corresponding DocBlocks.
221 | 
222 | Array values should be documented using WordPress' flavor of hash notation style similar to how [Hooks](https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/#4-hooks-actions-and-filters) can be documented, each array value beginning with the `@type` tag, and taking the form of:
223 | 
224 | ```php
225 | *     @type type $key Description. Default 'value'. Accepts 'value', 'value'.
226 | *                     (aligned with Description, if wraps to a new line)
227 | ```
228 | 
229 | An example of an "originating" function and re-use of an argument array is [`wp_remote_request|post|get|head()`](https://core.trac.wordpress.org/browser/tags/6.0/src/wp-includes/http.php/#L114).
230 | 
231 | ```php
232 | /**
233 |  * Summary.
234 |  *
235 |  * Description.
236 |  *
237 |  * @since x.x.x
238 |  *
239 |  * @param type  $var Description.
240 |  * @param array $args {
241 |  *     Optional. An array of arguments.
242 |  *
243 |  *     @type type $key Description. Default 'value'. Accepts 'value', 'value'.
244 |  *                     (aligned with Description, if wraps to a new line)
245 |  *     @type type $key Description.
246 |  * }
247 |  * @param type  $var Description.
248 |  * @return type Description.
249 |  */
250 | ```
251 | 
252 | In most cases, there is no need to mark individual arguments in a hash notation as _optional_, as the entire array is usually optional. Specifying "Optional." in the hash notation description should suffice. In the case where the array is NOT optional, individual key/value pairs may be optional and should be marked as such as necessary.
253 | 
254 | #### 1.2 Deprecated Functions
255 | 
256 | If the function is deprecated and should not be used any longer, the `@deprecated` tag, along with the version and description of what to use instead, should be added. Note the additional use of an `@see` tag - the Code Reference uses this information to attempt to link to the replacement function.
257 | 
258 | ```php
259 | /**
260 |  * Summary.
261 |  *
262 |  * Description.
263 |  *
264 |  * @since x.x.x
265 |  * @deprecated x.x.x Use new_function_name()
266 |  * @see new_function_name()
267 |  *
268 |  * @param type $var Optional. Description.
269 |  * @param type $var Description.
270 |  * @return type Description.
271 |  */
272 | ```
273 | 
274 | ### 2. Classes
275 | 
276 | Class DocBlocks should be formatted as follows:
277 | 
278 | - **Summary**: A brief, one sentence explanation of the **purpose** of the class spanning a maximum of two lines. Use a period at the end.
279 | - **Description**: A supplement to the summary, providing a more detailed description. Use a period at the end.
280 | - **`@since x.x.x`**: Should always be 3-digit (e.g. `@since 3.9.0`). Exception is `@since MU (3.0.0)`.
281 | 
282 | ```php
283 | /**
284 |  * Summary.
285 |  *
286 |  * Description.
287 |  *
288 |  * @since x.x.x
289 |  */
290 | ```
291 | 
292 | If documenting a sub-class, it's also helpful to include an `@see` tag reference to the super class:
293 | 
294 | ```php
295 | /**
296 |  * Summary.
297 |  *
298 |  * Description.
299 |  *
300 |  * @since x.x.x
301 |  *
302 |  * @see Super_Class
303 |  */
304 | ```
305 | 
306 | #### 2.1 Class Members
307 | 
308 | ##### 2.1.1 Properties
309 | 
310 | Class properties should be formatted as follows:
311 | 
312 | - **Summary**: Use a period at the end.
313 | - **`@since x.x.x`**: Should always be 3-digit (e.g. `@since 3.9.0`). Exception is `@since MU (3.0.0)`.
314 | - **`@var`**: Formatted the same way as `@param`, though the description may be omitted.
315 | 
316 | ```php
317 | /**
318 |  * Summary.
319 |  *
320 |  * @since x.x.x
321 |  * @var type $var Description.
322 |  */
323 | ```
324 | 
325 | ##### 2.1.2 Constants
326 | 
327 | - **Summary**: Use a period at the end.
328 | - **`@since x.x.x`**: Should always be 3-digit (e.g. `@since 3.9.0`). Exception is `@since MU (3.0.0)`.
329 | - **`@var`**: Formatted the same way as `@param`, though the description may be omitted.
330 | 
331 | ```php
332 | /**
333 |  * Summary.
334 |  *
335 |  * @since x.x.x
336 |  * @var type $var Description.
337 |  */
338 | const NAME = value;
339 | ```
340 | 
341 | ### 3. Requires and Includes
342 | 
343 | Files required or included should be documented with a summary description DocBlock. Optionally, this may apply to inline `get_template_part()` calls as needed for clarity.
344 | 
345 | ```php
346 | /**
347 |  * Summary.
348 |  */
349 | require_once( ABSPATH . WPINC . '/filename.php' );
350 | ```
351 | 
352 | ### 4. Hooks (Actions and Filters)
353 | 
354 | Both action and filter hooks should be documented on the line immediately preceding the call to `do_action()` or `do_action_ref_array()`, or `apply_filters()` or `apply_filters_ref_array()`, and formatted as follows:
355 | 
356 | - **Summary**: A brief, one line explanation of the purpose of the hook. Use a period at the end.
357 | - **Description**: A supplemental description to the summary, if warranted.
358 | - **`@ignore`**: Used when a hook is meant only for internal use and should be skipped from parsing.
359 | - **`@since x.x.x`**: Should always be 3-digit (e.g. `@since 3.9.0`). Exception is `@since MU (3.0.0)`.
360 | - **`@param`**: If the parameter is an array of arguments, document each argument using a hash notation (described above in the _Parameters That Are Arrays_ section), and include a period at the end of each line.
361 | 
362 | Note that `@return` is _not_ used for hook documentation, because action hooks return nothing, and filter hooks always return their first parameter.
363 | 
364 | ```php
365 | /**
366 |  * Summary.
367 |  *
368 |  * Description.
369 |  *
370 |  * @since x.x.x
371 |  *
372 |  * @param type  $var Description.
373 |  * @param array $args {
374 |  *     Short description about this hash.
375 |  *
376 |  *     @type type $var Description.
377 |  *     @type type $var Description.
378 |  * }
379 |  * @param type  $var Description.
380 |  */
381 | ```
382 | 
383 | If a hook is in the middle of a block of HTML or a long conditional, the DocBlock should be placed on the line immediately before the start of the HTML block or conditional, even if it means forcing line-breaks/PHP tags in a continuous line of HTML.
384 | 
385 | Tools to use when searching for the version a hook was added are [`svn blame`](http://make.wordpress.org/core/handbook/svn/code-history/#using-subversion-annotate), or the [WordPress Hooks Database](http://adambrown.info/p/wp_hooks) for older hooks. If, after using these tools, the version number cannot be determined, use `@since Unknown`.
386 | 
387 | #### 4.1 Duplicate Hooks
388 | 
389 | Occasionally, hooks will be used multiple times in the same or separate core files. In these cases, rather than list the entire DocBlock every time, only the first-added or most logically-placed version of an action or filter will be fully documented. Subsequent versions should have a single-line comment.
390 | 
391 | For actions:
392 | 
393 | ```php
394 | /** This action is documented in path/to/filename.php */
395 | ```
396 | 
397 | For filters:
398 | 
399 | ```php
400 | /** This filter is documented in path/to/filename.php */
401 | ```
402 | 
403 | To determine which instance should be documented, search for multiples of the same hook tag, then use [`svn blame`](http://make.wordpress.org/core/handbook/svn/code-history/#using-subversion-annotate) to find the first use of the hook in terms of the earliest revision. If multiple instances of the hook were added in the same release, document the one most logically-placed as the "primary".
404 | 
405 | ### 5. Inline Comments
406 | 
407 | Inline comments inside methods and functions should be formatted as follows:
408 | 
409 | #### 5.1 Single line comments
410 | 
411 | ```php
412 | // Allow plugins to filter an array.
413 | ```
414 | 
415 | #### 5.2 Multi-line comments
416 | 
417 | ```php
418 | /*
419 |  * This is a comment that is long enough to warrant being stretched over
420 |  * the span of multiple lines. You'll notice this follows basically
421 |  * the same format as the PHPDoc wrapping and comment block style.
422 |  */
423 | ```
424 | 
425 | **Important note**: Multi-line comments must not begin with `/**` (double asterisk) as the parser might mistake it for a DocBlock. Use `/*` (single asterisk) instead.
426 | 
427 | ### 6. File Headers
428 | 
429 | The file header DocBlock is used to give an overview of what is contained in the file.
430 | 
431 | Whenever possible, **all** WordPress files should contain a header DocBlock, regardless of the file's contents - this includes files containing classes.
432 | 
433 | ```php
434 | /**
435 |  * Summary (no period for file headers)
436 |  *
437 |  * Description. (use period)
438 |  *
439 |  * @link URL
440 |  *
441 |  * @package WordPress
442 |  * @subpackage Component
443 |  * @since x.x.x (when the file was introduced)
444 |  */
445 | ```
446 | 
447 | The _Summary_ section is meant to serve as a succinct description of **what** specific purpose the file serves.
448 | 
449 | Examples:
450 | 
451 | - Good: _"Widgets API: WP_Widget class"_
452 | - Bad: _"Core widgets class"_
453 | 
454 | The _Description_ section can be used to better explain overview information for the file such as how the particular file fits into the overall makeup of an API or component.
455 | 
456 | Examples:
457 | 
458 | - Good: _"The Widgets API is comprised of the WP_Widget and WP_Widget_Factory classes in addition to a variety of top-level functionality that implements the Widgets and related sidebar APIs. WordPress registers a number of common widgets by default."_
459 | 
460 | ### 7. Constants
461 | 
462 | The constant DocBlock is used to give a description of the constant for better use and understanding.
463 | 
464 | Constants should be formatted as follows:
465 | 
466 | - **Summary**: Use a period at the end.
467 | - **`@since x.x.x`**: Should always be 3-digit (e.g. `@since 3.9.0`). Exception is `@since MU (3.0.0)`.
468 | - **`@var`**: Formatted the same way as `@param`. The description is optional.
469 | 
470 | ```php
471 | /**
472 |  * Summary.
473 |  *
474 |  * @since x.x.x (if available)
475 |  * @var type $var Description.
476 |  */
477 | ```
478 | 
479 | ## PHPDoc Tags
480 | 
481 | Common PHPDoc tags used in WordPress include `@since`, `@see`, `@global` `@param`, and `@return` (see table below for full list).
482 | 
483 | For the most part, tags are used correctly, but not all the time. For instance, sometimes you'll see an `@link` tag inline, linking to a separate function or method. "Linking" to known classes, methods, or functions is not necessary, as the Code Reference automatically links these elements. For "linking" hooks inline, the proper tag to use is `@see` - see the _Other Descriptions_ section.
484 | 
485 | 
486 | | Tag               | Usage                                                       | Description                                                                                                                                                                                                                                    |
487 | |-------------------|-------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
488 | | **`@access`**     | private                                                     | Only used in limited circumstances, like when visibility modifiers cannot be used in the code, and only when private, such as for core-only functions or core classes implementing "private" APIs. Used directly below the `@since` line in block.                                                        |
489 | | **`@deprecated`** | version x.x.x Use _replacement function name_ instead       | What version of WordPress the function/method was deprecated. Use 3-digit version number. Should be accompanied by a matching `@see` tag.                                                                                                      |
490 | | **`@global`**     | datatype $variable description                              | Document global(s) used in the function/method. For boolean and integer types, use `bool` and `int`, respectively.                                                                                                                             |
491 | | **`@internal`**   | information string                                          | Typically used wrapped in `{}` for adding notes for internal use only.                                                                                                                                                                                         |
492 | | **`@ignore`**     | (standalone)                                                | Used to skip parsing of the entire element.                                                                                                                                                                                                    |
493 | | **`@link`**       | URL                                                         | Link to additional information for the function/method. For an external script/library, links to source. Not to be used for related functions/methods; use `@see` instead.                                                                     |
494 | | **`@method`**     | returntype description                                      | Shows a "magic" method found inside the class.                                                                                                                                                                                                 |
495 | | **`@package`**    | packagename                                                 | Specifies package that all functions, includes, and defines in the file belong to. Found in DocBlock at top of the file. For core (and bundled themes), this is always **WordPress**.                                                          |
496 | | **`@param`**      | datatype $variable description                              | Function/method parameter of the format: parameter type, variable name, description, default behavior. For boolean and integer types, use `bool` and `int`, respectively.                                                                      |
497 | | **`@return`**     | datatype description                                        | Document the return value of functions or methods. `@return void` should not be used outside of the default bundled themes. For boolean and integer types, use `bool` and `int`, respectively.                                                 |
498 | | **`@see`**        | elementname                                                 | References another function/method/class the function/method relies on. Should only be used inline for "linking" hooks.                                                                                                                        |
499 | | **`@since`**      | version x.x.x                                               | Documents release version function/method was added. Use 3-digit version number - this is to aid with version searches, and for use when comparing versions in code. Exception is `@since MU (3.0.0)`.                                         |
500 | | **`@static`**     | (standalone)                                                | Note: This tag has been used in the past, but should no longer be used. Just using the static keyword in your code is enough for phpDocumentor on PHP5+ to recognize static variables and methods, and PhpDocumentor will mark them as static. |
501 | | **`@staticvar`**  | datatype $variable description                              | Note: This tag has been used in the past, but should no longer be used. Document a static variable's use in a function/method. For boolean and integer types, use `bool` and `int`, respectively.                                              |
502 | | **`@subpackage`** | subpackagename                                              | For page-level DocBlock, specifies the Component that all functions and defines in file belong to. For class-level DocBlock, specifies the subpackage/component the class belongs to.                                                          |
503 | | **`@todo`**       | information string                                          | Documents planned changes to an element that have not been implemented.                                                                                                                                                                        |
504 | | **`@type`**       | datatype description for an argument array value            | Used to denote argument array value types. See the **Hooks** or **Parameters That Are Arrays** sections for example syntax.                                                                                                                    |
505 | | **`@uses`**       | class::methodname() / class::$variablename / functionname() | Note: This tag has been used in the past, but should no longer be used. References a key function/method used. May include a short description.                                                                                                |
506 | | **`@var`**        | datatype description                                        | Data type for a class variable and short description. Callbacks are marked callback.                                                                                                                                                           |
507 | 
508 | [info]
509 | PHPDoc tags work with some text editors/IDEs to display more information about a piece of code. It is useful to developers using those editors to understand what the purpose is, and where they would use it in their code. PhpStorm and Netbeans already support PHPDoc.
510 | 
511 | The following text editors/IDEs have extensions/bundles you can install that will help you auto-create DocBlocks:
512 | 
513 | - Notepad++: [DocIt for Notepad++](http://sourceforge.net/projects/nppdocit/) (Windows)
514 | - TextMate: [php.tmbundle](https://github.com/textmate/php.tmbundle) (Mac)
515 | - SublimeText: [sublime packages](https://packagecontrol.io/search/phpdoc) (Windows, Mac, Linux)
516 | 
517 | Note: Even with help generating DocBlocks, most code editors don't do a very thorough job - it's likely you'll need to manually fill in certain areas of any generated DocBlocks.
518 | [/info]
519 | 
520 | ### Deprecated Tags
521 | 
522 | > **Preface:** For the time being, and for the sake of consistency, WordPress Core will continue to use `@subpackage` tags - both when writing new DocBlocks, and editing old ones.
523 | >
524 | > Only when the new - external - PSR-5 recommendations are finalized, will across-the-board changes be considered, such as deprecating certain tags.
525 | 
526 | As proposed in the [new PSR-5](https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md) recommendations, the following PHPDoc tag should be deprecated:
527 | 
528 | - `@subpackage` (in favor of a unified package tag: `@package Package\Subpackage`)
529 | - `@static` (no longer needed)
530 | - `@staticvar` (no longer needed)
531 | 
532 | ### Other Tags
533 | 
534 | **`@package` Tag in Plugins and Themes (bundled themes excluded)**
535 | 
536 | Third-party plugin and theme authors **must not** use `@package WordPress` in their plugins or themes. The `@package` name for plugins should be the plugin name; for themes, it should be the theme name, spaced with underscores: `Twenty_Fifteen`.
537 | 
538 | **`@author` Tag**
539 | 
540 | It is WordPress' policy not to use the `@author` tag, except in the case of maintaining it in external libraries. We do not want to imply any sort of "ownership" over code that might discourage contribution.
541 | 
542 | **`@copyright` and `@license` Tags**
543 | 
544 | The `@copyright` and `@license` tags are used in external libraries and scripts, and should not be used in WordPress core files.
545 | 
546 | - `@copyright` is used to specify external script copyrights.
547 | - `@license` is used to specify external script licenses.
548 | 
549 | ## Resources
550 | 
551 | - [Wikipedia on PHPDoc](http://en.wikipedia.org/wiki/PHPDoc)
552 | - [PEAR Standards](http://pear.php.net/manual/en/standards.sample.php)
553 | - [phpDocumentor](http://www.phpdoc.org/)
554 | - [phpDocumentor Tutorial Tags](http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.pkg.html)
555 | - [Draft PSR-5 recommendations](https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md)
556 | - [Draft PSR-19 recommendations](https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc-tags.md)
557 | 


--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
 1 | {
 2 | 	"index": {
 3 | 		"title": "Coding Standards",
 4 | 		"slug": "index",
 5 | 		"parent": null,
 6 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/index.md"
 7 | 	},
 8 | 	"wordpress-coding-standards": {
 9 | 		"title": "WordPress Coding Standards",
10 | 		"slug": "wordpress-coding-standards",
11 | 		"parent": null,
12 | 		"order": 1,
13 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards.md"
14 | 	},
15 | 	"wordpress-coding-standards/accessibility": {
16 | 		"title": "Accessibility Coding Standards",
17 | 		"slug": "accessibility",
18 | 		"parent": "wordpress-coding-standards",
19 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/accessibility.md"
20 | 	},
21 | 	"wordpress-coding-standards/css": {
22 | 		"title": "CSS Coding Standards",
23 | 		"slug": "css",
24 | 		"parent": "wordpress-coding-standards",
25 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/css.md"
26 | 	},
27 | 	"wordpress-coding-standards/html": {
28 | 		"title": "HTML Coding Standards",
29 | 		"slug": "html",
30 | 		"parent": "wordpress-coding-standards",
31 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/html.md"
32 | 	},
33 | 	"wordpress-coding-standards/javascript": {
34 | 		"title": "JavaScript Coding Standards",
35 | 		"slug": "javascript",
36 | 		"parent": "wordpress-coding-standards",
37 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/javascript.md"
38 | 	},
39 | 	"wordpress-coding-standards/php": {
40 | 		"title": "PHP Coding Standards",
41 | 		"slug": "php",
42 | 		"parent": "wordpress-coding-standards",
43 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/wordpress-coding-standards/php.md"
44 | 	},
45 | 	"inline-documentation-standards": {
46 | 		"title": "Inline Documentation Standards",
47 | 		"slug": "inline-documentation-standards",
48 | 		"parent": null,
49 | 		"order": 2,
50 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/inline-documentation-standards.md"
51 | 	},
52 | 	"inline-documentation-standards/javascript": {
53 | 		"title": "JavaScript Documentation Standards",
54 | 		"slug": "javascript",
55 | 		"parent": "inline-documentation-standards",
56 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/inline-documentation-standards/javascript.md"
57 | 	},
58 | 	"inline-documentation-standards/php": {
59 | 		"title": "PHP Documentation Standards",
60 | 		"slug": "php",
61 | 		"parent": "inline-documentation-standards",
62 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/inline-documentation-standards/php.md"
63 | 	},
64 | 	"changelog": {
65 | 		"title": "Changelog",
66 | 		"slug": "changelog",
67 | 		"parent": null,
68 | 		"order": 3,
69 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/changelog.md"
70 | 	},
71 | 	"styleguide": {
72 | 		"title": "Markdown Style Guide",
73 | 		"slug": "styleguide",
74 | 		"parent": null,
75 | 		"order": 4,
76 | 		"markdown_source": "https://github.com/WordPress/wpcs-docs/blob/master/styleguide.md"
77 | 	}
78 | }
79 | 


--------------------------------------------------------------------------------
/styleguide.md:
--------------------------------------------------------------------------------
  1 | # Markdown Style Guide
  2 | 
  3 | ## Headings
  4 | 
  5 | ```md
  6 | # Heading h1
  7 | ## Heading h2
  8 | ### Heading h3
  9 | #### Heading h4
 10 | ##### Heading h5
 11 | ###### Heading h6
 12 | ```
 13 | 
 14 | Note: h1 - h4 items will be automatically added to the Table of Contents.
 15 | 
 16 | ## Emphasis
 17 | 
 18 | ### Italics
 19 | 
 20 | Wrap text with a single `_` for _Italic_ text:
 21 | 
 22 | ```md
 23 | This is _italic text_.
 24 | ```
 25 | 
 26 | ### Bold
 27 | 
 28 | Wrap text with double `**` for **Bold** text:
 29 | 
 30 | ```md
 31 | This is **bold text**.
 32 | ```
 33 | 
 34 | ### Strikethrough
 35 | 
 36 | Wrap text with double `~~` for ~~strikethrough~~ text:
 37 | 
 38 | ```md
 39 | This is ~~strikethrough~~ text.
 40 | ```
 41 | 
 42 | ## Links
 43 | 
 44 | Wrap the title in square brackets `[title]` immediately followed by the URL in `(https://example.com)`:
 45 | 
 46 | ```md
 47 | [WordPress](https://wordpress.org/)
 48 | ```
 49 | 
 50 | ## Blockquotes
 51 | 
 52 | Use `>` for blockquotes, double `>>` to further indent:
 53 | 
 54 | ```md
 55 | > Blockquote
 56 | >> Indented Blockquote
 57 | ```
 58 | 
 59 | ## Lists
 60 | 
 61 | ### Unordered Lists
 62 | 
 63 | Use `-` for unordered lists, and intent two spaces for list subitems:
 64 | 
 65 | ```md
 66 | - List
 67 |   - List
 68 | - List
 69 | - List
 70 | ```
 71 | 
 72 | ### Ordered Lists
 73 | 
 74 | Use numbered items followed by a `.:
 75 | 
 76 | ```md
 77 | 1. One
 78 | 2. Two
 79 | 3. Three
 80 | ```
 81 | 
 82 | ## Horizontal Rules
 83 | 
 84 | Use `---` for a horizontal rules:
 85 | 
 86 | ```md
 87 | ---
 88 | ```
 89 | 
 90 | ## Tables
 91 | 
 92 | ```md
 93 | | A     | B     |
 94 | | ----- | ----- |
 95 | | Alpha | Bravo |
 96 | ```
 97 | 
 98 | ## Example Code
 99 | 
100 | ### Inline Code
101 | 
102 | Wrap inline code with single `\`` backticks:
103 | 
104 | ````md
105 | ```
106 | This is `inline code` wrapped with backticks
107 | ```
108 | ````
109 | 
110 | When documenting an example, use the markdown `\`` code block to demarcate the beginning and end of the code sample:
111 | 
112 | ### Fenced Code Blocks
113 | 
114 | #### Javascript
115 | 
116 | ````md
117 | ```javascript
118 | var foo = function (bar) {
119 |   return bar++;
120 | };
121 | 
122 | console.log(foo(5));
123 | ```
124 | ````
125 | 
126 | #### JSON
127 | 
128 | ````md
129 | ```json
130 | {
131 |   "firstName": "John",
132 |   "lastName": "Smith",
133 |   "address": {
134 |     "streetAddress": "21 2nd Street",
135 |     "city": "New York",
136 |     "state": "NY",
137 |     "postalCode": "10021-3100"
138 |   },
139 |   "phoneNumbers": [
140 |     {
141 |       "type": "home",
142 |       "number": "212 555-1234"
143 |     },
144 |     {
145 |       "type": "office",
146 |       "number": "646 555-4567"
147 |     }
148 |   ],
149 |   "children": [],
150 |   "spouse": null
151 | }
152 | ```
153 | ````
154 | 
155 | #### CSS
156 | 
157 | ````md
158 | ```css
159 | foo {
160 |   padding: 5px;
161 |   margin-right: 3px;
162 | }
163 | 
164 | .bar {
165 |   background-color: #f00;
166 | }
167 | ```
168 | ````
169 | 
170 | #### SCSS
171 | 
172 | ````md
173 | ```scss
174 | foo {
175 |   padding: 5px;
176 |   margin-right: 3px;
177 | }
178 | 
179 | .bar {
180 |   background-color: #f00;
181 | }
182 | ```
183 | ````
184 | 
185 | #### HTML
186 | 
187 | ````md
188 | ```html
189 | Example
190 | ```
191 | ````
192 | 
193 | #### PHP
194 | 
195 | ````md
196 | ```php
197 | $array = array(
198 |     "foo" => "bar",
199 |     "bar" => "foo",
200 | );
201 | ```
202 | ````
203 | 
204 | #### Markdown
205 | 
206 | ````md
207 | ```md
208 | This is _italic text_. This is **bold text**.
209 | ```
210 | ````
211 | 


--------------------------------------------------------------------------------
/wordpress-coding-standards.md:
--------------------------------------------------------------------------------
 1 | # WordPress Coding Standards
 2 | 
 3 | The purpose of the WordPress Coding Standards is to create a baseline for collaboration and review within various aspects of the WordPress open source project and community, from core code to themes to plugins.
 4 | 
 5 | The WordPress community developed the standards contained in this section of the handbook, and those standards are part of the best practices that developers and core contributors are recommended to follow.
 6 | 

Why have coding standards?

7 | Coding standards help avoid common coding errors, improve the readability of code, and simplify modification. They ensure that files within the project appear as if they were created by a single person. 8 | 9 | Following the standards means anyone will be able to understand a section of code and modify it, if needed, without regard to when it was written or by whom. 10 | 11 | If you are planning to contribute to WordPress core, you need to familiarize yourself with these standards, as any code you submit will need to comply with them. 12 | 13 |

Language-specific Standards

14 | 20 | 21 |

Accessibility Standards

22 | 23 | WordPress is committed to meeting the Web Content Accessibility Guidelines (WCAG) at level AA for all new and updated code. We've provided a quick guide to common accessibility issues you should be aware of when creating patches or feature plug-ins. 24 | 25 |

Where do the coding standards _not_ apply?

26 | 27 | Third-party libraries are not subject to these standards, even when integrated with the primary project. This includes instances like WordPress core, where multiple third-party libraries are incorporated into its codebase. 28 | -------------------------------------------------------------------------------- /wordpress-coding-standards/accessibility.md: -------------------------------------------------------------------------------- 1 | # Accessibility Coding Standards 2 | 3 | Code integrated into the WordPress ecosystem - including WordPress core, WordPress.org websites, and official plugins, is expected to conform to the Web Content Accessibility Guidelines (WCAG), version 2.2, at level AA. 4 | 5 | New or updated interfaces are encouraged to incorporate the Authoring Tool Accessibility Guidelines (ATAG) 2.0. The most significant way that ATAG 2.0 guidelines can be incorporated is by emphasizing choices that help people make more accessible content: encouraging alternative text, captions, and semantic structures, for example. 6 | 7 | Official information about web accessibility standards can be divided into two groups: "normative" and "informative" documents. Only the guidelines themselves are normative, and establish the actual requirements for conforming to WCAG 2.2. Other documents should be considered to be informational, and offer help in interpreting the guidelines, but are not definitive. 8 | 9 | The WordPress A11y team is in the process of developing a library of recommended accessibility patterns to help describe the WordPress recommended way to accomplish a variety of interfaces. These may not be the only reasonable way to create an accessible example of the pattern, but are preferred for the sake of consistency across WordPress. 10 | 11 | Normative Documents: 12 | 13 | - [W3C WCAG 2.2](https://www.w3.org/TR/WCAG22) 14 | - [W3C ATAG 2.0](https://www.w3.org/TR/ATAG20/) 15 | - [W3C WAI ARIA 1.1](https://www.w3.org/TR/wai-aria/) 16 | 17 | Informative Documents: 18 | 19 | - [W3C Understanding WCAG 2.2](https://www.w3.org/WAI/WCAG22/Understanding/) 20 | - [W3C Using ARIA](https://www.w3.org/TR/using-aria/) 21 | - [W3C WAI-ARIA Authoring Practices Guide (accessible design patterns)](https://www.w3.org/WAI/ARIA/apg/) 22 | - [W3C Introduction to ATAG](https://www.w3.org/WAI/standards-guidelines/atag) 23 | 24 | ## About WCAG A, AA, and AAA Conformance Levels 25 | 26 | The WordPress commitment is to conform to all WCAG 2.2 Level A and Level AA guidelines. Conformance to level AAA success criteria is encouraged where relevant, as is exceeding the accessibility of any of these guidelines. 27 | 28 | **Level A** success criteria address concerns considered to be accessibility barriers on a very wide scale that will prevent many people from accessing the site and the minimum set of accomplished goals required for the majority of web-based interfaces. 29 | 30 | **Level AA** success criteria address concerns that are generally somewhat more complicated to address and may impact smaller groups of people, but are still common needs with broad reach. 31 | 32 | **Level AAA** success criteria are mostly targeted at very specific needs and may be quite difficult to implement effectively. 33 | 34 | [W3C Quick Reference to WCAG 2.2 Level A and Level AA Requirements](https://www.w3.org/WAI/WCAG22/quickref/?versions=2.2¤tsidebar=%23col_customize&levels=aaa) 35 | 36 | ## Applying WCAG Conformance Levels 37 | 38 | WCAG 2.2 consists of 4 layers: 39 | 40 | - Principles 41 | - Guidance 42 | - Success criteria 43 | - Sufficient and advisory techniques 44 | 45 | ### Principles 46 | 47 | When applying WCAG 2.2, the guidance and success criteria are organized around 4 principles. These principles place emphasis on how people interact with content and must be: 48 | 49 | - **Perceivable** - interacting with the content using the medium that they are familiar with. For example, providing text alternatives for those who are blind. 50 | - **Operable** - finding and using content is accessible. For example, being able to use a keyboard or a screen reader. 51 | - **Understandable** - content uses clear language and is understandable. For example, use meaningful labels, explain all abbreviations. 52 | - **Robust** - content can be interpreted in a range of ways. For example, assistive technologies are able to interpret and parse content. 53 | 54 | ### Guidance 55 | 56 | Each principle is supported by a list of guidelines to ensure that content is more accessible and presentable across the different devices that meet a user’s disability. The guidelines are listed below, the full detail can be found in the WCAG 2.2. 57 | 58 | #### Principle: Perceivable 59 | 60 | **Guideline 1.1 Text Alternatives** 61 | Provide text alternatives for any non-text content so that it can be changed into other forms people need, such as large print, braille, speech, symbols or simpler language. 62 | 63 | **Guideline 1.2 Time-based Media** 64 | Provide alternatives for time-based media. For example, include captions and transcripts for audio or video clips. 65 | 66 | **Guideline 1.3 Adaptable** 67 | Create content that can be presented in different ways (for example simpler layout) without losing information or structure. 68 | 69 | **Guideline 1.4 Distinguishable** 70 | Make it easier for users to see and hear content including separating foreground from background. 71 | 72 | #### Principle: Operable 73 | 74 | **Guideline 2.1 Keyboard Accessible** 75 | Make all functionality available from a keyboard. 76 | 77 | **Guideline 2.2 Enough Time** 78 | Provide users enough time to read and use content. 79 | 80 | **Guideline 2.3 Seizures and Physical Reactions** 81 | Do not design content in a way that is known to cause seizures or physical reactions. 82 | 83 | **Guideline 2.4 Navigable** 84 | Provide ways to help users navigate, find content, and determine where they are. 85 | 86 | **Guideline 2.5 Input Modalities** 87 | Make it easier for users to operate functionality through various inputs beyond keyboard. 88 | 89 | #### Principle: Understandable 90 | 91 | **Guideline 3.1 Readable** 92 | Make text content readable and understandable. 93 | 94 | **Guideline 3.2 Predictable** 95 | Make Web pages appear and operate in predictable ways. 96 | 97 | **Guideline 3.3 Input Assistance** 98 | Help users avoid and correct mistakes. 99 | 100 | #### Principle: Robust 101 | 102 | **Guideline 4.1 Compatible** 103 | Maximize compatibility with current and future user agents, including assistive technologies. 104 | 105 | ### Success Criteria 106 | 107 | Each guidance has a [specific list requirements that must be met for your content to be accessible](https://www.w3.org/WAI/WCAG21/quickref/). These tests can be carried out using automated software and or human testers. You can find more information on how to meet the success criteria in [Understanding Levels of Conformance](https://www.w3.org/WAI/WCAG21/Understanding/conformance#levels). Whilst these criteria are important, usability testing is still important and should be carried out alongside any accessibility testing. 108 | 109 | ### Techniques: Sufficient, Advisory, and Failures 110 | 111 | Techniques (code examples, resources, and tests) for guidance and success criteria that can help in making content more accessible, are divided into three categories: 112 | 113 | - Sufficient - required and help meet the success criteria 114 | - Advisory - suggestions and go beyond what is required 115 | - Failures - cause problems and fail to meet the success criteria 116 | 117 | For more information on techniques, visit [Understanding Techniques for WCAG Success Criteria](https://www.w3.org/WAI/WCAG21/Understanding/understanding-techniques). 118 | 119 | ## Authoritative Resources 120 | 121 | - [WebAIM: Web Accessibility In Mind](https://webaim.org/) (see Articles and Resources) 122 | - [UK Government Digital Service](https://gds.blog.gov.uk) 123 | - [Accessibility in Government Blog (UK)](https://accessibility.blog.gov.uk/) 124 | - [Create Accessible Software & Websites - Section 508 (US)](https://www.section508.gov/develop/software-websites/) 125 | - [Blog | TPGi](https://www.tpgi.com/blog/) 126 | - [Web Accessibility Blog (Deque)](https://www.deque.com/blog/) 127 | - [Tink - Léonie Watson](https://tink.uk) (Léonie Watson) 128 | - [Adrian Roselli](https://adrianroselli.com) 129 | - [Scott O'Hara](https://www.scottohara.me) 130 | - [Joe Dolson](https://www.joedolson.com/blog) 131 | - [Sarah Higley](https://sarahmhigley.com/) 132 | - [Marco's Accessibility Blog](https://www.marcozehe.de/) 133 | - [Karl Groves](https://karlgroves.com/) 134 | - [Inclusive Components](https://inclusive-components.design) (Heydon Pickering) 135 | - [Accessibility London (London, United Kingdom)](https://www.meetup.com/London-Accessibility-Meetup/) (London accessibility meetup: they live stream meetups on youtube) 136 | - [24 Accessibility](https://www.24a11y.com/) 137 | - [Mozilla Accessibility - Users first, no matter their abilities](https://blog.mozilla.org/accessibility/) 138 | - [WordPress Accessibility Meetup](https://www.meetup.com/wordpress-accessibility-meetup-group/) 139 | - [Equalize Digital Blog](https://equalizedigital.com/resources/) 140 | - [WordPress Accessibility Day Conference](https://wpaccessibility.day) 141 | 142 | ### Technical and / or specific topics 143 | 144 | - [Accessibility Support](https://a11ysupport.io/) (Will your code work with assistive technologies?) 145 | - [Accessibility APIs: A Key To Web Accessibility](https://www.smashingmagazine.com/2015/03/web-accessibility-with-accessibility-api/) (by Léonie Watson) 146 | - [How accessibility trees inform assistive tech](https://hacks.mozilla.org/2019/06/how-accessibility-trees-inform-assistive-tech/) (by Hidde de Vries) 147 | - [What is this thing and what does it do?](https://www.youtube.com/watch?v=YLihNhn_MO4 ) (presentation by Karl Groves) 148 | - [The Browser Accessibility Tree](https://www.tpgi.com/the-browser-accessibility-tree/) (by Steve Faulkner) 149 | - [Brief history of browser accessibility support](https://www.tpgi.com/brief-history-of-browser-accessibility-support/) (by Steve Faulkner) 150 | - [ARIA Landmarks Example: General Principles](https://www.w3.org/TR/wai-aria-practices/examples/landmarks/) 151 | - [ARIA Landmarks Example: HTML Sectioning Elements](https://www.w3.org/TR/wai-aria-practices/examples/landmarks/HTML5.html) 152 | - [Mozilla Developer Docs - Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility) 153 | -------------------------------------------------------------------------------- /wordpress-coding-standards/css.md: -------------------------------------------------------------------------------- 1 | # CSS Coding Standards 2 | 3 | Like any coding standard, the purpose of the WordPress CSS Coding Standards is to create a baseline for collaboration and review within various aspects of the WordPress open source project and community, from core code to themes to plugins. Files within a project should appear as though created by a single entity. Above all else, create code that is readable, meaningful, consistent, and beautiful. 4 | 5 | Within core stylesheets, inconsistencies will often be found. We are working on addressing these and make every effort to have patches and commits from this point forward follow the CSS coding standards. More information on the above and contributing to UI/front-end development will be forthcoming in a separate set of guidelines. 6 | 7 | ## Structure 8 | 9 | There are plenty of different methods for structuring a stylesheet. With the CSS in core, it is important to retain a high degree of legibility. This enables subsequent contributors to have a clear understanding of the flow of the document. 10 | 11 | - Use tabs, not spaces, to indent each property. 12 | - Add two blank lines between sections and one blank line between blocks in a section. 13 | - Each selector should be on its own line, ending in either a comma or an opening curly brace. Property-value pairs should be on their own line, with one tab of indentation and an ending semicolon. The closing brace should be flush left, using the same level of indentation as the opening selector. 14 | 15 | Correct: 16 | 17 | ```css 18 | #selector-1, 19 | #selector-2, 20 | #selector-3 { 21 | background: #fff; 22 | color: #000; 23 | } 24 | ``` 25 | 26 | Incorrect: 27 | 28 | ```css 29 | #selector-1, #selector-2, #selector-3 { 30 | background: #fff; 31 | color: #000; 32 | } 33 | 34 | #selector-1 { background: #fff; color: #000; } 35 | ``` 36 | 37 | ## Selectors 38 | 39 | With specificity, comes great responsibility. Broad selectors allow us to be efficient, yet can have adverse consequences if not tested. Location-specific selectors can save us time, but will quickly lead to a cluttered stylesheet. Exercise your best judgment to create selectors that find the right balance between contributing to the overall style and layout of the DOM. 40 | 41 | - Similar to the [WordPress PHP Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#naming-conventions) for file names, use lowercase and separate words with hyphens when naming selectors. Avoid camelcase and underscores. 42 | - Use human readable selectors that describe what element(s) they style. 43 | - Attribute selectors should use double quotes around values. 44 | - Refrain from using over-qualified selectors, `div.container` can simply be stated as `.container`. 45 | 46 | Correct: 47 | 48 | ```css 49 | #comment-form { 50 | margin: 1em 0; 51 | } 52 | 53 | input[type="text"] { 54 | line-height: 1.1; 55 | } 56 | ``` 57 | 58 | Incorrect: 59 | 60 | ```css 61 | #commentForm { /&042; Avoid camelcase. &042;/ 62 | margin: 0; 63 | } 64 | 65 | #comment_form { /&042; Avoid underscores. &042;/ 66 | margin: 0; 67 | } 68 | 69 | div#comment_form { /&042; Avoid over-qualification. &042;/ 70 | margin: 0; 71 | } 72 | 73 | #c1-xr { /&042; What is a c1-xr?! Use a better name. &042;/ 74 | margin: 0; 75 | } 76 | 77 | input[type=text] { /&042; Should be [type="text"] &042;/ 78 | line-height: 110% /&042; Also doubly incorrect &042;/ 79 | } 80 | ``` 81 | 82 | ## Properties 83 | 84 | Similar to selectors, properties that are too specific will hinder the flexibility of the design. Less is more. Make sure you are not repeating styling or introducing fixed dimensions (when a fluid solution is more acceptable). 85 | 86 | - Properties should be followed by a colon and a space. 87 | - All properties and values should be lowercase, except for font names and vendor-specific properties. 88 | - Use hex code for colors, or `rgba()` if opacity is needed. Avoid RGB format and uppercase, and shorten values when possible: `#fff` instead of `#FFFFFF`. 89 | - Use shorthand, except when overriding styles, for `background`, `border`, `font`, `list-style`, `margin`, and `padding` values as much as possible. For a shorthand reference, see [CSS Shorthand](https://codex.wordpress.org/CSS_Shorthand). 90 | 91 | Correct: 92 | 93 | ```css 94 | #selector-1 { 95 | background: #fff; 96 | display: block; 97 | margin: 0; 98 | margin-left: 20px; 99 | } 100 | ``` 101 | 102 | Incorrect: 103 | 104 | ```css 105 | #selector-1 { 106 | background:#FFFFFF; 107 | display: BLOCK; 108 | margin-left: 20PX; 109 | margin: 0; 110 | } 111 | ``` 112 | 113 | ### Property Ordering 114 | 115 | > "Group like properties together, especially if you have a lot of them." 116 | > -- Nacin 117 | 118 | Above all else, choose something that is meaningful to you and semantic in some way. Random ordering is chaos, not poetry. In WordPress Core, our choice is logical or grouped ordering, wherein properties are grouped by meaning and ordered specifically within those groups. The properties within groups are also strategically ordered to create transitions between sections, such as `background` directly before `color`. The baseline for ordering is: 119 | 120 | - Display 121 | - Positioning 122 | - Box model 123 | - Colors and Typography 124 | - Other 125 | 126 | Things that are not yet used in core itself, such as CSS3 animations, may not have a prescribed place above but likely would fit into one of the above in a logical manner. Just as CSS is evolving, so our standards will evolve with it. 127 | 128 | Top/Right/Bottom/Left (TRBL/trouble) should be the order for any relevant properties (e.g. `margin`), much as the order goes in values. Corner specifiers (e.g. `border-radius-*-*`) should be ordered as top-left, top-right, bottom-right, bottom-left. This is derived from how shorthand values would be ordered. 129 | 130 | Example: 131 | 132 | ```css 133 | #overlay { 134 | position: absolute; 135 | z-index: 1; 136 | padding: 10px; 137 | background: #fff; 138 | color: #777; 139 | } 140 | ``` 141 | 142 | Another method that is often used, including by the Automattic/WordPress.com Themes Team, is to order properties alphabetically, with or without certain exceptions. 143 | 144 | Example: 145 | 146 | ```css 147 | #overlay { 148 | background: #fff; 149 | color: #777; 150 | padding: 10px; 151 | position: absolute; 152 | z-index: 1; 153 | } 154 | ``` 155 | 156 | ### Vendor Prefixes 157 | 158 | Updated on 2014-02-13, after [[27174](https://core.trac.wordpress.org/changeset/27174)]: 159 | 160 | We use [Autoprefixer](https://github.com/postcss/autoprefixer) as a pre-commit tool to easily manage necessary browser prefixes, thus making the majority of this section moot. For those interested in following that output without using Grunt, vendor prefixes should go longest (-webkit-) to shortest (unprefixed). All other spacing remains as per the rest of the standards. 161 | 162 | ```css 163 | .sample-output { 164 | -webkit-box-shadow: inset 0 0 1px 1px #eee; 165 | -moz-box-shadow: inset 0 0 1px 1px #eee; 166 | box-shadow: inset 0 0 1px 1px #eee; 167 | } 168 | ``` 169 | 170 | ## Values 171 | 172 | There are numerous ways to input values for properties. Follow the guidelines below to help us retain a high degree of consistency. 173 | 174 | - Space before the value, after the colon. 175 | - Do not pad parentheses with spaces. 176 | - Always end in a semicolon. 177 | - Use double quotes rather than single quotes, and only when needed, such as when a font name has a space or for the values of the `content` property. 178 | - Font weights should be defined using numeric values (e.g. `400` instead of `normal`, `700` rather than `bold`). 179 | - 0 values should not have units unless necessary, such as with `transition-duration`. 180 | - Line height should also be unit-less, unless necessary to be defined as a specific pixel value. This is more than just a style convention, but is worth mentioning here. More information: . 181 | - Use a leading zero for decimal values, including in `rgba()`. 182 | - Multiple comma-separated values for one property should be separated by either a space or a newline. For better readability newlines should be used for lengthier multi-part values such as those for shorthand properties like `box-shadow` and `text-shadow`, including before the first value. Values should then be indented one level in from the property. 183 | - Lists of values within a value, like within `rgba()`, should be separated by a space. 184 | 185 | Correct: 186 | 187 | ```css 188 | .class { /&042; Correct usage of quotes &042;/ 189 | background-image: url(images/bg.png); 190 | font-family: "Helvetica Neue", sans-serif; 191 | font-weight: 700; 192 | } 193 | 194 | .class { /&042; Correct usage of zero values &042;/ 195 | font-family: Georgia, serif; 196 | line-height: 1.4; 197 | text-shadow: 198 | 0 -1px 0 rgba(0, 0, 0, 0.5), 199 | 0 1px 0 #fff; 200 | } 201 | 202 | .class { /&042; Correct usage of short and lengthier multi-part values &042;/ 203 | font-family: Consolas, Monaco, monospace; 204 | transition-property: opacity, background, color; 205 | box-shadow: 206 | 0 0 0 1px #5b9dd9, 207 | 0 0 2px 1px rgba(30, 140, 190, 0.8); 208 | } 209 | ``` 210 | 211 | Incorrect: 212 | 213 | ```css 214 | .class { /&042; Avoid missing space and semicolon &042;/ 215 | background:#fff 216 | } 217 | 218 | .class { /&042; Avoid adding a unit on a zero value &042;/ 219 | margin: 0px 0px 20px 0px; 220 | } 221 | 222 | .class { 223 | font-family: Times New Roman, serif; /&042; Quote font names when required &042;/ 224 | font-weight: bold; /&042; Avoid named font weights &042;/ 225 | line-height: 1.4em; /&042; Avoid adding a unit for line height &042;/ 226 | } 227 | 228 | .class { /&042; Incorrect usage of multi-part values &042;/ 229 | text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5), 230 | 0 1px 0 #fff; 231 | box-shadow: 0 1px 0 rgba(0, 0, 232 | 0, 0.5), 233 | 0 1px 0 rgba(0,0,0,0.5); 234 | } 235 | ``` 236 | 237 | ## Media Queries 238 | 239 | Media queries allow us to gracefully degrade the DOM for different screen sizes. If you are adding any, be sure to test above and below the break-point you are targeting. 240 | 241 | - It is generally advisable to keep media queries grouped by media at the bottom of the stylesheet. 242 | - An exception is made for the `wp-admin.css` file in core, as it is very large and each section essentially represents a stylesheet of its own. Media queries are therefore added at the bottom of sections as applicable. 243 | - Rule sets for media queries should be indented one level in. 244 | 245 | Example: 246 | 247 | ```css 248 | @media all and (max-width: 699px) and (min-width: 520px) { 249 | /&042; Your selectors &042;/ 250 | } 251 | ``` 252 | 253 | ## Commenting 254 | 255 | - Comment, and comment liberally. If there are concerns about file size, utilize minified files and the `SCRIPT_DEBUG` constant. Long comments should manually break the line length at 80 characters. 256 | - A table of contents should be utilized for longer stylesheets, especially those that are highly sectioned. Using an index number (`1.0`, `1.1`, `2.0`, etc.) aids in searching and jumping to a location. 257 | - Comments should be formatted much as PHPDoc is. The [CSSDoc](https://web.archive.org/web/20070601200419/http://cssdoc.net/) standard is not necessarily widely accepted or used but some aspects of it may be adopted over time. Section/subsection headers should have newlines before and after. Inline comments should not have empty newlines separating the comment from the item to which it relates. 258 | 259 | For sections and subsections: 260 | 261 | ```css 262 | /** 263 | * #.# Section title 264 | * 265 | * Description of section, whether or not it has media queries, etc. 266 | */ 267 | 268 | .selector { 269 | float: left; 270 | } 271 | ``` 272 | 273 | For inline: 274 | 275 | ```css 276 | /* This is a comment about this selector */ 277 | .another-selector { 278 | position: absolute; 279 | top: 0 !important; /* I should explain why this is so !important */ 280 | } 281 | ``` 282 | 283 | ## Best Practices 284 | 285 | Stylesheets tend to grow in length and complexity, and as they grow the chance of redundancy increases. By following some best practices we can help our CSS maintain focus and flexibility as it evolves: 286 | 287 | - If you are attempting to fix an issue, attempt to remove code before adding more. 288 | - Magic Numbers are unlucky. These are numbers that are used as quick fixes on a one-off basis. Example: `.box { margin-top: 37px }`. 289 | - DOM will change over time, target the element you want to use as opposed to "finding it" through its parents. Example: Use `.highlight` on the element as opposed to `.highlight a` (where the selector is on the parent) 290 | - Know when to use the `height` property. It should be used when you are including outside elements (such as images). Otherwise use `line-height` for more flexibility. 291 | - Do not restate default property and value combinations (for instance `display: block;` on block-level elements). 292 | 293 | ### WP Admin CSS 294 | 295 | Check out the [WP Admin CSS Audit](https://wordpress.github.io/css-audit/public/wp-admin), a report generated to document the health of the WP Admin CSS code. Read more in [the repository's README](https://github.com/WordPress/css-audit/blob/trunk/README.md). 296 | 297 | ## Related Links 298 | 299 | - Principles of writing consistent, idiomatic CSS: [https://github.com/necolas/idiomatic-css](https://github.com/necolas/idiomatic-css). 300 | -------------------------------------------------------------------------------- /wordpress-coding-standards/html.md: -------------------------------------------------------------------------------- 1 | # HTML Coding Standards 2 | 3 | ## HTML 4 | 5 | ### Validation 6 | 7 | All HTML pages should be verified against [the W3C validator](https://validator.w3.org/) to ensure that the markup is well formed. This in and of itself is not directly indicative of good code, but it helps to weed out problems that are able to be tested via automation. It is no substitute for manual code review. (For other validators, see [HTML Validation](https://codex.wordpress.org/Validating_a_Website#HTML_-_Validation) in the Codex.) 8 | 9 | ### Self-closing Elements 10 | 11 | All tags must be properly closed. For tags that can wrap nodes such as text or other elements, termination is a trivial enough task. For tags that are self-closing, the forward slash should have exactly one space preceding it: 12 | 13 | ```html 14 |
15 | ``` 16 | 17 | rather than the compact but incorrect: 18 | 19 | ```html 20 |
21 | ``` 22 | 23 | The W3C specifies that a single space should precede the self-closing slash ([source](https://w3.org/TR/xhtml1/#C_2)). 24 | 25 | ### Attributes and Tags 26 | 27 | All tags and attributes must be written in lowercase. Additionally, attribute values should be lowercase when the purpose of the text therein is only to be interpreted by machines. For instances in which the data needs to be human readable, proper title capitalization should be followed. 28 | 29 | For machines: 30 | 31 | ```html 32 | 33 | ``` 34 | 35 | For humans: 36 | 37 | ```html 38 | Example.com 39 | ``` 40 | 41 | ### Quotes 42 | 43 | According to the W3C specifications for XHTML, all attributes must have a value, and must use double- or single-quotes ([source](https://www.w3.org/TR/xhtml1/#h-4.4)). The following are examples of proper and improper usage of quotes and attribute/value pairs. 44 | 45 | Correct: 46 | 47 | ```html 48 | 49 | 50 | ``` 51 | 52 | Incorrect: 53 | 54 | ```html 55 | 56 | ``` 57 | 58 | In HTML, attributes do not all have to have values, and attribute values do not always have to be quoted. While all of the examples above are valid HTML, _failing to quote attributes can lead to security vulnerabilities_. Always quote attributes. Omitting the value on boolean attributes is allowed. The values `true` and `false` are not valid on boolean attributes ([HTML5 source](https://www.w3.org/TR/2011/WD-html5-20110405/common-microsyntaxes.html#boolean-attributes)). 59 | 60 | Correct: 61 | 62 | ```html 63 | 64 | ``` 65 | 66 | Incorrect: 67 | 68 | ```html 69 | 70 | ``` 71 | 72 | ### Indentation 73 | 74 | As with PHP, HTML indentation should always reflect logical structure. Use tabs and not spaces. 75 | 76 | When mixing PHP and HTML together, indent PHP blocks to match the surrounding HTML code. Closing PHP blocks should match the same indentation level as the opening block. 77 | 78 | Correct: 79 | 80 | ```php 81 | 82 |
83 |

Not Found

84 |
85 |

Apologies, but no results were found.

86 | 87 |
88 |
89 | 90 | ``` 91 | 92 | Incorrect: 93 | 94 | ```php 95 | 96 |
97 |

Not Found

98 |
99 |

Apologies, but no results were found.

100 | 101 |
102 |
103 | 104 | ``` 105 | 106 | ## Credits 107 | 108 | - HTML code standards adapted from [Fellowship Tech Code Standards](https://developer.fellowshipone.com/patterns/code.php) ([CC license](https://creativecommons.org/licenses/by-nc-sa/3.0/)). 109 | -------------------------------------------------------------------------------- /wordpress-coding-standards/javascript.md: -------------------------------------------------------------------------------- 1 | # JavaScript Coding Standards 2 | 3 | JavaScript has become a critical component in developing WordPress-based applications (themes and plugins) as well as WordPress core. Standards are needed for formatting and styling JavaScript code to maintain the same code consistency as the WordPress standards provide for core PHP, HTML, and CSS code. 4 | 5 | > All code in any code-base should look like a single person typed it, no matter how many people contributed. - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwaldron/idiomatic.js/) 6 | 7 | The WordPress JavaScript Coding Standards are adapted from the [jQuery JavaScript Style Guide](https://contribute.jquery.org/style-guide/js). Our standard differs from the jQuery guidelines in the following ways: 8 | 9 | - WordPress uses single quotation marks for string declarations. 10 | - Case statements are indented within switch blocks. 11 | - Function contents are consistently indented, including full-file closure wrappers. 12 | - Some whitespace rules differ, for consistency with the WordPress PHP coding standards. 13 | - jQuery’s 100-character hard line limit is encouraged, but not strictly enforced. 14 | 15 | Many of the examples below have been adapted directly from the jQuery style guide; these differences have all been integrated into the examples on this page. Any of the below standards and examples should be considered best practice for WordPress code, unless explicitly noted as anti-patterns. 16 | 17 | ## Code Refactoring 18 | 19 | > "[Code refactoring should not be done just because we can.](https://make.wordpress.org/core/2011/03/23/code-refactoring/)" - Lead Developer Andrew Nacin 20 | 21 | Many parts of the WordPress code structure for JavaScript are inconsistent in their style. WordPress is working to gradually improve this, so the code will be clean and easy to read at a glance. 22 | 23 | While the coding standards are important, refactoring older .js files simply to conform to the standards is not an urgent issue. "Whitespace-only" patches for older files are strongly discouraged. 24 | 25 | All new or updated JavaScript code will be reviewed to ensure it conforms to the standards, and passes JSHint. 26 | 27 | ## Spacing 28 | 29 | Use spaces liberally throughout your code. "When in doubt, space it out." 30 | 31 | These rules encourage liberal spacing for improved developer readability. The minification process creates a file that is optimized for browsers to read and process. 32 | 33 | - Indentation with tabs. 34 | - No whitespace at the end of line or on blank lines. 35 | - Lines should usually be no longer than 80 characters, and should not exceed 100 (counting tabs as 4 spaces). _This is a "soft" rule, but long lines generally indicate unreadable or disorganized code._ 36 | - `if`/`else`/`for`/`while`/`try` blocks should always use braces, and always go on multiple lines. 37 | - Unary special-character operators (e.g., `++`, `--`) must not have space next to their operand. 38 | - Any `,` and `;` must not have preceding space. 39 | - Any `;` used as a statement terminator must be at the end of the line. 40 | - Any `:` after a property name in an object definition must not have preceding space. 41 | - The `?` and `:` in a ternary conditional must have space on both sides. 42 | - No filler spaces in empty constructs (e.g., `{}`, `[]`, `fn()`). 43 | - There should be a new line at the end of each file. 44 | - Any `!` negation operator should have a following space.* 45 | - All function bodies are indented by one tab, even if the entire file is wrapped in a closure.* 46 | - Spaces may align code within documentation blocks or within a line, but only tabs should be used at the start of a line.* 47 | 48 | *: The WordPress JavaScript standards prefer slightly broader whitespace rules than the jQuery style guide. These deviations are for consistency between the PHP and JavaScript files in the WordPress codebase. 49 | 50 | Whitespace can easily accumulate at the end of a line – avoid this, as trailing whitespace is caught as an error in JSHint. One way to catch whitespace buildup is enabling visible whitespace characters within your text editor. 51 | 52 | ### Object Declarations 53 | 54 | Object declarations can be made on a single line if they are short (remember the line length guidelines). When an object declaration is too long to fit on one line, there must be one property per line and each line ended by a comma. Property names only need to be quoted if they are reserved words or contain special characters: 55 | 56 | Arrays can be declared on a single line if they are short (remember the line length guidelines). When an array is too long to fit on one line, each member must be placed on its own line and each line ended by a comma. 57 | 58 | ```javascript 59 | // Preferred 60 | var obj = { 61 | ready: 9, 62 | when: 4, 63 | 'you are': 15, 64 | }; 65 | var arr = [ 66 | 9, 67 | 4, 68 | 15, 69 | ]; 70 | 71 | // Acceptable for small objects and arrays 72 | var obj = { ready: 9, when: 4, 'you are': 15 }; 73 | var arr = [ 9, 4, 15 ]; 74 | 75 | // Bad 76 | var obj = { ready: 9, 77 | when: 4, 'you are': 15 }; 78 | var arr = [ 9, 79 | 4, 15 ]; 80 | ``` 81 | 82 | ### Arrays and Function Calls 83 | 84 | Always include extra spaces around elements and arguments: 85 | 86 | ```javascript 87 | array = [ a, b ]; 88 | 89 | foo( arg ); 90 | 91 | foo( 'string', object ); 92 | 93 | foo( options, object[ property ] ); 94 | 95 | foo( node, 'property', 2 ); 96 | 97 | prop = object[ 'default' ]; 98 | 99 | firstArrayElement = arr[ 0 ]; 100 | ``` 101 | 102 | ### Examples of Good Spacing 103 | 104 | ```javascript 105 | var i; 106 | 107 | if ( condition ) { 108 | doSomething( 'with a string' ); 109 | } else if ( otherCondition ) { 110 | otherThing( { 111 | key: value, 112 | otherKey: otherValue 113 | } ); 114 | } else { 115 | somethingElse( true ); 116 | } 117 | 118 | // Unlike jQuery, WordPress prefers a space after the ! negation operator. 119 | // This is also done to conform to our PHP standards. 120 | while ( ! condition ) { 121 | iterating++; 122 | } 123 | 124 | for ( i = 0; i < 100; i++ ) { 125 | object[ array[ i ] ] = someFn( i ); 126 | $( '.container' ).val( array[ i ] ); 127 | } 128 | 129 | try { 130 | // Expressions 131 | } catch ( e ) { 132 | // Expressions 133 | } 134 | ``` 135 | 136 | ## Semicolons 137 | 138 | Use them. Never rely on Automatic Semicolon Insertion (ASI). 139 | 140 | ## Indentation and Line Breaks 141 | 142 | Indentation and line breaks add readability to complex statements. 143 | 144 | Tabs should be used for indentation. Even if the entire file is contained in a closure (i.e., an immediately invoked function), the contents of that function should be indented by one tab: 145 | 146 | ```javascript 147 | ( function ( $ ) { 148 | // Expressions indented 149 | 150 | function doSomething() { 151 | // Expressions indented 152 | } 153 | } )( jQuery ); 154 | ``` 155 | 156 | ### Blocks and Curly Braces 157 | 158 | `if`, `else`, `for`, `while`, and `try` blocks should always use braces, and always go on multiple lines. The opening brace should be on the same line as the function definition, the conditional, or the loop. The closing brace should be on the line directly following the last statement of the block. 159 | 160 | ```javascript 161 | var a, b, c; 162 | 163 | if ( myFunction() ) { 164 | // Expressions 165 | } else if ( ( a && b ) || c ) { 166 | // Expressions 167 | } else { 168 | // Expressions 169 | } 170 | ``` 171 | 172 | ### Multi-line Statements 173 | 174 | When a statement is too long to fit on one line, line breaks must occur after an operator. 175 | 176 | ```javascript 177 | // Bad 178 | var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c 179 | + ' is ' + ( a + b + c ) + '</p>'; 180 | 181 | // Good 182 | var html = '<p>The sum of ' + a + ' and ' + b + ' plus ' + c + 183 | ' is ' + ( a + b + c ) + '</p>'; 184 | ``` 185 | 186 | Lines should be broken into logical groups if it improves readability, such as splitting each expression of a ternary operator onto its own line, even if both will fit on a single line. 187 | 188 | ```javascript 189 | // Acceptable 190 | var baz = ( true === conditionalStatement() ) ? 'thing 1' : 'thing 2'; 191 | 192 | // Better 193 | var baz = firstCondition( foo ) && secondCondition( bar ) ? 194 | qux( foo, bar ) : 195 | foo; 196 | ``` 197 | 198 | When a conditional is too long to fit on one line, each operand of a logical operator in the boolean expression must appear on its own line, indented one extra level from the opening and closing parentheses. 199 | 200 | ```javascript 201 | if ( 202 | firstCondition() && 203 | secondCondition() && 204 | thirdCondition() 205 | ) { 206 | doStuff(); 207 | } 208 | ``` 209 | 210 | ### Chained Method Calls 211 | 212 | When a chain of method calls is too long to fit on one line, there must be one call per line, with the first call on a separate line from the object the methods are called on. If the method changes the context, an extra level of indentation must be used. 213 | 214 | ```javascript 215 | elements 216 | .addClass( 'foo' ) 217 | .children() 218 | .html( 'hello' ) 219 | .end() 220 | .appendTo( 'body' ); 221 | ``` 222 | 223 | ## Assignments and Globals 224 | 225 | ### Declaring Variables with `const` and `let` 226 | 227 | For code written using ES2015 or newer, `const` and `let` should always be used in place of `var`. A declaration should use `const` unless its value will be reassigned, in which case `let` is appropriate. 228 | 229 | Unlike `var`, it is not necessary to declare all variables at the top of a function. Instead, they are to be declared at the point at which they are first used. 230 | 231 | ### Declaring Variables With `var` 232 | 233 | Each function should begin with a single comma-delimited `var` statement that declares any local variables necessary. If a function does not declare a variable using `var`, that variable can leak into an outer scope (which is frequently the global scope, a worst-case scenario), and can unwittingly refer to and modify that data. 234 | 235 | Assignments within the `var` statement should be listed on individual lines, while declarations can be grouped on a single line. Any additional lines should be indented with an additional tab. Objects and functions that occupy more than a handful of lines should be assigned outside of the `var` statement, to avoid over-indentation. 236 | 237 | ```javascript 238 | // Good 239 | var k, m, length, 240 | // Indent subsequent lines by one tab 241 | value = 'WordPress'; 242 | 243 | // Bad 244 | var foo = true; 245 | var bar = false; 246 | var a; 247 | var b; 248 | var c; 249 | ``` 250 | 251 | ### Globals 252 | 253 | In the past, WordPress core made heavier use of global variables. Since core JavaScript files are sometimes used within plugins, existing globals should not be removed. 254 | 255 | All globals used within a file should be documented at the top of that file. Multiple globals can be comma-separated. 256 | 257 | This example would make `passwordStrength` an allowed global variable within that file: 258 | 259 | ```javascript 260 | /* global passwordStrength:true */ 261 | ``` 262 | 263 | The "true" after `passwordStrength` means that this global is being defined within this file. If you are accessing a global which is defined elsewhere, omit `:true` to designate the global as read-only. 264 | 265 | ### Common Libraries 266 | 267 | Backbone, jQuery, Underscore, and the global `wp` object are all registered as allowed globals in the root `.jshintrc` file. 268 | 269 | Backbone and Underscore may be accessed directly at any time. jQuery should be accessed through `$` by passing the `jQuery` object into an anonymous function: 270 | 271 | ```javascript 272 | ( function ( $ ) { 273 | // Expressions 274 | } )( jQuery ); 275 | ``` 276 | 277 | This will negate the need to call `.noConflict()`, or to set `$` using another variable. 278 | 279 | Files which add to, or modify, the `wp` object must safely access the global to avoid overwriting previously set properties: 280 | 281 | ```javascript 282 | // At the top of the file, set "wp" to its existing value (if present) 283 | window.wp = window.wp || {}; 284 | ``` 285 | 286 | ## Naming Conventions 287 | 288 | Variable and function names should be full words, using camel case with a lowercase first letter. This is an area where this standard differs from the [WordPress PHP coding standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#naming-conventions). 289 | 290 | Names should be descriptive, but not excessively so. Exceptions are allowed for iterators, such as the use of `i` to represent the index in a loop. 291 | 292 | ### Abbreviations and Acronyms 293 | 294 | [Acronyms](https://en.wikipedia.org/wiki/Acronym) must be written with each of its composing letters capitalized. This is intended to reflect that each letter of the acronym is a proper word in its expanded form. 295 | 296 | All other [abbreviations](https://en.wikipedia.org/wiki/Abbreviation) must be written as camel case, with an initial capitalized letter followed by lowercase letters. 297 | 298 | If an abbreviation or an acronym occurs at the start of a variable name, it must be written to respect the camelcase naming rules covering the first letter of a variable or class definition. For variable assignment, this means writing the abbreviation entirely as lowercase. For class definitions, its initial letter should be capitalized. 299 | 300 | ```javascript 301 | // "Id" is an abbreviation of "Identifier": 302 | const userId = 1; 303 | 304 | // "DOM" is an acronym of "Document Object Model": 305 | const currentDOMDocument = window.document; 306 | 307 | // Acronyms and abbreviations at the start of a variable name are consistent 308 | // with camelcase rules covering the first letter of a variable or class. 309 | const domDocument = window.document; 310 | class DOMDocument {} 311 | class IdCollection {} 312 | ``` 313 | 314 | ### Class Definitions 315 | 316 | Constructors intended for use with `new` should have a capital first letter (UpperCamelCase). 317 | 318 | A [`class` definition](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) must use the UpperCamelCase convention, regardless of whether it is intended to be used with `new` construction. 319 | 320 | ```javascript 321 | class Earth { 322 | static addHuman( human ) { 323 | Earth.humans.push( human ); 324 | } 325 | 326 | static getHumans() { 327 | return Earth.humans; 328 | } 329 | } 330 | 331 | Earth.humans = []; 332 | ``` 333 | 334 | All [`@wordpress/element`](https://www.npmjs.com/package/@wordpress/element) Components, including stateless function components, should be named using Class Definition naming rules, both for consistency and to reflect the fact that a component may need to be transitioned from a function to a class without breaking compatibility. 335 | 336 | ### Constants 337 | 338 | An exception to camel case is made for constant values which are never intended to be reassigned or mutated. Such variables must use the [SCREAMING_SNAKE_CASE convention](https://en.wikipedia.org/wiki/Snake_case#History). 339 | 340 | In almost all cases, a constant should be defined in the top-most scope of a file. It is important to note that [JavaScript’s `const` assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) is conceptually more limited than what is implied here, where a value assigned by `const` in JavaScript can in-fact be mutated, and is only protected against reassignment. A constant as defined in these coding guidelines applies only to values which are expected to never change, and is a strategy for developers to communicate intent, more than it is a technical restriction. 341 | 342 | ## Comments 343 | 344 | Comments come before the code to which they refer, and should always be preceded by a blank line. Capitalize the first letter of the comment, and include a period at the end when writing full sentences. There must be a single space between the comment token (`//`) and the comment text. 345 | 346 | ```javascript 347 | someStatement(); 348 | 349 | // Explanation of something complex on the next line 350 | $( 'p' ).doSomething(); 351 | 352 | // This is a comment that is long enough to warrant being stretched 353 | // over the span of multiple lines. 354 | ``` 355 | 356 | JSDoc comments should use the `/**` multi-line comment opening. Refer to the [JavaScript Documentation Standards](https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/javascript/#multi-line-comments) for more information. 357 | 358 | Inline comments are allowed as an exception when used to annotate special arguments in formal parameter lists: 359 | 360 | ```javascript 361 | function foo( types, selector, data, fn, /* INTERNAL */ one ) { 362 | // Do stuff 363 | } 364 | ``` 365 | 366 | ## Equality 367 | 368 | Strict equality checks (`===`) must be used in favor of abstract equality checks (`==`). 369 | 370 | ## Type Checks 371 | 372 | These are the preferred ways of checking the type of an object: 373 | 374 | - String: `typeof object === 'string'` 375 | - Number: `typeof object === 'number'` 376 | - Boolean: `typeof object === 'boolean'` 377 | - Object: `typeof object === 'object'` or `_.isObject( object )` 378 | - Plain Object: `jQuery.isPlainObject( object )` 379 | - Function: `_.isFunction( object )` or `jQuery.isFunction( object )` 380 | - Array: `_.isArray( object )` or `jQuery.isArray( object )` 381 | - Element: `object.nodeType` or `_.isElement( object )` 382 | - null: `object === null` 383 | - null or undefined: `object == null` 384 | - undefined: 385 | - Global Variables: `typeof variable === 'undefined'` 386 | - Local Variables: `variable === undefined` 387 | - Properties: `object.prop === undefined` 388 | - Any of the above: `_.isUndefined( object )` 389 | 390 | Anywhere Backbone or Underscore are already used, you are encouraged to use [Underscore.js](http://underscorejs.org/#isElement)'s type checking methods over jQuery's. 391 | 392 | ## Strings 393 | 394 | Use single-quotes for string literals: 395 | 396 | ```javascript 397 | var myStr = 'strings should be contained in single quotes'; 398 | ``` 399 | 400 | When a string contains single quotes, they need to be escaped with a backslash (`\`): 401 | 402 | ```javascript 403 | // Escape single quotes within strings: 404 | 'Note the backslash before the \'single quotes\''; 405 | ``` 406 | 407 | ## Switch Statements 408 | 409 | The usage of `switch` statements is generally discouraged, but can be useful when there are a large number of cases - especially when multiple cases can be handled by the same block, or fall-through logic (the `default` case) can be leveraged. 410 | 411 | When using `switch` statements: 412 | 413 | - Use a `break` for each case other than `default`. When allowing statements to "fall through," note that explicitly. 414 | - Indent `case` statements one tab within the `switch`. 415 | 416 | ```javascript 417 | switch ( event.keyCode ) { 418 | // ENTER and SPACE both trigger x() 419 | case $.ui.keyCode.ENTER: 420 | case $.ui.keyCode.SPACE: 421 | x(); 422 | break; 423 | case $.ui.keyCode.ESCAPE: 424 | y(); 425 | break; 426 | default: 427 | z(); 428 | } 429 | ``` 430 | 431 | It is not recommended to return a value from within a switch statement: use the `case` blocks to set values, then `return` those values at the end. 432 | 433 | ```javascript 434 | function getKeyCode( keyCode ) { 435 | var result; 436 | 437 | switch ( event.keyCode ) { 438 | case $.ui.keyCode.ENTER: 439 | case $.ui.keyCode.SPACE: 440 | result = 'commit'; 441 | break; 442 | case $.ui.keyCode.ESCAPE: 443 | result = 'exit'; 444 | break; 445 | default: 446 | result = 'default'; 447 | } 448 | 449 | return result; 450 | } 451 | ``` 452 | 453 | ## Best Practices 454 | 455 | ### Arrays 456 | 457 | Creating arrays in JavaScript should be done using the shorthand `[]` constructor rather than the `new Array()` notation. 458 | 459 | ```javascript 460 | var myArray = []; 461 | ``` 462 | 463 | You can initialize an array during construction: 464 | 465 | ```javascript 466 | var myArray = [ 1, 'WordPress', 2, 'Blog' ]; 467 | ``` 468 | 469 | In JavaScript, associative arrays are defined as objects. 470 | 471 | ### Objects 472 | 473 | There are many ways to create objects in JavaScript. Object literal notation, `{}`, is both the most performant, and also the easiest to read. 474 | 475 | ```javascript 476 | var myObj = {}; 477 | ``` 478 | 479 | Object literal notation should be used unless the object requires a specific prototype, in which case the object should be created by calling a constructor function with `new`. 480 | 481 | ```javascript 482 | var myObj = new ConstructorMethod(); 483 | ``` 484 | 485 | Object properties should be accessed via dot notation, unless the key is a variable or a string that would not be a valid identifier: 486 | 487 | ```javascript 488 | prop = object.propertyName; 489 | prop = object[ variableKey ]; 490 | prop = object['key-with-hyphens']; 491 | ``` 492 | 493 | ### Iteration 494 | 495 | When iterating over a large collection using a `for` loop, it is recommended to store the loop's max value as a variable rather than re-computing the maximum every time: 496 | 497 | ```javascript 498 | // Good & Efficient 499 | var i, max; 500 | 501 | // getItemCount() gets called once 502 | for ( i = 0, max = getItemCount(); i < max; i++ ) { 503 | // Do stuff 504 | } 505 | 506 | // Bad & Potentially Inefficient: 507 | // getItemCount() gets called every time 508 | for ( i = 0; i < getItemCount(); i++ ) { 509 | // Do stuff 510 | } 511 | ``` 512 | 513 | ### Underscore.js Collection Functions 514 | 515 | Learn and understand Underscore's [collection and array methods](http://underscorejs.org/#collections). These functions, including `_.each`, `_.map`, and `_.reduce`, allow for efficient, readable transformations of large data sets. 516 | 517 | Underscore also permits jQuery-style chaining with regular JavaScript objects: 518 | 519 | ```javascript 520 | var obj = { 521 | first: 'thing 1', 522 | second: 'thing 2', 523 | third: 'lox' 524 | }; 525 | 526 | var arr = _.chain( obj ) 527 | .keys() 528 | .map( function ( key ) { 529 | return key + ' comes ' + obj[ key ]; 530 | } ) 531 | // Exit the chain 532 | .value(); 533 | 534 | // arr === [ 'first comes thing 1', 'second comes thing 2', 'third comes lox' ] 535 | ``` 536 | 537 | ### Iterating Over jQuery Collections 538 | 539 | The only time jQuery should be used for iteration is when iterating over a collection of jQuery objects: 540 | 541 | ```javascript 542 | $tabs.each( function ( index, element ) { 543 | var $element = $( element ); 544 | 545 | // Do stuff to $element 546 | } ); 547 | ``` 548 | 549 | Never use jQuery to iterate over raw data or vanilla JavaScript objects. 550 | 551 | ## JSHint 552 | 553 | [JSHint](https://jshint.com) is an automated code quality tool, designed to catch errors in your JavaScript code. JSHint is used in WordPress development to quickly verify that a patch has not introduced any logic or syntax errors to the front-end. 554 | 555 | ### Installing and Running JSHint 556 | 557 | JSHint is run using a tool called [Grunt](https://gruntjs.com/). Both JSHint and Grunt are programs written in [Node.js](https://nodejs.org/). The `package.json` configuration file that comes with the WordPress development code allows you to install and configure these tools. 558 | 559 | To install Node.js, click the Install link on the [Node.js](https://nodejs.org/) website. The correct install file for your operating system will be downloaded. Follow the installation steps for your operating system to install the program. 560 | 561 | Once Node.js is installed, open a command line window and navigate to the directory where you [checked out a copy of the WordPress SVN repository](https://make.wordpress.org/core/handbook/tutorials/installing-wordpress-locally/from-svn/) (use `cd ~/directoryname`. You should be in the root directory which contains the `package.json` file. 562 | 563 | Next, type `npm install` into the command line window. This will download and install all the Node packages used in WordPress development. 564 | 565 | You should now be able to type `npm run grunt jshint` to have Grunt check all the WordPress JavaScript files for syntax and logic errors. To only check core code, type `npm run grunt jshint:core`; to only check unit test .js files, type `npm run grunt jshint:tests`. 566 | 567 | ### JSHint Settings 568 | 569 | The configuration options used for JSHint are stored within a [`.jshintrc`](https://develop.svn.wordpress.org/trunk/.jshintrc "WordPress JSHint file in svn trunk") in the WordPress SVN repository. This file defines which errors JSHint should flag if it finds them within the WordPress source code. 570 | 571 | ### Target A Single File 572 | 573 | To specify a single file for JSHint to check, add `--file=filename.js` to the end of the command. For example, this will only check the file named "admin-bar.js" within WordPress's core JavaScript files: 574 | 575 | `npm run grunt jshint:core --file=admin-bar.js` 576 | 577 | And this would only check the "password-strength-meter.js" file within the unit tests directory: 578 | 579 | `npm run grunt jshint:tests --file=password-strength-meter.js` 580 | 581 | Limiting JSHint to a single file can be useful if you are only working on one or two specific files and don't want to wait for JSHint to process every single file each time it runs. 582 | 583 | ### JSHint Overrides: Ignore Blocks 584 | 585 | In some situations, parts of a file should be excluded from JSHint. As an example, the script file for the admin bar contains the minified code for the jQuery HoverIntent plugin - this is third-party code that should not pass through JSHint, even though it is part of a WordPress core JavaScript file. 586 | 587 | To exclude a specific file region from being processed by JSHint, enclose it in JSHint directive comments: 588 | 589 | ```javascript 590 | /* jshint ignore:start */ 591 | if ( typeof jQuery.fn.hoverIntent === 'undefined' ) { 592 | // hoverIntent r6 - Copy of wp-includes/js/hoverIntent.min.js 593 | (function(a){a.fn.hoverIntent=............... 594 | } 595 | /* jshint ignore:end */ 596 | ``` 597 | 598 | ## Credits 599 | 600 | - The jQuery examples are adapted from the [jQuery JavaScript Style Guide](https://contribute.jquery.org/style-guide/js), which is made available under the MIT license. 601 | -------------------------------------------------------------------------------- /wordpress-coding-standards/php.md: -------------------------------------------------------------------------------- 1 | # PHP Coding Standards 2 | 3 | These PHP coding standards are intended for the WordPress community as a whole. They are mandatory for WordPress Core and we encourage you to use them for your themes and plugins as well. 4 | 5 | While themes and plugins may choose to follow a different _coding style_, these **_coding standards_** are not just about _code style_, but also encompass established best practices regarding interoperability, translatability, and security in the WordPress ecosystem, so, even when using a different _code style_, we recommend you still adhere to the WordPress Coding Standards in regard to these best practices. 6 | 7 | While not all code may fully comply with these standards (yet), all newly committed and/or updated code should fully comply with these coding standards. 8 | 9 | Also see the [PHP Inline Documentation Standards](https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/) for further guidelines. 10 | 11 | If you want to automatically check your code against this standard, you can use the official [WordPress Coding Standards](https://github.com/WordPress/WordPress-Coding-Standards) tooling, which is run using [PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/). 12 | 13 | ## General 14 | 15 | ### Opening and Closing PHP Tags 16 | 17 | When embedding multi-line PHP snippets within an HTML block, the PHP open and close tags must be on a line by themselves. 18 | 19 | Correct (Multiline): 20 | 21 | ```php 22 | function foo() { 23 | ?> 24 |
25 | 33 |
34 | " /> 42 | ``` 43 | 44 | Incorrect: 45 | 46 | ```php 47 | if ( $a === $b ) { ?> 48 | 49 | 60 | 61 | ``` 62 | 63 | Incorrect: 64 | 65 | ```php 66 | 67 | 68 | ``` 69 | 70 | ### Single and Double Quotes 71 | 72 | Use single and double quotes when appropriate. If you're not evaluating anything in the string, use single quotes. You should almost never have to escape quotes in a string, because you can just alternate your quoting style, like so: 73 | 74 | ```php 75 | echo 'Link name'; 76 | echo "text with a ' single quote"; 77 | ``` 78 | 79 | Text that goes into HTML or XML attributes should be escaped so that single or double quotes do not end the attribute value and invalidate the HTML, causing a security issue. See [Data Validation](https://developer.wordpress.org/plugins/security/data-validation/) in the Plugin Handbook for further details. 80 | 81 | ### Writing require/include statements 82 | 83 | Because `require[_once]` and `include[_once]` are language constructs, they do not need parentheses around the path, so those shouldn't be used. There should only be one space between the path and the require/include keywords. 84 | 85 | It is _strongly recommended_ to use `require[_once]` for unconditional includes. When using `include[_once]`, PHP will throw a warning when the file is not found but will continue execution, which will almost certainly lead to other errors/warnings/notices being thrown if your application depends on the file loaded, potentially leading to security leaks. For that reason, `require[_once]` is generally the better choice as it will throw a `Fatal Error` if the file cannot be found. 86 | 87 | ```php 88 | // Correct. 89 | require_once ABSPATH . 'file-name.php'; 90 | 91 | // Incorrect. 92 | include_once ( ABSPATH . 'file-name.php' ); 93 | require_once __DIR__ . '/file-name.php'; 94 | ``` 95 | 96 | ## Naming 97 | 98 | ### Naming Conventions 99 | 100 | Use lowercase letters in variable, action/filter, and function names (never `camelCase`). Separate words via underscores. Don't abbreviate variable names unnecessarily; let the code be unambiguous and self-documenting. 101 | 102 | ```php 103 | function some_name( $some_variable ) {} 104 | ``` 105 | 106 | For function parameter names, it is _strongly recommended_ to avoid reserved keywords as names, as it leads to hard to read and confusing code when using the PHP 8.0 "named parameters in function calls" feature. 107 | Also keep in mind that renaming a function parameter should be considered a breaking change since PHP 8.0, so name function parameters with due care! 108 | 109 | Class, trait, interface and enum names should use capitalized words separated by underscores. Any acronyms should be all upper case. 110 | 111 | ```php 112 | class Walker_Category extends Walker {} 113 | class WP_HTTP {} 114 | 115 | interface Mailer_Interface {} 116 | trait Forbid_Dynamic_Properties {} 117 | enum Post_Status {} 118 | ``` 119 | 120 | Constants should be in all upper-case with underscores separating words: 121 | 122 | ```php 123 | define( 'DOING_AJAX', true ); 124 | ``` 125 | 126 | Files should be named descriptively using lowercase letters. Hyphens should separate words. 127 | 128 | ```php 129 | my-plugin-name.php 130 | ``` 131 | 132 | Class file names should be based on the class name with `class-` prepended and the underscores in the class name replaced with hyphens, for example, `WP_Error` becomes: 133 | 134 | ```php 135 | class-wp-error.php 136 | ``` 137 | 138 | This file-naming standard is for all current and new files with classes, except test classes. 139 | For files containing test classes, the file name should reflect the class name exactly, as per PSR4. This is to ensure cross-version [compatibility with all supported PHPUnit versions](https://github.com/sebastianbergmann/phpunit/pull/4109). 140 | 141 | Files containing template tags in the `wp-includes` directory should have `-template` appended to the end of the name so that they are obvious. 142 | 143 | ```php 144 | general-template.php 145 | ``` 146 | 147 | ### Interpolation for Naming Dynamic Hooks 148 | 149 | Dynamic hooks should be named using interpolation rather than concatenation for readability and discoverability purposes. 150 | 151 | Dynamic hooks are hooks that include dynamic values in their tag name, e.g. `{$new_status}_{$post->post_type}` (publish_post). 152 | 153 | Variables used in hook tags should be wrapped in curly braces `{` and `}`, with the complete outer tag name wrapped in double quotes. This is to ensure PHP can correctly parse the given variables' types within the interpolated string. 154 | 155 | ```php 156 | do_action( "{$new_status}_{$post->post_type}", $post->ID, $post ); 157 | ``` 158 | 159 | Where possible, dynamic values in tag names should also be as succinct and to the point as possible. `$user_id` is much more self-documenting than, say, `$this->id`. 160 | 161 | ## Whitespace 162 | 163 | ### Space Usage 164 | 165 | Always put spaces after commas, and on both sides of logical, arithmetic, comparison, string and assignment operators. 166 | 167 | ```php 168 | SOME_CONST === 23; 169 | foo() && bar(); 170 | ! $foo; 171 | array( 1, 2, 3 ); 172 | $baz . '-5'; 173 | $term .= 'X'; 174 | if ( $object instanceof Post_Type_Interface ) {} 175 | $result = 2 ** 3; // 8. 176 | ``` 177 | 178 | Put spaces on both sides of the opening and closing parentheses of control structure blocks. 179 | 180 | ```php 181 | foreach ( $foo as $bar ) { ... 182 | ``` 183 | 184 | When defining a function, do it like so: 185 | 186 | ```php 187 | function my_function( $param1 = 'foo', $param2 = 'bar' ) { ... 188 | 189 | function my_other_function() { ... 190 | ``` 191 | 192 | When calling a function, do it like so: 193 | 194 | ```php 195 | my_function( $param1, func_param( $param2 ) ); 196 | my_other_function(); 197 | ``` 198 | 199 | When performing logical comparisons, do it like so: 200 | 201 | ```php 202 | if ( ! $foo ) { ... 203 | ``` 204 | 205 | [Type casts](https://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting) must be lowercase. Always prefer the short, canonical form of type casts, `(int)` instead of `(integer)` and `(bool)` rather than `(boolean)`. For float casts use `(float)`. 206 | 207 | ```php 208 | $foo = (bool) $bar; // Correct. 209 | $foo = (boolean) $bar; // Incorrect. 210 | ``` 211 | 212 | When referring to array items, only include a space around the index if it is a variable, for example: 213 | 214 | ```php 215 | $x = $foo['bar']; // Correct. 216 | $x = $foo[ 'bar' ]; // Incorrect. 217 | 218 | $x = $foo[0]; // Correct. 219 | $x = $foo[ 0 ]; // Incorrect. 220 | 221 | $x = $foo[ $bar ]; // Correct. 222 | $x = $foo[$bar]; // Incorrect. 223 | ``` 224 | 225 | In a `switch` block, there must be no space between the `case` condition and the colon. 226 | 227 | ```php 228 | switch ( $foo ) { 229 | case 'bar': // Correct. 230 | case 'bar' : // Incorrect. 231 | } 232 | ``` 233 | 234 | Unless otherwise specified, parentheses should have spaces inside them. 235 | 236 | ```php 237 | if ( $foo && ( $bar || $baz ) ) { ... 238 | 239 | my_function( ( $x - 1 ) * 5, $y ); 240 | ``` 241 | 242 | When using increment (`++`) or decrement (`--`) operators, there should be no spaces between the operator and the variable it applies to. 243 | 244 | ```php 245 | // Correct. 246 | for ( $i = 0; $i < 10; $i++ ) {} 247 | 248 | // Incorrect. 249 | for ( $i = 0; $i < 10; $i ++ ) {} 250 | ++ $b; // Multiple spaces. 251 | ``` 252 | 253 | ### Indentation 254 | 255 | Your indentation should always reflect logical structure. Use **real tabs**, **not spaces**, as this allows the most flexibility across clients. 256 | 257 | Exception: if you have a block of code that would be more readable if things are aligned, use spaces: 258 | 259 | ```php 260 | [tab]$foo = 'somevalue'; 261 | [tab]$foo2 = 'somevalue2'; 262 | [tab]$foo34 = 'somevalue3'; 263 | [tab]$foo5 = 'somevalue4'; 264 | ``` 265 | 266 | For associative arrays, _each item_ should start on a new line when the array contains more than one item: 267 | 268 | ```php 269 | $query = new WP_Query( array( 'ID' => 123 ) ); 270 | ``` 271 | 272 | ```php 273 | $args = array( 274 | [tab]'post_type' => 'page', 275 | [tab]'post_author' => 123, 276 | [tab]'post_status' => 'publish', 277 | ); 278 | 279 | $query = new WP_Query( $args ); 280 | ``` 281 | 282 | Note the comma after the last array item: this is recommended because it makes it easier to change the order of the array, and makes for cleaner diffs when new items are added. 283 | 284 | ```php 285 | $my_array = array( 286 | [tab]'foo' => 'somevalue', 287 | [tab]'foo2' => 'somevalue2', 288 | [tab]'foo3' => 'somevalue3', 289 | [tab]'foo34' => 'somevalue3', 290 | ); 291 | ``` 292 | 293 | For `switch` control structures, `case` statements should be indented one tab from the `switch` statement and the contents of the `case` should be indented one tab from the `case` condition statement. 294 | 295 | ```php 296 | switch ( $type ) { 297 | [tab]case 'foo': 298 | [tab][tab]some_function(); 299 | [tab][tab]break; 300 | [tab]case 'bar': 301 | [tab][tab]some_function(); 302 | [tab][tab]break; 303 | } 304 | ``` 305 | 306 | **Rule of thumb:** Tabs should be used at the beginning of the line for indentation, while spaces can be used mid-line for alignment. 307 | 308 | ### Remove Trailing Spaces 309 | 310 | Remove trailing whitespace at the end of each line. Omitting the closing PHP tag at the end of a file is preferred. If you use the tag, make sure you remove trailing whitespace. 311 | 312 | There should be no trailing blank lines at the end of a function body. 313 | 314 | ## Formatting 315 | 316 | ### Brace Style 317 | 318 | Braces shall be used for all blocks in the style shown here: 319 | 320 | ```php 321 | if ( condition ) { 322 | action1(); 323 | action2(); 324 | } elseif ( condition2 && condition3 ) { 325 | action3(); 326 | action4(); 327 | } else { 328 | defaultaction(); 329 | } 330 | ``` 331 | 332 | If you have a really long block, consider whether it can be broken into two or more shorter blocks, functions, or methods, to reduce complexity, improve ease of testing, and increase readability. 333 | 334 | Braces should always be used, even when they are not required: 335 | 336 | ```php 337 | if ( condition ) { 338 | action0(); 339 | } 340 | 341 | if ( condition ) { 342 | action1(); 343 | } elseif ( condition2 ) { 344 | action2a(); 345 | action2b(); 346 | } 347 | 348 | foreach ( $items as $item ) { 349 | process_item( $item ); 350 | } 351 | ``` 352 | 353 | Note that requiring the use of braces means that _single-statement inline control structures_ are prohibited. You are free to use the [alternative syntax for control structures](https://www.php.net/manual/en/control-structures.alternative-syntax.php) (e.g. `if`/`endif`, `while`/`endwhile`)—especially in templates where PHP code is embedded within HTML, for instance: 354 | 355 | ```php 356 | 357 |
358 | 359 |
360 | 361 |
362 | 363 |
364 | 365 | ``` 366 | 367 | ### Declaring Arrays 368 | 369 | Using long array syntax ( `array( 1, 2, 3 )` ) for declaring arrays is generally more readable than short array syntax ( `[ 1, 2, 3 ]` ), particularly for those with vision difficulties. Additionally, it's much more descriptive for beginners. 370 | 371 | Arrays must be declared using long array syntax. 372 | 373 | ### Multiline Function Calls 374 | 375 | When splitting a function call over multiple lines, each parameter must be on a separate line. Single line inline comments can take up their own line. 376 | 377 | Each parameter must take up no more than a single line. Multi-line parameter values must be assigned to a variable and then that variable should be passed to the function call. 378 | 379 | ```php 380 | $bar = array( 381 | 'use_this' => true, 382 | 'meta_key' => 'field_name', 383 | ); 384 | $baz = sprintf( 385 | /* translators: %s: Friend's name */ 386 | __( 'Hello, %s!', 'yourtextdomain' ), 387 | $friend_name 388 | ); 389 | 390 | $a = foo( 391 | $bar, 392 | $baz, 393 | /* translators: %s: cat */ 394 | sprintf( __( 'The best pet is a %s.' ), 'cat' ) 395 | ); 396 | ``` 397 | 398 | ### Type declarations 399 | 400 | Type declarations must have exactly one space before and after the type. The nullability operator (`?`) is regarded as part of the type declaration and there should be no space between this operator and the actual type. Class/interface/enum name based type declarations should use the case of the class/interface/enum name as declared, while the keyword-based type declarations should be lowercased. 401 | 402 | Return type declarations should have no space between the closing parenthesis of the function declaration and the colon starting a return type. 403 | 404 | These rules apply to all structures allowing for type declarations: functions, closures, enums, catch conditions as well as the PHP 7.4 arrow functions and typed properties. 405 | 406 | ```php 407 | // Correct. 408 | function foo( Class_Name $parameter, callable $callable, int $number_of_things = 0 ) { 409 | // Do something. 410 | } 411 | 412 | function bar( 413 | Interface_Name&Concrete_Class $param_a, 414 | string|int $param_b, 415 | callable $param_c = 'default_callable' 416 | ): User|false { 417 | // Do something. 418 | } 419 | 420 | // Incorrect. 421 | function baz(Class_Name $param_a, String$param_b, CALLABLE $param_c ) : ? iterable { 422 | // Do something. 423 | } 424 | ``` 425 | 426 | [info] 427 | Type declaration usage has the following restrictions based on the minimum required PHP version of an application, whether it is WordPress Core, a plugin or a theme: 428 | 429 | - The scalar `bool`, `int`, `float`, and `string` type declarations cannot be used until the minimum PHP version is PHP 7.0 or higher. 430 | - Return type declarations cannot be used until the minimum PHP version is PHP 7.0 or higher. 431 | - Nullable type declarations cannot be used until the minimum PHP version is PHP 7.1 or higher. 432 | - The `iterable` and `void` type declarations cannot be used until the minimum PHP version is PHP 7.1 or higher. The `void` type can only be used as a return type. 433 | - The `object` type declaration cannot be used until the minimum PHP version is PHP 7.2 or higher. 434 | - Property type declarations cannot be used until the minimum PHP version is PHP 7.4 or higher. 435 | - `static` (return type only) cannot be used until the minimum PHP version is PHP 8.0 or higher. 436 | - `mixed` type cannot be used until the minimum PHP version is PHP 8.0 or higher. Take note that the `mixed` type includes `null`, so cannot be made nullable. 437 | - Union types cannot be used until the minimum PHP version is PHP 8.0 or higher. 438 | - Intersection types cannot be used until the minimum PHP version is PHP 8.1 or higher. 439 | - `never` (return type only) cannot be used until the minimum PHP version is PHP 8.1 or higher. 440 | - Disjunctive normal form types (combining union types and intersection types) cannot be used until the minimum PHP version is PHP 8.2 or higher. 441 | [/info] 442 | 443 | _Usage in WordPress Core_ 444 | 445 | [warning] 446 | Adding type declarations to existing WordPress Core functions should be done with extreme care. 447 | [/warning] 448 | 449 | The function signature of any function (method) which can be overloaded by plugins or themes should not be touched. 450 | This leaves, for now, only unconditionally declared functions in the global namespace, `private` class methods, and code new to Core, as candidates for adding type declarations. 451 | 452 | Note: Using the `array` keyword in type declarations is **strongly discouraged** for now, as most often, it would be better to use `iterable` to allow for more flexibility in the implementation and that keyword is not yet available for use in WordPress Core until the minimum requirements are raised to PHP 7.1. 453 | 454 | ### Magic constants 455 | 456 | The [PHP native `__*__` magic constants](https://www.php.net/manual/en/language.constants.magic.php), like `__CLASS__` and `__DIR__`, should be written in uppercase when used. 457 | 458 | When using the `::class` constant for class name resolution, the `class` keyword should be in lowercase and there should be no spaces around the `::` operator. 459 | 460 | ```php 461 | // Correct. 462 | add_action( 'action_name', array( __CLASS__, 'method_name' ) ); 463 | add_action( 'action_name', array( My_Class::class, 'method_name' ) ); 464 | 465 | // Incorrect. 466 | require_once __dIr__ . '/relative-path/file-name.php'; 467 | add_action( 'action_name', array( My_Class :: CLASS, 'method_name' ) ); 468 | ``` 469 | 470 | ### Spread operator `...` 471 | 472 | When using the spread operator, there should be one space or a new line with the appropriate indentation before the spread operator. There should be no spaces between the spread operator and the variable/function call it applies to. When combining the spread operator with the reference operator (`&`), there should be no spaces between them. 473 | 474 | ```php 475 | // Correct. 476 | function foo( &...$spread ) { 477 | bar( ...$spread ); 478 | 479 | bar( 480 | array( ...$foo ), 481 | ...array_values( $keyed_array ) 482 | ); 483 | } 484 | 485 | // Incorrect. 486 | function fool( & ... $spread ) { 487 | bar(... 488 | $spread ); 489 | 490 | bar( 491 | [... $foo ],... array_values( $keyed_array ) 492 | ); 493 | } 494 | ``` 495 | 496 | [info] 497 | The spread operator (or splat operator as it's known in other languages) can be used for packing arguments in function declarations (variadic functions) and unpacking them in function calls as of PHP 5.6. Since PHP 7.4, the spread operator is also used for unpacking numerically-indexed arrays, with string-keyed array unpacking available since PHP 8.1. 498 | When used in a function declaration, the spread operator can only be used with the last parameter. 499 | [/info] 500 | 501 | ## Declare Statements, Namespace, and Import Statements 502 | 503 | ### Namespace declarations 504 | 505 | Each part of a namespace name should consist of capitalized words separated by underscores. 506 | 507 | Namespace declarations should have exactly one blank line before the declaration and at least one blank line after. 508 | 509 | ```php 510 | namespace Prefix\Admin\Domain_URL\Sub_Domain\Event; // Correct. 511 | ``` 512 | 513 | There should be only one namespace declaration per file, and it should be at the top of the file. Namespace declarations using curly brace syntax are not allowed. Explicit global namespace declaration (namespace declaration without name) are also not allowed. 514 | 515 | ```php 516 | // Incorrect: namespace declaration using curly brace syntax. 517 | namespace Foo { 518 | // Code. 519 | } 520 | 521 | // Incorrect: namespace declaration for the global namespace. 522 | namespace { 523 | // Code. 524 | } 525 | ``` 526 | 527 | _There is currently no timeline for introducing namespaces to WordPress Core._ 528 | 529 | The use of namespaces in plugins and themes is strongly encouraged. It is a great way to prefix a lot of your code to prevent naming conflicts with other plugins, themes and/or WordPress Core. 530 | 531 | Please do make sure you use a unique and long enough namespace prefix to actually prevent conflicts. Generally speaking, using a namespace prefix along the lines of `Vendor\Project_Name` is a good idea. 532 | 533 | [warning] 534 | The `wp` and `WordPress` namespace prefixes are reserved for WordPress itself. 535 | [/warning] 536 | 537 | [info] 538 | Namespacing has no effect on variables, constants declared with `define()` or non-PHP native constructs, like the hook names as used in WordPress. 539 | Those still need to be prefixed individually. 540 | [/info] 541 | 542 | ### Using import `use` statements 543 | 544 | Using import `use` statements allows you to refer to constants, functions, classes, interfaces, namespaces, enums and traits that live outside of the current namespace. 545 | 546 | Import `use` statements should be at the top of the file and follow the (optional) `namespace` declaration. They should follow a specific order based on the **type** of the import: 547 | 548 | 1. `use` statements for namespaces, classes, interfaces, traits and enums 549 | 2. `use` statements for functions 550 | 3. `use` statements for constants 551 | 552 | Aliases can be used to prevent name collisions (two classes in different namespaces using the same class name). 553 | When using aliases, make sure the aliases follow the WordPress naming convention and are unique. 554 | 555 | The following examples showcase the correct and incorrect usage of import `use` statements regarding things like spacing, groupings, leading backslashes, etc. 556 | 557 | Correct: 558 | 559 | ```php 560 | namespace Project_Name\Feature; 561 | 562 | use Project_Name\Sub_Feature\Class_A; 563 | use Project_Name\Sub_Feature\Class_C as Aliased_Class_C; 564 | use Project_Name\Sub_Feature\{ 565 | Class_D, 566 | Class_E as Aliased_Class_E, 567 | } 568 | 569 | use function Project_Name\Sub_Feature\function_a; 570 | use function Project_Name\Sub_Feature\function_b as aliased_function; 571 | 572 | use const Project_Name\Sub_Feature\CONSTANT_A; 573 | use const Project_Name\Sub_Feature\CONSTANT_D as ALIASED_CONSTANT; 574 | 575 | // Rest of the code. 576 | ``` 577 | 578 | Incorrect: 579 | 580 | ```php 581 | namespace Project_Name\Feature; 582 | 583 | use const Project_Name\Sub_Feature\CONSTANT_A; // Superfluous whitespace after the "use" and the "const" keywords. 584 | use function Project_Name\Sub_Feature\function_a; // Function import after constant import. 585 | use \Project_Name\Sub_Feature\Class_C as aliased_class_c; // Leading backslash shouldn't be used, alias doesn't comply with naming conventions. 586 | use Project_Name\Sub_Feature\{Class_D, Class_E as Aliased_Class_E} // Extra spaces around the "as" keyword, incorrect whitespace use inside the brace opener and closer. 587 | use Vendor\Package\{ function function_a, function function_b, 588 | Class_C, 589 | const CONSTANT_NAME}; // Combining different types of imports in one use statement, incorrect whitespace use within group use statement. 590 | 591 | class Foo { 592 | // Code. 593 | } 594 | 595 | use const \Project_Name\Sub_Feature\CONSTANT_D as Aliased_constant; // Import after class definition, leading backslash, naming conventions violation. 596 | use function Project_Name\Sub_Feature\function_b as Aliased_Function; // Import after class definition, naming conventions violation. 597 | 598 | // Rest of the code. 599 | ``` 600 | 601 | [alert] 602 | Import `use` statements have no effect on dynamic class, function or constant names. 603 | Group `use` statements are available from PHP 7.0, and trailing commas in group `use` statements are available from PHP 7.2. 604 | [/alert] 605 | 606 | [info] 607 | Note that, unless you have implemented [autoloading](https://www.php.net/manual/en/language.oop5.autoload.php), the `use` statement won't automatically load whatever is being imported. For OO constructs, you'll either need to set up autoloading or load the file(s) containing the OO declaration(s) using `require[_once]` or `include[_once]` statement(s). 608 | Autoloading is only applicable to OO constructs; for functions and constants, you must always use `require[_once]` or `include[_once]`. 609 | [/info] 610 | 611 | **Note about WordPress Core usage** 612 | 613 | While import `use` statements can already be used in WordPress Core, it is, for the moment, **strongly discouraged**. 614 | 615 | Import `use` statements are most useful when combined with namespaces and a class autoloading implementation. 616 | As neither of these are currently in place for WordPress Core and discussions about this are ongoing, holding off on adding import `use` statements to WordPress Core is the sensible choice for now. 617 | 618 | ## Object-Oriented Programming 619 | 620 | ### Only One Object Structure (Class/Interface/Trait/Enum) per File 621 | 622 | For instance, if we have a file called `class-example-class.php` it can only contain one class in that file. 623 | 624 | ```php 625 | // Incorrect: file class-example-class.php. 626 | class Example_Class {} 627 | 628 | class Example_Class_Extended {} 629 | ``` 630 | 631 | The second class should be in its own file called `class-example-class-extended.php`. 632 | 633 | ```php 634 | // Correct: file class-example-class.php. 635 | class Example_Class {} 636 | ``` 637 | 638 | ```php 639 | // Correct: file class-example-class-extended.php. 640 | class Example_Class_Extended {} 641 | ``` 642 | 643 | ### Trait Use Statements 644 | 645 | Trait `use` statements should be at the top of a class and should have exactly one blank line before the first `use` statement, and at least one blank line after the last statement. The only exception is when the class only contains trait `use` statements, in which case the blank line after may be omitted. 646 | 647 | The following code examples show the formatting requirements for trait `use` statements regarding things like spacing, grouping and indentation. 648 | 649 | ```php 650 | // Correct. 651 | class Foo { 652 | 653 | use Bar_Trait; 654 | use Foo_Trait, 655 | Bazinga_Trait { 656 | Bar_Trait::method_name insteadof Bar_Trait; 657 | Bazinga_Trait::method_name as bazinga_method; 658 | } 659 | use Loopy_Trait { 660 | eat as protected; 661 | } 662 | 663 | public $baz = true; 664 | 665 | ... 666 | } 667 | 668 | // Incorrect. 669 | class Foo { 670 | // No blank line before trait use statement, multiple spaces after the use keyword. 671 | use Bar_Trait; 672 | 673 | /* 674 | * Multiple spaces when importing traits, no new line after opening brace. 675 | * Aliasing should be done on the same line as the method it's replacing. 676 | */ 677 | use Foo_Trait, Bazinga_Trait{Bar_Trait::method_name insteadof Foo_Trait; Bazinga_Trait::method_name 678 | as bazinga_method; 679 | }; // Wrongly indented brace. 680 | public $baz = true; // Missing blank line after trait import. 681 | 682 | ... 683 | } 684 | ``` 685 | 686 | ### Visibility should always be declared 687 | 688 | For all constructs that allow it (properties, methods, class constants since PHP 7.1), visibility should be explicitly declared. 689 | Using the `var` keyword for property declarations is not allowed. 690 | 691 | ```php 692 | // Correct. 693 | class Foo { 694 | public $foo; 695 | 696 | protected function bar() {} 697 | } 698 | 699 | // Incorrect. 700 | class Foo { 701 | var $foo; 702 | 703 | function bar() {} 704 | } 705 | ``` 706 | 707 | _Usage in WordPress Core_ 708 | 709 | Visibility for class constants can not be used in WordPress Core until the minimum PHP version has been raised to PHP 7.1. 710 | 711 | ### Visibility and modifier order 712 | 713 | When using multiple modifiers for a _class declaration_, the order should be as follows: 714 | 715 | 1. First the optional `abstract` or `final` modifier. 716 | 2. Next, the optional `readonly` modifier. 717 | 718 | When using multiple modifiers for a _constant declaration_ inside object-oriented structures, the order should be as follows: 719 | 720 | 1. First the optional `final` modifier. 721 | 2. Next, the visibility modifier. 722 | 723 | When using multiple modifiers for a _property declaration_, the order should be as follows: 724 | 725 | 1. First a visibility modifier. 726 | 2. Next, the optional `static` or `readonly` modifier (these keywords are mutually exclusive). 727 | 3. Finally, the optional `type` declaration. 728 | 729 | When using multiple modifiers for a _method declaration_, the order should be as follows: 730 | 731 | 1. First the optional `abstract` or `final` modifier. 732 | 2. Then, a visibility modifier. 733 | 3. Finally, the optional `static` modifier. 734 | 735 | ```php 736 | // Correct. 737 | abstract readonly class Foo { 738 | private const LABEL = 'Book'; 739 | 740 | public static $foo; 741 | 742 | private readonly string $bar; 743 | 744 | abstract protected static function bar(); 745 | } 746 | 747 | // Incorrect. 748 | class Foo { 749 | protected final const SLUG = 'book'; 750 | 751 | static public $foo; 752 | 753 | static protected final function bar() { 754 | // Code. 755 | }; 756 | } 757 | ``` 758 | 759 | [info] 760 | - Visibility for OO constants can be declared since PHP 7.1. 761 | - Typed properties are available since PHP 7.4. 762 | - Readonly properties are available since PHP 8.1. 763 | - `final` modifier for constants in object-oriented structures is available since PHP 8.1. 764 | - Readonly classes are available since PHP 8.2. 765 | [/info] 766 | 767 | ### Object Instantiation 768 | 769 | When instantiating a new object instance, parenthesis must always be used, even when not strictly necessary. 770 | There should be no space between the name of the class being instantiated and the opening parenthesis. 771 | 772 | ```php 773 | // Correct. 774 | $foo = new Foo(); 775 | $anonymous_class = new class( $parameter ) { ... }; 776 | $instance = new static(); 777 | 778 | // Incorrect. 779 | $foo = new Foo; 780 | $anonymous_class = new class ( $input ) { ... }; 781 | ``` 782 | 783 | ## Control Structures 784 | 785 | ### Use `elseif`, not `else if` 786 | 787 | `else if` is not compatible with the colon syntax for `if|elseif` blocks. For this reason, use `elseif` for conditionals. 788 | 789 | ### Yoda Conditions 790 | 791 | ```php 792 | if ( true === $the_force ) { 793 | $victorious = you_will( $be ); 794 | } 795 | ``` 796 | 797 | When doing logical comparisons involving variables, always put the variable on the right side and put constants, literals, or function calls on the left side. If neither side is a variable, the order is not important. (In [computer science terms](https://en.wikipedia.org/wiki/Value_(computer_science)#Assignment:_l-values_and_r-values), in comparisons always try to put l-values on the right and r-values on the left.) 798 | 799 | In the above example, if you omit an equals sign (admit it, it happens even to the most seasoned of us), you'll get a parse error, because you can't assign to a constant like `true`. If the statement were the other way around `( $the_force = true )`, the assignment would be perfectly valid, returning `1`, causing the if statement to evaluate to `true`, and you could be chasing that bug for a while. 800 | 801 | A little bizarre, it is, to read. Get used to it, you will. 802 | 803 | This applies to `==`, `!=`, `===`, and `!==`. Yoda conditions for `<`, `>`, `<=` or `>=` are significantly more difficult to read and are best avoided. 804 | 805 | ## Operators 806 | 807 | ### Ternary Operator 808 | 809 | [Ternary operators](https://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary) are fine, but always have them test if the statement is true, not false. Otherwise, it just gets confusing. (An exception would be using `! empty()`, as testing for false here is generally more intuitive.) 810 | 811 | The short ternary operator must not be used. 812 | 813 | For example: 814 | 815 | ```php 816 | // (if statement is true) ? (do this) : (else, do this); 817 | $musictype = ( 'jazz' === $music ) ? 'cool' : 'blah'; 818 | // (if field is not empty ) ? (do this) : (else, do this); 819 | ``` 820 | 821 | ### Error Control Operator `@` 822 | 823 | As noted in the [PHP docs](https://www.php.net/manual/en/language.operators.errorcontrol.php): 824 | 825 | > PHP supports one error control operator: the at sign (@). When prepended to an expression in PHP, any diagnostic error that might be generated by that expression will be suppressed. 826 | 827 | While this operator does exist in Core, it is often used lazily instead of doing proper error checking. Its use is highly discouraged, as even the PHP docs also state: 828 | 829 | > Warning: Prior to PHP 8.0.0, it was possible for the @ operator to disable critical errors that will terminate script execution. For example, prepending @ to a call of a function that did not exist, by being unavailable or mistyped, would cause the script to terminate with no indication as to why. 830 | 831 | ### Increment/decrement operators 832 | 833 | Pre-increment/decrement should be favored over post-increment/decrement for stand-alone statements. 834 | 835 | Pre-increment/decrement will increment/decrement and then return, while post-increment/decrement will return and then increment/decrement. 836 | Using the "pre" version is slightly more performant and can prevent future bugs when code gets moved around. 837 | 838 | ```php 839 | // Correct: Pre-decrement. 840 | --$a; 841 | 842 | // Incorrect: Post-decrement. 843 | $a--; 844 | ``` 845 | 846 | ## Database 847 | 848 | ### Database Queries 849 | 850 | Avoid touching the database directly. If there is a defined function that can get the data you need, use it. Database abstraction (using functions instead of queries) helps keep your code forward-compatible and, in cases where results are cached in memory, it can be many times faster. 851 | 852 | If you must touch the database, consider creating a [Trac](https://core.trac.wordpress.org/) ticket. There you can discuss the possibility of adding a new function to cover the functionality you wanted, for a future version of WordPress. 853 | 854 | ### Formatting SQL statements 855 | 856 | When formatting SQL statements you may break them into several lines and indent if it is sufficiently complex to warrant it. Most statements work well as one line though. Always capitalize the SQL parts of the statement like `UPDATE` or `WHERE`. 857 | 858 | Functions that update the database should expect their parameters to lack SQL slash escaping when passed. Escaping should be done as close to the time of the query as possible, preferably by using `$wpdb->prepare()` 859 | 860 | `$wpdb->prepare()` is a method that handles escaping, quoting, and int-casting for SQL queries. It uses a subset of the `sprintf()` style of formatting. Example : 861 | 862 | ```php 863 | $var = "dangerous'"; // Raw data that may or may not need to be escaped. 864 | $id = some_foo_number(); // Data we expect to be an integer, but we're not certain. 865 | 866 | $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $var, $id ) ); 867 | ``` 868 | 869 | The following placeholders can be used in the query string: 870 | 871 | - %d (integer) 872 | - %f (float) 873 | - %s (string) 874 | - %i (identifier, e.g. table/field names) 875 | 876 | Note that these placeholders should not be 'quoted'! `$wpdb->prepare()` will take care of escaping and quoting for us. This makes it easy to see at a glance whether something has been escaped or not because it happens right when the query happens. 877 | 878 | See [Data Validation](https://developer.wordpress.org/plugins/security/data-validation/) in the Plugin Handbook for further details. 879 | 880 | ## Recommendations 881 | 882 | ### Self-Explanatory Flag Values for Function Arguments 883 | 884 | Prefer string values to just `true` and `false` when calling functions. 885 | 886 | ```php 887 | // Incorrect. 888 | function eat( $what, $slowly = true ) { 889 | ... 890 | } 891 | eat( 'mushrooms' ); 892 | eat( 'mushrooms', true ); // What does true mean? 893 | eat( 'dogfood', false ); // What does false mean? The opposite of true? 894 | ``` 895 | 896 | PHP only supports named arguments as of PHP 8.0. However, as WordPress currently still supports older PHP versions, we cannot yet use those. 897 | Without named arguments, the values of the flags are meaningless, and each time we come across a function call like the examples above, we have to search for the function definition. The code can be made more readable by using descriptive string values, instead of booleans. 898 | 899 | ```php 900 | // Correct. 901 | function eat( $what, $speed = 'slowly' ) { 902 | ... 903 | } 904 | eat( 'mushrooms' ); 905 | eat( 'mushrooms', 'slowly' ); 906 | eat( 'dogfood', 'quickly' ); 907 | ``` 908 | 909 | When more words are needed to describe the function parameters, an `$args` array may be a better pattern. 910 | 911 | ```php 912 | function eat( $what, $args ) { 913 | ... 914 | } 915 | eat ( 'noodles', array( 'speed' => 'moderate' ) ); 916 | ``` 917 | 918 | Be careful when using this pattern, as it can lead to "Undefined array index" notices if input isn't validated before use. Use this pattern only where it makes sense (i.e. multiple possible arguments), not just for the sake of it. 919 | 920 | ### Clever Code 921 | 922 | In general, readability is more important than cleverness or brevity. 923 | 924 | ```php 925 | isset( $var ) || $var = some_function(); 926 | ``` 927 | 928 | Although the above line is clever, it takes a while to grok if you're not familiar with it. So, just write it like this: 929 | 930 | ```php 931 | if ( ! isset( $var ) ) { 932 | $var = some_function(); 933 | } 934 | ``` 935 | 936 | Unless absolutely necessary, loose comparisons should not be used, as their behavior can be misleading. 937 | 938 | Correct: 939 | 940 | ```php 941 | if ( 0 === strpos( $text, 'WordPress' ) ) { 942 | echo esc_html__( 'Yay WordPress!', 'textdomain' ); 943 | } 944 | ``` 945 | 946 | Incorrect: 947 | 948 | ```php 949 | if ( 0 == strpos( 'WordPress', 'foo' ) ) { 950 | echo esc_html__( 'Yay WordPress!', 'textdomain' ); 951 | } 952 | ``` 953 | 954 | Assignments must not be placed in conditionals. 955 | 956 | Correct: 957 | 958 | ```php 959 | $data = $wpdb->get_var( '...' ); 960 | if ( $data ) { 961 | // Use $data. 962 | } 963 | ``` 964 | 965 | Incorrect: 966 | 967 | ```php 968 | if ( $data = $wpdb->get_var( '...' ) ) { 969 | // Use $data. 970 | } 971 | ``` 972 | 973 | In a `switch` statement, it's okay to have multiple empty cases fall through to a common block. If a case contains a block, then falls through to the next block, however, this must be explicitly commented. 974 | 975 | ```php 976 | switch ( $foo ) { 977 | case 'bar': // Correct, an empty case can fall through without comment. 978 | case 'baz': 979 | echo esc_html( $foo ); // Incorrect, a case with a block must break, return, or have a comment. 980 | case 'cat': 981 | echo 'mouse'; 982 | break; // Correct, a case with a break does not require a comment. 983 | case 'dog': 984 | echo 'horse'; 985 | // no break // Correct, a case can have a comment to explicitly mention the fall through. 986 | case 'fish': 987 | echo 'bird'; 988 | break; 989 | } 990 | ``` 991 | 992 | The `goto` statement must never be used. 993 | 994 | The `eval()` construct is _very dangerous_ and is impossible to secure. Additionally, the `create_function()` function, which internally performs an `eval()`, is deprecated since PHP 7.2 and has been removed in PHP 8.0. Neither of these must be used. 995 | 996 | ### Closures (Anonymous Functions) 997 | 998 | Where appropriate, closures may be used as an alternative to creating new functions to pass as callbacks. For example: 999 | 1000 | ```php 1001 | $caption = preg_replace_callback( 1002 | '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', 1003 | function ( $matches ) { 1004 | return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] ); 1005 | }, 1006 | $caption 1007 | ); 1008 | ``` 1009 | 1010 | Closures should not be passed as filter or action callbacks, as removing these via `remove_action()` / `remove_filter()` is complex (at this time) (see [#46635](https://core.trac.wordpress.org/ticket/46635 "Improve identifying of non–trivial callbacks in hooks") for a proposal to address this). 1011 | 1012 | ### Regular Expressions 1013 | 1014 | Perl compatible regular expressions ([PCRE](https://www.php.net/pcre), `preg_` functions) should be used. 1015 | Never use the `/e` switch, use `preg_replace_callback` instead. 1016 | 1017 | It's most convenient to use single-quoted strings for regular expressions since, contrary to double-quoted strings, they have only two metasequences which need escaping: `\'` and `\\`. 1018 | 1019 | ### Don't `extract()` 1020 | 1021 | Per [#22400](https://core.trac.wordpress.org/ticket/22400 "Remove all, or at least most, uses of extract() within WordPress"): 1022 | 1023 | > `extract()` is a terrible function that makes code harder to debug and harder to understand. We should discourage it's [sic] use and remove all of our uses of it. 1024 | 1025 | Joseph Scott has [a good write-up of why it's bad](https://blog.josephscott.org/2009/02/05/i-dont-like-phps-extract-function/). 1026 | 1027 | ### Shell commands 1028 | 1029 | Use of the [backtick operator](https://www.php.net/manual/en/language.operators.execution.php) is not allowed. 1030 | 1031 | Use of the backtick operator is identical to [`shell_exec()`](https://www.php.net/manual/en/function.shell-exec.php), and most hosts disable this function in the `php.ini` file for security reasons. 1032 | --------------------------------------------------------------------------------