Skip to content

Commit

Permalink
add include exclude feature for property (#1)
Browse files Browse the repository at this point in the history
* add include exclude feature for properties
  • Loading branch information
manasbala authored Jun 20, 2020
1 parent 5880e45 commit 4d9fd0e
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 23 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@

/bundle-maker-app
/vendor/
.idea
composer.lock
96 changes: 95 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ $ php bin/console doctrine:schema:update --force

### Step 4: Configure entities you need to log

Add `@Loggable` annotation in the entity you want to log changes.
Add `@Loggable` annotation in the entity you want to log changes. By default strategy will be `include_all`, all properties changes will be logged.

```php
// src/Entity/User.php
Expand All @@ -88,6 +88,98 @@ class User
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

}
```

#### Strategy
There are two strategies. `exclude_all` & `include_all`. Exclude all will automatically skip all properties. And icclude all will automatically log all properties.

Strategies are used only for update. Create and Delete actions always logged.

If you want to exclude all properties and only log one property then use strategy `exclude_all` and use `@Log` annotation only in the property you want to log.

```php
// src/Entity/User.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Mb\DoctrineLogBundle\Annotation\Log;
use Mb\DoctrineLogBundle\Annotation\Loggable;

/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\Table(name="user")
*
* @Loggable(strategy="exclude_all")
*/
class User
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(type="text", column="name")
* @Log
*/
protected $name;

/**
* @ORM\Column(type="text", column="user_name")
*/
protected $username;

}
```

Above example will only log for the `$name` property.

If you want to log all but skip one property. Then use strategy `include_all` and in the property use annotation `@Exclude` to skip that property.

```php
// src/Entity/User.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Mb\DoctrineLogBundle\Annotation\Exclude;
use Mb\DoctrineLogBundle\Annotation\Loggable;

/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\Table(name="user")
*
* @Loggable(strategy="include_all")
*/
class User
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(type="text", column="name")
* @Exclude
*/
protected $name;

/**
* @ORM\Column(type="text", column="user_name")
*/
protected $username;

}
```

Expand All @@ -110,6 +202,8 @@ mb_doctrine_log:

```

Any property name you configure here, if the Loggable entity has that property will be ignored.

How data will be saved
----------------------

Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"name": "manasbala/doctrine-log-bundle",
"description": "Symfony bundle to enable auto logging doctrine entity chanages.",
"description": "Symfony bundle to enable auto logging doctrine entity changes.",
"type": "symfony-bundle",
"require": {
"php": "^7.1.3",
"jms/serializer-bundle": "^3.4",
"symfony/orm-pack": "*",
"stof/doctrine-extensions-bundle": "^1.3"
"stof/doctrine-extensions-bundle": "^1.3",
"symfony/monolog-bundle": "^3.5"
},
"license": "MIT",
"authors": [
Expand Down
14 changes: 14 additions & 0 deletions src/Annotation/Exclude.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Mb\DoctrineLogBundle\Annotation;

/**
* Class Exclude
* @package Mb\DoctrineLogBundle\Annotation
*
* @Annotation
* @Target("PROPERTY")
*/
class Exclude
{
}
14 changes: 14 additions & 0 deletions src/Annotation/Log.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Mb\DoctrineLogBundle\Annotation;

/**
* Class Log
* @package Mb\DoctrineLogBundle\Annotation
*
* @Annotation
* @Target("PROPERTY")
*/
class Log
{
}
8 changes: 8 additions & 0 deletions src/Annotation/Loggable.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@
* @package Mb\DoctrineLogBundle\Annotation
*
* @Annotation
* @Target("CLASS")
*/
class Loggable
{
const STRATEGY_EXCLUDE_ALL = 'exclude_all';
const STRATEGY_INCLUDE_ALL = 'include_all';

/**
* @var string
* @Enum({"exclude_all", "include_all"})
*/
public $strategy = self::STRATEGY_INCLUDE_ALL;
}
2 changes: 1 addition & 1 deletion src/DependencyInjection/MbDoctrineLogExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public function load(array $configs, ContainerBuilder $container)
$config = $this->processConfiguration($configuration, $configs);

$definition = $container->getDefinition('mb_doctrine_log.event_listener.logger');
$definition->setArgument(4, $config['ignore_properties']);
$definition->setArgument(5, $config['ignore_properties']);
}
}
44 changes: 28 additions & 16 deletions src/EventListener/Logger.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

namespace Mb\DoctrineLogBundle\EventListener;

use ReflectionClass;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\PostFlushEventArgs;
use JMS\Serializer\SerializerInterface as Serializer;

use Mb\DoctrineLogBundle\Service\AnnotationReader;
use Mb\DoctrineLogBundle\Service\Logger as LoggerService;
use Mb\DoctrineLogBundle\Entity\Log as LogEntity;
use Mb\DoctrineLogBundle\Annotation\Loggable;
use Psr\Log\LoggerInterface;

/**
* Class Logger
Expand Down Expand Up @@ -42,10 +42,15 @@ class Logger
private $serializer;

/**
* @var Reader $reader
* @var AnnotationReader
*/
private $reader;

/**
* @var LoggerInterface
*/
private $monolog;

/**
* @var array
*/
Expand All @@ -56,21 +61,23 @@ class Logger
* @param EntityManagerInterface $em
* @param LoggerService $loggerService
* @param Serializer $serializer
* @param Reader $reader
* @param AnnotationReader $reader
* @param array $ignoreProperties
*/
public function __construct(
EntityManagerInterface $em,
LoggerService $loggerService,
Serializer $serializer,
Reader $reader,
AnnotationReader $reader,
LoggerInterface $monolog,
array $ignoreProperties
) {
$this->em = $em;
$this->loggerService = $loggerService;
$this->serializer = $serializer;
$this->reader = $reader;
$this->ignoreProperties = $ignoreProperties;
$this->monolog = $monolog;
}

/**
Expand Down Expand Up @@ -134,9 +141,8 @@ public function postFlush(PostFlushEventArgs $args)
private function log($entity, $action)
{
try {
$class = new ReflectionClass(str_replace('Proxies\__CG__\\', '', get_class($entity)));
$annotation = $this->reader->getClassAnnotation($class, Loggable::class);
if ($annotation instanceof Loggable) {
$this->reader->init($entity);
if ($this->reader->isLoggable()) {
$changes = null;
if ($action === LogEntity::ACTION_UPDATE) {
$uow = $this->em->getUnitOfWork();
Expand All @@ -150,7 +156,7 @@ private function log($entity, $action)

// just getting the changed objects ids
foreach ($changeSet as $key => &$values) {
if (in_array($key, $this->ignoreProperties)) {
if (in_array($key, $this->ignoreProperties) || !$this->reader->isLoggable($key)) {
// ignore configured properties
unset($changeSet[$key]);
}
Expand All @@ -164,17 +170,23 @@ private function log($entity, $action)
}
}

$changes = $this->serializer->serialize($changeSet, 'json');
if (!empty($changeSet)) {
$changes = $this->serializer->serialize($changeSet, 'json');
}
}

$this->logs[] = $this->loggerService->log(
$entity,
$action,
$changes
);
if ($action === LogEntity::ACTION_UPDATE && !$changes) {
// Log nothing
} else {
$this->logs[] = $this->loggerService->log(
$entity,
$action,
$changes
);
}
}
} catch (\Exception $e) {
// todo: log error
$this->monolog->error($e->getMessage());
}
}
}
7 changes: 6 additions & 1 deletion src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@
<argument type="service" id="doctrine.orm.default_entity_manager"/>
<argument type="service" id="mb_doctrine_log.service.logger"/>
<argument type="service" id="jms_serializer.serializer"/>
<argument type="service" id="annotations.reader"/>
<argument type="service" id="mb_doctrine_log.service.annotation_reader"/>
<argument type="service" id="monolog.logger"/>
</service>

<service class="Mb\DoctrineLogBundle\Service\Logger" id="mb_doctrine_log.service.logger">
<argument type="service" id="doctrine.orm.default_entity_manager" />
</service>

<service class="Mb\DoctrineLogBundle\Service\AnnotationReader" id="mb_doctrine_log.service.annotation_reader">
<argument type="service" id="annotations.reader"/>
</service>
</services>
</container>
Loading

0 comments on commit 4d9fd0e

Please sign in to comment.