Completed
Push — master ( a38f02...4631a3 )
by Peter
02:48
created

TargetChecker   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 4

Test Coverage

Coverage 89.66%

Importance

Changes 0
Metric Value
wmc 21
lcom 0
cbo 4
dl 0
loc 75
ccs 26
cts 29
cp 0.8966
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
C check() 0 63 21
1
<?php
2
3
/**
4
 * This software package is licensed under AGPL, Commercial license.
5
 *
6
 * @package maslosoft/addendum
7
 * @licence AGPL, Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]> (Meta container, further improvements, bugfixes)
9
 * @copyright Copyright (c) Maslosoft (Meta container, further improvements, bugfixes)
10
 * @copyright Copyright (c) Jan Suchal (Original version, builder, parser)
11
 * @link http://maslosoft.com/addendum/ - maslosoft addendum
12
 * @link https://code.google.com/p/addendum/ - original addendum project
13
 */
14
15
namespace Maslosoft\Addendum\Utilities;
16
17
use Maslosoft\Addendum\Annotations\TargetAnnotation;
18
use Maslosoft\Addendum\Exceptions\TargetException;
19
use Maslosoft\Addendum\Interfaces\AnnotationInterface;
20
use Maslosoft\Addendum\Reflection\ReflectionAnnotatedClass;
21
use ReflectionClass;
22
use ReflectionMethod;
23
use ReflectionProperty;
24
25
/**
26
 * Check target constraits
27
 *
28
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
29
 */
30
class TargetChecker
31
{
32
33
	/**
34
	 * Check target constraints
35
	 * @param AnnotationInterface $annotation Annotation
36
	 * @param ReflectionClass|ReflectionMethod|ReflectionProperty|bool $target
37
	 * @return type
38
	 * @throws TargetException
39
	 */
40 49
	public static function check($annotation, $target)
41
	{
42 49
		$reflection = new ReflectionAnnotatedClass($annotation);
43 49
		if (!$reflection->hasAnnotation('Target'))
44
		{
45 49
			return;
46
		}
47 16
		$value = $reflection->getAnnotation('Target')->value;
0 ignored issues
show
Bug introduced by
Accessing value on the interface Maslosoft\Addendum\Interfaces\AnnotationInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
48 16
		$values = is_array($value) ? $value : [$value];
49
		
50 16
		foreach ($values as $value)
51
		{
52 16
			if ($value == TargetAnnotation::TargetClass && $target instanceof ReflectionClass)
53
			{
54 1
				return;
55
			}
56 15
			if ($value == TargetAnnotation::TargetMethod && $target instanceof ReflectionMethod)
57
			{
58 5
				return;
59
			}
60 13
			if ($value == TargetAnnotation::TargetProperty && $target instanceof ReflectionProperty)
61
			{
62 6
				return;
63
			}
64 10
			if ($value == TargetAnnotation::TargetNested && $target === false)
65
			{
66 10
				return;
67
			}
68
		}
69 7
		if ($target !== false && $value && !in_array($value, [
70 7
					TargetAnnotation::TargetClass,
71
					TargetAnnotation::TargetMethod,
72
					TargetAnnotation::TargetProperty,
73
					TargetAnnotation::TargetNested
74
				]))
75
		{
76 3
			if ($target instanceof ReflectionClass)
77
			{
78 3
				$interfaceTarget = $target;
79
			}
80
			else
81
			{
82
				/* @var $target ReflectionProperty */
83
				$interfaceTarget = new ReflectionClass($target->class);
84
			}
85 3
			if(!ClassChecker::exists($value))
86
			{
87
				throw new TargetException(sprintf('Annotation "%s" used in "%s" is only allowed on instances of "%s", but this class does not exists (see @Target)', basename($reflection->name), $interfaceTarget->name, $value));
88
			}
89 3
			if (!$interfaceTarget->implementsInterface($value))
90
			{
91 1
				throw new TargetException(sprintf('Annotation "%s" used in "%s" is only allowed on instances of "%s" (see @Target)',  basename($reflection->name), $interfaceTarget->name, $value));
92
			}
93
		}
94 6
		if ($target === false && $value == TargetAnnotation::TargetNested)
95
		{
96
			throw new TargetException("Annotation '" . get_class($annotation) . "' nesting not allowed");
97
		}
98 6
		elseif (in_array($value, TargetAnnotation::getTargets()))
99
		{
100 4
			throw new TargetException(sprintf("Annotation '%s' not allowed on %s, it's target is %s  (see @Target)", get_class($annotation), ReflectionName::createName($target), $value));
101
		}
102 2
	}
103
104
}
105