diff --git a/docs/README.md b/docs/README.md index 648a49b3..350db2a3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,8 @@ # Documentation -![](./assets/banner-docs.png) +![Documentation banner](./assets/banner-docs.png) The Documentation module provides documentation for Altis. -This module is used to generate the documentation you're currently reading, and can also be used [for your own custom project documentation](custom-documentation.md). +This module is used to generate the documentation you're currently reading, and can also be +used [for your own custom project documentation](custom-documentation.md). diff --git a/docs/additional-doc-set.md b/docs/additional-doc-set.md index 83854336..0b870c6b 100644 --- a/docs/additional-doc-set.md +++ b/docs/additional-doc-set.md @@ -15,49 +15,49 @@ const PROJECT_DOCS_SET_ID = 'project-docs'; // Custom user documentation Set. add_filter( 'altis.documentation.sets', static function ( array $sets ) { - if ( empty( $sets[ PROJECT_DOCS_SET_ID ] ) ) { - // Create our documentation set - $doc_set = new Set( PROJECT_DOCS_SET_ID, 'Project Documentation' ); + if ( empty( $sets[ PROJECT_DOCS_SET_ID ] ) ) { + // Create our documentation set + $doc_set = new Set( PROJECT_DOCS_SET_ID, 'Project Documentation' ); - // Add all documentation pages in a group. - $proj_docs = dirname( __DIR__ ) . '/project-docs'; - $group = new Group( 'Project Guides' ); - Altis\Documentation\add_docs_for_group( $group, $proj_docs ); + // Add all documentation pages in a group. + $proj_docs = dirname( __DIR__ ) . '/project-docs'; + $group = new Group( 'Project Guides' ); + Altis\Documentation\add_docs_for_group( $group, $proj_docs ); - // Add the group to the set - $doc_set->add_group( 'guides-group', $group ); - $doc_set->set_default_group_id( 'guides-group' ); + // Add the group to the set + $doc_set->add_group( 'guides-group', $group ); + $doc_set->set_default_group_id( 'guides-group' ); - // Add our set to the others. - $sets[ PROJECT_DOCS_SET_ID ] = $doc_set; - } + // Add our set to the others. + $sets[ PROJECT_DOCS_SET_ID ] = $doc_set; + } - return $sets; + return $sets; } ); ``` If you wish to include a link to your additional documentation page under a different menu, for example a top level -functional menu you can. Add a submenu page under a different menu but with the same menu id as the system uses. +functional menu you can. Add a sub-menu page under a different menu but with the same menu id as the system uses. ```php const PROJECT_DOCS_SET_ID = 'project-docs'; add_action( 'admin_menu', static function () { - $doc_set = \Altis\Documentation\get_documentation_set( PROJECT_DOCS_SET_ID ); - $page_hook = add_submenu_page( - 'my-custom-menu-id', - $doc_set->get_title(), - $doc_set->get_title(), - 'edit_posts', - sprintf( '%s-%s', \Altis\Documentation\UI\PAGE_SLUG, PROJECT_DOCS_SET_ID ), - static function () { - \Altis\Documentation\UI\render_page( PROJECT_DOCS_SET_ID ); - } ); - - // Add custom call back to load styles and scripts. - add_action( "load-$page_hook", static function () { - \Altis\Documentation\UI\load_page_assets(); - } ); + $doc_set = \Altis\Documentation\get_documentation_set( PROJECT_DOCS_SET_ID ); + $page_hook = add_submenu_page( + 'my-custom-menu-id', + $doc_set->get_title(), + $doc_set->get_title(), + 'edit_posts', + sprintf( '%s-%s', \Altis\Documentation\UI\PAGE_SLUG, PROJECT_DOCS_SET_ID ), + static function () { + \Altis\Documentation\UI\render_page( PROJECT_DOCS_SET_ID ); + } ); + + // Add custom call back to load styles and scripts. + add_action( "load-$page_hook", static function () { + \Altis\Documentation\UI\load_page_assets(); + } ); } ); ``` diff --git a/docs/custom-documentation.md b/docs/custom-documentation.md index affb9c93..9138b487 100644 --- a/docs/custom-documentation.md +++ b/docs/custom-documentation.md @@ -1,21 +1,28 @@ # Custom Documentation -The documentation module can be used for your own [custom modules](docs://getting-started/custom-modules.md), allowing you to build an internal knowledge base for your development team. +The documentation module can be used for your own [custom modules](docs://getting-started/custom-modules.md), allowing you to build +an internal knowledge base for your development team. -The built-in Documentation Set is intended for developer documentation. To add your documentation to the Developer Docs set, see the information below. To add additional sets of Documentation, perhaps for the users of your system, see [Additional Documentation Sets](./additional-doc-set.md). +The built-in Documentation Set is intended for developer documentation. To add your documentation to the Developer Docs set, see the +information below. To add additional sets of Documentation, perhaps for the users of your system, +see [Additional Documentation Sets](./additional-doc-set.md). ## Documentation Structure -Each module provides its own documentation. The Documentation module also includes project-level documentation, such as the [Guides](docs://guides/) and [Getting Started](docs://getting-started/) documentation. - -The Documentation module automatically takes Markdown files from a `docs/` directory within each module's root directory, and parses them into pages. These are hierarchically-structured based on the directory structure, with `README.md` acting as the index file for each directory. +Each module provides its own documentation. The Documentation module also includes project-level documentation, such as +the [Guides](docs://guides/) and [Getting Started](docs://getting-started/) documentation. +The Documentation module automatically takes Markdown files from a `docs/` directory within each module's root directory, and parses +them into pages. These are hierarchically-structured based on the directory structure, with `README.md` acting as the index file for +each directory. ## Formatting -Documentation files are standard Markdown, as supported by [Parsedown](https://parsedown.org/). They also support [relative and in-project links](linking.md). +Documentation files are standard Markdown, as supported by [Parsedown](https://parsedown.org/). They also +support [relative and in-project links](linking.md). -Markdown files can contain YAML front-matter, which specifies a list of "meta" information about the page itself. The following fields are supported: +Markdown files can contain YAML front-matter, which specifies a list of "meta" information about the page itself. The following +fields are supported: ```yaml --- @@ -30,18 +37,21 @@ order: 0 --- ``` -Headers have automatically generated fragment IDs attached for in-page linking. This automatic ID can be overridden if desired by suffixing with `{#id-name}`: +Headers have automatically generated fragment IDs attached for in-page linking. This automatic ID can be overridden if desired by +suffixing with `{#id-name}`: ```md # Header Name {#override-id} ``` - ## Custom Behavior -Internally, the Documentation module stores an ordered list of "groups", which have an ID and associated top-level pages. Each page has metadata, content, and potentially sub-pages. +Internally, the Documentation module stores an ordered list of "groups", which have an ID and associated top-level pages. Each page +has metadata, content, and potentially sub-pages. -The `altis.documentation.groups` filter is provided the ordered list of `Group` objects, and you can add or remove groups from here, or manipulate existing groups. The `Documentation\add_docs_for_group()` function may be useful for this; see `Documentation\filter_add_dev_docs_set()` to see how Altis generates developer documentation for modules. +The `altis.documentation.groups` filter is provided the ordered list of `Group` objects, and you can add or remove groups from here, +or manipulate existing groups. The `Documentation\add_docs_for_group()` function may be useful for this; +see `Documentation\filter_add_dev_docs_set()` to see how Altis generates developer documentation for modules. For example, to add your own Guides-style section: @@ -50,10 +60,10 @@ use Altis\Documentation\Group; use function Altis\Documentation\add_docs_for_group; add_filter( 'altis.documentation.groups', function ( array $groups, string $set_id ) { - if ( $set_id === 'dev-docs' ) { - $groups['project-guides'] = new Group( 'Project Guides' ); - add_docs_for_group( $groups['project-guides'], __DIR__ . '/our-guides' ); - } - return $groups; + if ( $set_id === 'dev-docs' ) { + $groups['project-guides'] = new Group( 'Project Guides' ); + add_docs_for_group( $groups['project-guides'], __DIR__ . '/our-guides' ); + } + return $groups; } ); ``` diff --git a/docs/linking.md b/docs/linking.md index b51ef311..71f13038 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -1,14 +1,15 @@ --- order: 10 --- + # Linking The Documentation module supports relative links and cross-linking between pages in documentation. - ## Relative Links -Within a given module's documentation, you can use relative links between files. These will be resolved during the rendering of the documentation. +Within a given module's documentation, you can use relative links between files. These will be resolved during the rendering of the +documentation. For example, to link to a document in the same directory called `doc.md`, you can format your link as: @@ -24,17 +25,20 @@ To link to a document in a subdirectory or a parent directory, use similar relat [Document in a subdirectory](./subdir/doc.md) ``` -Note that relative links can only be used between documents in a single module, and links to other modules should instead use cross-linking. - +Note that relative links can only be used between documents in a single module, and links to other modules should instead use +cross-linking. ## Cross-Linking Cross-linking refers to links from one module to another. This allows creating richer documentation, tying together various modules. -To link from one module to another, use the special URL scheme `docs://`. This should be followed by the name of the documentation group (typically the module ID), followed by a slash, followed by the page ID (typically a file path within the module's documentation directory). You can also link between Sets of documentation, for example from a developer document to a custom project guide, using an optional leading Set ID. +To link from one module to another, use the special URL scheme `docs://`. This should be followed by the name of the documentation +group (typically the module ID), followed by a slash, followed by the page ID (typically a file path within the module's +documentation directory). You can also link between Sets of documentation, for example from a developer document to a custom project +guide, using an optional leading Set ID. The full format is: -``` +```md docs://[{set}/]{group}/{id} ``` @@ -47,22 +51,25 @@ Consult the [branding documentation](docs://cms/branding.md) Or to link to a `block-templates.md` document in the 'Layout guide' of your project's custom documentation set. ```md -All available [block templates](docs://project-docs/layout/block-templates.md) are listed in the [Layout guide](docs://project-docs/layout/) +All available [block templates](docs://project-docs/layout/block-templates.md) are listed in +the [Layout guide](docs://project-docs/layout/) ``` -**Note:** while documentation group IDs generally align with module IDs, some special groups exist for meta documentation. This includes the Getting Started (ID `getting-started`) and Guides (ID `guides`) documentation, which are located in the `other-docs` directory of the Documentation module. - +**Note:** while documentation group IDs generally align with module IDs, some special groups exist for meta documentation. This +includes the Getting Started (ID `getting-started`) and Guides (ID `guides`) documentation, which are located in the `other-docs` +directory of the Documentation module. ## Internal Linking To enable rich documentation, you can link to internal resources on the site. -These links use the special `internal://` URL scheme. This is followed by the type of internal link, followed by a slash, followed by an optional additional path. The following types are available: +These links use the special `internal://` URL scheme. This is followed by the type of internal link, followed by a slash, followed +by an optional additional path. The following types are available: -* `internal://home/{path}` - URL on the frontend, equivalent to `home_url( $path )` -* `internal://site/{path}` - URL on the backend, equivalent to `site_url( $path )` -* `internal://admin/{path}` - Page in the admin, equivalent to `admin_url( $path )` -* `internal://network-admin/{path}` - Page in the network admin, equivalent to `network_admin_url( $path )` +- `internal://home/{path}` - URL on the frontend, equivalent to `home_url( $path )` +- `internal://site/{path}` - URL on the backend, equivalent to `site_url( $path )` +- `internal://admin/{path}` - Page in the admin, equivalent to `admin_url( $path )` +- `internal://network-admin/{path}` - Page in the network admin, equivalent to `network_admin_url( $path )` For example, to link to the current user's profile page: @@ -70,7 +77,6 @@ For example, to link to the current user's profile page: [View your profile](internal://admin/profile.php) ``` - ## Link to support You can easily display a direct link to the Altis support ticket system, pre-filled with the current environment stack name. diff --git a/other-docs/getting-started/README.md b/other-docs/getting-started/README.md index 643d7874..6d84e894 100644 --- a/other-docs/getting-started/README.md +++ b/other-docs/getting-started/README.md @@ -1,38 +1,46 @@ # Getting Started -![](./assets/banner-getting-started.png) +![Getting started banner](./assets/banner-getting-started.png) This guide covers getting started with a brand new Altis project. After reading this guide, you'll know: -* How to start a new Altis project -* How to run your Altis project locally -* The layout of an Altis project - +- How to start a new Altis project +- How to run your Altis project locally +- The layout of an Altis project ## Core concepts in Altis -Before you get started, it's important to be aware of a few core concepts which affect how you think about and build sites for Altis. - -With Altis, you will work on a **project**. This encompasses the codebase and the hosting provided by Altis Cloud. Each project can have multiple **sites** ("multisite"), which can represent multiple domains, subdomains, or other distinct websites. Sites within a single project share a common codebase, but can have different customizations applied to each site. +Before you get started, it's important to be aware of a few core concepts which affect how you think about and build sites for +Altis. -Altis is built on top of a WordPress foundation. WordPress and other dependencies of Altis are managed for you as part of the Altis version. +With Altis, you will work on a **project**. This encompasses the codebase and the hosting provided by Altis Cloud. Each project can +have multiple **sites** ("multisite"), which can represent multiple domains, subdomains, or other distinct websites. Sites within a +single project share a common codebase, but can have different customizations applied to each site. -Custom functionality on top of the Altis platform is implemented via WordPress **plugins**, and Altis is generally compatible with most WordPress plugins. (Subject to our [cloud environment limitations](docs://cloud/limitations.md).) +Altis is built on top of a WordPress foundation. WordPress and other dependencies of Altis are managed for you as part of the Altis +version. -Design and styling of sites is implemented via WordPress **themes**. Projects can contain many themes, and each site has a single theme active. Themes can be shared across sites, or used on only a single site. +Custom functionality on top of the Altis platform is implemented via WordPress **plugins**, and Altis is generally compatible with +most WordPress plugins. (Subject to our [cloud environment limitations](docs://cloud/limitations.md).) -Development work on your project will take place on your **local environment**, which is a full copy of the cloud environment you run locally with Docker. For testing and quality assurance, you'll use your **non-production cloud environment(s)** including development and staging. And when you're ready to go live, your **production environment** will serve live traffic to users. (Collectively, your cloud environments belong to a single **Altis instance**.) +Design and styling of sites is implemented via WordPress **themes**. Projects can contain many themes, and each site has a single +theme active. Themes can be shared across sites, or used on only a single site. +Development work on your project will take place on your **local environment**, which is a full copy of the cloud environment you +run locally with Docker. For testing and quality assurance, you'll use your **non-production cloud environment(s)** including +development and staging. And when you're ready to go live, your **production environment** will serve live traffic to users. ( +Collectively, your cloud environments belong to a single **Altis instance**.) ## Creating a new Altis project -The quickest way to get started with Altis is to use Composer. If you don't already have Composer, [follow the Composer installation guide](https://getcomposer.org/download/). +The quickest way to get started with Altis is to use Composer. If you don't already have +Composer, [follow the Composer installation guide](https://getcomposer.org/download/). To get started, run: -``` +```shell composer create-project altis/skeleton my-project ``` @@ -40,45 +48,51 @@ composer create-project altis/skeleton my-project Follow the interactive prompts to get started. -This will create a new directory called `my-project`, set up the project, and install the Composer dependencies. This directory is now ready for you to start working on your project. - -Composer is used to manage the version of Altis and its dependencies, and you'll need to be familiar with its commands including `install` and `upgrade`. +This will create a new directory called `my-project`, set up the project, and install the Composer dependencies. This directory is +now ready for you to start working on your project. +Composer is used to manage the version of Altis and its dependencies, and you'll need to be familiar with its commands +including `install` and `upgrade`. ## Your project's layout -Your project directory will contain a number of autogenerated files and directories. +Your project directory will contain a number of auto-generated files and directories. -* `composer.json` and `composer.lock` - These files allow you to specify the dependencies for your project. These files are used by Composer. -* `content/` - Contains all the functional code that makes up your project. - * `mu-plugins/` - Contains any custom modules for your project. - * `plugins/` - Contains WordPress plugins which can be activated on a per-site basis. - * `themes/` - Contains the available themes for your project. -* `index.php` - The main entrypoint used by Altis. Don't edit this file. -* `vendor/` - Contains the third-party dependencies for your project, including Altis. -* `wordpress/` - Contains WordPress, the core CMS used by Altis. -* `wp-config.php` - The main configuration used by Altis. Don't edit this file. +- `composer.json` and `composer.lock` - These files allow you to specify the dependencies for your project. These files are used by + Composer. +- `content/` - Contains all the functional code that makes up your project. + - `mu-plugins/` - Contains any custom modules for your project. + - `plugins/` - Contains WordPress plugins which can be activated on a per-site basis. + - `themes/` - Contains the available themes for your project. +- `index.php` - The main entrypoint used by Altis. Don't edit this file. +- `vendor/` - Contains the third-party dependencies for your project, including Altis. +- `wordpress/` - Contains WordPress, the core CMS used by Altis. +- `wp-config.php` - The main configuration used by Altis. Don't edit this file. -Generally, you'll be mostly working on files inside the `content` directory. This directory contains most of your project-specific code, including new functionality (in the form of "plugins") and visual styling (in the form of "themes"). +Generally, you'll be mostly working on files inside the `content` directory. This directory contains most of your project-specific +code, including new functionality (in the form of "plugins") and visual styling (in the form of "themes"). To start using your project, you'll need to set up a development environment. - ## Running your project locally -For local development, you'll also need to add a local server to your development dependencies. Altis includes a Docker based development environment out-of-the-box. See the [Local Server documentation](docs://local-server/) for more details. +For local development, you'll also need to add a local server to your development dependencies. Altis includes a Docker based +development environment out-of-the-box. See the [Local Server documentation](docs://local-server/) for more details. -Local Server requires [Docker Desktop for Mac or Windows](https://www.docker.com/products/docker-desktop), or Docker Engine on Linux. +Local Server requires [Docker Desktop for Mac or Windows](https://www.docker.com/products/docker-desktop), or Docker Engine on +Linux. To set up Local Server for Altis, run the following inside your project's directory: -``` +```shell composer server start ``` This will download and start all the services needed for Altis development. -The first time you run Local Server, it may take a little longer than usual, as it downloads the containers. Once this is complete, you will now have a working local site at https://my-project.altis.dev/. Visit `/wp-admin/` and login with `admin` / `password` to get started! +The first time you run Local Server, it may take a little longer than usual, as it downloads the containers. Once this is complete, +you will now have a working local site at . Visit `/wp-admin/` and login with `admin` / `password` to +get started! If you used a directory name other than `my-project` the default URL will be `https://.altis.dev`. @@ -88,11 +102,16 @@ To start the virtual machine again run `composer server start`. ### Docker alternative -If you are unable to use Docker on your computer, consider trying a [GitHub Codespaces environment](docs://dev-tools/cloud-dev-env/), which makes it possible to spin up a complete Altis development environment within your browser, without having to install any additional software on your computer. +If you are unable to use Docker on your computer, consider trying +a [GitHub Codespaces environment](docs://dev-tools/cloud-dev-env/), which makes it possible to spin up a complete Altis development +environment within your browser, without having to install any additional software on your computer. + ## Ready for development! + -When you first view your local site, you'll see the Altis splash page. This indicates that the site has been set up, and is awaiting your custom code. +When you first view your local site, you'll see the Altis splash page. This indicates that the site has been set up, and is awaiting +your custom code. Not familiar with WordPress already? Check out our guide to working on [your first theme](first-theme.md). diff --git a/other-docs/getting-started/configuration.md b/other-docs/getting-started/configuration.md index be9e1ace..285f6519 100644 --- a/other-docs/getting-started/configuration.md +++ b/other-docs/getting-started/configuration.md @@ -1,142 +1,156 @@ --- order: 20 --- + # Configuration -Configuration of Altis is done via the `composer.json` file in the root of your project. To configure specific modules, features and settings for Altis, add an `extra.altis` section to your `composer.json`. +Configuration of Altis is done via the `composer.json` file in the root of your project. To configure specific modules, features and +settings for Altis, add an `extra.altis` section to your `composer.json`. -``` +```json { - "name": "example/my-site", - "require": { - "altis/altis": "*", - }, - ... - "extra": { - "altis": { - - } - } + "name": "example/my-site", + "require": { + "altis/altis": "*" + }, + ... + "extra": { + "altis": { + } + } } ``` -When documentation refers to the configuration file, it's referring to this section of the `composer.json` file. In the event that something can be configured that can also edited via the admin UI the configuration in `composer.json` takes precedence. +When documentation refers to the configuration file, it's referring to this section of the `composer.json` file. In the event that +something can be configured that can also edited via the admin UI the configuration in `composer.json` takes precedence. -By convention, most module's settings reside in the path `altis.modules.$module.$setting`. For example, to require all users be logged in to view the website, you'd set the `modules.security.require-login` setting to `true`. +By convention, most module's settings reside in the path `altis.modules.$module.$setting`. For example, to require all users be +logged in to view the website, you'd set the `modules.security.require-login` setting to `true`. ```json { - "name": "example/my-site", - "require": { - "altis/altis": "*", - }, - ... - "extra": { - "altis": { - "modules": { - "security": { - "require-login": true - } - } - } - } + "name": "example/my-site", + "require": { + "altis/altis": "*" + }, + ... + "extra": { + "altis": { + "modules": { + "security": { + "require-login": true + } + } + } + } } ``` ## Environment Specific Configuration -It's not unusual to want different configuration options for difference environments. For example, you may want to have the `require-login` feature enabled for all environments, except the `local` environment. Environment specific configuration is provided in the form `altis.environments.$environment`. +It's not unusual to want different configuration options for difference environments. For example, you may want to have +the `require-login` feature enabled for all environments, except the `local` environment. Environment specific configuration is +provided in the form `altis.environments.$environment`. ```json { - "name": "example/my-site", - "require": { - "altis/altis": "*", - }, - ... - "extra": { - "altis": { - "modules": { - "security": { - "require-login": true - } - }, - "environments": { - "local": { - "modules": { - "security": { - "require-login": false - } - } - } - } - } - } + "name": "example/my-site", + "require": { + "altis/altis": "*" + }, + ... + "extra": { + "altis": { + "modules": { + "security": { + "require-login": true + } + }, + "environments": { + "local": { + "modules": { + "security": { + "require-login": false + } + } + } + } + } + } } ``` -Environment configuration is merged with the global `altis` configuration, with the matching environment options overriding anything specific in the global configuration. The environment type is matched against the value return by the function `Altis\get_environment_type()`. The environment type will typically be any of `local`, `development`, `staging` or `production`. +Environment configuration is merged with the global `altis` configuration, with the matching environment options overriding anything +specific in the global configuration. The environment type is matched against the value return by the +function `Altis\get_environment_type()`. The environment type will typically be any of `local`, `development`, `staging` +or `production`. ### Continuous Integration -There is a special environment type you can use to override the configuration in CI environments which extends the `local` environment settings if any. Use the key `ci` to apply these settings: +There is a special environment type you can use to override the configuration in CI environments which extends the `local` +environment settings if any. Use the key `ci` to apply these settings: ```json { - "name": "example/my-site", - "require": { - "altis/altis": "*", - }, - "extra": { - "altis": { - "environments": { - "ci": { - "modules": { - "cloud": { - "cavalcade": false - } - } - } - } - } - } + "name": "example/my-site", + "require": { + "altis/altis": "*" + }, + "extra": { + "altis": { + "environments": { + "ci": { + "modules": { + "cloud": { + "cavalcade": false + } + } + } + } + } + } } ``` ## Custom Configuration -When developing custom code and features, it's recommended to make use of the configuration file and APIs so all configuration can be centrally located and machine readable. By convention it's also recommended to use a namespace in the `extra.altis` object to ensure your custom configuration settings don't collide with Altis current or future settings. +When developing custom code and features, it's recommended to make use of the configuration file and APIs so all configuration can +be centrally located and machine readable. By convention it's also recommended to use a namespace in the `extra.altis` object to +ensure your custom configuration settings don't collide with Altis current or future settings. -Suppose you have built a feature that published stories to Twitter on publish. You can make use of the configuration file to provide the Twitter OAuth 2 credentials that should be used. It's quite likely you'd want to make use of environment specific overrides so the `staging` site publishes to a different Twitter account. +Suppose you have built a feature that published stories to Twitter on publish. You can make use of the configuration file to provide +the Twitter OAuth 2 credentials that should be used. It's quite likely you'd want to make use of environment specific overrides so +the `staging` site publishes to a different Twitter account. ```json { - "name": "example/my-site", - "require": { - "altis/altis": "*", - }, - ... - "extra": { - "altis": { - "environments": { - "staging": { - "my-project": { - "twitter-oauth2-token": "xxxxxxxxx" - } - }, - "production": { - "my-project": { - "twitter-oauth2-token": "yyyyyyyyy" - } - } - } - } - } + "name": "example/my-site", + "require": { + "altis/altis": "*" + }, + ... + "extra": { + "altis": { + "environments": { + "staging": { + "my-project": { + "twitter-oauth2-token": "xxxxxxxxx" + } + }, + "production": { + "my-project": { + "twitter-oauth2-token": "yyyyyyyyy" + } + } + } + } + } } ``` -To get the value of your custom configuration at runtime, use the `Altis\get_config()` function. This function will automatically handle the environment specific overrides. +To get the value of your custom configuration at runtime, use the `Altis\get_config()` function. This function will automatically +handle the environment specific overrides. ```php $token = Altis\get_config()['my-project']['twitter-oauth2-token']; @@ -146,9 +160,12 @@ new TwitterClient( $token ); ## Configuration in PHP -While it is preferred to use the JSON configuration wherever possible in some cases you may need an escape hatch or some further processing of the JSON config such as defining constants. +While it is preferred to use the JSON configuration wherever possible in some cases you may need an escape hatch or some further +processing of the JSON config such as defining constants. -Altis will automatically load a file located at `.config/load.php` in the root directory of your project if present. This is designed to be an entry point for loading files with more appropriate names. In addition the [Core Module functions](docs://core/README.md) will be available to you. For example: +Altis will automatically load a file located at `.config/load.php` in the root directory of your project if present. This is +designed to be an entry point for loading files with more appropriate names. In addition +the [Core Module functions](docs://core/README.md) will be available to you. For example: ```php -
-

-
- -
-
+ the_post(); + ?> +
+

+
+ +
+
@@ -111,23 +135,27 @@ endwhile; Reload your site, and you'll see the example post created on installation rendered onto the page. -This basic loop uses template tags, recognizable by the `the_` prefix. These functions output their data directly to the page, and are escaped automatically for their typical contexts. To access this data instead, most template tags also have a `get_the_` variant, which returns the data instead. - +This basic loop uses template tags, recognizable by the `the_` prefix. These functions output their data directly to the page, and +are escaped automatically for their typical contexts. To access this data instead, most template tags also have a `get_the_` +variant, which returns the data instead. ### More Complex Loops and Templates -For more complex loops, we recommend using a more complex starter theme. [Underscores by Automattic](https://github.com/Automattic/_s) includes a full set of templates, providing much more functionality out of the box. - -Consult the [WordPress theme documentation](https://developer.wordpress.org/themes/) for more information about loops, the template hierarchy, and other parts of themes. +For more complex loops, we recommend using a more complex starter +theme. [Underscores by Automattic](https://github.com/Automattic/_s) includes a full set of templates, providing much more +functionality out of the box. +Consult the [WordPress theme documentation](https://developer.wordpress.org/themes/) for more information about loops, the template +hierarchy, and other parts of themes. ## Full Site Editing -While the above documentation will guide you through setting up a basic classic theme, you may also wish to explore enabling Full Site Editing for your theme. +While the above documentation will guide you through setting up a basic classic theme, you may also wish to explore enabling Full +Site Editing for your theme. [You can read more about the Full Site Editing feature and how to enable it here](docs://cms/full-site-editing.md). - ## Next Steps -With a visual style established, the next step to getting started is to begin enabling custom functionality for your site. This is controlled through the [project's configuration](configuration.md). +With a visual style established, the next step to getting started is to begin enabling custom functionality for your site. This is +controlled through the [project's configuration](configuration.md). diff --git a/other-docs/getting-started/third-party-plugins.md b/other-docs/getting-started/third-party-plugins.md index cd43b6f2..053018ca 100644 --- a/other-docs/getting-started/third-party-plugins.md +++ b/other-docs/getting-started/third-party-plugins.md @@ -1,58 +1,75 @@ --- order: 40 --- -# Third-Party Plugins -Altis is built atop the open-source WordPress CMS. In addition to custom Altis modules, you can also use third-party WordPress plugins to take advantage of the open-source ecosystem. +# Third-Party Plugins -There are two ways to add plugins to your project: either by managing them via Composer, or commit the plugins to your project (or use submodules). +Altis is built atop the open-source WordPress CMS. In addition to custom Altis modules, you can also use third-party WordPress +plugins to take advantage of the open-source ecosystem. +There are two ways to add plugins to your project: either by managing them via Composer, or commit the plugins to your project (or +use submodules). ## Managing Plugins via Composer Plugins can be managed via Composer dependencies, similar to how Altis modules are added. -Some plugins are natively available via Composer, and can be found on Packagist via the [`wordpress-plugin` type](https://packagist.org/?type=wordpress-plugin). +Some plugins are natively available via Composer, and can be found on Packagist via +the [`wordpress-plugin` type](https://packagist.org/?type=wordpress-plugin). -The starter project automatically configures Composer to install plugins into the correct place for your project, but if you started from scratch you may need to configure this yourself. First, install `composer/installers` as a dependency, which will allow installing these types of projects. Next, configure Composer under `extra.installer-paths` in your `composer.json` to place them into the correct directory: +The starter project automatically configures Composer to install plugins into the correct place for your project, but if you started +from scratch you may need to configure this yourself. First, install `composer/installers` as a dependency, which will allow +installing these types of projects. Next, configure Composer under `extra.installer-paths` in your `composer.json` to place them +into the correct directory: ```json -"extra": { - "installer-paths": { - "content/plugins/{$name}/": [ - "type:wordpress-plugin" - ], - "content/themes/{$name}/": [ - "type:wordpress-theme" - ] - } +{ + "extra": { + "installer-paths": { + "content/plugins/{$name}/": [ + "type:wordpress-plugin" + ], + "content/themes/{$name}/": [ + "type:wordpress-theme" + ] + } + } } ``` -Some plugins are not available natively on Packagist, and are available only via the [WordPress.org Plugin Repository](https://wordpress.org/plugins/). These can be installed via a third-party Composer repository called [WordPress Packagist](https://wpackagist.org/). +Some plugins are not available natively on Packagist, and are available only via +the [WordPress.org Plugin Repository](https://wordpress.org/plugins/). These can be installed via a third-party Composer repository +called [WordPress Packagist](https://wpackagist.org/). -To set up and configure WordPress Packagist, first add the custom repository to your project's `composer.json` under a `repositories` key: +To set up and configure WordPress Packagist, first add the custom repository to your project's `composer.json` under +a `repositories` key: ```json -"repositories": [ - { - "type":"composer", - "url":"https://wpackagist.org" - } -] +{ + "repositories": [ + { + "type": "composer", + "url": "https://wpackagist.org" + } + ] +} ``` -To install plugins, you can now use `composer require wpackagist-plugin/{plugin-name}`, where `{plugin-name}` is the "slug" of the plugin from the WordPress.org Plugin Repository to install. +To install plugins, you can now use `composer require wpackagist-plugin/{plugin-name}`, where `{plugin-name}` is the "slug" of the +plugin from the WordPress.org Plugin Repository to install. -For example, [Akismet](https://wordpress.org/plugins/akismet/) is available at `https://wordpress.org/plugins/akismet/`, so the "slug" of the plugin is `akismet`. You can install this with: +For example, [Akismet](https://wordpress.org/plugins/akismet/) is available at `https://wordpress.org/plugins/akismet/`, so the " +slug" of the plugin is `akismet`. You can install this with: ```sh composer require wpackagist-plugin/akismet ``` - ## Managing Plugins Manually -Third-party plugins should be placed inside the `content/plugins/` directory. Each plugin should be contained in its own directory within the plugins directory, with one file containing a [comment header](https://developer.wordpress.org/plugins/plugin-basics/#getting-started). +Third-party plugins should be placed inside the `content/plugins/` directory. Each plugin should be contained in its own directory +within the plugins directory, with one file containing +a [comment header](https://developer.wordpress.org/plugins/plugin-basics/#getting-started). -Generally speaking, we recommend using Git submodules if you're installing modules manually. This reduces the amount of code necessary in your repository, and makes managing updates much easier. +Generally speaking, we recommend using Git submodules if you're installing modules manually. This reduces the amount of code +necessary in your repository, and makes managing updates much easier. diff --git a/other-docs/guides/3rd-party-compatibility/README.md b/other-docs/guides/3rd-party-compatibility/README.md index cb3eaafc..d5c8eace 100644 --- a/other-docs/guides/3rd-party-compatibility/README.md +++ b/other-docs/guides/3rd-party-compatibility/README.md @@ -1,13 +1,16 @@ # 3rd Party Compatibility -The [WordPress plugin ecosystem](https://wordpress.org/plugins/) offers a huge variety of features and tools that can supercharge your application even further than those provided out of the box by Altis. +The [WordPress plugin ecosystem](https://wordpress.org/plugins/) offers a huge variety of features and tools that can supercharge +your application even further than those provided out of the box by Altis. -This guide outlines known compatibility issues and remediations for the most popular third party plugins used on the Altis platform. +This guide outlines known compatibility issues and remediation for the most popular third party plugins used on the Altis platform. ## MultilingualPress Pro -[MultilingualPress](https://multilingualpress.org/) by Inpsyde provides advanced capabilities for connecting content across sites on a network and detecting user language preferences. +[MultilingualPress](https://multilingualpress.org/) by Inpsyde provides advanced capabilities for connecting content across sites on +a network and detecting user language preferences. **Known issues:** -- MultilingualPress uses built in caches that are not compatible or required with Altis' object caching. It is recommended to switch off the built in caches via the MultilingualPress settings screen. +- MultilingualPress uses built in caches that are not compatible or required with Altis' object caching. It is recommended to switch + off the built in caches via the MultilingualPress settings screen. diff --git a/other-docs/guides/README.md b/other-docs/guides/README.md index 037302c9..060d76b4 100644 --- a/other-docs/guides/README.md +++ b/other-docs/guides/README.md @@ -1,5 +1,7 @@ # Guides -![](./assets/banner-guides.png) +![Guides banner](./assets/banner-guides.png) -Altis Guides are here to help you with meta issues and larger tasks that don't fit in to any specific module. Here you can find help with [how to upgrade](./upgrading/README.md), [how to migrate to Altis](./migrating-from-wordpress.md), [how to use Altis as a headless CMS](./headless/), [how to automate updates](./automatic-updates.md) and more. +Altis Guides are here to help you with meta issues and larger tasks that don't fit in to any specific module. Here you can find help +with [how to upgrade](./upgrading/README.md), [how to migrate to Altis](./migrating-from-wordpress.md), +[how to use Altis as a headless CMS](./headless/), [how to automate updates](./automatic-updates.md) and more. diff --git a/other-docs/guides/altis-releases.md b/other-docs/guides/altis-releases.md index 44a83061..b04645ff 100644 --- a/other-docs/guides/altis-releases.md +++ b/other-docs/guides/altis-releases.md @@ -1,35 +1,41 @@ # Altis Releases -Altis has one major version for the entire platform, and each module underneath it also has a major version and a bugfix version. The full version number for all modules follows the following scheme: +Altis has one major version for the entire platform, and each module underneath it also has a major version and a bug fix version. +The full version number for all modules follows the following scheme: -``` -.. +```text +.. ``` -Every Altis major release synchronises all versions. For example, Altis version 42 would contain CMS version 42.0.0, Cloud 42.0.0, etc upon release. +Every Altis major release synchronises all versions. For example, Altis version 42 would contain CMS version 42.0.0, Cloud 42.0.0, +etc upon release. The `.0` version is treated as the [long-term support](./long-term-support.md) version. ![Release timeline diagram](./assets/release-timeline.png) +## Bug fix Releases -## Bugfix Releases - -Each module releases bugfixes separately when necessary. You should ensure you are always running the latest bugfix version of each module by periodically running `composer update` and committing the updated `composer.lock` file. +Each module releases bug fixes separately when necessary. You should ensure you are always running the latest bug fix version of +each module by periodically running `composer update` and committing the updated `composer.lock` file. -These bugfix versions are generally not synchronised. Bugs occurring across multiple modules may trigger bugfix releases for each module. +These bug fix versions are generally not synchronised. Bugs occurring across multiple modules may trigger bug fix releases for each +module. For example, the latest versions for Altis version 42 may include CMS version 42.0.6, Cloud 42.0.2 and Media 42.0.0. - ## Module Releases -Modules may preview new features periodically, and outside of the Altis major version. These new features are stable and production-ready, but may be incomplete, so we treat them as preview releases. Once they are feature-complete, they will be included in the next Altis major release. +Modules may preview new features periodically, and outside of the Altis major version. These new features are stable and +production-ready, but may be incomplete, so we treat them as preview releases. Once they are feature-complete, they will be included +in the next Altis major release. These preview releases always have a `` component larger than `0`. -For example: with latest version of Altis at version 42, the CMS module may preview a new feature. We will release 42.1.0 with this new feature, and those who want to use it could opt-in to using 42.1.0, while keeping the other modules at 42.0.0 +For example: with latest version of Altis at version 42, the CMS module may preview a new feature. We will release 42.1.0 with this +new feature, and those who want to use it could opt-in to using 42.1.0, while keeping the other modules at 42.0.0 -Only the latest module major release and the `0` release are supported. For example, if the CMS module has releases at 42.0.0, 42.1.0, 42.2.0, and 42.3.0, only the 42.0.0 and 42.3.0 release lines would be supported. +Only the latest module major release and the `0` release are supported. For example, if the CMS module has releases at 42.0.0, +42.1.0, 42.2.0, and 42.3.0, only the 42.0.0 and 42.3.0 release lines would be supported. [Learn how to opt in to module preview releases here](./module-preview-releases.md) diff --git a/other-docs/guides/automatic-updates.md b/other-docs/guides/automatic-updates.md index 98c45a5c..a926449a 100644 --- a/other-docs/guides/automatic-updates.md +++ b/other-docs/guides/automatic-updates.md @@ -1,39 +1,42 @@ # Automating Updates -The recommended approach to automating updates to Altis is to use GitHub's Dependabot feature. This feature is provided for free by GitHub. +The recommended approach to automating updates to Altis is to use GitHub's Dependabot feature. This feature is provided by GitHub. -The service monitors the dependencies in your project and creates automatic pull requests whenever there are updates. This will help you to keep your projects healthy and always running the latest patch release of all Altis modules. +The service monitors the dependencies in your project and creates automatic pull requests whenever there are updates. This will help +you to keep your projects healthy and always running the latest patch release of all Altis modules. ## Setting Up Dependabot -To get started create a `dependabot.yml` file in your project's `.github` directory, or if you already have an existing `dependabot.yml`, add the following config to it. +To get started create a `dependabot.yml` file in your project's `.github` directory, or if you already have an +existing `dependabot.yml`, add the following config to it. The minimum recommended configuration for Altis updates is as follows: ```yaml version: 2 updates: -# Enable version updates for Altis modules -- package-ecosystem: composer - # Look for `composer.json` and `composer.lock` files in the `root` directory - directory: / - # Create pull requests for updates (if any) once a day: - schedule: - interval: daily - versioning-strategy: lockfile-only - # Ensure all Altis modules recieve update PRs - allow: - - dependency-name: altis/* - - dependency-type: all - # Increase limit to number of Altis modules - open-pull-requests-limit: 15 + # Enable version updates for Altis modules + - package-ecosystem: composer + # Look for `composer.json` and `composer.lock` files in the `root` directory + directory: / + # Create pull requests for updates (if any) once a day: + schedule: + interval: daily + versioning-strategy: lockfile-only + # Ensure all Altis modules recieve update PRs + allow: + - dependency-name: altis/* + - dependency-type: all + # Increase limit to number of Altis modules + open-pull-requests-limit: 15 ``` -Finally commit this file to your repo, and you're done. +Finally commit this file to your repository, and you're done. ## Automatically Merging Dependabot PRs -You can also optionally use the [Dependabot Auto Merge GitHub Action](https://github.com/marketplace/actions/dependabot-auto-merge) to automatically merge Dependabot Pull Requests for Altis modules. +You can also optionally use the [Dependabot Auto Merge GitHub Action](https://github.com/marketplace/actions/dependabot-auto-merge) +to automatically merge Dependabot Pull Requests for Altis modules. To get started add the following to a new workflow called `.github/workflows/auto-merge.yml`: @@ -41,29 +44,30 @@ To get started add the following to a new workflow called `.github/workflows/aut name: auto-merge on: - pull_request_target: + pull_request_target: jobs: - auto-merge: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: ahmadnassri/action-dependabot-auto-merge@v2 - with: - github-token: ${{ secrets.mytoken }} + auto-merge: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ahmadnassri/action-dependabot-auto-merge@v2 + with: + github-token: ${{ secrets.mytoken }} ``` Secondly to target Altis modules only add a config file called `.github/auto-merge.yml` with the following configuration: ```yaml -- match: - dependency_name: altis/* - dependency_type: all - update_type: semver:patch +- match: + dependency_name: altis/* + dependency_type: all + update_type: semver:patch ``` ## Further Configuration -There are many more configuration options available and you can add additional update rules for different package ecosystems like npm to this file as well. +There are many more configuration options available and you can add additional update rules for different package ecosystems like +`npm` to this file as well. [The full Dependabot configuration documentation can be found here](https://help.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates). diff --git a/other-docs/guides/code-review/README.md b/other-docs/guides/code-review/README.md index e849be18..e637ffe7 100644 --- a/other-docs/guides/code-review/README.md +++ b/other-docs/guides/code-review/README.md @@ -1,38 +1,42 @@ # Code Review -All Code Review for Altis is done via GitHub in the pre set-up GitHub repository for your project. Specific development flow process varies project to project, this document only covers the required Human Made Code Review. +All Code Review for Altis is done via GitHub in the set up GitHub repository for your project. Specific development flow process +varies project to project, this document only covers the required Human Made Code Review. -It is required that all code review be performed on Git branches, via a GitHub Pull Request. When a given Git branch is ready for review, the following process should be followed: +It is required that all code review be performed on Git branches, via a GitHub Pull Request. When a given Git branch is ready for +review, the following process should be followed: 1. Open a Pull Request against the "mainline" branch (typically `main`, `development` or `staging`) 1. Make sure your Pull Request passes all status checks -Once the Pull Request is submitted, an automated code review will be performed. In this case, the Pull Request will be marked as "Changes Requested" and you should fix up any errors that are highlighted. +Once the Pull Request is submitted, an automated code review will be performed. In this case, the Pull Request will be marked as +"Changes Requested" and you should fix any errors that are highlighted. ## How will I know if there are issues with my code? Errors are highlighted within GitHub, under the review section. -![](../assets/altis-review-pr-failed.png) +![Screenshot of failed review output](../assets/altis-review-pr-failed.png) Details: -![](../assets/altis-review-pr-failed-details.png) +![Screenshot of failed review output showing details](../assets/altis-review-pr-failed-details.png) If no errors are found: -![](../assets/altis-review-pr.png) - +![Screenshot showing green checkmarks for test ](../assets/altis-review-pr.png) ## What types of code are checked? The types of code that are reviewed are JavaScript and PHP. CSS files can also be reviewed but are not at this point. -Note that [JavaScript code should not be minified](./minified-code.md), and instead should be built via the [build process](docs://cloud/build-scripts.md). +Note that [JavaScript code should not be minified](./minified-code.md), and instead should be built via +the [build process](docs://cloud/build-scripts.md). ## What is looked for? -Code review focuses on security, performance, and stability by testing for common vulnerabilities and problems, such as the OWASP Top Ten. +Code review focuses on security, performance, and stability by testing for common vulnerabilities and problems, such as the OWASP +Top Ten. This includes, but is not limited to: @@ -45,18 +49,22 @@ The [coding standards documentation](./standards.md) contains much more detail a ## What should I do if errors are found? -Before a pull request can be merged, the altis-review check must pass. - -In general, the errors should be addressed, using the provided details in order to resolve the issue. The Altis Cloud team is happy to provide guidance on how to solve specific errors, or potential changes to your architecture to avoid these. +Before a pull request can be merged, the `altis-review` check must pass. -In rare cases, the error may be a false positive or a result where the check does not possess the required logic to adequately evaluate the part of code. If you are certain this is the case (such as for false positives), the error may be ignored, using the method below. +In general, the errors should be addressed, using the provided details in order to resolve the issue. The Altis Cloud team is happy +to provide guidance on how to solve specific errors, or potential changes to your architecture to avoid these. +In rare cases, the error may be a false positive or a result where the check does not possess the required logic to adequately +evaluate the part of code. If you are certain this is the case (such as for false positives), the error may be ignored, using the +method below. ## Is there a way I can have lines ignored? {#ignore} -Lines of code can be ignored however entire files and folders can not. A comment is also required so that future reviewers understand why the part of code is ignored from ACR/ +Lines of code can be ignored however entire files and folders can not. A comment is also required so that future reviewers +understand why the part of code is ignored from ACR/ Example + ```php -1`. The Altis standards limit `posts_per_page` to 100. +The typical unbounded query in WordPress is using `WP_Query` with `'posts_per_page' => -1`. The Altis standards +limit `posts_per_page` to 100. Likewise, raw database queries without a `LIMIT` clause should not be used. -If you really do need to touch every post in the database, consider whether you can move your code into an offline solution; that is, into a wp-cli command or a cron task. This ensures that end users are shielded from potential scaling issues, and makes the operation fail-safe. These queries must still be bounded, but you can work in batches. - +If you really do need to touch every post in the database, consider whether you can move your code into an offline solution; that +is, into a wp-cli command or a cron task. This ensures that end users are shielded from potential scaling issues, and makes the +operation fail-safe. These queries must still be bounded, but you can work in batches. ### Prepare all database queries {#prepare-queries} @@ -39,8 +50,8 @@ If you really do need to touch every post in the database, consider whether you All dynamic parameters in database queries must be escaped for the SQL query to avoid SQL injection bugs. -Ensure all SQL statements are wrapped in a call to [`$wpdb->prepare()`](https://developer.wordpress.org/reference/classes/wpdb/prepare/). - +Ensure all SQL statements are wrapped in a call +to [`$wpdb->prepare()`](https://developer.wordpress.org/reference/classes/wpdb/prepare/). ## Check input and output @@ -48,14 +59,18 @@ Ensure all SQL statements are wrapped in a call to [`$wpdb->prepare()`](https:// *Sniff: `HM.Security.EscapeOutput`* -Escaping is used to ensure that data is safe to be output to the browser. Data must be escaped using one of Altis' built-in escaping functions before output. The type of escaping function to use depends on the context in which the data is output. - -This is because data might be safe or unsafe depending on where it is output. Data that is perfectly safe to output between two HTML tags might not be safe to output inside of a piece of inline JavaScript. +Escaping is used to ensure that data is safe to be output to the browser. Data must be escaped using one of Altis' built-in escaping +functions before output. The type of escaping function to use depends on the context in which the data is output. -When writing code, always escape immediately before output. This is referred to as **late escaping**. This makes it clear when and how data is escaped, making the code easy to review and to understand. +This is because data might be safe or unsafe depending on where it is output. Data that is perfectly safe to output between two HTML +tags might not be safe to output inside of a piece of inline JavaScript. -It also avoids introducing security issues by accident. If the contents of a variable are escaped first, and then output later in the code, then this code is secure at the time it's written. However if at a later time, then escaping is removed from the variable, then all the instances in which the variable is output are now vulnerable. Late escaping avoids this problem. +When writing code, always escape immediately before output. This is referred to as **late escaping**. This makes it clear when and +how data is escaped, making the code easy to review and to understand. +It also avoids introducing security issues by accident. If the contents of a variable are escaped first, and then output later in +the code, then this code is secure at the time it's written. However if at a later time, then escaping is removed from the variable, +then all the instances in which the variable is output are now vulnerable. Late escaping avoids this problem. ### Validate and sanitize input {#validate-sanitize-input} @@ -65,21 +80,27 @@ All user input must be validated and sanitized before being used in the codebase Validation and sanitization are two separate but related concepts. -When validating data, you are looking for certain criteria in the data. Or simply put, you’re saying "I want the data to have this, this, and this". Sanitisation on the other hand is about removing all the harmful elements from the data. In essence you’re saying "I don’t want the data to have this, this, and this". - -But the difference is more than just conceptual. With validation, we store the data once we have verified it’s valid. If not, we discard it. +When validating data, you are looking for certain criteria in the data. Or simply put, you’re saying "I want the data to have this, +this, and this". Sanitization on the other hand is about removing all the harmful elements from the data. In essence you’re +saying "I don’t want the data to have this, this, or this". -With sanitization, we take the data, and remove everything we don’t want. This means that we might change the data during the sanitization process. So in the case of user input, it is not guaranteed that all the input is kept. So it’s important that you choose the right sanitization functions, to keep the data intact. +The difference is more than just conceptual. With validation, we store the data once we have verified it’s valid. If not, we +discard it. +With sanitization, we take the data, and remove everything we don’t want. This means that we might change the data during the +sanitization process. So in the case of user input, it is not guaranteed that all the input is kept. So it’s important that you +choose the right sanitization functions, to keep the data intact. ## Check CSRF tokens (nonces) on destructive requests {#nonce} *Sniff: `HM.Security.NonceVerification`* -Altis provides a system called [nonces](https://developer.wordpress.org/plugins/security/nonces/) which prevent [cross-site request forgery (CSRF)](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) vulnerabilities. - -Nonces should be checked on every request which performs a destructive action, as they check the user intended to take the action. This should be paired with checking user capabilities, so that you are checking both user authorization and user intent. +Altis provides a system called [nonces](https://developer.wordpress.org/plugins/security/nonces/) which +prevent [cross-site request forgery (CSRF)](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) +vulnerabilities. +Nonces should be checked on every request which performs a destructive action, as they check the user intended to take the action. +This should be paired with checking user capabilities, so that you are checking both user authorization and user intent. ## Hide debugging data @@ -87,19 +108,24 @@ Nonces should be checked on every request which performs a destructive action, a *Sniff: `WordPress.Security.PluginMenuSlug`* -`__FILE__` should not be used in admin menu slugs, as it exposes information to users about the underlying filesystem. While this is not a security issue directly, it can make privilege escalation much easier, so is to be avoided as part of a security-in-depth mentality. - +`__FILE__` should not be used in admin menu slugs, as it exposes information to users about the underlying filesystem. While this is +not a security issue directly, it can make privilege escalation much easier, so is to be avoided as part of a security-in-depth +mentality. ### Do not output debugging information {#development-functions} *Sniff: `WordPress.PHP.DevelopmentFunctions`* -Debugging functions such as `var_dump()` and `print_r()` must not be used, as they can output debug information directly to unauthorized users, and can expose internal implementation data of the application. Additionally, errors must not be set to be output directly to users for the same reason. - -Altis provides full error logging functionality via the [Altis Dashboard](docs://cloud/dashboard.md). Custom logging information can be output to these logs via the `error_log()` and `trigger_error()` functions. +Debugging functions such as `var_dump()` and `print_r()` must not be used, as they can output debug information directly to +unauthorized users, and can expose internal implementation data of the application. Additionally, errors must not be set to be +output directly to users for the same reason. -Additionally, the [Altis Dev Tools](docs://dev-tools/) can be used for inspecting data and logging detailed information. The Dev Tools module is enabled by default on development and staging environments, and can be enabled via your configuration on production environments if desired. +Altis provides full error logging functionality via the [Altis Dashboard](docs://cloud/dashboard.md). Custom logging information can +be output to these logs via the `error_log()` and `trigger_error()` functions. +Additionally, the [Altis Dev Tools](docs://dev-tools/) can be used for inspecting data and logging detailed information. The Dev +Tools module is enabled by default on development and staging environments, and can be enabled via your configuration on production +environments if desired. ## Use Altis functionality @@ -109,8 +135,9 @@ Additionally, the [Altis Dev Tools](docs://dev-tools/) can be used for inspectin When built-in functions in Altis exist, they should be preferred over using PHP or third-party code. -This includes functionality like making remote requests via cURL, which should instead use the [HTTP API](https://developer.wordpress.org/apis/handbook/http/). This ensures that remote requests appear in debugging tooling and logging. - +This includes functionality like making remote requests via cURL, which should instead use +the [HTTP API](https://developer.wordpress.org/apis/handbook/http/). This ensures that remote requests appear in debugging tooling +and logging. ### Do not use deprecated functions {#no-deprecated} @@ -118,16 +145,14 @@ This includes functionality like making remote requests via cURL, which should i Deprecated functions should not be used, as they often contain out-moded functionality, and may be removed at a later date. - ### Use better alternatives where possible {#no-discouraged} *Sniff: `WordPress.WP.DiscouragedConstants`, `WordPress.WP.DiscouragedFunctions`* Certain Altis functions and constants have alternatives, prefer the better alternative. -For example, use `wp_safe_redirect()` instead of `wp_redirect()`. This validates the redirect is to an allowed domain (current site by default), and avoids the [open redirect vulnerability class](https://cwe.mitre.org/data/definitions/601.html). - - +For example, use `wp_safe_redirect()` instead of `wp_redirect()`. This validates the redirect is to an allowed domain (current site +by default), and avoids the [open redirect vulnerability class](https://cwe.mitre.org/data/definitions/601.html). ## Best practices @@ -135,26 +160,29 @@ For example, use `wp_safe_redirect()` instead of `wp_redirect()`. This validates *Sniff: `Generic.PHP.DisallowShortOpenTag`* -Only full php tags (``, `<%=`), or the `