Initial export of the repository

Signed-off-by: Ryan McCue <me@ryanmccue.info>
This commit is contained in:
Ryan McCue 2025-06-05 11:51:30 +02:00
commit 583d434505
76 changed files with 39023 additions and 0 deletions

22
docs/config.md Normal file
View file

@ -0,0 +1,22 @@
# Configuration
FAIR is designed to operate without user configuration, and with minimal changes to user workflows. Some configuration is provided for specific parts of FAIR for users and for hosts.
## Central repository mirror URL
By default, plugin and theme data for the central repository (`wordpress.org`) is provided from the AspirePress mirror at api.aspirecloud.net.
For hosts which prefer to use their own mirror for plugin and theme data, the `FAIR_DEFAULT_REPO_DOMAIN` constant can be set to a different domain. This domain must mirror the APIs available at `api.wordpress.org/plugins/` and `api.wordpress.org/themes/` (and sub-APIs thereof):
```php
define( 'FAIR_DEFAULT_REPO_DOMAIN', 'api.myhost.example.com' );
```
This can also be configured to use the original WordPress.org domain by setting the constant to api.wordpress.org:
```php
define( 'FAIR_DEFAULT_REPO_DOMAIN', 'api.wordpress.org' );
```
This constant only affects the default repository used for plugin and theme data. Using a different mirror (including WordPress.org) for code distribution does not affect any other APIs (such as the events API or Gravatar).

View file

@ -0,0 +1,27 @@
# Use Markdown Architectural Decision Records
## Context and Problem Statement
We want to record architectural decisions made in this project independent of whether decisions concern the architecture ("architectural decision record"), the code, or other fields.
Which format and structure should these records follow?
## Considered Options
* [MADR](https://adr.github.io/madr/) 4.0.0 The Markdown Architectural Decision Records
* [Michael Nygard's template](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions) The first incarnation of the term "ADR"
* [Sustainable Architectural Decisions](https://www.infoq.com/articles/sustainable-architectural-design-decisions) The Y-Statements
* Other templates listed at <https://github.com/joelparkerhenderson/architecture_decision_record>
* Formless No conventions for file format and structure
## Decision Outcome
Chosen option: "MADR 4.0.0", because
* Implicit assumptions should be made explicit.
Design documentation is important to enable people understanding the decisions later on.
See also ["A rational design process: How and why to fake it"](https://doi.org/10.1109/TSE.1986.6312940).
* MADR allows for structured capturing of any decision.
* The MADR format is lean and fits our development style.
* The MADR structure is comprehensible and facilitates usage & maintenance.
* The MADR project is vivid.

View file

@ -0,0 +1,164 @@
---
# These are optional metadata elements. Feel free to remove any of them.
status: proposed
date: 2025-04-19
---
# Coding Standards
## Context and Problem Statement
In order to work effectively as a team, we need to agree on coding standards for consistency.
## Considered Options
* WP Core standard ("WordPress" in wpcs)
* PSR-12
* A variant of either
* Other modernised WP standards from the ecosystem
## Rationale
We have two primary options to pick from, namely WP' standards or an industry standard like PSR-4.
Given the nature of this project as something that may become part of core itself, staying close to the patterns already used in core would assist with merging the project in the future. Additionally, with a large number of contributors who are familiar with WP core, there's a greater familiarity generally with this style than with rest-of-PHP standards like PSR-4.
However, the WP standards don't fully account for some modern coding techniques, like namespaces. The norms of core development can also be outdated in various aspects, such as long arrays (`array()` instead of `[]`) or the use of classes as pseudo-namespaces (since much of core predates real namespaces). Alternative WordPress-based standards such as the Human Made standard account for this while remaining "WordPress-y", but are by their nature less familiar.
## Decision Outcome
Proposed outcome is a standard derived from the WordPress coding standards, with customization as necessary inspired by the Human Made standard. This achieves a good balance of familiarity and modernity.
## Coding Standard Details
This project uses the WP coding standards, with various additions based on other standards (such as the Human Made coding standards).
The following represent the changes and additions compared to the standard WP coding standards.
### File Layout
PHP files should either declare symbols (classes, functions, etc) or run code (function calls, etc), but not both. The only place that code is run at the top-level outside of a function/class should be in the root `plugin.php`
(An exception is allowed for `require` statements only if there isn't a better way to include those files, but preferentially these should be included in the top-level `plugin.php`)
Classes must be in their own file, which should not declare any other functions or classes, or run any code.
Generally, the file should follow the following order (with each group separated by a blank line):
* `namespace` declaration
* `use` declarations
* `const` declarations for the namespace
* require when allowed
* Declarations or run code
For namespaced functions which are primarily action and filter callbacks, the `add_action`/`add_filter` calls should generally live in a `bootstrap()` function in the namespace. This allows the file to be loaded without adding hooks immediately, but still allows the hook declarations to live with the callbacks.
### Project Layout and File Naming
`inc/` contains the bulk of the code for the project, with only necessary files (like the `plugin.php` entrypoint) living outside of it.
Each directory within `inc/` directly represents a "module" of functionality within FAIR, and is designed so that each module may be maintained independently. Generally speaking, avoid adding any functionality directly outside of a module unless it is strictly necessary.
Namespaces (excluding the parent `FAIR` namespace) are mapped to filesystem directories (or files) by lower-casing them and replacing underscores with dashes. For example, `FAIR\Foo_Bar\Quux\Zorb` becomes `inc/foo-bar/quux/zorb`.
If a namespace consists entirely of functions and constants, contains no classes, and contains no sub-namespaces, it can live in a file directly. For example, `FAIR\Foo_Bar\Quux` could live at `inc/foo-bar/quux.php`.
Namespaces which have sub-namespaces or have classes must use a directory instead, with any namespace symbols (functions, constants, etc) in a `namespace.php` file inside this directory.
Generally, you should use the directory style when you expect more classes or subnamespaces, and you should use the file style when you expect this to be functions only. Both styles have their place, and you should carefully consider the future of this code when you decide.
For example, the file layout could look like:
```sh
inc/ # namespace FAIR
inc/foo/ # namespace FAIR\Foo
inc/foo/class-bar.php # namespace FAIR\Foo, class Bar
inc/foo/namespace.php # namespace FAIR\Foo, functions
inc/quux/ # namespace FAIR\Quux
inc/quux/namespace.php # namespace FAIR\Quux, functions
inc/quux/zorb/ # namespace FAIR\Quux\Zorb
inc/quux/zorb/class-waldo.php # namespace FAIR\Quux\Zorb, class Waldo
inc/quux/zorb/thud.php # namespace FAIR\Quux\Zorb\Thud, functions
inc/quux/zorb/xyzzy.php # namespace FAIR\Quux\Zorb\Xyzzy, functions
```
### Namespaces and Classes
FAIR is built for a modern era of PHP, and so is built namespace-first. Generally, non-stateful functions should live in namespaces, and classes should be used only for object-oriented, stateful needs.
Namespaces should be logical groupings of related functionality. Typically, this means along feature lines, not along technology lines; a WP-CLI command for example should live alongside the functionality it serves, rather than in a dedicated `FAIR\CLI` namespace.
Where functions or classes from other namespaces are used, the namespace should be explicitly `use`'d into the file. You should `use` classes directly, but avoid `use function`, as this gets confusing with the overlap of large number of un-prefixed functions in WP. `use` statements should not start with a redundant `\`, and there's no need to `use` global functions.
Avoid aliasing unless you need to, as it reduces the readability of the code.
```php
// Good:
use FAIR\Foo;
use FAIR\Foo\Bar;
Foo\some_function();
new Bar();
// Bad:
use \FAIR\Foo;
use function FAIR\Foo\some_function();
\get_option();
```
### Classes
Use classes for places where you need objects, and avoid using them only for pseudo-namespacing. (A class composed of all `static` functions should likely be a namespace instead.)
Class methods and properties should always be marked with a visibility keyword, one of `public`, `protected` or `private`.
Generally speaking, `private` should be avoided in favour of `protected`, as it doesn't allow subclasses to access the method. In most cases, this is an unnecessary hindrance, and leads to subclasses simply copy-and-pasting the code when they need to override it.
In some cases, for forward compatibility, `private` or `final` may be required. Use these sparingly.
### Statements
Avoid using Yoda-style backwards statements, as they hurt readability.
Anonymous functions should use nacin-spacin, with extra spaces between elements. This applies both for long (`function ()`) and short (`fn ()`) functions:
```php
// Good:
function () {}
function ( $x ) {}
function ( $x ) use ( $y ) {}
fn ( $x ) => $x + 1
// Bad:
function() {}
function( $x ) {}
function( $x ) use( $y ) {}
function( $x ) use ( $y ) {}
fn($x)=>$x+1
fn($x) => $x + 1
```
Arrays should be specified as short arrays (`[]`). Unless the array is a list of short items (such as a few integers or a couple of strings), each item should be on its own line.
### Documentation
Generally, follow the WP standard for inline documentation.
An exception is made for the description. Descriptions should be written in the imperative (as a command) rather than third-person indicative. This is the **opposite** of what WordPress coding standards recommend.
This is an intentional stylistic choice and deviation from the WordPress coding standards. The WordPress standards produce an incomplete sentence, missing a subject, which can be confusing. The imperative reads more clearly in many cases.
The short description should be able to replace the function name. Doing this for all your functions should produce a sentence that describes what you're doing (just like a flowchart!):
* Bad: "Queries the database. Formats the data for output."
* Good: "Query the database. Format the data."

5
docs/decisions/README.md Normal file
View file

@ -0,0 +1,5 @@
# Decisions
Decisions on the architecture of this plugin are made through Architecture Decision Records (ADRs), following the patterns documented at <https://adr.github.io/> (and using the <https://adr.github.io/madr/> templates).
Decisions are made on a consensus basis of the working group, as documented in [CONTRIBUTING.md](../../CONTRIBUTING.md).

View file

@ -0,0 +1,74 @@
---
# These are optional metadata elements. Feel free to remove any of them.
status: "{proposed | rejected | accepted | deprecated | … | superseded by ADR-0123"
date: {YYYY-MM-DD when the decision was last updated}
decision-makers: {list everyone involved in the decision}
consulted: {list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication}
informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication}
---
# {short title, representative of solved problem and found solution}
## Context and Problem Statement
{Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story. You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.}
<!-- This is an optional element. Feel free to remove. -->
## Decision Drivers
* {decision driver 1, e.g., a force, facing concern, …}
* {decision driver 2, e.g., a force, facing concern, …}
* … <!-- numbers of drivers can vary -->
## Considered Options
* {title of option 1}
* {title of option 2}
* {title of option 3}
* … <!-- numbers of options can vary -->
## Decision Outcome
Chosen option: "{title of option 1}", because {justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | … | comes out best (see below)}.
<!-- This is an optional element. Feel free to remove. -->
### Consequences
* Good, because {positive consequence, e.g., improvement of one or more desired qualities, …}
* Bad, because {negative consequence, e.g., compromising one or more desired qualities, …}
* … <!-- numbers of consequences can vary -->
<!-- This is an optional element. Feel free to remove. -->
### Confirmation
{Describe how the implementation of/compliance with the ADR can/will be confirmed. Are the design that was decided for and its implementation in line with the decision made? E.g., a design/code review or a test with a library such as ArchUnit can help validate this. Not that although we classify this element as optional, it is included in many ADRs.}
<!-- This is an optional element. Feel free to remove. -->
## Pros and Cons of the Options
### {title of option 1}
<!-- This is an optional element. Feel free to remove. -->
{example | description | pointer to more information | …}
* Good, because {argument a}
* Good, because {argument b}
<!-- use "neutral" if the given argument weights neither for good nor bad -->
* Neutral, because {argument c}
* Bad, because {argument d}
* … <!-- numbers of pros and cons can vary -->
### {title of other option}
{example | description | pointer to more information | …}
* Good, because {argument a}
* Good, because {argument b}
* Neutral, because {argument c}
* Bad, because {argument d}
* …
<!-- This is an optional element. Feel free to remove. -->
## More Information
{You might want to provide additional evidence/confidence for the decision outcome here and/or document the team agreement on the decision and/or define when/how this decision the decision should be realized and if/when it should be re-visited. Links to other decisions and resources might appear here as well.}