From b7b92f562e5817bd7fa164fdbbeadc44995cacfa Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 22 Feb 2024 21:56:01 +0100 Subject: [PATCH] Disable events from mass changes; closes #1733 --- .../Crud/ContributionsController.php | 1 + .../Controllers/Crud/MembersController.php | 4 +- galette/lib/Galette/Entity/Adherent.php | 24 +- galette/lib/Galette/Entity/Contribution.php | 24 +- galette/lib/Galette/Features/HasEvent.php | 237 ++++++++++++++++++ .../Galette/Features/tests/units/HasEvent.php | 124 +++++++++ 6 files changed, 407 insertions(+), 7 deletions(-) create mode 100644 galette/lib/Galette/Features/HasEvent.php create mode 100644 tests/Galette/Features/tests/units/HasEvent.php diff --git a/galette/lib/Galette/Controllers/Crud/ContributionsController.php b/galette/lib/Galette/Controllers/Crud/ContributionsController.php index 146e37fe9..ebee1834e 100644 --- a/galette/lib/Galette/Controllers/Crud/ContributionsController.php +++ b/galette/lib/Galette/Controllers/Crud/ContributionsController.php @@ -337,6 +337,7 @@ class ContributionsController extends CrudController foreach ($members_ids as $member_id) { $post[Adherent::PK] = (int)$member_id; $contrib = new Contribution($this->zdb, $this->login); + $contrib->disableEvents(); // regular fields $valid = $contrib->check($post, $contrib->getRequired(), $disabled); diff --git a/galette/lib/Galette/Controllers/Crud/MembersController.php b/galette/lib/Galette/Controllers/Crud/MembersController.php index d9b1fcaf3..6891ee25d 100644 --- a/galette/lib/Galette/Controllers/Crud/MembersController.php +++ b/galette/lib/Galette/Controllers/Crud/MembersController.php @@ -1307,7 +1307,9 @@ class MembersController extends CrudController && !$this->login->isStaff() && $this->login->isGroupManager(); $member = new Adherent($this->zdb); - $member->disableAllDeps(); + $member + ->disableAllDeps() + ->disableEvents(); if ($is_manager) { $member->enableDep('groups'); } diff --git a/galette/lib/Galette/Entity/Adherent.php b/galette/lib/Galette/Entity/Adherent.php index 9b844fc23..e6d67b4d9 100644 --- a/galette/lib/Galette/Entity/Adherent.php +++ b/galette/lib/Galette/Entity/Adherent.php @@ -38,6 +38,7 @@ namespace Galette\Entity; use ArrayObject; use Galette\Events\GaletteEvent; +use Galette\Features\HasEvent; use Galette\Features\Socials; use Throwable; use Analog\Analog; @@ -126,6 +127,7 @@ class Adherent { use Dynamics; use Socials; + use HasEvent; public const TABLE = 'adherents'; public const PK = 'id_adh'; @@ -237,6 +239,12 @@ class Adherent } } + $this + ->withAddEvent() + ->withEditEvent() + ->withoutDeleteEvent() + ->activateEvents(); + if ($args == null || is_int($args)) { if (is_int($args) && $args > 0) { $this->load($args); @@ -1569,7 +1577,7 @@ class Adherent ); } - $event = 'member.add'; + $event = $this->getAddEventName(); } else { $hist->add(_T("Fail to add new member.")); throw new \Exception( @@ -1605,7 +1613,7 @@ class Adherent $this->sname ); } - $event = 'member.edit'; + $event = $this->getEditEventName(); } //dynamic fields @@ -1613,7 +1621,7 @@ class Adherent $this->storeSocials($this->id); //send event at the end of process, once all has been stored - if ($event !== null) { + if ($event !== null && $this->areEventsEnabled()) { $emitter->dispatch(new GaletteEvent($event, $this)); } return true; @@ -2267,4 +2275,14 @@ class Adherent $this->loadParent(); return $this; } + + /** + * Get prefix for events + * + * @return string + */ + protected function getEventsPrefix(): string + { + return 'member'; + } } diff --git a/galette/lib/Galette/Entity/Contribution.php b/galette/lib/Galette/Entity/Contribution.php index f8cc8bd0d..3457da44e 100644 --- a/galette/lib/Galette/Entity/Contribution.php +++ b/galette/lib/Galette/Entity/Contribution.php @@ -40,6 +40,7 @@ namespace Galette\Entity; use ArrayObject; use DateTime; use Galette\Events\GaletteEvent; +use Galette\Features\HasEvent; use Throwable; use Analog\Analog; use Laminas\Db\Sql\Expression; @@ -85,6 +86,7 @@ use Galette\Features\Dynamics; class Contribution { use Dynamics; + use HasEvent; public const TABLE = 'cotisations'; public const PK = 'id_cotis'; @@ -135,6 +137,12 @@ class Contribution global $preferences; $this->_payment_type = (int)$preferences->pref_default_paymenttype; + $this + ->withAddEvent() + ->withEditEvent() + ->withoutDeleteEvent() + ->activateEvents(); + /* * Fields configuration. Each field is an array and must reflect: * array( @@ -683,7 +691,7 @@ class Contribution _T("Contribution added"), Adherent::getSName($this->zdb, $this->_member) ); - $event = 'contribution.add'; + $event = $this->getAddEventName(); } else { $hist->add(_T("Fail to add new contribution.")); throw new \Exception( @@ -705,7 +713,7 @@ class Contribution ); } - $event = 'contribution.edit'; + $event = $this->getEditEventName(); } //update deadline if ($this->isFee()) { @@ -719,7 +727,7 @@ class Contribution $this->_orig_amount = $this->_amount; //send event at the end of process, once all has been stored - if ($event !== null) { + if ($event !== null && $this->areEventsEnabled()) { $emitter->dispatch(new GaletteEvent($event, $this)); } @@ -1505,4 +1513,14 @@ class Contribution return false; } + + /** + * Get prefix for events + * + * @return string + */ + protected function getEventsPrefix(): string + { + return 'contribution'; + } } diff --git a/galette/lib/Galette/Features/HasEvent.php b/galette/lib/Galette/Features/HasEvent.php new file mode 100644 index 000000000..b1d076517 --- /dev/null +++ b/galette/lib/Galette/Features/HasEvent.php @@ -0,0 +1,237 @@ +. + * + * @category Features + * @package Galette + * + * @author Johan Cwiklinski + * @copyright 2024 The Galette Team + * @license https://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version + * @link https://galette.eu + */ + +namespace Galette\Features; + +/** + * Has events trait + * + * @category Features + * @name HasEvents + * @package Galette + * @author Johan Cwiklinski + * @copyright 2024 The Galette Team + * @license https://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version + * @link https://galette.eu + */ + +trait HasEvent +{ + private bool $has_add_event = false; + private bool $has_edit_event = false; + private bool $has_delete_event = false; + protected bool $events_active = true; + + /** + * Get prefix for events + * + * @return string + */ + abstract protected function getEventsPrefix(): string; + + /** + * Activate events + * + * @return self + */ + public function activateEvents(): self + { + $this->events_active = true; + return $this; + } + + /** + * Disable events + * + * @return self + */ + public function disableEvents(): self + { + $this->events_active = false; + return $this; + } + + /** + * Are events enabled + * + * @return bool + */ + public function areEventsEnabled(): bool + { + return $this->events_active; + } + + /** + * Activate add event + * + * @return self + */ + public function withAddEvent(): self + { + $this->has_add_event = true; + return $this; + } + + /** + * Disable add event + * + * @return self + */ + public function withoutAddEvent(): self + { + $this->has_add_event = false; + return $this; + } + + /** + * Get add event name + * + * @return ?string + */ + public function getAddEventName(): ?string + { + if (!$this->hasAddEvent()) { + return null; + } + return sprintf( + '%1$s.add', + $this->getEventsPrefix() + ); + } + + /** + * Has add event + * + * @return bool + */ + public function hasAddEvent(): bool + { + return $this->areEventsEnabled() && $this->has_add_event; + } + + /** + * Activate edit event + * + * @return self + */ + public function withEditEvent(): self + { + $this->has_edit_event = true; + return $this; + } + + /** + * Disable edit event + * + * @return self + */ + public function withoutEditEvent(): self + { + $this->has_edit_event = false; + return $this; + } + + /** + * Get edit event name + * + * @return ?string + */ + public function getEditEventName(): ?string + { + if (!$this->hasEditEvent()) { + return null; + } + return sprintf( + '%1$s.edit', + $this->getEventsPrefix() + ); + } + + /** + * Has edit event + * + * @return bool + */ + public function hasEditEvent(): bool + { + return $this->areEventsEnabled() && $this->has_edit_event; + } + + /** + * Activate add event + * + * @return self + */ + public function withDeleteEvent(): self + { + $this->has_delete_event = true; + return $this; + } + + /** + * Disable delete event + * + * @return self + */ + public function withoutDeleteEvent(): self + { + $this->has_delete_event = false; + return $this; + } + + /** + * Get edit event name + * + * @return ?string + */ + public function getDeleteEventName(): ?string + { + if (!$this->hasDeleteEvent()) { + return null; + } + return sprintf( + '%1$s.delete', + $this->getEventsPrefix() + ); + } + + /** + * Has delete event + * + * @return bool + */ + public function hasDeleteEvent(): bool + { + return $this->areEventsEnabled() && $this->has_delete_event; + } +} diff --git a/tests/Galette/Features/tests/units/HasEvent.php b/tests/Galette/Features/tests/units/HasEvent.php new file mode 100644 index 000000000..2f175922d --- /dev/null +++ b/tests/Galette/Features/tests/units/HasEvent.php @@ -0,0 +1,124 @@ +. + * + * @category Features + * @package GaletteTests + * + * @author Johan Cwiklinski + * @copyright 2024 The Galette Team + * @license https://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version + * @link https://galette.eu + */ + +namespace Galette\Entity\test\units; + +use Galette\GaletteTestCase; + +/** + * HasEvent tests class + * + * @category Features + * @name HasEvents + * @package GaletteTests + * @author Johan Cwiklinski + * @copyright 2024 The Galette Team + * @license https://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version + * @link https://galette.eu + */ +class HasEvent extends GaletteTestCase +{ + protected int $seed = 20240223092214; + + /** + * Test HasEvent capacities + * + * @return void + */ + public function testCapacities(): void + { + $this->adh = new \Galette\Entity\Adherent($this->zdb); + + //per default, add and edit events are active on contributions + $contrib = new \Galette\Entity\Contribution($this->zdb, $this->login); + $this->assertTrue($contrib->areEventsEnabled()); + $this->assertTrue($contrib->hasAddEvent()); + $this->assertTrue($contrib->hasEditEvent()); + $this->assertFalse($contrib->hasDeleteEvent()); + $this->assertEquals('contribution.add', $contrib->getAddEventName()); + $this->assertEquals('contribution.edit', $contrib->getEditEventName()); + $this->assertNull($contrib->getDeleteEventName()); + + //per default, add and edit events are active on members + $this->assertTrue($this->adh->areEventsEnabled()); + $this->assertTrue($this->adh->hasAddEvent()); + $this->assertTrue($this->adh->hasEditEvent()); + $this->assertFalse($this->adh->hasDeleteEvent()); + $this->assertEquals('member.add', $this->adh->getAddEventName()); + $this->assertEquals('member.edit', $this->adh->getEditEventName()); + $this->assertNull($this->adh->getDeleteEventName()); + + //disable add event + $this->adh->withoutAddEvent(); + $this->assertFalse($this->adh->hasAddEvent()); + $this->assertNull($this->adh->getAddEventName()); + $this->assertTrue($this->adh->hasEditEvent()); + //enable add event + $this->adh->withAddEvent(); + $this->assertTrue($this->adh->hasAddEvent()); + + //disable edit event + $this->adh->withoutEditEvent(); + $this->assertTrue($this->adh->hasAddEvent()); + $this->assertFalse($this->adh->hasEditEvent()); + $this->assertNull($this->adh->getEditEventName()); + //enable edit event + $this->adh->withEditEvent(); + $this->assertTrue($this->adh->hasEditEvent()); + + //enable delete event + $this->adh->withDeleteEvent(); + $this->assertTrue($this->adh->hasDeleteEvent()); + $this->assertEquals('member.delete', $this->adh->getDeleteEventName()); + //disable delete event + $this->adh->withoutDeleteEvent(); + $this->assertFalse($this->adh->hasDeleteEvent()); + + // disable all events + $this->adh->disableEvents(); + $this->assertFalse($this->adh->areEventsEnabled()); + $this->assertFalse($this->adh->hasAddEvent()); + $this->assertFalse($this->adh->hasEditEvent()); + $this->assertFalse($this->adh->hasDeleteEvent()); + $this->assertNull($this->adh->getAddEventName()); + $this->assertNull($this->adh->getEditEventName()); + $this->assertNull($this->adh->getDeleteEventName()); + + //reactivate events + $this->adh->activateEvents(); + $this->assertTrue($this->adh->areEventsEnabled()); + $this->assertTrue($this->adh->hasAddEvent()); + $this->assertTrue($this->adh->hasEditEvent()); + $this->assertFalse($this->adh->hasDeleteEvent()); + } +} -- 2.39.2