Code Book, part 4 (Obscure Coding Standards)
Written by Chris Graham
« Return to Code Book table of contentsThis section covers coding standards that should be upheld, but are either:
- relate to a very specific Composr scenario that most developers won't be facing day-to-day
- so obvious you don't need to learn them in advance either
It serves as a reference guide for settling disagreements, as a general reference when doing more extensive quality reviews, and a reference for what some of our automated tests do.
Back-end programming
General
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
1) Export metadata |
Standards compliance | Composr development + | Manually | Export metadata using seo_meta_load_for and set_extra_request_metadata for content modules supporting it. |
2) Never include <? within your PHP source |
Portability | All development | Code Quality Checker | PHP short_tags option may be on. This string is used within XML so is fairly common to type in; if you need it append two strings together to form it so that it doesn't have to be literally written into the code. |
3) Any page should be accessible as standalone |
Usability | All development | Manually | You shouldn't add modules that are never intended to be used independently, because they will come up on the sitemap. If you intend to write some kind of helper script that may be called by a module then either use an "entry-point script" for that or build the functionality into the module file itself (you are allowed to exit out of a module with your own HTTP headers etc rather than returning Tempcode). |
4) Write appropriate hooks etc for new content types |
Consistency | Composr development + | Manually | When adding new content types remember to write all appropriate hooks for them (e.g. search hooks). And implement standard systems like SEO metadata, feedback systems, validation, and permissions. |
5) Communicate upload limits |
Usability | Product development only | Manually | Show the appropriate maximum-upload size on all screens that support file uploads, unless the size is very unlikely to be reached by the user (e.g. just uploading an avatar). Composr has a standard mechanism to do this, which can be automated within CRUD modules. For code examples search the code for get_upload_limit_config_url. |
6) Don't define too many functions in a single file |
Portability: PHP memory_limit setting / performance | Composr development + | Composr development mode sets a low memory_limit | Instead put the script into code files that are loaded only when needed. |
7) Pass in extra useful template parameters |
Themeing | Product development only | Manually | Pass in any additional unused parameters to the template where they might be useful; raw timestamps, IDs, etc. |
8) E-mail subject lines must be unique, or the e-mail sender must be a specific user (not the website itself) |
Usability | Composr development + | Manually | This convention makes e-mails easier to scan in an inbox and stops incorrect automatic threading. |
9) Use cms_ini_set |
Portability | Product development only | Manually | Use cms_ini_set rather than ini_set, as it allows us to control for factors such as ini_set being disabled on the hosting platform (some hosts do this for security reasons). |
10) Block access when closed |
Stability | All development | Manually |
Any URL that a user may reasonably navigate to manually that is not passed through index.php, must show the closed site message by its own means. Look to see how other code does it for example. |
Files
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
11) 1 KB = 1024 bytes, etc |
Consistency | Product development only | Manually | We don't say KiB or use 1000s. People don't understand KiB (the term never caught on), and 1024 is the long term convention in computing. |
12) No .php files in writable directories |
Portability | Product development only | Automated test async_tests/suphp | suPHP will not allow .php files in directories with group/other write permissions. |
Log files
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
13) Define log file in a hook |
GDPR, Administration | Composr development | Manually | A systems/logs hook needs to define that your log exists. This allows the log purger to clear out old records, and the administrative error-log interface to find your log. |
14) Use correct date format |
GDPR | Composr development | Manually | Start your log entries using the output of loggable_date(). This consistent date formatting will allow the log purger to read the log. Multiple lines per entry and lead-in text at the top of the log are allowed; these special lines should not include the date/time. Other than this function there's no explicit log-writing API, because it's pretty standard PHP file I/O. |
15) Lock your file when writing |
Stability | Composr development | Manually | Multiple processes may want to write to the log at the same time. Look how other logging code handles locking. In rare situations it may be guaranteed an operation is not going to happen concurrently, in which case you can forget about locking. |
16) Store log as data_custom/whatever.log |
Security | Composr development | Manually | This allows the default Apache .htaccess to deny web access to the log. The only exception should be logs which are created by default, which must be .php files with some lead-in code to prevent PHP command execution (using .php is the only 100%-reliable way to prevent unintended file download by URL access). |
17) Do not create log by default |
Security | Composr development | Manually | Logs should usually only be used if the standard file has been pre-created by hand. This avoids bloated unneeded logs that may not be properly secured against unwanted access. See the note above for stipulations around the exception to this rule. |
18) Reference in web.config file |
Security | Composr development | Manually | We support IIS, which does not support wild-card blocking of file access. So we must manually block access to each individual log file. |
URLs and file paths
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
19) Don't append to URLs in templates |
URL schemes | All development | Manually | Do not try and appending something to a URL inside a template, unless it is a URL to a helper script (rather than a screen) or if you have explicitly disabled SEO for the URL. URL schemes involve different URL structures. Pass in all the URLs you need to the template so you don't need to deploy hacks. |
20) Don't assume directories already exist to write into |
Shared installs: multiple sites with one Composr install, GAE | Product development only | Manually |
If running a blank custom directory, none of the bundled directory structure will be initially present. You must therefore detect and auto-create missing directories, using make_missing_directory. |
Databases
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
21) Don't require write queries on normal page views |
Stability, Performance | Product development only | Manually | Some webhosts will restrict SQL write permission if a database size limit is exceeded, so any routine write queries should have the $fail_ok option set so that it doesn't take the whole site down. |
22) Do maintenance using cms_register_shutdown_function_safe |
Performance | Product development only | Manually | Non-critical maintenance such as logging, updating view counts, or deleting expired records, should be done at script end and using the cms_register_shutdown_function_safe function. This is to decrease the time before rendering the page output. Note that we use the cms_register_shutdown_function_safe instead of the register_shutdown_function function, as a minority of servers do not support register_shutdown_function. |
23) Use statistical_update_model function for controlling view count maintenance, and increment directly |
Performance | Product development only | Manually | The statistical_update_model function does a number of checks to see if and how view counts should change. Use this function in the same pattern as it is used elsewhere in the code. Do not increment by explicitly passing in a new view count, as that would assume the view count hasn't changed since it came out of the database – run a query to directly increment from the in-database field. |
24) Stay within common denominator of limits |
Portability | Product development only | Table creation code checks | There are maximum numbers of indices, fields, fields in keys and indexes, total field size in keys and indexes, length of field names, and length of table names. |
Templates and Interfaces
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
25) Nest your templates |
Themeing | Composr development + | Manually | Templates should nest, not be split up into start/end pairs. |
26) Use handle_max_file_size ($hidden) when using upload fields so that your form has the right file-size limits on it |
Usability for webmasters: stops nasty server-side upload-limit errors | Composr development + | Manually |
Modifying core classes
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
27) Object orientated principles |
Technical debt | Product development only |
Use object-orientated principles properly where Composr does already. For example, forum drivers all have a database object as a property, rather than referencing the global FORUM_DB object. This is because they provide a core service and cannot make assumptions about the environment (e.g. it must be possible to have multiple simultaneous forum drivers running). |
Blocks
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
28) Blocks should not exit |
Stability | Product development only | Automated test async_tests/blocks |
If a block hits an error condition it must return an error message, not call a function like warn_exit. An error on a block can't be a fatal thing. |
Attachments
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
29) Remember posted Comcode might be invalid |
Stability | All development | Manually |
If you are supporting Composr attachments in a field, run the check_comcode function on the Comcode that references the attachments before the main row for the content is added to the database. This ensures the Comcode is valid, so you can proceed to add the content row (using the integer 0 temporarily as the field value for where the Comcode will be placed). The attachment Comcode can then be fully parsed (given the ID of the content row, so it can store its security properly) and then the content row updated with the new content language string ID for that parsed Comcode. |
Comcode parser/renderer code
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
30) No context-sensitivity |
Stability | All development | Manually | When programming the Comcode system, never allow Comcode to become context-sensitive (e.g. behaving differently when run from different URL paths). |
31) Don't use require_javascript or require_css |
Stability: cache safety | All development | Manually |
When implementing tags, CSS must all be in global.css, and any JavaScript must be by using a symbol to load the JavaScript file – this is because any inclusion code put in the PHP rendering code only runs when the Comcode is first compiled, and not when it is loaded out of the cache. |
Regular expressions
If you are writing regular expressions to extract data from HTML, you should anticipate…Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
32) …there may be extra whitespace (there may be extra spaces inside tag definitions) |
||||
33) …whitespace may come in other forms than the \t symbol (there may be tabs) |
||||
34) …HTML used instead of XHTML. (there may be <br> instead of <br />) |
||||
35) …that tags may be written in upper case |
||||
36) …attribute quotes can be given as single-quotes as well as double quotes, and attribute contents may span multiple lines |
||||
37) …there may be whitespace around tag-contents |
||||
38) …tag contents may not be properly entity-encoded |
||||
39) …quoted data may contain quotes of the other-type (there may be <a title="He's saying hello">) |
You may assume…
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
40) …a tag opener/closer stays on one line |
||||
41) …attribute values are quoted |
||||
42) …the text is in either well-formed SGML (HTML) or well-formed XML (XHTML) |
Installation code
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
43) Installation code must respect the multi-language system |
Internationalisation | Product development only | Manually | Make sure the lang_code_to_default_content function is used where appropriate in installation code. This function puts in content language strings to the database such that they get stored automatically for all translations available on the installation. |
44) Upgrades must be handled correctly |
Stability | Product development only | Manually | Make sure that modules upgrade properly between major versions of Composr, and preferably between all versions. Do not assume a module will never be upgraded: if your module has undergone database structure revisions then you must make sure there is upgrade code to apply these revisions. See how existing code does it for examples. |
45) Reinstalls must be handled correctly |
Stability | Product development only | Automated test cli_tests/installer | If a module is reinstalled, it should not give errors about existing tables or privileges. For this to work, the uninstall function must fully uninstall what the install function creates. |
Cryptography
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
46) Do not use hashing in cryptographic randomness |
Security | Product development only | Manually | When developing cryptographic functions in crypt.php to generate randomness of some kind, do not use hashing algorithms in the process. Hashing algorithms, particularly MD5, carry the risk of clashes (when two or more strings evaluate to the same hash). Furthermore, they defeat the purpose of cryptography because they increase the risk of hackers being able to predict the randomness. |
47) Always use cryptographically-secure entropy when generating cryptographically-secure randomness |
Security | Product development only | Manually | When developing cryptographic functions in crypt.php to generate randomness of some kind, use cryptographically-secure entropy in every step of the process involving randomness. If even one random number/string/etc is not generated with cryptographically-secure entropy, the entire process is compromised and left open to prediction by hackers. |
48) Do not use the site salt on non-volatile data (e.g. passwords) |
Stability | Product development only | Manually | When hashing passwords or other non-volatile data, do not salt them with the site salt. Instead, generate a specific salt (such as for the member) and store that along with the hashed password. Using the site salt can cause lock-outs in the rare event the site salt gets changed or re-generated. The site salt is more appropriate for URL hashes (e.g. verification), cookies, hashed session IDs, caches, and temporary files or data. |
Front-end programming
Spelling/grammar/lexicon
(examples of what not to do are in italics)Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
49) Don't spell things rong or use incorrect grammar |
Usability | Composr development + | Automated test async_tests/lang_spelling, Automated test sync_tests/__lang_spelling_epic, Automated test async_tests/lang_grammar | |
50) Be careful where you put your apostrophe's |
Usability | Composr development + | Manually + use the .ini files with Microsoft Word's checking tools | Apostrophes are not used for plurals. |
51) When needed, add comments to the language files to define context |
Internationalisation | Product development only | Manually | For an example of how to do this, see global.ini. |
52) Use quotes consistently |
Consistent UI | Product development only | Manually |
When quoting phrases use double quotes (speech marks), which in language files and templates would generally be done using the HTML ldquo and rdquo entities. When quoting single words or terms use single quotes, which in language files and templates would generally be done using the HTML lsquo and rsquo entities. When quoting something code-related like a language keyword use Comcode's tt or HTML's kbd. When referencing keyboard key names, refer to them like Ctrl or Shift or Option or Alt: capitalise the first letter. When in general trying to draw attention to a word/term/phrase that isn't part of any quotation, use bold. |
53) Don't use software-specific terms on the main website |
Consistent UI | Composr development + | Manually | Composr 'brands' or unique terminology ('Zone', 'Comcode', …) should not be seen on the main website. |
54) Use the term ‘link’ correctly |
Consistent UI | Product development only | Manually |
A ‘link’ is specifically a hyperlink (i.e. something that can be clicked), it is not a synonym for ‘URL’. Most of the time in code you will use the term ‘URL’. A ‘link’ goes to a ‘URL’. |
Markup/Tempcode
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
55) Exclude robots appropriately |
SEO | All development | Manually |
You need to stop search engines indexing utility scripts, or pages that only should be navigated to manually by a human. This can be done using an attach_to_screen_header call that adds a meta tag for HTML pages, a NOINDEX parameter to the STANDALONE_HTML_WRAP template, or a X-Robots-Tag HTTP header for non-HTML pages. |
JavaScript
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
56) Use modern DOM (so no document.all, or window.images) |
Standards compliance | Product development only | Automated test sync_tests/web_resources | document.all, form.foo, etc, are all non-standard (even though they're commonplace) – use getElementById etc. |
57) Don't use any deprecated methods (so no escape) |
Standards compliance | Product development only | Automated test sync_tests/web_resources | Instead of escape, use encodeURIComponent. |
58) Choose wisely in how to force form submission |
Framework | Composr development + | Manually | There are cases where you need to manually submit a form, e.g. if the user clicks a button to submit a form but your validation requires a promise to pass first. form.submit(); will submit the form without calling event handling, while $dom.trigger(form, 'submit'); will call event handling. Choose which makes sense for your situation. |
59) Use localName not nodeName |
Stability | Composr development + | ESLint |
Using nodeName is not reliable when namespaces are involved, and may also return in upper case. localName is much more reliable, although only works on HTML Element DOM nodes not any DOM node. |
Documentation
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
60) Use top-level heading correctly |
Communication | Product development only | Automated test async_tests/tutorial_quality | The top level heading must be structured correctly, including attributing the tutorial author. Refer to existing tutorials for an example. |
61) Include a table of contents |
Communication | Product development only | Automated test async_tests/tutorial_quality | Include a table of contents after the introduction paragraph and before subsequent titles. Refer to existing tutorials for an example. |
62) Include a sensible title structure |
Communication | Product development only | Automated test async_tests/tutorial_title_structure | Have a title structure that uses the title levels sensibly. |
63) Standardised image linking |
Communication, consistency | Product development only | Automated test async_tests/tutorial_quality, Automated test async_tests/tutorial_image_consistency | Include images via Comcode media tags to files in data_custom/images/docs/<tutorial_name>. Typically use floating to put images to the right of text content, and use the surround Comcode tag to hold things together. Refer to existing tutorials for an example. |
64) Meet minimum image density |
Communication: visual learners appreciate images | Product development only | Automated test async_tests/tutorial_quality | Have a reasonable number of images per tutorial. |
65) Define a keyword table |
Communication | Product development only | Automated test async_tests/tutorial_quality | Define new keywords in a table near the bottom of the tutorial. Refer to existing tutorials for an example. |
66) Have a See Also list |
Communication: strong cross-linking | Product development only | Automated test async_tests/tutorial_quality | Provide a list of other tutorials to reference. Refer to existing tutorials for an example. |
67) Link to other tutorials using the _SEARCH zone |
Stability | Product development only | Automated test async_tests/tutorial_quality | By linking using the _SEARCH zone we allow tutorials to run from different contexts, but also to link to tutorials within the same zone as they are in when possible (so we can host multiple copies of the documentation with correct internal cross-linking). |
68) Use code tags correctly |
Communication: syntax highlighting | Product development only | Automated test async_tests/tutorials_codebox | Any Comcode code tag must specify the language of the code, which must be one of the languages listed in the automated test (we try and match ones we can syntax highlight). |
69) Supply tutorial tags |
Communication: strong cross-linking | Product development only | Automated test async_tests/tutorial_quality, Automated test async_tests/tutorials_all_linked | Provide a list of applicable tags for the tutorial at the bottom. At least one of these should be the title of a broad documentation category (the first of which is where the icon is drawn from). Tags that do not refer to a documentation category must refer to a Composr addon codename. If you refer to an addon, the addon's registry hook must refer back in it's list of tutorials. Refer to existing tutorials for an example. |
70) Include a tutorial date |
Communication | Product development only | Automated test async_tests/tutorial_quality | Include the date the tutorial was written on. Refer to existing tutorials for an example. |
71) Include a rating block |
Product feedback | Product development only | Automated test async_tests/tutorial_quality | Include a rating block. Refer to existing tutorials for an example. |
72) Include a summary |
Communication: use on indexes | Product development only | Automated test async_tests/tutorial_quality | Include a summary. Refer to existing tutorials for an example. |
Agency standards
Standard | Reason | Scope | Test method | Notes |
---|---|---|---|---|
73) Use a staging server system |
Deployment, collaboration | Projects | Manually | The Staging Servers tutorial lays out processes for deploying in a professional way. |
74) Run Health Check |
Deployment, stability | Projects | Manually | Run Admin Zone > Tools > Health Check to confirm things are good. |
75) Use a good upgrade and maintenance process |
Deployment, collaboration | Projects | Manually |
The Professional upgrading tutorial lays out a good process for maintaining and upgrading websites. |
Feedback
Please rate this tutorial:
Have a suggestion? Report an issue on the tracker.