<?php

use SplObjectStorage, SplObserver, SplSubject;

class Communicator implements SplSubject {

    private $employees;
    public $message;

    public function __construct () {
        $this->employees = new SplObjectStorage();
    }

    public function attach (SplObserver $employee): void {
        $this->employees->attach($employee);
    }

    public function detach (SplObserver $employee): void {
        $this->employees->detach($employee);
    }

    public function inform (string $message): void {
        $this->message = $message;
        $this->notify();
    }

    public function notify (): void {
        foreach ($this->employees as $employee) {
            $employee->update($this);
        }
    }
}


use SplObserver, SplSubject;

class Employee implements SplObserver {

    public $name;
    private $email;

    public function __construct (string $name, string $email) {
        $this->name = $name;
        $this->email = $email;
    }

    public function update (SplSubject $communicator): void {
        $this->sendEmail($communicator->message);
    }

    protected function sendEmail (string $message) {
        echo "Sending email to: " . $this->email . " -  Hello " . $this->name . ", " . $message . PHP_EOL;
    }
}


class HumanResources {

    private $communicator;

    public function __construct (array $employees) {
        $this->communicator = new Communicator();

        foreach ($employees as $employee) {
            $this->communicator->attach($employee);
        }
    }

    public function inform (string $message): void {
        $this->communicator->inform($message);
    }

    public function layOf (Employee $employee) {
        $this->communicator->detach($employee);
    }

    public function employ (Employee $employee) {
        $this->communicator->attach($employee);
    }
}


// USAGE
$testEmployees = [
    new Employee("Jonny", 'CEO'),
    new Employee("Donny", "software"),
    new Employee("Monny", 'hardware')
];

$hr = new HumanResources($testEmployees);
$hr->inform("Important news everyone");

$software = new Employee("Ben", "software");
$hr->employ($software);

$hr->inform("New employee: " . $software->name);

$hr->layOf($software);
$hr->inform("New employee laid off: " . $software->name);