http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 4 LOC: 171 Statements: 82
Legend: executednot executeddead code
Source file Statements Methods Total coverage
Autowiring.php 100.0% 100.0% 100.0%
 
1
<?php
2
/**
3
 * Xyster Framework
4
 *
5
 * This source file is subject to the new BSD license that is bundled
6
 * with this package in the file LICENSE.txt.
7
 * It is also available through the world-wide-web at this URL:
8
 * http://www.opensource.org/licenses/bsd-license.php
9
 *
10
 * @category  Xyster
11
 * @package   Xyster_Container
12
 * @copyright Copyright LibreWorks, LLC (http://libreworks.net)
13
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
14
 * @version   $Id$
15
 */
16
namespace Xyster\Container\Injector;
17
use Xyster\Type\Type;
18
use Xyster\Container\Autowire;
19
/**
20
 * Autowires dependencies of a component as it creates it
21
 *
22
 * @category  Xyster
23
 * @package   Xyster_Container
24
 * @copyright Copyright LibreWorks, LLC (http://libreworks.net)
25
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
26
 */
27
class Autowiring extends Standard
28 1
{
29
    /**
30
     * @var \Xyster\Container\Autowire
31
     */
32
    protected $_autowire;
33
    protected $_ignore = array();
34
35
    /**
36
     * Creates a new provider
37
     *
38
     * @param \Xyster\Container\Definition $def The component definintion
39
     * @param \Xyster\Container\Autowire $autowire Optional. The autowire mode.
40
     * @param array $ignore The autowire candidates (names or types) to ignore.
41
     */
42
    public function __construct(\Xyster\Container\Definition $def, Autowire $autowire = null, array $ignore = array())
43
    {
44 19
        parent::__construct($def);
45 19
        $this->_autowire = $autowire === null ? Autowire::None() : $autowire;
46 19
        $this->_ignore = $ignore;
47
    }
48
49
    /**
50
     * Gets the label for the type of provider.
51
     *
52
     * @return string The provider label
53
     */
54
    public function getLabel()
55
    {
56 1
        return 'Autowiring';
57
    }
58
59
    /**
60
     * Gets the member arguments.
61
     *
62
     * This method handles Constructor autowiring.  It will look in the
63
     * container for a component matching the type, if more than one is found,
64
     * it will try to use the parameter name to select the correct one.   If no
65
     * component is found and the method parameter has a default value available
66
     * it will be used.  If all else fails, an exception is thrown.
67
     *
68
     * @param \Xyster\Container\IContainer $container
69
     * @param \ReflectionMethod $member
70
     * @return array
71
     * @throws Xyster_Container_Injector_Exception if a parameter could not be autowired
72
     */
73
    public function getMemberArguments( \Xyster\Container\IContainer $container, \ReflectionMethod $member = null )
74
    {
75 14
        if ( $member === null || !$member->getNumberOfParameters()
76 14
            || $this->_autowire !== Autowire::Constructor() ) {
77 9
            return array();
78
        }
79 5
        $result = array();
80 5
        $types = Type::getForParameters($member);
81 5
        foreach( $member->getParameters() as $k => $reflectionParameter ) {
82
            /* @var $reflectionParameter \ReflectionParameter */
83 5
            $instance = null;
84 5
            $paramType = $types[$k];
85
            /* @var $paramType \Xyster\Type\Type */
86 5
            if ( !$paramType->isObject() && !$reflectionParameter->isOptional() ) {
87 1
                throw new Exception('Cannot inject method argument ' .
88 1
                    $reflectionParameter->getName() .
89 1
                    ' into ' . $member->getDeclaringClass()->getName() .
90 1
                    ': non-object parameters cannot be autowired');
91
            }
92 4
            $names = $container->getNames($paramType);
93 4
            if ( count($names) == 1 ) {
94 2
                $instance = $container->get($names[0]);
95 4
            } else if ( count($names) > 1 && in_array($reflectionParameter->getName(), $names) ) {
96 1
                $instance = $container->get($reflectionParameter->getName());
97 4
            } else if ( $reflectionParameter->isDefaultValueAvailable() ) {
98 2
                $instance = $reflectionParameter->getDefaultValue();
99 4
            } else if ( !count($names) ) {
100 1
                throw new Exception('Cannot inject method argument ' .
101 1
                    $reflectionParameter->getName() .
102 1
                    ' into ' . $member->getDeclaringClass()->getName() .
103 1
                    ': no matching types were found in the container');
104 1
            } else if ( count($names) > 1 ) {
105 1
                throw new Exception('Cannot inject method argument ' .
106 1
                    $reflectionParameter->getName() .
107 1
                    ' into ' . $member->getDeclaringClass()->getName() .
108 1
                    ': more than one value is available in the container');
109
            }
110 2
            $result[] = $instance;
111 2
        }
112 2
        return $result;
113
    }
114
115
    /**
116
     * Injects properties into an instance
117
     *
118
     * @param object $instance
119
     * @param \Xyster\Container\IContainer $container
120
     */
121
    public function injectProperties($instance, \Xyster\Container\IContainer $container)
122
    {
123 11
        if ( $this->_autowire === Autowire::ByType() ) {
124 6
            foreach( $this->_type->getClass()->getMethods() as $k => $method ) {
125
                /* @var $method \ReflectionMethod */
126 6
                if ( $method->getNumberOfParameters() == 1 &&
127 6
                    substr($method->getName(), 0, 3) == 'set' ) {
128 6
                    $types = Type::getForParameters($method);
129 6
                    $propertyType = $types[0];
130
                    /* @var $propertyType \Xyster\Type\Type */
131 6
                    $name = strtolower(substr($method->getName(),3,1)) . substr($method->getName(),4);
132 6
                    if ( in_array($name, $this->_ignore) || !$propertyType->isObject() ) {
133 3
                        continue;
134
                    }
135 6
                    if ( $container->containsType($propertyType) ) {
136 5
                        $propertyValues = $container->getForType($propertyType);
137 5
                        if ( count($propertyValues) == 1 ) {
138
                            // @todo wrap this exception if it occurs?
139 4
                            \Xyster\Type\Property\Factory::get($instance, $name)
140 4
                                ->set($instance, array_pop($propertyValues));
141 4
                        } else {
142 1
                            throw new Exception('Cannot inject property ' . $name .
143 1
                                ' into ' . $method->getDeclaringClass()->getName() .
144 1
                                ': more than one value is available in the container');
145
                        }
146 4
                    } else {
147 1
                        throw new Exception(
148 1
                            'Cannot inject property ' . $name . ' into ' .
149 1
                            $method->getDeclaringClass()->getName() .
150 1
                            ': type not found in the container: ' . $propertyType);
151
                    }
152 4
                }
153 6
            }
154 9
        } else if ( $this->_autowire === Autowire::ByName() ) {
155 2
            foreach( $this->_type->getClass()->getMethods() as $k => $method ) {
156
                /* @var $method \ReflectionMethod */
157 2
                if ( $method->getNumberOfParameters() == 1 &&
158 2
                    substr($method->getName(), 0, 3) == 'set' ) {
159 2
                    $name = strtolower(substr($method->getName(),3,1)) . substr($method->getName(),4);
160 2
                    $types = Type::getForParameters($method);
161 2
                    $propertyType = $types[0];
162
                    /* @var $propertyType \Xyster\Type\Type */
163 2
                    if ( in_array($name, $this->_ignore) || !$propertyType->isObject() ) {
164 1
                        continue;
165
                    }
166 2
                    $this->_injectByNameFromContainer($container, $instance, $name, $name);
167 2
                }
168 2
            }
169 2
        }
170
    }
171 1
}


Report generated at 2010-10-18T17:19:49-04:00