Implement a hook system

We can't use `add_action()` and `do_action()` since it needs to work without having WordPress installed.

Related: #468 #498