<?php 
namespace eMacros\Runtime\Property; 
 
use eMacros\Applicable; 
use eMacros\Scope; 
use eMacros\GenericList; 
 
class PropertyGet implements Applicable { 
    /** 
     * Property to obtain 
     * @var mixed 
     */ 
    public $property; 
     
    public function __construct($property = null) { 
        $this->property = $property; 
    } 
     
    /** 
     * Obtains a key/property in an array/object 
     * Usage: (# 'name' _obj) (# 3 _array) (#name _obj) 
     * Returns: Key/property value 
     * (non-PHPdoc) 
     * @see \eMacros\Applicable::apply() 
     */ 
    public function apply(Scope $scope, GenericList $arguments) { 
        //get index and value 
        if (is_null($this->property)) { 
            if (count($arguments) == 0) { 
                throw new \BadFunctionCallException("PropertyGet: No parameters found."); 
            } 
             
            $key = $arguments[0]->evaluate($scope); 
             
            if (count($arguments) == 1) { 
                if (!array_key_exists(0, $scope->arguments)) { 
                    throw new \BadFunctionCallException("PropertyGet: Expected value of type array/object as second parameter but none found."); 
                } 
                 
                $value = $scope->arguments[0]; 
            } 
            else { 
                $value = $arguments[1]->evaluate($scope); 
            } 
        } 
        else { 
            $key = $this->property; 
             
            if (count($arguments) == 0) { 
                if (!array_key_exists(0, $scope->arguments)) { 
                    throw new \BadFunctionCallException("PropertyGet: Expected value of type array/object as first parameter but none found."); 
                } 
                 
                $value = $scope->arguments[0]; 
            } 
            else { 
                $value = $arguments[0]->evaluate($scope); 
            } 
        } 
         
        //get index/property 
        if (is_array($value)) { 
            if (!array_key_exists($key, $value)) { 
                if (is_int($key)) { 
                    throw new \OutOfBoundsException(sprintf("PropertyGet: Key %s does not exists.", strval($key))); 
                } 
                 
                throw new \InvalidArgumentException(sprintf("PropertyGet: Key '%s' does not exists.", strval($key))); 
            } 
                 
            return $value[$key]; 
        } 
        elseif ($value instanceof \ArrayObject || $value instanceof \ArrayAccess) { 
            if (!$value->offsetExists($key)) { 
                if (is_int($key)) { 
                    throw new \OutOfBoundsException(sprintf("PropertyGet: Key %s does not exists.", strval($key))); 
                } 
                 
                throw new \InvalidArgumentException(sprintf("PropertyGet: Key '%s' does not exists.", strval($key))); 
            } 
                 
            return $value[$key]; 
        } 
        elseif (is_object($value)) { 
            //check property existence 
            if (!property_exists($value, $key)) { 
                //check existence through __isset 
                if (method_exists($value, '__isset') && !$value->__isset($key)) { 
                    throw new \InvalidArgumentException(sprintf("PropertyGet: Property '%s' not found.", strval($key))); 
                } 
         
                //try calling __get 
                if (method_exists($value, '__get')) { 
                    return $value->__get($key); 
                } 
         
                throw new \InvalidArgumentException(sprintf("PropertyGet: Property '%s' not found.", strval($key))); 
            } 
                 
            //check property access 
            $rp = new \ReflectionProperty($value, $key); 
                 
            if (!$rp->isPublic()) { 
                $rp->setAccessible(true); 
            } 
 
            return $rp->getValue($value); 
        } 
         
        throw new \InvalidArgumentException(sprintf("PropertyGet: Expected value of type array/object but %s found instead", gettype($value))); 
    } 
} 
?>
 
 |