<?php
class Composable {
private $behaviors = array ( ) ;
public function __call( $name , $arguments ) {
foreach ( $this -> behaviors as $behavior ) {
if ( $behavior -> provides ( $name ) ) {
return $behavior -> invoke ( $this , $name , $arguments ) ;
}
}
throw new Exception( "No method $name and no behavior that implements it!" ) ;
}
public function attach( $behavior ) {
$this -> behaviors [ ] = $behavior ;
}
}
class User extends Composable {
}
abstract class Behavior {
public function provides( $name ) {
}
public function invoke( $target , $name , $arguments ) {
}
}
class GrouppableBehavior extends Behavior {
public function join ( User
$user , $groupName ) { echo "The user has joined group $groupName ." ;
}
}
$user1 = new User;
$user2 = new User;
$user1 -> attach ( new GrouppableBehavior) ;
$user1 -> join ( 'Test Group' ) ; $user2 -> join ( 'Test Group' ) ;
PD9waHAKY2xhc3MgQ29tcG9zYWJsZSB7CiAgICBwcml2YXRlICRiZWhhdmlvcnMgPSBhcnJheSgpOwogICAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX19jYWxsKCRuYW1lLCAkYXJndW1lbnRzKSB7CiAgICAgICAgZm9yZWFjaCAoJHRoaXMtPmJlaGF2aW9ycyBhcyAkYmVoYXZpb3IpIHsKICAgICAgICAgICAgaWYgKCRiZWhhdmlvci0+cHJvdmlkZXMoJG5hbWUpKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gJGJlaGF2aW9yLT5pbnZva2UoJHRoaXMsICRuYW1lLCAkYXJndW1lbnRzKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICB0aHJvdyBuZXcgRXhjZXB0aW9uKCJObyBtZXRob2QgJG5hbWUgYW5kIG5vIGJlaGF2aW9yIHRoYXQgaW1wbGVtZW50cyBpdCEiKTsKICAgIH0KICAgIAogICAgcHVibGljIGZ1bmN0aW9uIGF0dGFjaCgkYmVoYXZpb3IpIHsKICAgICAgICAkdGhpcy0+YmVoYXZpb3JzW10gPSAkYmVoYXZpb3I7CiAgICB9Cn0KCmNsYXNzIFVzZXIgZXh0ZW5kcyBDb21wb3NhYmxlIHsKfQoKYWJzdHJhY3QgY2xhc3MgQmVoYXZpb3IgewogICAgcHVibGljIGZ1bmN0aW9uIHByb3ZpZGVzKCRuYW1lKSB7CiAgICAgICAgcmV0dXJuIG1ldGhvZF9leGlzdHMoJHRoaXMsICRuYW1lKTsKICAgIH0KICAgIAogICAgcHVibGljIGZ1bmN0aW9uIGludm9rZSgkdGFyZ2V0LCAkbmFtZSwgJGFyZ3VtZW50cykgewogICAgICAgIGFycmF5X3Vuc2hpZnQoJGFyZ3VtZW50cywgJHRhcmdldCk7CiAgICAgICAgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCR0aGlzLCAkbmFtZSksICRhcmd1bWVudHMpOwogICAgfQp9CgpjbGFzcyBHcm91cHBhYmxlQmVoYXZpb3IgZXh0ZW5kcyBCZWhhdmlvciB7CiAgICBwdWJsaWMgZnVuY3Rpb24gam9pbihVc2VyICR1c2VyLCAkZ3JvdXBOYW1lKSB7CiAgICAgICAgZWNobyAiVGhlIHVzZXIgaGFzIGpvaW5lZCBncm91cCAkZ3JvdXBOYW1lLiI7CiAgICB9Cn0KCiR1c2VyMSA9IG5ldyBVc2VyOwokdXNlcjIgPSBuZXcgVXNlcjsKCiR1c2VyMS0+YXR0YWNoKG5ldyBHcm91cHBhYmxlQmVoYXZpb3IpOwokdXNlcjEtPmpvaW4oJ1Rlc3QgR3JvdXAnKTsKJHVzZXIyLT5qb2luKCdUZXN0IEdyb3VwJyk7Cg==