Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Greeting extends ValueObjectVisitor
/**
* @param \App\Rest\Values\Greeting $data
*/
public function visit(Visitor $visitor, Generator $generator, $data)
public function visit(Visitor $visitor, Generator $generator, $data): void
{
$visitor->setHeader('Content-Type', $generator->getMediaType('Greeting'));
$generator->startObjectElement('Greeting');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public function __construct(private string $staticThumbnail)
{
}

public function getThumbnail(ContentType $contentType, array $fields, ?VersionInfo $versionInfo = null): ?Thumbnail
public function getThumbnail(ContentType $contentType, array $fields, ?VersionInfo $versionInfo = null): Thumbnail
{
return new Thumbnail([
'resource' => $this->staticThumbnail,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Menus are extensible using event subscribers, for example:

``` php
[[= include_file('code_samples/back_office/menu/menu_item/src/EventSubscriber/MyMenuSubscriber.php', 0, 29) =]]
[[= include_file('code_samples/back_office/menu/menu_item/src/EventSubscriber/MyMenuSubscriber.php', 48, 50) =]]
```

!!! tip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@

A custom tab can extend one of the following classes:

- `Ibexa\Contracts\AdminUi\Tab\AbstractTab` - base tab.
- `Ibexa\Contracts\AdminUi\Tab\AbstractControllerBasedTab` - embeds the results of a controller action in the tab.
- `Ibexa\Contracts\AdminUi\Tab\AbstractRouteBasedTab` - embeds the results of the selected route, passing applicable parameters.
- [`AbstractTab`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-AdminUi-Tab-AbstractTab.html) - base tab

Check failure on line 17 in docs/administration/back_office/back_office_tabs/back_office_tabs.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/back_office_tabs/back_office_tabs.md#L17

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": "docs/administration/back_office/back_office_tabs/back_office_tabs.md", "range": {"start": {"line": 17, "column": 58}}}, "severity": "ERROR"}

Check failure on line 17 in docs/administration/back_office/back_office_tabs/back_office_tabs.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/back_office_tabs/back_office_tabs.md#L17

[Ibexa.DomainTerms] Use 'back office' instead of 'AdminUi'
Raw output
{"message": "[Ibexa.DomainTerms] Use 'back office' instead of 'AdminUi'", "location": {"path": "docs/administration/back_office/back_office_tabs/back_office_tabs.md", "range": {"start": {"line": 17, "column": 74}}}, "severity": "ERROR"}
- [`AbstractControllerBasedTab`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-AdminUi-Tab-AbstractControllerBasedTab.html) - embeds the results of a controller action in the tab

Check failure on line 18 in docs/administration/back_office/back_office_tabs/back_office_tabs.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/back_office_tabs/back_office_tabs.md#L18

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": "docs/administration/back_office/back_office_tabs/back_office_tabs.md", "range": {"start": {"line": 18, "column": 73}}}, "severity": "ERROR"}

Check failure on line 18 in docs/administration/back_office/back_office_tabs/back_office_tabs.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/back_office_tabs/back_office_tabs.md#L18

[Ibexa.DomainTerms] Use 'back office' instead of 'AdminUi'
Raw output
{"message": "[Ibexa.DomainTerms] Use 'back office' instead of 'AdminUi'", "location": {"path": "docs/administration/back_office/back_office_tabs/back_office_tabs.md", "range": {"start": {"line": 18, "column": 89}}}, "severity": "ERROR"}
- [`AbstractRouteBasedTab`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-AdminUi-Tab-AbstractRouteBasedTab.html) - embeds the results of the selected route, passing applicable parameters

Check failure on line 19 in docs/administration/back_office/back_office_tabs/back_office_tabs.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/back_office_tabs/back_office_tabs.md#L19

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": "docs/administration/back_office/back_office_tabs/back_office_tabs.md", "range": {"start": {"line": 19, "column": 68}}}, "severity": "ERROR"}

Check failure on line 19 in docs/administration/back_office/back_office_tabs/back_office_tabs.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/back_office_tabs/back_office_tabs.md#L19

[Ibexa.DomainTerms] Use 'back office' instead of 'AdminUi'
Raw output
{"message": "[Ibexa.DomainTerms] Use 'back office' instead of 'AdminUi'", "location": {"path": "docs/administration/back_office/back_office_tabs/back_office_tabs.md", "range": {"start": {"line": 19, "column": 84}}}, "severity": "ERROR"}

``` php
//...
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 16, 17) =]]
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 16, 18) =]]
//...
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 34, 43) =]][[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 49, 51) =]]
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 27, 31) =]]
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 42, 44) =]]
//...
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 70, 73) =]]
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 63, 68) =]]
```

!!! tip
Expand All @@ -46,7 +47,7 @@
The order depends on the numerical value returned by the `getOrder` method:

``` php
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 44, 48) =]]
[[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php', 37, 41) =]]
```

Tabs are displayed according to this value in ascending order.
Expand Down
6 changes: 4 additions & 2 deletions docs/administration/back_office/customize_calendar.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ One such built-in implementation is `InMemoryEventSource`.
To add an in-memory collection as an event source, create `src/Calendar/Holidays/EventSourceFactory.php`:

```php
[[= include_file('code_samples/back_office/calendar/src/Calendar/Holidays/EventSourceFactory.php', 0, 23) =]][[= include_file('code_samples/back_office/calendar/src/Calendar/Holidays/EventSourceFactory.php', 29, 40) =]]
[[= include_file('code_samples/back_office/calendar/src/Calendar/Holidays/EventSourceFactory.php', 0, 20) =]]
[[= include_file('code_samples/back_office/calendar/src/Calendar/Holidays/EventSourceFactory.php', 26, 36) =]]

```

!!! note
Expand Down Expand Up @@ -107,7 +109,7 @@ To do this, place the following `holidays.json` file in `src/Calendar/Holidays`:
Next, import this file in `src/Calendar/Holidays/EventSourceFactory.php`:

``` php hl_lines="6-9"
[[= include_file('code_samples/back_office/calendar/src/Calendar/Holidays/EventSourceFactory.php', 19, 33) =]]
[[= include_file('code_samples/back_office/calendar/src/Calendar/Holidays/EventSourceFactory.php', 16, 30) =]]
```

The calendar now displays the events listed in the JSON file.
4 changes: 2 additions & 2 deletions docs/administration/recent_activity/recent_activity.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ See [Activity Log Search Criteria reference](activity_log_criteria.md) and [Acti
In the following example, log groups that contain at least one creation of a Content item are displayed in terminal, with a maximum of 10 groups within the last hour.
It uses the default `admin` user that has a [permission](#permission-and-security) to list everyone's entries.

```php hl_lines="39-43"
```php hl_lines="34-38"
[[= include_file('code_samples/recent_activity/src/Command/MonitorRecentContentCreationCommand.php') =]]
```

Expand Down Expand Up @@ -190,7 +190,7 @@ In the following example, several actions are logged into one context group, eve
- `complete`

``` php
[[= include_file('code_samples/recent_activity/src/Command/ActivityLogContextTestCommand.php', 62, 82) =]]
[[= include_file('code_samples/recent_activity/src/Command/ActivityLogContextTestCommand.php', 46, 66) =]]
```

Context groups can't be nested.
Expand Down
12 changes: 6 additions & 6 deletions docs/api/php_api/php_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ While [using `sudo()`](#using-sudo) is the recommended option, you can also set
To identify as a different user, you need to use the `UserService` together with `PermissionResolver` (in the example `admin` is the login of the administrator user):

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 40, 41) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 44, 46) =]]
```

!!! tip
Expand All @@ -150,11 +150,11 @@ Both cases should be covered with error messages:
``` php
try {
// ...
} catch (\Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException $e) {
$output->writeln("<error>No content with id $contentId found</error>");
} catch (\Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException $e) {
$output->writeln("<error>Permission denied on content with id $contentId</error>");
}
} catch (\Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException $e) {
$output->writeln("<error>No content with id $contentId found</error>");
} catch (\Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException $e) {
$output->writeln("<error>Permission denied on content with id $contentId</error>");
}
```

## Service container
Expand Down
40 changes: 21 additions & 19 deletions docs/content_management/content_api/browsing_content.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ The service should be [injected into the constructor of your command or controll
Basic content metadata is available through [`ContentInfo`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html) objects and their properties.
This value object provides primitive fields, such as `contentTypeId`, `publishedDate`, or `mainLocationId`, and methods for retrieving selected properties.

You can also use it to request other Content-related value objects from various services:
You can also use it to request other content-related value objects from various services:

``` php hl_lines="8"
``` php hl_lines="14"
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 0, 5) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 21, 23) =]]
// ...
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 4, 5) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 18, 22) =]]
// ...
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 44, 46) =]][[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 54, 65) =]]
```

[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 42, 44) =]][[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 50, 58) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 113, 116) =]]
```

`ContentInfo` is loaded from the [`ContentService`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html) (line 8).
It provides you with basic content metadata such as modification and publication dates or main language code.
Expand Down Expand Up @@ -68,21 +68,21 @@ The [`URLAliasService`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-C
You can retrieve the content type of a content item through the [`getContentType`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html#method_getContentType) method of the ContentInfo object:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 82, 84) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 69, 71) =]]
```

### Versions

To iterate over the versions of a content item, use the [`ContentService::loadVersions`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_loadVersions) method, which returns an array of `VersionInfo` value objects.

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 86, 92) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 73, 79) =]]
```

You can additionally provide the `loadVersions` method with the version status to get only versions of a specific status, for example:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 93, 94) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 80, 81) =]]
```

!!! note
Expand All @@ -98,7 +98,7 @@ This method loads only the specified subset of relations to improve performance
You can get the current version's `VersionInfo` using [`ContentService::loadVersionInfo`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_loadVersionInfo).

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 105, 112) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 92, 99) =]]
```

You can also specify the version number as the second argument to get Relations for a specific version:
Expand All @@ -117,7 +117,7 @@ It also holds the [relation type](content_relations.md), and the optional field
You can use the `getOwner` method of the `ContentInfo` object to load the content item's owner as a `User` value object.

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 114, 115) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 101, 102) =]]
```

To get the creator of the current version and not the content item's owner, you need to use the `creatorId` property from the current version's `VersionInfo` object.
Expand All @@ -127,7 +127,7 @@ To get the creator of the current version and not the content item's owner, you
You can find the section to which a content item belongs through the [`getSection`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html#method_getSection) method of the ContentInfo object:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 117, 118) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 104, 105) =]]
```

!!! note
Expand All @@ -142,17 +142,19 @@ You need to provide it with the object state group.
All object state groups can be retrieved through [`loadObjectStateGroups`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_loadObjectStateGroups).

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 120, 125) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 107, 112) =]]
```

## Viewing content with fields

To retrieve the fields of the selected content item, you can use the following command:

```php hl_lines="9-10 12-19"
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentCommand.php', 4, 7) =]] // ...
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentCommand.php', 42, 60) =]]
}
```php hl_lines="17-18 20-27"
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentCommand.php', 0, 7) =]]
// ...
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentCommand.php', 17, 19) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/ViewContentCommand.php', 35, 54) =]]

```

Line 9 shows how [`ContentService::loadContent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_loadContent) loads the content item provided to the command.
Expand Down Expand Up @@ -182,7 +184,7 @@ $contentService->loadContent($content->id, Language::ALL);
To go through all the content items contained in a subtree, you need to use the [`LocationService`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html).

``` php hl_lines="5 15"
[[= include_file('code_samples/api/public_php_api/src/Command/BrowseLocationsCommand.php', 35, 54) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/BrowseLocationsCommand.php', 31, 50) =]]
```

`loadLocation` (line 15) returns a value object, here a `Location`.
Expand Down
17 changes: 9 additions & 8 deletions docs/content_management/content_api/creating_content.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Value objects such as content items are read-only, so to create or modify them y
[`ContentService::newContentCreateStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_newContentCreateStruct)
returns a new [`ContentCreateStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentCreateStruct.html) object.

``` php hl_lines="1-2 6"
[[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 47, 53) =]]
``` php hl_lines="2-3 7"
[[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 51, 60) =]]
```

This command creates a draft using [`ContentService::createContent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_createContent) (line 6).
Expand All @@ -42,7 +42,7 @@ Therefore, when creating a content item of the Image type (or any other content
the `ContentCreateStruct` is slightly more complex than in the previous example:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/CreateImageCommand.php', 47, 62) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/CreateImageCommand.php', 51, 63) =]]
```

Value of the Image field type contains the path to the image file and other basic information based on the input file.
Expand All @@ -66,7 +66,7 @@ To publish it, use [`ContentService::publishVersion`](/api/php_api/php_api_refer
This method must get the [`VersionInfo`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-VersionInfo.html) object of a draft version.

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 58, 59) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 62, 63) =]]
```

## Updating content
Expand All @@ -76,7 +76,7 @@ and pass it to [`ContentService::updateContent`](/api/php_api/php_api_reference/
This method works on a draft, so to publish your changes you need to use [`ContentService::publishVersion`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_publishVersion) as well:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/UpdateContentCommand.php', 45, 50) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/UpdateContentCommand.php', 44, 53) =]]
```

## Translating content
Expand All @@ -86,15 +86,16 @@ Content [translations](languages.md#language-versions) are created per version.
To translate a content item to a new language, you need to update it and provide a new `initialLanguageCode`:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/TranslateContentCommand.php', 50, 52) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/TranslateContentCommand.php', 58, 60) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/TranslateContentCommand.php', 49, 55) =]]

[[= include_file('code_samples/api/public_php_api/src/Command/TranslateContentCommand.php', 60, 62) =]]
```

You can also update content in multiple languages at once using the `setField` method's third argument.
Only one language can still be set as a version's initial language:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/TranslateContentCommand.php', 55, 55) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/TranslateContentCommand.php', 57, 58) =]]
```

### Deleting a translation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ description: You can use the PHP API to view the bookmark list, and add or remov
To view a list of all bookmarks, use [`BookmarkService::loadBookmarks`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_loadBookmarks):

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 42, 48) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 43, 50) =]]
```

You can add a bookmark to a content item by providing its Location object to the [`BookmarkService::createBookmark`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_createBookmark) method:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 38, 40) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 37, 40) =]]
```

You can remove a bookmark from a location with [`BookmarkService::deleteBookmark`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_deleteBookmark):

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 51, 51) =]]
[[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 52, 53) =]]
```
Loading
Loading