Skip to content

Commit

Permalink
Enable PHPStan CI
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxime Rainville committed Nov 13, 2024
1 parent e410533 commit aa2593f
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 28 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,7 @@ jobs:
run: composer install --prefer-dist --no-progress

- name: Check coding standards
run: php-cs-fixer fix --dry-run --diff
run: php-cs-fixer fix --dry-run --diff

- name: Static Analysis
run: vendor/bin/phpstan analyse
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
.DS_Store
composer.lock
/public/
.php-cs-fixer.cache
.php-cs-fixer.cache
phpstan.cache/
12 changes: 5 additions & 7 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ parameters:
paths:
- src
- tests
tmpDir: phpstan.cache
excludePaths:
- vendor/*
silverstripe:
checkUnusedViewVariables: false
analyseAndScan:
- vendor
ignoreErrors:
- '#Access to an undefined property .+::\$owner#'
- '#Call to an undefined method .+::hasExtension\(\)#'
includes:
- vendor/symbiote/silverstripe-phpstan/phpstan.neon
- '#Static property ArchiPro\\Silverstripe\\EventDispatcher\\Service\\EventService::\$listeners is never read, only written\.#'
- '#Static property ArchiPro\\Silverstripe\\EventDispatcher\\Service\\EventService::\$loaders is never read, only written\.#'
4 changes: 3 additions & 1 deletion src/Event/DataObjectEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ public function getObject(bool $useVersion = false): ?DataObject
}

if (!$useVersion || empty($this->version)) {
return DataObject::get_by_id($this->objectClass, $this->objectID, false);
/** @var T|null $object*/
$object = DataObject::get($this->objectClass)->byID($this->objectID);
return $object;
}

return Versioned::get_version($this->objectClass, $this->objectID, $this->version);
Expand Down
34 changes: 24 additions & 10 deletions src/Extension/EventDispatchExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ArchiPro\Silverstripe\EventDispatcher\Extension;

use Amp\Future;
use ArchiPro\Silverstripe\EventDispatcher\Event\DataObjectEvent;
use ArchiPro\Silverstripe\EventDispatcher\Event\Operation;
use ArchiPro\Silverstripe\EventDispatcher\Service\EventService;
Expand All @@ -14,9 +15,8 @@
/**
* Extension that adds event dispatching capabilities to DataObjects.
*
* @property DataObject|Versioned $owner
*
* @method DataObject getOwner()
* @phpstan-template T of DataObject
* @phpstan-extends Extension<T>
*/
class EventDispatchExtension extends Extension
{
Expand All @@ -32,7 +32,7 @@ public function onAfterWrite(): void
// By this point isInDB() will return true even for new records since the ID is already set
// Instead check if the ID field was changed which indicates this is a new record
$owner->isChanged('ID') ? Operation::CREATE : Operation::UPDATE,
$owner->hasExtension(Versioned::class) ? $owner->Version : null,
$this->getVersion(),
Security::getCurrentUser()?->ID
);

Expand All @@ -49,7 +49,7 @@ public function onBeforeDelete(): void
get_class($owner),
$owner->ID,
Operation::DELETE,
$owner->hasExtension(Versioned::class) ? $owner->Version : null,
$this->getVersion(),
Security::getCurrentUser()?->ID
);

Expand All @@ -70,7 +70,7 @@ public function onAfterPublish(): void
get_class($owner),
$owner->ID,
Operation::PUBLISH,
$owner->Version,
$this->getVersion(),
Security::getCurrentUser()?->ID
);

Expand All @@ -91,7 +91,7 @@ public function onAfterUnpublish(): void
get_class($owner),
$owner->ID,
Operation::UNPUBLISH,
$owner->Version,
$this->getVersion(),
Security::getCurrentUser()?->ID
);

Expand All @@ -112,7 +112,7 @@ public function onAfterArchive(): void
get_class($owner),
$owner->ID,
Operation::ARCHIVE,
$owner->Version,
$this->getVersion(),
Security::getCurrentUser()?->ID
);

Expand All @@ -133,7 +133,7 @@ public function onAfterRestore(): void
get_class($owner),
$owner->ID,
Operation::RESTORE,
$owner->Version,
$this->getVersion(),
Security::getCurrentUser()?->ID
);

Expand All @@ -142,9 +142,23 @@ public function onAfterRestore(): void

/**
* Dispatches an event using the EventService
*
* @phpstan-param DataObjectEvent<T> $event
* @phpstan-return Future<DataObjectEvent<T>>
*/
protected function dispatchEvent(DataObjectEvent $event): DataObjectEvent
protected function dispatchEvent(DataObjectEvent $event): Future
{
return Injector::inst()->get(EventService::class)->dispatch($event);
}

private function getVersion(): ?int
{
$owner = $this->getOwner();
if (!$owner->hasExtension(Versioned::class)) {
return null;
}

/** @var Versioned $owner */
return $owner->Version;
}
}
13 changes: 7 additions & 6 deletions src/Listener/DataObjectEventListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,20 @@ class DataObjectEventListener
{
use Injectable;

/** @var Operation[] */
private array $operations;

/**
* Creates a new DataObject event listener.
*
* @template T of DataObject
*
* @param Closure(DataObjectEvent<T>): void $callback Callback to execute when an event matches
* @param class-string<T>[] $classes Array of DataObject class names to listen for
* @param Operation[]|null $operations Array of operations to listen for. If null, listens for all operations.
* @param Operation[] $operations Array of operations to listen for. If null, listens for all operations.
*/
public function __construct(
private Closure $callback,
private array $classes,
private ?array $operations = null
private readonly Closure $callback,
private readonly array $classes,
array $operations = null
) {
$this->operations = $operations ?? Operation::cases();
}
Expand Down
5 changes: 4 additions & 1 deletion src/Service/EventService.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class EventService

/**
* @config
*
* @var array<string,array<callable>> Map of event class names to arrays of listener callbacks
*/
private static array $listeners = [];
Expand Down Expand Up @@ -80,6 +79,10 @@ private function loadListeners(): void

/**
* Adds a listener to the event service
*
* @template T of object
* @param class-string<T> $event The event class name
* @param callable(T): void $listener The listener callback
*/
public function addListener(string $event, callable $listener): void
{
Expand Down
9 changes: 8 additions & 1 deletion tests/php/Event/DataObjectEventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

class DataObjectEventTest extends SapphireTest
{
/** @var string */
protected static $fixture_file = 'DataObjectEventTest.yml';

/** @var string[] */
protected static $extra_dataobjects = [
SimpleDataObject::class,
VersionedDataObject::class,
Expand Down Expand Up @@ -50,18 +52,23 @@ public function testGetVersionedObject(): void
$object->Title = 'Updated Title';
$object->write();

/** @var DataObjectEvent<VersionedDataObject> $event */
$event = DataObjectEvent::create(VersionedDataObject::class, $object->ID, Operation::UPDATE, $object->Version);

// Get current version
/** @var VersionedDataObject $currentObject */
$currentObject = $event->getObject(false);
$this->assertEquals('Updated Title', $currentObject->Title);

// Get specific version
/** @var VersionedDataObject $versionedObject */
$versionedObject = $event->getObject(true);
$this->assertEquals('Updated Title', $versionedObject->Title);

// Get previous version
/** @var DataObjectEvent<VersionedDataObject> $previousEvent */
$previousEvent = DataObjectEvent::create(VersionedDataObject::class, $object->ID, Operation::UPDATE, $object->Version - 1);
/** @var VersionedDataObject $previousVersion */
$previousVersion = $previousEvent->getObject(true);
$this->assertEquals('Original Title', $previousVersion->Title);
}
Expand All @@ -82,7 +89,7 @@ public function testSerialization(): void
$event = DataObjectEvent::create(SimpleDataObject::class, 1, Operation::CREATE, 2, 3);

$serialized = serialize($event);
/** @var DataObjectEvent $unserialized */
/** @var DataObjectEvent<SimpleDataObject> $unserialized */
$unserialized = unserialize($serialized);

$this->assertEquals(1, $unserialized->getObjectID());
Expand Down

0 comments on commit aa2593f

Please sign in to comment.