Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
--------- Co-authored-by: Adrien Dupuis <adrien.dupuis@ibexa.co> Co-authored-by: Paweł Niedzielski <pawel.niedzielski@ibexa.co> Co-authored-by: Bertrand Dunogier <bertrand.dunogier@gmail.com> Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com> Co-authored-by: julitafalcondusza <117284672+julitafalcondusza@users.noreply.github.com> Co-authored-by: Marek Nocoń <mnocon@users.noreply.github.com>
- Loading branch information
1 parent
9d12036
commit 6cbbb5f
Showing
35 changed files
with
2,560 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
services: | ||
|
||
App\ActivityLog\ClassNameMapper\MyFeatureNameMapper: ~ |
24 changes: 24 additions & 0 deletions
24
code_samples/recent_activity/src/ActivityLog/ClassNameMapper/MyFeatureNameMapper.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\ActivityLog\ClassNameMapper; | ||
|
||
use App\MyFeature\MyFeature; | ||
use Ibexa\Contracts\ActivityLog\ClassNameMapperInterface; | ||
use JMS\TranslationBundle\Model\Message; | ||
use JMS\TranslationBundle\Translation\TranslationContainerInterface; | ||
|
||
class MyFeatureNameMapper implements ClassNameMapperInterface, TranslationContainerInterface | ||
{ | ||
public function getClassNameToShortNameMap(): iterable | ||
{ | ||
yield MyFeature::class => 'my_feature'; | ||
} | ||
|
||
public static function getTranslationMessages(): array | ||
{ | ||
return [ | ||
(new Message('ibexa.activity_log.search_form.object_class.my_feature', 'ibexa_activity_log')) | ||
->setDesc('My Feature'), | ||
]; | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
code_samples/recent_activity/src/Command/ActivityLogContextTestCommand.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\Command; | ||
|
||
use App\Event\MyFeatureEvent; | ||
use App\MyFeature\MyFeature; | ||
use Ibexa\Contracts\ActivityLog\ActivityLogServiceInterface; | ||
use Ibexa\Contracts\Core\Repository\ContentService; | ||
use Ibexa\Contracts\Core\Repository\ContentTypeService; | ||
use Ibexa\Contracts\Core\Repository\PermissionResolver; | ||
use Ibexa\Contracts\Core\Repository\UserService; | ||
use Ibexa\Contracts\Core\Repository\Values\Content\LocationCreateStruct; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | ||
|
||
class ActivityLogContextTestCommand extends Command | ||
{ | ||
protected static $defaultName = 'doc:test:activity-log-context'; | ||
|
||
protected static $defaultDescription = 'Test activity log context usage'; | ||
|
||
private ActivityLogServiceInterface $activityLogService; | ||
|
||
private ContentService $contentService; | ||
|
||
private ContentTypeService $contentTypeService; | ||
|
||
private EventDispatcherInterface $eventDispatcher; | ||
|
||
private PermissionResolver $permissionResolver; | ||
|
||
private UserService $userService; | ||
|
||
public function __construct( | ||
ActivityLogServiceInterface $activityLogService, | ||
ContentService $contentService, | ||
ContentTypeService $contentTypeService, | ||
EventDispatcherInterface $eventDispatcher, | ||
PermissionResolver $permissionResolver, | ||
UserService $userService | ||
) { | ||
parent::__construct(self::$defaultName); | ||
$this->activityLogService = $activityLogService; | ||
$this->contentService = $contentService; | ||
$this->contentTypeService = $contentTypeService; | ||
$this->eventDispatcher = $eventDispatcher; | ||
$this->permissionResolver = $permissionResolver; | ||
$this->userService = $userService; | ||
} | ||
|
||
protected function configure(): void | ||
{ | ||
$this->addArgument('id', InputArgument::REQUIRED, 'A test number'); | ||
} | ||
|
||
protected function execute(InputInterface $input, OutputInterface $output): int | ||
{ | ||
$id = $input->getArgument('id'); | ||
$this->permissionResolver->setCurrentUserReference($this->userService->loadUserByLogin('admin')); | ||
|
||
$this->activityLogService->prepareContext('my_feature', 'Operation description'); | ||
|
||
$activityLogStruct = $this->activityLogService->build(MyFeature::class, $id, 'init'); | ||
$activityLogStruct->setObjectName("My Feature #$id"); | ||
$this->activityLogService->save($activityLogStruct); | ||
|
||
$contentCreateStruct = $this->contentService->newContentCreateStruct($this->contentTypeService->loadContentTypeByIdentifier('folder'), 'eng-GB'); | ||
$contentCreateStruct->setField('name', "My Feature Folder #$id", 'eng-GB'); | ||
$locationCreateStruct = new LocationCreateStruct(['parentLocationId' => 2]); | ||
$draft = $this->contentService->createContent($contentCreateStruct, [$locationCreateStruct]); | ||
$this->contentService->publishVersion($draft->versionInfo); | ||
|
||
$event = new MyFeatureEvent(new MyFeature(['id' => $id, 'name' => "My Feature #$id"]), 'simulate'); | ||
$this->eventDispatcher->dispatch($event); | ||
|
||
$activityLogStruct = $this->activityLogService->build(MyFeature::class, $id, 'complete'); | ||
$activityLogStruct->setObjectName("My Feature #$id"); | ||
$this->activityLogService->save($activityLogStruct); | ||
|
||
$this->activityLogService->dismissContext(); | ||
|
||
return Command::SUCCESS; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
code_samples/recent_activity/src/Command/DispatchMyFeatureEventCommand.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\Command; | ||
|
||
use App\Event\MyFeatureEvent; | ||
use App\MyFeature\MyFeature; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | ||
|
||
class DispatchMyFeatureEventCommand extends Command | ||
{ | ||
protected static $defaultName = 'app:test:throw-my-feature-event'; | ||
|
||
protected static $defaultDescription = 'Throw/Dispatch a MyFeatureEvent'; | ||
|
||
private EventDispatcherInterface $eventDispatcher; | ||
|
||
public function __construct(EventDispatcherInterface $eventDispatcher) | ||
{ | ||
$this->eventDispatcher = $eventDispatcher; | ||
parent::__construct(); | ||
} | ||
|
||
protected function execute(InputInterface $input, OutputInterface $output): int | ||
{ | ||
$event = new MyFeatureEvent(new MyFeature(['id' => 123, 'name' => 'Logged Name']), 'simulate'); | ||
$this->eventDispatcher->dispatch($event); | ||
|
||
$event = new MyFeatureEvent((object) ['id' => 456, 'name' => 'Some Name'], 'simulate'); | ||
$this->eventDispatcher->dispatch($event); | ||
|
||
return Command::SUCCESS; | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
code_samples/recent_activity/src/Command/MonitorRecentContentCreationCommand.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\Command; | ||
|
||
use Ibexa\Contracts\ActivityLog\ActivityLogServiceInterface; | ||
use Ibexa\Contracts\ActivityLog\Values\ActivityLog\Criterion; | ||
use Ibexa\Contracts\ActivityLog\Values\ActivityLog\Query; | ||
use Ibexa\Contracts\ActivityLog\Values\ActivityLog\SortClause\LoggedAtSortClause; | ||
use Ibexa\Contracts\Core\Repository\PermissionResolver; | ||
use Ibexa\Contracts\Core\Repository\UserService; | ||
use Ibexa\Contracts\Core\Repository\Values\Content\Content; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Style\SymfonyStyle; | ||
|
||
class MonitorRecentContentCreationCommand extends Command | ||
{ | ||
protected static $defaultName = 'app:monitor-content-creation'; | ||
|
||
protected static $defaultDescription = 'List last 10 log entry groups with creations in the last hour'; | ||
|
||
private ActivityLogServiceInterface $activityLogService; | ||
|
||
private PermissionResolver $permissionResolver; | ||
|
||
private UserService $userService; | ||
|
||
public function __construct(ActivityLogServiceInterface $activityLogService, PermissionResolver $permissionResolver, UserService $userService) | ||
{ | ||
$this->permissionResolver = $permissionResolver; | ||
$this->userService = $userService; | ||
$this->activityLogService = $activityLogService; | ||
parent::__construct(); | ||
} | ||
|
||
protected function execute(InputInterface $input, OutputInterface $output): int | ||
{ | ||
$query = new Query([ | ||
new Criterion\ObjectCriterion(Content::class), | ||
new Criterion\ActionCriterion([ActivityLogServiceInterface::ACTION_CREATE]), | ||
new Criterion\LoggedAtCriterion(new \DateTime('- 1 hour'), Criterion\LoggedAtCriterion::GTE), | ||
], [new LoggedAtSortClause(LoggedAtSortClause::DESC)], 0, 10); | ||
|
||
$io = new SymfonyStyle($input, $output); | ||
|
||
$this->permissionResolver->setCurrentUserReference($this->userService->loadUserByLogin('admin')); | ||
|
||
foreach ($this->activityLogService->findGroups($query) as $activityLogGroup) { | ||
if ($activityLogGroup->getSource()) { | ||
$io->section($activityLogGroup->getSource()->getName()); | ||
} | ||
if ($activityLogGroup->getDescription()) { | ||
$io->text($activityLogGroup->getDescription()); | ||
} | ||
$table = []; | ||
foreach ($activityLogGroup->getActivityLogs() as $activityLog) { | ||
/** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */ | ||
$content = $activityLog->getRelatedObject(); | ||
$name = $content && $content->getName() && $content->getName() !== $activityLog->getObjectName() ? "“{$content->getName()}” (formerly “{$activityLog->getObjectName()}”)" : "“{$activityLog->getObjectName()}”"; | ||
$table[] = [ | ||
$activityLogGroup->getLoggedAt()->format(\DateTime::ATOM), | ||
$activityLog->getObjectId(), | ||
$name, | ||
$activityLog->getAction(), | ||
$activityLogGroup->getUser()->login, | ||
]; | ||
} | ||
$io->table([ | ||
'Logged at', | ||
'Obj. ID', | ||
'Object Name', | ||
'Action', | ||
'User', | ||
], $table); | ||
} | ||
|
||
return Command::SUCCESS; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\Event; | ||
|
||
use Symfony\Contracts\EventDispatcher\Event; | ||
|
||
class MyFeatureEvent extends Event | ||
{ | ||
private object $object; | ||
|
||
private string $action; | ||
|
||
public function __construct(object $object, string $action) | ||
{ | ||
$this->object = $object; | ||
$this->action = $action; | ||
} | ||
|
||
public function getObject(): object | ||
{ | ||
return $this->object; | ||
} | ||
|
||
public function getAction(): string | ||
{ | ||
return $this->action; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
code_samples/recent_activity/src/EventSubscriber/MyFeatureEventSubscriber.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\EventSubscriber; | ||
|
||
use App\Event\MyFeatureEvent; | ||
use Ibexa\Contracts\ActivityLog\ActivityLogServiceInterface; | ||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
|
||
class MyFeatureEventSubscriber implements EventSubscriberInterface | ||
{ | ||
private ActivityLogServiceInterface $activityLogService; | ||
|
||
public function __construct(ActivityLogServiceInterface $activityLogService) | ||
{ | ||
$this->activityLogService = $activityLogService; | ||
} | ||
|
||
public static function getSubscribedEvents(): array | ||
{ | ||
return [ | ||
MyFeatureEvent::class => 'onMyFeatureEvent', | ||
]; | ||
} | ||
|
||
public function onMyFeatureEvent(MyFeatureEvent $event): void | ||
{ | ||
/** @var App\MyFeature\MyFeature $object */ | ||
$object = $event->getObject(); | ||
$className = get_class($object); | ||
$id = (string)$object->id; | ||
$action = $event->getAction(); | ||
$activityLog = $this->activityLogService->build($className, $id, $action); | ||
$activityLog->setObjectName($object->name); | ||
$this->activityLogService->save($activityLog); | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
...ples/recent_activity/src/EventSubscriber/MyFeaturePostActivityListLoadEventSubscriber.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\EventSubscriber; | ||
|
||
use App\MyFeature\MyFeature; | ||
use App\MyFeature\MyFeatureService; | ||
use Ibexa\Contracts\ActivityLog\Event\PostActivityGroupListLoadEvent; | ||
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException; | ||
use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException; | ||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||
|
||
class MyFeaturePostActivityListLoadEventSubscriber implements EventSubscriberInterface | ||
{ | ||
private MyFeatureService $myFeatureService; | ||
|
||
public function __construct( | ||
MyFeatureService $myFeatureService | ||
) { | ||
$this->myFeatureService = $myFeatureService; | ||
} | ||
|
||
public static function getSubscribedEvents(): array | ||
{ | ||
return [ | ||
PostActivityGroupListLoadEvent::class => ['loadMyFeature'], | ||
]; | ||
} | ||
|
||
public function loadMyFeature(PostActivityGroupListLoadEvent $event): void | ||
{ | ||
$visitedIds = []; | ||
$list = $event->getList(); | ||
foreach ($list as $logGroup) { | ||
foreach ($logGroup->getActivityLogs() as $log) { | ||
if ($log->getObjectClass() !== MyFeature::class) { | ||
continue; | ||
} | ||
|
||
$id = (int)$log->getObjectId(); | ||
try { | ||
if (!array_key_exists($id, $visitedIds)) { | ||
$visitedIds[$id] = $this->myFeatureService->load($id); | ||
} | ||
|
||
if ($visitedIds[$id] === null) { | ||
continue; | ||
} | ||
|
||
$log->setRelatedObject($visitedIds[$id]); | ||
} catch (NotFoundException|UnauthorizedException $e) { | ||
$visitedIds[$id] = null; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\MyFeature; | ||
|
||
class MyFeature extends \stdClass | ||
{ | ||
public function __construct(array $properties) | ||
{ | ||
foreach ($properties as $propertyName => $propertyValue) { | ||
$this->$propertyName = $propertyValue; | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
code_samples/recent_activity/src/MyFeature/MyFeatureService.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace App\MyFeature; | ||
|
||
class MyFeatureService | ||
{ | ||
public function load(int $myFeatureId) | ||
{ | ||
return new MyFeature(['id' => $myFeatureId, 'name' => 'Actual Name']); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
code_samples/recent_activity/templates/themes/admin/activity_log/ui/default.html.twig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{% extends '@IbexaActivityLog/themes/admin/activity_log/ui/default.html.twig' %} | ||
|
||
{%- block activity_log_description_widget -%} | ||
{{ dump(log) }} | ||
{%- endblock activity_log_description_widget -%} |
Oops, something went wrong.