Skip to content

Commit

Permalink
DOC Add information about deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Dec 20, 2022
1 parent 3ffd586 commit e646a9b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 24 deletions.
2 changes: 1 addition & 1 deletion en/00_Getting_Started/03_Environment_Management.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ Silverstripe core environment variables are listed here, though you're free to d
| `SS_DATABASE_TIMEZONE`| Set the database timezone to something other than the system timezone.
| `SS_DATABASE_NAME` | Set the database name. Assumes the `$database` global variable in your config is missing or empty. |
| `SS_DATABASE_CHOOSE_NAME`| Boolean/Int. If defined, then the system will choose a default database name for you if one isn't give in the $database variable. The database name will be "SS_" followed by the name of the folder into which you have installed Silverstripe. If this is enabled, it means that the phpinstaller will work out of the box without the installer needing to alter any files. This helps prevent accidental changes to the environment. If `SS_DATABASE_CHOOSE_NAME` is an integer greater than one, then an ancestor folder will be used for the database name. This is handy for a site that's hosted from /sites/examplesite/www or /buildbot/allmodules-2.3/build. If it's 2, the parent folder will be chosen; if it's 3 the grandparent, and so on.|
| `SS_DEPRECATION_ENABLED` | Enable deprecation notices for this environment.|
| `SS_DEPRECATION_ENABLED` | Enable deprecation notices for this environment. `SS_ENVIRONMENT_TYPE` must be set to `dev` for deprecation notices to show. |
| `SS_ENVIRONMENT_TYPE`| The environment type: dev, test or live.|
| `SS_DEFAULT_ADMIN_USERNAME`| The username of the default admin. This is a user with administrative privileges.|
| `SS_DEFAULT_ADMIN_PASSWORD`| The password of the default admin. This will not be stored in the database.|
Expand Down
75 changes: 52 additions & 23 deletions en/05_Contributing/04_Release_Process.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,59 +150,88 @@ In these cases, it is best practice to "refactor" these APIs into something more
The Silverstripe CMS team acknowledges that developers have built a lot of code on top of existing APIs,
so we strive for giving ample warning on any upcoming changes through a "deprecation cycle".

How to deprecate an API:
### Deprecating API:

* Add a `@deprecated` item to the docblock tag, with a `{@link <class>}` item pointing to the new API to use.
* Update the deprecated code to throw a [Deprecation::notice()](api:SilverStripe\Dev\Deprecation::notice()) error.
* Both the docblock and error message should contain the **target version** where the functionality is removed.
So, if you're committing the change to a *3.1* minor release, the target version will be *4.0*.
* Deprecations should not be committed to patch releases
* Both the docblock and error message should contain the **version** where the functionality is deprecated from.
So, if you're committing the change to a *4.12* minor release, the target version will be *4.12.0*.
* Deprecations should only be committed to pre-release branches, ideally before they enter the "beta" phase.
If deprecations are introduced after this point, their target version needs to be increased by one.
* Make sure that the old deprecated function works by calling the new function - don't have duplicated code!
* The commit message should contain an `API` prefix (see ["commit message format"](code#commit-messages))
* Document the change in the [changelog](/changelogs) for the next release
* Deprecated APIs can be removed only after developers have had sufficient time to react to the changes. Hence, deprecated APIs should be removed in MAJOR releases only. Between MAJOR releases, leave the code in place with a deprecation warning.
* Exceptions to the deprecation cycle are APIs that have been moved into their own module, and continue to work with the new minor release. These changes can be performed in a single minor release without a deprecation period.
* Add a `warnings` entry to the module's `.upgrade.yml` file so the
[Silverstripe Upgrader can flag deprecated APIs](/upgrading/upgrading_module#upgradeyml).

When deprecating a method:

* Add the following docblock `@deprecated 1.2.3 Use anotherMethod() instead`
* Deprecation::notice('1.2.3', 'Use anotherMethod() instead'); to the top of the method

When deprecating a class:

* Add the following docblock `@deprecated 1.2.3 Use AnotherClass instead`
* Add `Deprecation::notice('1.2.3', 'Use AnotherClass instead', SCOPE_CLASS);` to the top of `__construct()`

When deprecating config:

* Add the following docblock `@deprecated 1.2.3 Use different_config instead`

If there is no immediate replacement for deprecated code that is being called, either because the replacement is not available until the next major version, or because there is not a plan for there to be a replacement, the message should be "Will be removed without equivalent functionality to replace it."

### Avoiding deprecated API

Wherever possible, once some API has been deprecated, we should stop using it. This allows projects to emit deprecation notices and have an accurate list of code that they need to change.

In some cases, we may not yet have a replacement for code that is required for the current major - but that we still have to call and support internally. In these cases, since we can't stop calling the code, wrap the call to the deprecated code in `Deprecation::withNoReplacement()` e.g:

```php
Deprecation::withNoReplacement(function () {
$this->myDeprecatedMethod();
});
```

For any unit tests using the deprecated method/class/config, add the following the the top of the unit test. This ensures that deprecated code is still supported as usual when `Deprecation` notices are not enabled, though the tests are skipped whenever you are testing to see if deprecated code is still be called.
```php
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
```

Here's an example for replacing `Director::isDev()` with a (theoretical) `Env::is_dev()`:

```php
/**
* Returns true if you are in development mode
* @deprecated 4.0 Use {@link Env::is_dev()} instead.
* Returns true if your are in development mode
* @deprecated 4.12.0 Use Env::is_dev() instead.
*/
public function isDev()
{
Deprecation::notice('4.0', 'Use Env::is_dev() instead');
Deprecation::notice('4.12.0', 'Use Env::is_dev() instead');
return Env::is_dev();
}
```

This change could be committed to a minor release like *3.2.0*, and remains deprecated in all subsequent minor releases
(e.g. *3.3.0*, *3.4.0*), until a new major release (e.g. *4.0.0*), at which point it gets removed from the codebase.

Deprecation notices are enabled by default on dev environment, but can be
turned off via either `.env` or in your _config.php. Deprecation
notices are always disabled on both live and test.
This change could be committed to a minor release like *4.12.0*, and remains deprecated in all subsequent minor releases
(e.g. *4.13.0*), until a new major release (e.g. *5.0.0*), at which point it gets removed from the codebase.

## Enabling deprecation notices

`app/_config.php`



```php
Deprecation::set_enabled(false);
```
Deprecation notices aren't enabled by default. They can be turned on for dev environments with one of the following methods:

`.env`

```
SS_DEPRECATION_ENABLED="0"
SS_DEPRECATION_ENABLED=true
```

`app/_config.php`
```php
Deprecation::enable();
```

To test that deprecated code is no longer being called, run code via CI in an installer/kitchen-sink project that has deprecations enabled. Then view the CI output in the "Run tests" of the github actions CI job and/or view the contents of silverstripe.log in the github actions CI artifact to see if there are deprecation warnings. There should be zero deprecation warnings.

## Security Releases

Expand Down
30 changes: 30 additions & 0 deletions en/05_Contributing/18_Deprecations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Deprecations
---

# Upgrade a project to CMS 5

## Updating your codebase to use Silverstripe CMS 5 API

You'll need to go through your codebase to remove references to deprecated APIs and update your project logic.

Silverstripe CMS 5 introduces many API changes. They include a deprecation message that will either tell you:
- to simply use a different yet equivalent API instead, or
- the API in question has no replacement. This is usually for API that was mostly irrelevant.

To see deprecation warnings in your project and in your project's CI, add `SS_DEPRECATION_ENABLED=true` to your project's `.env` file.

Alternatively, add the following line to you project's `app/_config.php`.
```php
Deprecation::enable()
```

Deprecation notices will only ever show if your `SS_ENVIRONMENT_TYPE` is set to `dev`.

Your project will now start emitting deprecation warnings on the frontend if you are calling deprecated code, along with the different API you should now use instead, if a replacement exists.

Not all API that was deprecated in CMS 4 that has an equivalent API has that API in CMS 4; some of the API is only available from CMS 5. A good example of this is the upgrade for what powers the `SilverStripe\Control\Email\Email` class from `swiftmailer` in CMS 4 to `symfony/mailer` in CMS 5. You'll need to upgrade to CMS 5 before you can access the `symfony/mailer` API.

Your project will emit deprecation notices for these, although there may be nothing you can do to stop calling that code until you upgrade to CMS 5. In this case you should use the deprecation notice to construct a list of what you may need to change after upgrading.

Once you have resolved all of the deprecation notices you can, it is recommended to turn off deprecation notices again.

0 comments on commit e646a9b

Please sign in to comment.