Skip to content

Commit

Permalink
multiple watchdog support (#3) (#4)
Browse files Browse the repository at this point in the history
* multiple watchdog support

* code fixes & yaml dep in req-dev

* few refactors

* extension flexibility add

* reverts & refactors

* legacy support & config & test

* compound unit infection cover fix

Co-authored-by: marek <marek@choosit.com>
  • Loading branch information
raneomik and marek authored Mar 6, 2022
1 parent ab740c2 commit 7adf742
Show file tree
Hide file tree
Showing 33 changed files with 739 additions and 160 deletions.
1 change: 1 addition & 0 deletions .github/workflows/workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ jobs:
fail_ci_if_error: true

- name: "Infection"
continue-on-error: true
timeout-minutes: 10
run: vendor/bin/infection --ansi --threads=$(nproc) --coverage=coverage --skip-initial-tests
env:
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ check-deps:
check-code: cs psalm stan

cs:
$(SF) php vendor/bin/php-cs-fixer fix --verbose --allow-risky=yes
vendor/bin/php-cs-fixer fix --verbose --allow-risky=yes
psalm:
$(SF) php vendor/bin/psalm --no-progress --show-info=true --no-cache
stan:
$(SF) php vendor/bin/phpstan --no-progress

lint:
vendor/bin/neon-lint .
vendor/bin/yaml-lint config tests --parse-tags
vendor/bin/yaml-lint tests --parse-tags

test:
ifdef FILTER
Expand All @@ -50,4 +50,4 @@ cover:
XDEBUG_MODE=coverage $(SF) php vendor/bin/simple-phpunit --coverage-xml=cov/xml --coverage-html=cov/html --log-junit=cov/junit.xml

infection:
XDEBUG_MODE=coverage vendor/bin/infection --ansi --threads=$(nproc)
XDEBUG_MODE=coverage vendor/bin/infection --ansi
46 changes: 34 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,58 @@ It can be configured as follows:
#config/packages/watchdog.yml

watchdog:
dates: # raise an event if current date time matches (following "Or" logic)
- { date_time: '2019-12-01 11:00' } # a date and time
- { date: '2019-12-03' } # a specific date
- { hour: '14:00' } # a specific hour
- { time: '14:15' } # or time
default: # raise an event if current date time matches (following "Or" logic)
- date_time: '2019-12-01 11:00' # a date and time
- date: '2019-12-03' # a specific date
- hour: '14:00' # a specific hour
- time: '14:15' # or time
- { start: '2019-12-01', end: '2019-12-31' } # an interval of dates
- { start: '10:00', end: '11:00' } # or of times
- { relative: 'first wednesday of' } # a relative format*
- compound: # or a composite of the rules above, following "And" logic, for example :
- { relative: 'monday' } # "On mondays"
- { start: '20:00', end: '22:30' } # "and between 20:00 and 22:30"
- { start: '10:00', end: '11:00' } # or of times
- relative: 'first wednesday of' # a relative format*
- compound: # or a composite of the rules above, following "And" logic, for example :
- relative: 'monday' # "On mondays"
- { start: '20:00', end: '22:30' } # "and between 20:00 and 22:30"

maintenance: # define another watchdogs, independent of each other.
- compound:
- relative: 'sundays'
- { start: '05:00', end: '06:00' }
```
\* [relative format](https://www.php.net/manual/datetime.formats.relative.php)
### Watchdog service
This bundle provides the `Raneomik\WatchdogBundle\Watchdog\Watchdog` service that can be injected anywhere.
This bundle provides the `Raneomik\WatchdogBundle\Watchdog\WatchdogInterface` service that can be injected anywhere.
It has a `isWoofTime` method returning true once configuration matches current date time.
If several ones are defined, they can be injected as follows (based on the example above) :

```php
use Raneomik\WatchdogBundle\Watchdog\WatchdogInterface;
class Service
{
__construct(
private WatchdogInterface $default,
private WatchdogInterface $maintenance
) {
}
....
```

### WatchdogHandlerInterface and WatchdogWoofCheckEvent

This bundle also provides the `Raneomik\WatchdogBundle\Handler\WatchdogHandlerInterface` interface with `processWoof(array $parameters = [])` method, for more complex processes.
It works with the `WatchdogEventSubscriber` subscribed to `WatchdogWoofCheckEvent`.

Anywhere you wish to check if it `isWoofTime`, dispatch a `new WatchdogWoofCheckEvent($parameters)`,
Anywhere you wish to check if it `isWoofTime`, dispatch a `new WatchdogWoofCheckEvent($parameters, $watchdogId)`,
and if it `isWoofTime`, it will trigger all `WatchdogHandlerInterface`s
and their `processWoof(array $parameters = []) // passed to the WatchdogWoofCheckEvent constructor`.

`$watchdogId` is null by default, which results in all defined watchdogs check.
If on is passed by this parameter, it check only the concerned one.

If you wish to use it but your project isn't set to be autoconfigured, all your `Handlers` implementing `WatchdogHandlerInterface` must be tagged with `raneomik_watchdog.handler`.

[License](LICENCE)
32 changes: 32 additions & 0 deletions Resources/config/watchdog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Raneomik\WatchdogBundle\DependencyInjection\WatchdogExtension;
use Raneomik\WatchdogBundle\Handler\WatchdogHandlerInterface;
use Raneomik\WatchdogBundle\Subscriber\WatchdogEventSubscriber;
use Raneomik\WatchdogBundle\Watchdog\Watchdog;
use Raneomik\WatchdogBundle\Watchdog\WatchdogInterface;

return static function (ContainerConfigurator $container) {
$container->services()
->set(Watchdog::class)
->public()
->arg('$watchdogParameters', '%watchdog_config%')
->tag(WatchdogExtension::SERVICE_TAG, ['id' => 'default'])

->alias(WatchdogInterface::class, Watchdog::class)
;

$container->services()
->instanceof(WatchdogHandlerInterface::class)
->tag(WatchdogExtension::HANDLER_SERVICE_TAG)
;

$container->services()
->set(WatchdogEventSubscriber::class)
->arg('$watchdogCollection', tagged_iterator(WatchdogExtension::SERVICE_TAG, 'id'))
->arg('$watchdogHandlers', tagged_iterator(WatchdogExtension::HANDLER_SERVICE_TAG))
->tag('kernel.event_subscriber')
;
};
24 changes: 24 additions & 0 deletions Resources/config/watchdog.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="Raneomik\WatchdogBundle\Watchdog\Watchdog" class="Raneomik\WatchdogBundle\Watchdog\Watchdog">
<tag name="raneomik_watchdog" id="default"/>
<argument>%watchdog_config%</argument>
</service>
<service id="Raneomik\WatchdogBundle\Watchdog\WatchdogInterface" alias="Raneomik\WatchdogBundle\Watchdog\Watchdog" />

<instanceof id="Raneomik\WatchdogBundle\Handler\WatchdogHandlerInterface" autowire="true">
<tag name="raneomik_watchdog.handler"/>
</instanceof >

<service id="Raneomik\WatchdogBundle\Subscriber\WatchdogEventSubscriber" class="Raneomik\WatchdogBundle\Subscriber\WatchdogEventSubscriber">
<tag name="kernel.event_subscriber"/>
<argument type="tagged_iterator" tag="raneomik_watchdog" index-by="id"/>
<argument type="tagged_iterator" tag="raneomik_watchdog.handler"/>
</service>
</services>
</container>
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
],
"require": {
"php": "^7.4|^8.0",
"symfony/framework-bundle": "^4.4|^5.4|^6.0",
"symfony/yaml": "^4.4|^5.4|^6.0"
"symfony/framework-bundle": "^4.4|^5.4|^6.0"
},
"require-dev": {
"ekino/phpstan-banned-code": "*",
Expand All @@ -26,6 +25,7 @@
"phpunit/phpunit": "^9.5",
"psalm/plugin-symfony": "*",
"symfony/phpunit-bridge": "^6.0.0",
"symfony/yaml": "^4.4|^5.4|^6.0",
"symplify/coding-standard": "*",
"symplify/phpstan-rules": "*",
"vimeo/psalm": "*"
Expand All @@ -40,6 +40,7 @@
"sort-packages": true
},
"extra": {
"sort-packages": true,
"allow-plugins": {
"phpstan/extension-installer": true,
"infection/extension-installer": true,
Expand Down
15 changes: 0 additions & 15 deletions config/services.yml

This file was deleted.

3 changes: 3 additions & 0 deletions infection.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"source": {
"directories": [
"src"
],
"excludes": [
"DependencyInjection/SymfonyVersionChecker"
]
},
"logs": {
Expand Down
3 changes: 3 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<include>
<directory>src/</directory>
</include>
<exclude>
<directory>src/DependencyInjection/SymfonyVersionChecker/</directory>
</exclude>
</coverage>

<testsuites>
Expand Down
31 changes: 26 additions & 5 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,43 @@

namespace Raneomik\WatchdogBundle\DependencyInjection;

use Raneomik\WatchdogBundle\DependencyInjection\SymfonyVersionChecker\LegacyChecker;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
public const LEGACY_CONFIG_ERROR_MESSAGE = 'The attribute "whatever" must be set for path "watchdog"';

private LegacyChecker $symfonyVersionChecker;

public function __construct(LegacyChecker $symfonyVersionChecker)
{
$this->symfonyVersionChecker = $symfonyVersionChecker;
}

public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('watchdog');

$treeBuilder->getRootNode()
->children()
->arrayNode('dates')
->variablePrototype()->end()
->end()
$this->configureLegacyPartIfNeeded($treeBuilder->getRootNode())
->fixXmlConfig('watchdog')
->variablePrototype()->end()
->end();

return $treeBuilder;
}

private function configureLegacyPartIfNeeded(ArrayNodeDefinition $definition): ArrayNodeDefinition
{
if ($this->symfonyVersionChecker->isLegacy()) {
$definition
->useAttributeAsKey('whatever') // some legacy magic
->arrayPrototype()
;
}

return $definition;
}
}
14 changes: 14 additions & 0 deletions src/DependencyInjection/SymfonyVersionChecker/LegacyChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Raneomik\WatchdogBundle\DependencyInjection\SymfonyVersionChecker;

use Symfony\Component\HttpKernel\Kernel;

class LegacyChecker
{
public function isLegacy(): bool
{
/* @phpstan-ignore-next-line */
return 5 > Kernel::MAJOR_VERSION;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Raneomik\WatchdogBundle\DependencyInjection\SymfonyVersionChecker;

class LegacyCheckerFactory
{
private static bool $testMode = false;

public static function create(bool $forceLegacy = false): LegacyChecker
{
if ($forceLegacy) {
return new LegacyFaker($forceLegacy);
}

return self::$testMode
? new LegacyFaker()
: new LegacyChecker()
;
}

public static function testMode(): void
{
self::$testMode = true;
}
}
18 changes: 18 additions & 0 deletions src/DependencyInjection/SymfonyVersionChecker/LegacyFaker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Raneomik\WatchdogBundle\DependencyInjection\SymfonyVersionChecker;

class LegacyFaker extends LegacyChecker
{
private bool $isLegacy;

public function __construct(bool $isLegacy = false)
{
$this->isLegacy = $isLegacy;
}

public function isLegacy(): bool
{
return $this->isLegacy;
}
}
Loading

0 comments on commit 7adf742

Please sign in to comment.