<?php

class Farmer {
  public $Farm;
  public $first_name,$last_name;
  public function __construct($first_name,$last_name){
    $this->first_name = $first_name;
    $this->last_name = $last_name;
    $this->Farm = new Farm($this);
  }
}

class Farm {
  private $Farmer,$Animal;
  public function __construct(Farmer $Farmer){$this->Farmer = $Farmer;}
  private function HadAFarm(){
    return "{$this->Farmer->first_name} {$this->Farmer->last_name} Had a Farm";
  }
  private function EIEIO(){return 'E-I-E-I-O';}
  public function hasA(Animal $Animal){
    $this->Animal = $Animal;
  }
  private function hadA(){
    return "And on that farm he had a...{$this->Animal}";
  }

  public function Song(){
    $song[] = null;//for blank line
    $song[] = $this->HadAFarm();
    $song[] = $this->EIEIO();
    $song[] = $this->hadA();
    $song[] = $this->EIEIO();
    $song[] = $this->MakeAlotOfNoise();
    $song[] = $this->HadAFarm();
    $song[] = $this->EIEIO();
    $song[] = null; // for blank line
    return implode("\n",$song);
  }
  private function MakeAlotOfNoise(){
    $sound = $this->Animal->MakeNoise();
    $an = (preg_match('/^[aeiou]/',$sound)) ? 'an' : 'a';
    $An = ucfirst($an);
    $part[] = "With {$an} {$sound}-{$sound} here";
    $part[] = "{$An} {$sound}-{$sound} there";
    $part[] = "Here {$an} {$sound}";
    $part[] = "There {$an} {$sound}";
    $part[] = "Everywhere {$an} {$sound}-{$sound}";
    return implode("\n",$part);
  }
}

interface IAnimal{public function MakeNoise();}

class Animal{
  private $type;
  public function __construct($type){$this->type = $type;}
  public function __toString(){return strtolower($this->type);}
}

class Cow extends Animal implements IAnimal {
  public function MakeNoise(){return 'moo';}
}

class Pig extends Animal implements IAnimal {
  public function MakeNoise(){return 'oink';}
}

class Duck extends Animal implements IAnimal {
  public function MakeNoise(){return 'quack';}
}

class Turkey extends Animal implements IAnimal {
  public function MakeNoise(){return 'gobble';}
}

class Rooster extends Animal implements IAnimal {
  public function MakeNoise(){return 'cock-a-doodle-doo';}
}

$OldMacDonald = new Farmer('Old','MacDonald');
$animals_on_the_farm = array('Cow','Rooster','Pig','Duck','Turkey');

foreach($animals_on_the_farm as $Animal){
	$OldMacDonald->Farm->hasA( new $Animal($Animal) );
	echo $OldMacDonald->Farm->Song();
}
?>