PHP code example of snicco / better-wp-hooks

1. Go to this page and download the library: Download snicco/better-wp-hooks library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

snicco / better-wp-hooks example snippets


use Snicco\Component\BetterWPHooks\WPEventDispatcher;

$dispatcher = WPEventDispatcher::fromDefaults();

use Snicco\Component\BetterWPHooks\WPEventDispatcher;
use Snicco\Component\EventDispatcher\BaseEventDispatcher;
use Snicco\Component\EventDispatcher\ListenerFactory\PsrListenerFactory;

$your_psr_container = /* */

$base_dispatcher = new BaseEventDispatcher(new PsrListenerFactory($your_psr_container));

$dispatcher = new WPEventDispatcher($base_dispatcher);

use Snicco\Component\BetterWPHooks\WPEventDispatcher;

$dispatcher = WPEventDispatcher::fromDefaults();

// Assumes OrderListener has an __invoke method
$dispatcher->listen(OrderCreated::class, OrderListener::class);

// String names work for events
$dispatcher->listen('order_created', OrderListener::class);

// Any public method works
$dispatcher->listen(OrderCreated::class, [OrderListener::class, 'someMethod']);

// A simple closure listener
$dispatcher->listen(OrderCreated::class, function(OrderCreated $event) {
    // 
});

// This is the same as above
$dispatcher->listen(function(OrderCreated $event) {
    // 
});


use Snicco\Component\BetterWPHooks\WPEventDispatcher;

$dispatcher = WPEventDispatcher::fromDefaults();
$dispatcher->listen(OrderCreated::class, function (OrderCreated $event) {
    // Do stuff with order
    $order = $event->order;
});

$order = /* */

$event = new OrderCreated($order);

// This will lazily create and call all listeners
// that are attached to OrderCreated::class event
$result = $dispatcher->dispatch($event);

var_dump($event === $result); // true

use Snicco\Component\BetterWPHooks\WPEventDispatcher;
use Snicco\Component\EventDispatcher\GenericEvent;

$dispatcher = WPEventDispatcher::fromDefaults();

$dispatcher->listen('order_created', function (Order $order) {
    // Do stuff with order
});

$order = /* */

$dispatcher->dispatch(new GenericEvent('order_created', [$order]));

interface Event
{
    public function name(): string;
    
   /**
    * @return mixed  
    */
    public function payload();
}

class OrderCreated implements Event {
            
    private Order $order;
    
    public function __construct(Order $order) {
        $this->order = $order;
    }        
            
    public function name() :string {
        return 'order.created'
    }
    
    public function payload() : {
        return [$this, time()];
    }
}

use Snicco\Component\BetterWPHooks\WPEventDispatcher;
use Snicco\Component\EventDispatcher\GenericEvent;

$dispatcher = WPEventDispatcher::fromDefaults();

$dispatcher->listen('order.created', function (Order $order, int $timestamp) {
    // Do stuff with order
});

$order = /* */

$dispatcher->dispatch(new OrderCreated($order));

use Snicco\Component\BetterWPHooks\WPEventDispatcher;
use Snicco\Component\EventDispatcher\EventSubscriber;
use Snicco\Component\EventDispatcher\GenericEvent;

class OrderSubscriber implements EventSubscriber {
    
   public static function subscribedEvents() : array{
        
        return [
           OrderCreated::class => 'sendShippingNotification',
           OrderCanceled::class => 'sendCancelNotification'
        ];
   }
   
   public function sendShippingNotification(OrderCreated $event) :void {
        // 
   }
   
   public function sendCancelNotification(OrderCreated $event) :void {
        // 
   }
   
}

$dispatcher = WPEventDispatcher::fromDefaults();

$dispatcher->subscribe(OrderSubscriber::class);

$order = /* */

$dispatcher->dispatch(new OrderCreated($order));
$dispatcher->dispatch(new OrderCanceled($order));

use Snicco\Component\BetterWPHooks\WPEventDispatcher;

$dispatcher = WPEventDispatcher::fromDefaults();

// This will remove ALL listeners for the order created event.
$dispatcher->remove(OrderCreated::class);

// This will remove only one listener
$dispatcher->remove(OrderCreated::class, [OrderListener::class, 'someMethod']);

use Snicco\Component\BetterWPHooks\WPEventDispatcher;
use Snicco\Component\EventDispatcher\Unremovable;

class OrderListener implements Unremovable {

    public function someMethod(OrderCreated $event){
        //
    }

}

$dispatcher = WPEventDispatcher::fromDefaults();

// This will throw an exception
$dispatcher->remove(OrderCreated::class, [OrderListener::class, 'someMethod']);

use Snicco\Component\BetterWPHooks\EventMapping\EventMapper;
use Snicco\Component\BetterWPHooks\EventMapping\MappedHook;
use Snicco\Component\BetterWPHooks\WPEventDispatcher;

class LoggedInUserCreatedOrder implements MappedHook {
    
    public int $order_id;
    public int $current_user_id;
    
    public function __construct(int $order_id, int $current_user_id) {
    
       $this->order_id = $order_id;
       $this->current_user_id = $current_user_id;
       
    }
    
    public function shouldDispatch() : bool{
        return $this->current_user_id > 0;
    }
    
}

$wp_dispatcher = WPEventDispatcher::fromDefaults();

$wp_dispatcher->listen(function (LoggedInUserCreatedOrder $event) {
    $id = $event->order_id;
    $user_id = $event->current_user_id;
});

$event_mapper = new EventMapper($wp_dispatcher);
$event_mapper->map('woocommerce_order_created', LoggedInUserCreatedOrder::class, 10);

do_action('woocommerce_order_created', 1000, 1);

use Snicco\Component\BetterWPHooks\EventMapping\EventMapper;
use Snicco\Component\BetterWPHooks\EventMapping\MappedFilter;
use Snicco\Component\BetterWPHooks\WPEventDispatcher;

class DeterminingOrderPrice implements MappedFilter {
    
    public int $new_total;
    public int $initial_order_total;
    
    public function __construct(int $initial_order_total) {
        $this->new_total = $intial_order_total;
        $this->initial_order_total = $intial_order_total;
    }
    
    public function filterableAttribute(){
        return $this->new_total;
    }
    
    public function shouldDispatch() : bool{
        return true;
    }
    
}

$wp_dispatcher = WPEventDispatcher::fromDefaults();

$wp_dispatcher->listen(function (DeterminingOrderPrice $event) {
   if($some_condition) {
        $event->new_total+= 5000;
   }
});

$wp_dispatcher->listen(function (DeterminingOrderPrice $event) {
   if($some_condition) {
        $event->new_total+= 4000;
   }
});

$event_mapper = new EventMapper($wp_dispatcher);
$event_mapper->map('woocommerce_order_total', DeterminingOrderPrice::class, 10);

// Somewhere in woocommerce
$order_total = apply_filters('woocommerce_order_total', 1000);

var_dump($order_total); // (int) 10000

use Snicco\Component\BetterWPHooks\EventMapping\EventMapper;
use Snicco\Component\BetterWPHooks\WPEventDispatcher;

$wp_dispatcher = WPEventDispatcher::fromDefaults();

$wp_dispatcher->listen(OrderCreated::class, OrderListener::class);

$event_mapper = new EventMapper($wp_dispatcher);
$event_mapper->mapFirst('woocommerce_order_created', OrderCreated::class);

function some_other_random_callback() {

}
add_action('woocommerce_order_created', 'some_other_random_callback', PHP_INT_MIN);

// OrderListener will still be called first. 
do_action('woocommerce_order_created', 1000, 1);

use Snicco\Component\BetterWPHooks\EventMapping\EventMapper;
use Snicco\Component\BetterWPHooks\WPEventDispatcher;

$wp_dispatcher = WPEventDispatcher::fromDefaults();

$wp_dispatcher->listen(OrderCreated::class, OrderListener::class);

$event_mapper = new EventMapper($wp_dispatcher);
$event_mapper->mapLast('woocommerce_order_created', OrderCreated::class);

function some_other_random_callback() {
    return 5000;
}
add_filter('woocommerce_order_created', 'some_other_random_callback', PHP_INT_MAX);

// OrderListener will still be called last. 
$order_total = apply_filters('woocommerce_order_total', 1000);

use Snicco\Component\BetterWPHooks\EventMapping\ExposeToWP;

class PrivateEvent {
    
}

class PublicEvent implements ExposeToWP {

}

add_action(PrivateEvent::class, function (PrivateEvent $event) {
    // This will never be called
});

add_action(PublicEvent::class, function (PublicEvent $event) {
     // This will be called.
});

$dispatcher->dispatch(new PrivateEvent());

$dispatcher->dispatch(new PublicEvent());


use Snicco\Component\BetterWPHooks\EventMapping\ExposeToWP;

class PerformingUserDeletion implements ExposeToWP {

    public bool $is_allowed = true;
    private int $user_being_deleted;
    private int $current_user_id;
    
    public function __construct(int $user_being_deleted, int $current_user_id) {
         $this->user_being_deleted = $user_being_deleted;
         $this->current_user_id = $current_user_id;
    }
    
    public function userBeingDeleted(): int{
        return $this->user_being_deleted;
    }
    
    public function currentUserId(): int{
        return $this->current_user_id;
    }
    
}

// Some third-party-code:
add_filter(PerformingUserDeletion::class, function(PerformingUserDeletion $event) {
    
    // The user with id 10 must never be deleted.
    if(10 === $event->userBeingDeleted()) {
        $event->is_allowed = false;
    }
    
});

// Your code.
$action = $dispatcher->dispatch(new PerformingUserDeletion(10, 1));

// There is no way that this is not a boolean.
if(!$action->is_allowed) {
    throw new Exception('You have no permission to delete this user.');
}

// Delete user.

use Psr\EventDispatcher\StoppableEventInterface;

class DeterminingOrderPrice implements StoppableEventInterface {
    
    public int $initial_price;
    public int $order_total;
    
    public function __construct( int $initial_price ) {
        $this->order_total = $initial_price;
        $this->initial_price = $initial_price;
    }
    
    public function isPropagationStopped() : bool{
        return $this->order_total >= 2000    
    }
    
    
}

$dispatcher->listen(function (DeterminingOrderPrice $event) {
    $event->order_total+=200
})

$dispatcher->listen(function (DeterminingOrderPrice $event) {
    $event->order_total+=800
})

$dispatcher->listen(function (DeterminingOrderPrice $event) {
   throw new Exception('This will never be called.');
})

$dispatcher->dispatch(new DeterminingOrderPrice(1000));


use Snicco\Component\EventDispatcher\Testing\TestableEventDispatcher;

$testable_dispatcher = new TestableEventDispatcher(WPEventDispatcher::fromDefaults());

$testable_dispatcher->assertNotingDispatched();

$testable_dispatcher->assertNotDispatched(OrderCreated::class);

$testable_dispatcher->assertDispatched(OrderCreated::class);

$testable_dispatcher->assertDispatchedTimes(OrderCreated::class, 2);

// With conditions.

$testable_dispatcher->assertDispatched(function (OrderCreated $event) {
    return $event->order->total >= 1000;
});

$testable_dispatcher->assertNotDispatched(function (OrderCreated $event) {
    return $event->order->total >= 1000;
});

use Snicco\Component\EventDispatcher\Testing\TestableEventDispatcher;

$testable_dispatcher = new TestableEventDispatcher(WPEventDispatcher::fromDefaults());

// No event will be passed to the real dispatcher, assertions still work.
$testable_dispatcher->fakeAll();

// Fake one (or more) events. They will be not passed to the real dispatcher
// while all other events will.
$testable_dispatcher->fake(OrderCreated::class);
$testable_dispatcher->fake([OrderCreated::class, OrderDeleted::class]);

$testable_dispatcher->fakeExcept(OrderCreated::class);

$testable_dispatcher->resetDispatchedEvents();