PHP Classes

File: lib/Injector/ClassProfile.php

Recommend this page to a friend!
  Classes of Emmanuel Antico   Injector   lib/Injector/ClassProfile.php   Download  
File: lib/Injector/ClassProfile.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Injector
Inject dependencies defined in annotation comments
Author: By
Last change:
Date: 9 years ago
Size: 4,360 bytes
 

Contents

Class file image Download
<?php
namespace Injector;

use
Minime\Annotations\Facade;

/**
 * Stores a class profile
 * @author emaphp
 * @package Injector
 */
class ClassProfile {
   
/**
     * Default annotation namespace
     * @var string
     */
   
const NS = 'inject';
   
   
/**
     * Reflection class
     * @var \ReflectionClass
     */
   
public $class;
   
   
/**
     * Class constructor
     * @var \ReflectionMethod
     */
   
public $constructor;
   
   
/**
     * Class name
     * @var string
     */
   
public $className;
   
   
/**
     * Service providers
     * @var array
     */
   
public $providers;
       
   
/**
     * Constructor injection values
     * @var array
     */
   
public $constructorParams = array();
   
   
/**
     * Injection properties
     * @var array
     */
   
public $properties = array();
   
   
/**
     * Reflection properties array
     * @var array
     */
   
public $reflectionProperties = array();
   
   
/**
     * Indicates if all dependecies must be fullfiled
     * When true, a RuntimeException is thrown if a dependency is not declared within the container
     * @var boolean
     */
   
public $isStrict = false;
   
   
/**
     * Creates a new class profile
     * @param string $className
     * @throws \RuntimeException
     */
   
public function __construct($className) {
       
$this->className = $className;
       
$this->initialize();
    }
   
   
/**
     * Obtains all providers for a given class
     * @param \ReflectionClass $class
     * @return array
     */
   
protected function getClassProviders(\ReflectionClass $class) {
       
$annotations = Facade::getAnnotations($class);
       
$values = $annotations->useNamespace(self::NS)->export();
       
        if (
array_key_exists('provider', $values)) {
            return
is_array($values['provider']) ? $values['provider'] : [$values['provider']];
        }
        else {
           
//try getting providers from parent class
           
$extend = array_key_exists('extend', $values) ? (bool) $values['extend'] : true;
           
            if (
$extend) {
               
$parent = $class->getParentClass();
                return
$parent instanceof \ReflectionClass ? $this->getClassProviders($parent) : [];
            }
        }
    }
   
   
/**
     * Initializes a class profile instance
     * @throws \RuntimeException
     */
   
protected function initialize() {
       
$this->class = new \ReflectionClass($this->className);
       
       
//parse class annotations
       
$annotations = Facade::getAnnotations($this->class);
       
$values = $annotations->useNamespace(self::NS)->export();
       
       
//get default providers
       
$this->providers = $this->getClassProviders($this->class);
       
       
//is strict?
       
if (array_key_exists('strict', $values)) {
           
$this->isStrict = is_array($values['strict']) ? array_shift($values['strict']) : (bool) $values['strict'];
        }
       
       
//parse properties
       
$properties = $this->class->getProperties();
       
        foreach (
$properties as $property) {
           
$annotations = Facade::getAnnotations($property);
           
$values = $annotations->useNamespace(self::NS)->export();
           
            if (
array_key_exists('service', $values)) {
               
//store service id
               
$propertyName = $property->getName();
               
$this->properties[$propertyName] = is_array($values['service']) ? array_shift($values['service']) : $values['service'];
               
               
//store ReflectionProperty instance and make it accesible
               
$this->reflectionProperties[$propertyName] = $property;
               
$this->reflectionProperties[$propertyName]->setAccessible(true);
            }
        }
       
       
//parse constructor
       
$this->constructor = $this->class->getConstructor();
       
        if (!
is_null($this->constructor)) {
           
$annotations = Facade::getAnnotations($this->constructor);
           
$values = $annotations->useNamespace(self::NS)->export();
           
            if (
array_key_exists('param', $values)) {
                if (
is_array($values['param'])) {
                    foreach (
$values['param'] as $arg) {
                        list(
$argname, $argid) = $this->parseParameter($arg);
                           
                        if (
$argname) {
                           
$this->constructorParams[$argname] = $argid;
                        }
                    }
                }
                else {
                    list(
$argname, $argid) = $this->parseParameter($values['param']);
           
                    if (
$argname) {
                       
$this->constructorParams[$argname] = $argid;
                    }
                }
            }
        }
    }
   
   
/**
     * Parses an injected argument expression
     * @param string $str
     * @return array
     * @throws \RuntimeException
     */
   
protected function parseParameter($str) {
       
$regex = '/(?:\s*)?\$?(\w+)(?:\s+)(\w+)(?:\s*)?$/';
       
        if (
preg_match($regex, $str, $matches)) {
            return [
$matches[1], $matches[2]];
        }
       
        throw new \
RuntimeException(sprintf("Invalid expression found in %s __construct method annotation", $this->className));
    }
}