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
2 changes: 1 addition & 1 deletion docs/administration/back_office/back_office.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ page_type: landing_page

# Back office

The back office interface is produced by the [`ibexa/admin-ui` bundle](https://github.com/ibexa/admin-ui).
The back office is the web interface where editors and administrators work with content.
Additionally, it uses React-based modules that make each part of the UI extensible, and Bootstrap for styling.
The interface is accessible in your browser at `http://<yourdomain>/admin`.

Expand Down
2 changes: 1 addition & 1 deletion docs/administration/back_office/integrated_help.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

![Integrated help menu](5_0_integrated_help_menu.png)

Integrated help is contextual, therefore, apart from user documentation, release notes, and partner guidelines, which are available to editors and store managers, developers can access API references, the GraphQL console, or the support portal.
Integrated help is contextual, therefore, apart from user documentation, release notes, and partner guidelines, which are available to editors and store managers, developers can access API references or the support portal.

Check warning on line 13 in docs/administration/back_office/integrated_help.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/administration/back_office/integrated_help.md#L13 <Ibexa.OxfordComma>

Use a comma before the last 'and' or 'or' in a list of four or more items.
Raw output
{"message":"Use a comma before the last 'and' or 'or' in a list of four or more items.","location":{"path":"docs/administration/back_office/integrated_help.md","range":{"start":{"line":13,"column":1},"end":{"line":13,"column":204}}},"severity":"WARNING","code":{"value":"Ibexa.OxfordComma"}}

## Product tours

Expand Down
6 changes: 0 additions & 6 deletions docs/administration/configuration/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ parameters:
an_array: [apple, banana, pear]
```

``` php
// Usage inside a controller
/** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */
$myParameter = $container->getParameter('myapp.parameter.name');
```

## Configuration settings

For specific configuration settings, see:
Expand Down
56 changes: 0 additions & 56 deletions docs/administration/configuration/dynamic_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,6 @@ parameters:

Inside a controller extending the `Ibexa\Core\MVC\Symfony\Controller\Controller` class, in `site_group` SiteAccess, you can use the parameters in the following way (the same applies for `hasParameter()`):

``` php {skip-validation}
$configResolver = $this->getConfigResolver();

// ibexa.site_access.config is the default namespace, so no need to specify it
// The following will resolve ibexa.site_access.config.<siteaccessName>.content.default_ttl
// In the case of site_group, it will return 3600.
// Otherwise it will return the value for ibexa.site_access.config.default.content.default_ttl (60)
$locationViewSetting = $configResolver->getParameter( 'content.default_ttl' );

// For you own namespace, you need to specify it, here as "myapp"
$myParamSetting = $configResolver->getParameter( 'my_param', 'myapp' );
// $myParamSetting's value will be 'value'

// You can also force the scope by naming it explicitly (here as "admin_group")
$myParamSettingAdmin = $configResolver->getParameter( 'my_param', 'myapp', 'admin_group' );
// $myParamSetting's value will be 'another value'
```

!!! tip

To learn more about scopes, see [SiteAccess documentation](multisite_configuration.md#scope).
Expand All @@ -56,41 +38,3 @@ Both `getParameter()` and `hasParameter()` can take three arguments:
1. `$paramName` - the name of the parameter
2. `$namespace` - your application namespace, `myapp` in the previous example. If null, the default namespace is used, which is `ibexa.site_access.config` by default.
3. `$scope` - a SiteAccess name. If null, the current SiteAccess is used.

## Inject ConfigResolver into services

You can use the ConfigResolver in your own services whenever needed.
To do this, inject the `ibexa.config.resolver` service:

``` yaml
services:
App\Service:
arguments: ['@ibexa.config.resolver']
```

You can also use the [autowire feature]([[= symfony_doc =]]/service_container/autowiring.html), by type hinting against `ConfigResolverInterface`.

For more information about dependency injection, see [Service container]([[= symfony_doc =]]/service_container.html).

!!! note

Don't store the retrieved config value unless you know what you're doing.
SiteAccess can change during code execution, which means you might work on the wrong value.

``` php
namespace App;

use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface;

class Service
{
public function __construct(private readonly ConfigResolverInterface $configResolver)
{
}

public function someMethodThatNeedConfig(): void
{
$configValue = $this->configResolver->getParameter('my_param', 'myapp');
}
}
```
214 changes: 0 additions & 214 deletions docs/administration/recent_activity/recent_activity.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ ibexa:
enabled: false
```

You can also disable activity log for a single action by using the [PHP API](#disable-logging-activities).

## Permission and security

The [`activity_log/read`](policies.md#activity-log) policy gives a role the access to the **Admin** -> **Activity list**, the dashboard's **Recent activity** block, and the user profile's **Recent activity**.
Expand All @@ -89,218 +87,6 @@ This policy is required to view [activity log in user profile]([[= user_doc =]]/

For example, if a content edition feature, such as reader's comments, is available in the front office, the recent activity log records the front users' IPs.

## PHP API

The `ActivityLogService` PHP API can be used to browse activity logs and write new entries.

### Searching in the Activity Log groups

You can search among the activity log entry groups with the `ActivityLogService::findGroups` method, by passing an `Ibexa\Contracts\ActivityLog\Values\ActivityLog\Query` object.
This `Query`'s constructor has four arguments:

- `$criteria` - an array of criteria from `Ibexa\Contracts\ActivityLog\Values\ActivityLog\Criterion` combined as a logical AND.
- `$sortClauses` - an array of `Ibexa\Contracts\ActivityLog\Values\ActivityLog\SortClause`.
- `$offset` - a zero-based index integer indicating at which group to start, its default value is `0` (zero, nothing skipped).
- `$limit` - an integer as the maximum returned group count, default is 25.

See [Activity Log Search Criteria reference](activity_log_criteria.md) and [Activity Log Search Sort Clauses reference](activity_log_sort_clauses.md) to discover query possibilities.

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="34-38"
[[= include_code('code_samples/recent_activity/src/Command/MonitorRecentContentCreationCommand.php') =]]
```

```console
% php bin/console app:monitor-content-creation

web
---

--------------------------- --------- --------------------------- -------- ---------- ------------
Logged at Obj. ID Object Name Action User IP
--------------------------- --------- --------------------------- -------- ---------- ------------
2024-01-29T15:01:57+00:00 323 “Bar” (formerly “Folder”) create jane_doe 172.20.0.5
--------------------------- --------- --------------------------- -------- ---------- ------------

migration
---------

Migrating file: create_foo_company
--------------------------- --------- -------------------- -------------- ------- ----
Logged at Obj. ID Object Name Action User IP
--------------------------- --------- -------------------- -------------- ------- ----
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin
2024-01-29T14:58:53+00:00 318 “Members“ create admin
2024-01-29T14:58:53+00:00 318 “Members“ publish admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create_draft admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ update admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin
2024-01-29T14:58:53+00:00 319 “Address Book“ create admin
2024-01-29T14:58:53+00:00 319 “Address Book“ publish admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create_draft admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ update admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin
2024-01-29T14:58:53+00:00 320 “HQ“ create admin
2024-01-29T14:58:53+00:00 320 “HQ“ publish admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create_draft admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ update admin
2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin
--------------------------- --------- -------------------- -------------- ------- ----
```

### Add custom Activity Log entries

!!! caution

Keep activity logging as light as possible.
Don't make database requests or heavy computation at logging time.
Keep them for activity log list display time.
If needed, you can [disable logging for specific operations](#disable-logging-activities) using the PHP API.

#### Create an entry

Your custom features can write into the activity log.

First, inject `Ibexa\Contracts\ActivityLog\ActivityLogServiceInterface` into your PHP class from where you want to log an activity (such as a custom event subscriber, event listener, service, or controller).

In the following example, an event subscriber is subscribing to an event dispatched by a custom feature.
This event has the information needed by a log entry (see details after the example).

``` php
[[= include_code('code_samples/recent_activity/src/EventSubscriber/MyFeatureEventSubscriber.php') =]]
```

`ActivityLogService::build()` function returns an `Ibexa\Contracts\ActivityLog\Values\CreateActivityLogStruct` which can then be passed to `ActivityLogService::save`.

`ActivityLogService::build` has three arguments:

- `$className` is a FQCN of the object actually manipulated by the feature, for example `Ibexa\Contracts\Core\Repository\Values\Content\Content::class`
- `$id` is an ID or identifier of the manipulated object, for example, the Content ID cast to string
- `$action` is an identifier of the performed object manipulation, or example, `create`, `update` or `delete`

The returned `CreateActivityLogStruct` is always related to the currently logged-in user.

You can still display activity log of an object which was deleted or renamed.
To store the name of the log, you need to use `CreateActivityLogStruct::setName` before saving the log entry.
This stored name can be used at the time of displaying information whether the associated object isn't available anymore, or to check if it has been renamed.

#### Context group

If you log several related entries at once, you can group them into a context.
Context is a set of actions done for the same purpose, for example, it could group the actions of a CRON that fetches third party data and updates content items.
The built-in contexts include:

- `web` - groups actions made in the back office, like the update and the publishing of a new content item's version
- `migration` - groups every action from a migration file execution

A context group counts as one item in regard to `activity_logs_limit` configuration and `ActivityLogService::findGroups`'s `$limit` argument.

To open a context group, use `ActivityLogService::prepareContext` which has two arguments:

- `$source` - describes, usually through a short identifier, what is triggering the set of actions.
For example, some already existing sources are `web` (incl. actions from the back office), `graphql`, `rest` and `migration`
- `$description` - an optional, more specific contextualisation.
For example, `migration` context source is associated with the migration file name in its context description.

To close a context group, use `ActivityLogService::dismissContext`.

In the following example, several actions are logged into one context group, even those triggered by a cascade outside the piece of code:

- `my_feature`
- `init`
- `create`
- `publish`
- `simulate`
- `complete`

``` php
[[= include_code('code_samples/recent_activity/src/Command/ActivityLogContextTestCommand.php', 47, 66, remove_indent=True) =]]
```

Context groups can't be nested.
If a new context is prepared when a context is already grouping log entries, this new context is ignored.
To start a new context, make sure to previously dismiss the existing one.

When displayed in the back office, a context group is folded below its first entry.
The `my_feature` context from the example is folded below its first action, the `init` action.
Other actions are displayed after you click the **Show more** button.

![The example context group displayed on the Recent Activity page](activity_log_group.png "`my_feature` context from the example")

#### Display log entries

To display your log entry, if your object's PHP class isn't already covered, you have to:

- implement `ClassNameMapperInterface` to associate the class name with an identifier,
- eventually create a `PostActivityListLoadEvent` subscriber if you need to load the object for the template,
- create a template to display this class log entries.

You can have a template that is:

- specific to a class identifier and placed in `templates/themes/<theme>/activity_log/ui/<identifier>.html.twig`
- specific to an action on an identifier and placed in `templates/themes/<theme>/activity_log/ui/<identifier>/<action>.html.twig`

Template existence is tested in reverse order: if there is no action that specifies the template, the identifier's default is used.
For the same identifier, you could have specific templates for few actions, and a default one for the remaining actions.

A default template is used if no template is found for the identifier.
The built-in default template `@ibexadesign/activity_log/ui/default.html.twig` has an empty `activity_log_description_widget` block and doesn't display anything for unknown objects.
Your template can extend `@ibexadesign/activity_log/ui/default.html.twig`, and only redefine the `activity_log_description_widget` block for your objects.

First, follow an example of a default template overriding the one from the bundle.
It can be used during development as a fallback for classes that aren't mapped yet.

``` twig
[[= include_code('code_samples/recent_activity/templates/themes/admin/activity_log/ui/default.html.twig') =]]
```

Here is an example of a `ClassNameMapperInterface` associating the class `App\MyFeature\MyFeature` with the identifier `my_feature`:

``` php
[[= include_code('code_samples/recent_activity/src/ActivityLog/ClassNameMapper/MyFeatureNameMapper.php') =]]
```

This mapper also provides a translation for the class name in the **Filters** menu.
This translation can be extracted with `php bin/console jms:translation:extract en --domain=ibexa_activity_log --dir=src --output-dir=translations`.

To be taken into account, this mapper must be registered as a service:

``` yaml
[[= include_code('code_samples/recent_activity/config/append_to_services.yaml') =]]
```

Here is an example of a `PostActivityListLoadEvent` subscriber which loads the related object when it's an `App\MyFeature\MyFeature`, and attaches it to the log entry:

``` php
[[= include_code('code_samples/recent_activity/src/EventSubscriber/MyFeaturePostActivityListLoadEventSubscriber.php') =]]
```

The following template is made to display the object of `App\MyFeature\MyFeature` (now identified as `my_feature`) when the action is `simulate`,
so, it's named in `templates/themes/admin/activity_log/ui/my_feature/simulate.html.twig`.
Thanks to the previous subscriber, the related object is available at display time:

``` twig
[[= include_code('code_samples/recent_activity/templates/themes/admin/activity_log/ui/my_feature/simulate.html.twig') =]]
```

### Disable logging activities

You can disable logging the activities with PHP API, for example, when loading large amounts of data in cases where you don't want logging to slow down the process or the actions to be included in the log.

Call `ActivityLogService::disable()`
before running the relevant code, then `ActivityLogService::enable()` to restore the logging process:

``` php
[[= include_code('code_samples/recent_activity/src/recent_activity_disable.php') =]]
```

When disabled, any call to `ActivityLogService::save()` has no effect and no entries are written to the database.

You can check the current state with `ActivityLogService::isEnabled()` and `ActivityLogService::isDisabled()`.

## REST API

You can browse activity logs with REST API.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Those Criteria are to be used with `Ibexa\Contracts\ActivityLog\Values\ActivityL
They're applied to log entry groups.
For example, with the criterion `ActionCriterion`, you get log entry groups that have at least one entry with this action (and possibly other actions as well).

See [Searching in the Activity Log groups](recent_activity.md#searching-in-the-activity-log-groups) for how to use a query, and an example combining several criteria.
See [Recent activity](../../administration/recent_activity/recent_activity.md#rest-api) for how to browse the activity log over the REST API.

## Value-based criteria

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Activity Log Search Sort Clauses reference

See [Searching in the Activity Log groups](recent_activity.md#searching-in-the-activity-log-groups) for the whole API.
See [Recent activity](../../administration/recent_activity/recent_activity.md#rest-api) for how to browse the activity log over the REST API.

Sort Clauses are found in the `Ibexa\Contracts\ActivityLog\Values\ActivityLog\SortClause` namespace.

Expand Down
20 changes: 0 additions & 20 deletions tests/python/invariants-baseline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,6 @@ deleted_product_variables: []

# 314 page(s) contain a PHP code sample (fenced block or .php include macro).
php_code_sample:
- administration/back_office/add_user_setting.md
- administration/back_office/back_office_elements/extending_thumbnails.md
- administration/back_office/back_office_elements/formatting_date_and_time.md
- administration/back_office/back_office_menus/add_menu_item.md
- administration/back_office/back_office_menus/back_office_menus.md
- administration/back_office/back_office_tabs/back_office_tabs.md
- administration/back_office/back_office_tabs/create_dashboard_tab.md
- administration/back_office/browser/browser.md
- administration/back_office/content_tab_switcher.md
- administration/back_office/customize_calendar.md
- administration/back_office/customize_integrated_help.md
- administration/back_office/customize_product_tour.md
- administration/back_office/customize_search_sorting.md
- administration/back_office/customize_search_suggestion.md
- administration/back_office/notifications.md
- administration/configuration/configuration.md
- administration/configuration/dynamic_configuration.md
- administration/configuration/repository_configuration.md
- administration/dashboard/php_api_dashboard_service.md
- administration/recent_activity/recent_activity.md
- ai/ai_actions/configure_ai_actions.md
- ai/ai_actions/extend_ai_actions.md
- ai/mcp/mcp_usage.md
Expand Down
Loading