Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch 1 #610

Open
wants to merge 22 commits into
base: 5.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d46ec6d
DOC Deprecate TopPage classes that are being renamed
emteknetnz Sep 5, 2024
a148cb0
Merge pull request #578 from creative-commoners/pulls/5/deprecate-top…
GuySartorelli Sep 9, 2024
98e36cb
DOC Changing ClassName from Enum to Varchar
emteknetnz Sep 10, 2024
06ea3ad
Merge pull request #577 from creative-commoners/pulls/5/varchar-class…
GuySartorelli Sep 11, 2024
347495a
Merge branch '5.3' into 5
github-actions[bot] Sep 11, 2024
c1b641b
DOC Document deprecating classes which will be renamed (#585)
GuySartorelli Sep 12, 2024
2142034
DOCS Document deprecated API and a few new features (#580)
GuySartorelli Sep 13, 2024
cc2ea0f
DOC Update deprecation warning docs (#588)
GuySartorelli Sep 19, 2024
6cc343c
DOC Document some more deprecations (#589)
GuySartorelli Sep 27, 2024
b46619e
Merge branch '5.3' into 5
github-actions[bot] Oct 9, 2024
c6afec4
DOC Document new methods on GridFieldFilterHeader (#597)
GuySartorelli Oct 13, 2024
6ffc53e
Merge branch '5.3' into 5
github-actions[bot] Oct 16, 2024
46384e8
DOC Update deprecation docs
emteknetnz Oct 17, 2024
690ab43
Merge pull request #599 from creative-commoners/pulls/5/depr-docs
GuySartorelli Oct 21, 2024
d01a317
DOC Add validations related to DBField
emteknetnz Oct 21, 2024
d70735f
Merge pull request #603 from creative-commoners/pulls/5/api-depr
GuySartorelli Oct 21, 2024
8f68c33
Merge branch '5.3' into 5
github-actions[bot] Oct 21, 2024
4fabad4
DOC Document deprecations for template layer refactor (#594)
GuySartorelli Oct 21, 2024
945cc3e
DOC Document deprecation (#608)
GuySartorelli Oct 24, 2024
cdd90a6
Adding clarification on how to edit predefined shortcodes
MauritzFunke Oct 25, 2024
addc819
DOC Adding clarification on how to edit predefined shortcodes
MauritzFunke Oct 25, 2024
10aa4f1
Merge branch 'patch-1' of github.com:MauritzFunke/developer-docs into…
Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions en/02_Developer_Guides/05_Extending/04_Shortcodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public function getMyHtmlVarcharField()
> See [Data types and Casting](/developer_guides/model/data_types_and_casting/#overriding) for more information about getter methods.

## Defining custom shortcodes
With custom shortscodes it is not only possible to add new shortcodes but it is also possible to edit the default behaviour of the CMS.


First we need to define a callback for the shortcode. These callbacks are usually static methods on some class, but they can also be anonymous functions or any other valid PHP callback.

Expand Down
23 changes: 23 additions & 0 deletions en/02_Developer_Guides/08_Performance/06_ORM.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,26 @@ SilverStripe\ORM\Connect\DBSchemaManager:
```

You can always manually trigger a check and repair (e.g. in a [`BuildTask`](api:SilverStripe/Dev/BuildTask)) by calling [`DB::check_and_repair_table()`](api:SilverStripe\ORM\DB::check_and_repair_table()). This ignores the above configuration.

## Changing `ClassName` column from enum to varchar {#classname-varchar}

On websites with very large database tables it can take a long time to run `dev/build`, which can be a problem when deploying changes to production. This is because the `ClassName` column is an `enum` type which requires an a `ALTER TABLE` query to be run affecting every row whenever there is a new valid value for the column.

For a very rough benchmark, running an `ALTER TABLE` query on a database table of 10 million records took 28.52 seconds on a mid-range 2023 laptop, though this time will vary depending on the database and hardware being used.

You may wish to change the `ClassName` column to a `varchar` type which remove the need to run `ALTER TABLE` whenever there is a new valid value. Enabling this will result in a trade-off where the size of the database will increase by approximately 7 MB per 100,000 rows.

> [!WARNING]
> There will also be a very slow initial `dev/build` as all of the `ClassName` columns are switched to `varchar`.

To enable this, add the following configuration:

```yml
SilverStripe\ORM\DataObject:
fixed_fields:
ClassName: DBClassNameVarchar

SilverStripe\ORM\FieldType\DBPolymorphicForeignKey:
composite_db:
Class: "DBClassNameVarchar('SilverStripe\\ORM\\DataObject', ['index' => false])"
```
158 changes: 158 additions & 0 deletions en/02_Developer_Guides/20_Deprecations/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
---
title: Deprecating code
summary: Details about how to deprecate code and emit or suppress deprecation warnings
icon: exclamation-circle
---

# Deprecating code

Needs of developers (both on core framework and custom projects) can outgrow the capabilities
of a certain API. Existing APIs might turn out to be hard to understand, maintain, test or stabilise.
In these cases, it is best practice to "refactor" these APIs into something more useful.

Sometimes refactoring API means we rename or entirely remove classes and methods in a major release.
To make upgrading to that release easier, deprecation warnings should be provided so developers know what is
going to be removed and how they need to update their code.

## Deprecating API best practice

- Add a `@deprecated` item to the docblock tag, with the version when the code was deprecated and a message indicating what to use instead.
- Update the deprecated code to throw a [Deprecation::notice()](api:SilverStripe\Dev\Deprecation::notice()) warning.
- 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 version will be *4.12.0*.
- Make sure that the old deprecated method works by calling the new function where possible - avoid duplicated code.
- 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.

> [!NOTE]
> 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."

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
- Wrap `Deprecation::notice()` with `Deprecation::withSuppressedNotice()` if there's no replacement for that deprecated method and it's not feasible to wrap all calls to 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', Deprecation::SCOPE_CLASS);` to the top of `__construct()`
- Wrap `Deprecation::notice()` with `Deprecation::withSuppressedNotice()` if there's no replacement for that deprecated class and it's not feasible to wrap all instantiations of the class

```php
namespace App;

/**
* @deprecated 4.12.0 Will be removed without equivalent functionality
*/
class MyDeprecatedClass extends AnotherClass
{
public function __construct()
{
Deprecation::withSuppressedNotice(function () {
Deprecation::notice(
'4.12.0',
'Will be removed without equivalent functionality',
Deprecation::SCOPE_CLASS
);
});
parent::__construct();
}
}
```

When deprecating config:

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

When deprecating some behaviour, combination of configuration values, parameters, etc:

- Add `Deprecation::notice('1.2.3', 'Using x with y is deprecated. Do [other thing] instead', Deprecation::SCOPE_GLOBAL);`
- It may not be immediately clear where this type of deprecation warning should go. In that case, add it to the `HTTPApplication::warnAboutDeprecatedSetups()` method.
- It may be appropriate to link to some documentation in the message for this type of deprecation warning.

In all cases if the replacement method or configuration property exists in another class, or you're replacing one class with another, refer to the replacement using its fully qualified class name.

## Avoiding deprecated API

Wherever possible, once some API has been deprecated, we should stop using it. This allows projects to emit deprecation warnings 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::withSuppressedNotice()` e.g:

```php
use SilverStripe\Dev\Deprecation;

// ...

// The $myVariable variable will get the result of the call to the deprecated $obj->myDeprecatedMethod()
$myVariable = Deprecation::withSuppressedNotice(function () {
return $obj->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` warnings are not enabled, though the tests are skipped whenever you are testing to see if deprecated code is still be called.

```php
namespace SilverStripe\Test;

use SilverStripe\Dev\Deprecation;
use SilverStripe\Dev\SapphireTest;

class MyTest extends SapphireTest
{
public function testSomething()
{
if (Deprecation::isEnabled()) {
$this->markTestSkipped('Test calls deprecated code');
}
// ...
}
}
```

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

```php
namespace SilverStripe\Control;

use SilverStripe\Dev\Deprecation;
// ...

class Director
{
// ...

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

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 warnings

Deprecation warnings aren't enabled by default. They can be turned on for dev environments with one of the following methods:

`.env`

```bash
SS_DEPRECATION_ENABLED=true
```

```php
// app/_config.php
use SilverStripe\Dev\Deprecation;

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.

See [upgrading - deprecations](/upgrading/deprecations/) for more details about enabling deprecation warnings.
10 changes: 8 additions & 2 deletions en/06_Upgrading/07_Deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,20 @@ Deprecation::enable();

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

Not all API that gets deprecated will have an equivalent replacement API in that same major version; some of the API is only available from the next major release. 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. In these cases, you'll need to upgrade to the new major version before you can access the replacement API.
Not all API that gets deprecated will have an equivalent replacement API in that same major version; some of the API is only available from the next major release. A good example of this is the upgrade for what powered the `SilverStripe\Control\Email\Email` class from `swiftmailer` in CMS 4 to `symfony/mailer` in CMS 5. In these cases, you'll need to upgrade to the new major version before you can access the replacement API.

Some code that has been deprecated with no immediate replacement will not emit deprecation notices by default. If you wish to also see notices for deprecated code with no immediate replacement, add the following line to you project's `app/_config.php` file. Note that this will also emit deprecation notices for usages of the deprecated code inside core modules.
Some code that has been deprecated with no immediate replacement will not emit deprecation notices by default. If you wish to also see notices for deprecated code with no immediate replacement, add the following line to you project's `app/_config.php` file:

```php
Deprecation::enable(true);
```

By default, deprecation warnings will not be emitted if the deprecated code was called by code in [supported modules](/project_governance/supported_modules/). This is because these warnings are simply not relevant for most developers. If you wish to see deprecation warnings for code called by core code, add the following line to your project's `app/_config.php` file:

```php
Deprecation::setShowNoticesCalledFromSupportedCode(true);
```

## How to view deprecation warnings

By default, deprecation warnings will be emitted to the error logger, and will be output at the end of CLI responses. They will not be included in HTTP responses by default.
Expand Down
Loading