Skip to content
This repository was archived by the owner on Oct 20, 2024. It is now read-only.

Repository files navigation

Symfony ActivityLog Component

SensioLabsInsightBuild StatusCoverage StatusLatest Stable VersionTotal DownloadsLicense

ActivityLogBundle - Extended doctrine loggable (StofDoctrineExtensionsBundle)

What's inside

ActivityLogBundle uses Loggable extension from StofDoctrineExtensionsBundle and DoctrineExtensions

This bundle extend Gedmo\Loggable\Entity\MappedSuperclass\AbstractLogEntry with below fields:

  • parentId - store depedency to "main entity"
  • parentClass - store "main entity" type
  • oldData - data that were changed
  • name - entry name (to show in activity log)
  • user - associations mapping with user who changed data

Bundle contain extended listener (LoggableListener) to process above fields.

Also available formatter to preprocessing activity log before show in view (html).

Installation

Pretty simple with Composer, run:

composer require madmis/activity-log-bundle

Then enable the bundle in the kernel:

publicfunctionregisterBundles()
{
$bundles = [
// ...newActivityLogBundle\ActivityLogBundle(),
// ...
];
...
}

Configure bundle:

# app/config/config.ymldoctrine:
dbal:
#...orm:
#...resolve_target_entities:
Symfony\Component\Security\Core\User\UserInterface: AppBundle\Entity\Usermappings:
gedmo_loggable:
type: annotationprefix: Gedmo\Loggable\Entitydir: "%kernel.root_dir%/../src/AppBundle/Entity/"alias: GedmoLoggableis_bundle: falsestof_doctrine_extensions:
class:
loggable: ActivityLogBundle\Listener\LoggableListenerorm:
default:
loggable: true

Create entity and make it loggable:

namespaceAppBundle\Entity;
useDoctrine\ORM\MappingasORM;
useGedmo\Mapping\AnnotationasGedmo;
useActivityLogBundle\Entity\Interfaces\StringableInterface;
/** * @package AppBundle\Entity * @ORM\Entity(repositoryClass="ProjectRepository") * @ORM\Table * @Gedmo\Loggable(logEntryClass="ActivityLogBundle\Entity\LogEntry") */class Project implements StringableInterface
{
/** * @var int * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */private$id;
/** * @var string * @ORM\Column(type="string", length=128) * @Gedmo\Versioned */private$name;
/** * @var string * @ORM\Column(type="string", length=16) * @Gedmo\Versioned */private$key;
//...

StringableInterface required to save LogEntry::name.

Then run command to update database schema:

php bin/console doctrine:schema:update --force

Using formatter to data view

Formatter class: ActivityLogBundle\Service\ActivityLog\ActivityLogFormatter Formatter service: activity_log.formatter

required: LoggerInterface as dependency

By default entity without custom formatter class formatted by ActivityLogBundle\Service\ActivityLog\EntityFormatter\UniversalFormatter

But you can implement custom formatter for each entity.

To register a custom formatter, add a service tag with the following (required) properties:

  • name: 'activity_log.formatter'
  • entity: Class name of the entity that should be formatted by the registered formatter

Example:

services:
app.formatter.project:
class: AppBundle\Service\ActivityFormatter\Project
tags:
- { name: activity_log.formatter, entity: 'Project'}

As example formatter for AppBundle\Entity\Project entity:

namespaceAppBundle\Service\ActivityFormatter;
class Project extends AbstractFormatter implements FormatterInterface
{
/** * @param LogEntryInterface $log * @return array */publicfunctionformat(LogEntryInterface$log)
{
$result = $log->toArray();
if ($log->isCreate()) {
$result['message'] = sprintf('The <b>Project <span class="font-green-jungle">"%s"</span></b> was created.', $log->getName());
} elseif ($log->isRemove()) {
$result['message'] = sprintf('The <b>Project <span class="font-red-flamingo">"%s"</span></b> was removed.', $log->getName());
} elseif ($log->isUpdate()) {
$result['message'] = '<dl><dt>The <b>Project <span class="font-yellow-gold">"%s"</span></b> was updated.</dt>%s</dl>';
$data = $log->getData();
$oldData = $log->getOldData();
$text = '';
foreach ($dataas$field => $value) {
$value = $this->normalizeValue($field, $value);
if (array_key_exists($field, $oldData)) {
$oldValue = $this->normalizeValue($field, $oldData[$field]);
$subText = sprintf('from "<b>%s</b>" to "<b>%s</b>".', $oldValue, $value);
} else {
$subText = sprintf('to "<b>%s</b>".', $value);
}
$text .= sprintf('<dd>Property "<b>%s</b>" was changed: %s</dd>', $field, $subText);
}
$result['message'] = sprintf($result['message'], $log->getName(), $text);
} else {
$result['message'] = "Undefined action: {$log->getAction()}.";
}
return$result;
}
}

If entity has association with other entity it can be resolved by AbstractFormatter::normalizeValue. This method call method from the entity formatter class, which named as appropriate property.

For example, Project entity has association mapping ManyToOne to Type entity. To get Type name we can add method type to Project formatter:

namespaceAppBundle\Service\ActivityFormatter;
class Project extends AbstractFormatter implements FormatterInterface
{
//.../** * @param array $value * @return string */protectedfunctiontype(array$value)
{
if (isset($value['id'])) {
/** @var Type $entity */$entity = $this->entityManager->getRepository('AppBundle:Type')
->find($value['id']);
if ($entity) {
return$entity->getName();
}
}
return'';
}

As result we have formatted response to show in view.

Using activity log in controller

$em = $this->getDoctrine()->getManager();
// get log entries for entity$entries = $em
->getRepository('AppBundle:LogEntry')
->getLogEntriesQueryBuilder($entity)
->getQuery()
->getResult();
// format log entries to show in the view$entries = $this
->get('activity_log.formatter')
->format($entries);

For $entity should be configured Entity formatter.

About

Activity log bundle - Extended doctrine loggable bundle

Resources

Stars

11 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages