Completed
Push — master ( e4bfce...b9fe45 )
by Vladimir
02:19
created

JailObject::coreInstanceOf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright 2016 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\Object;
9
10
/**
11
 * Class JailObject
12
 *
13
 * A wrapper object to only allow certain functions on the white list to be called. This is used in order to limit which
14
 * functions a user can call from Twig templates to prevent unexpected behavior.
15
 *
16
 * @package allejo\stakx\Object
17
 */
18
class JailObject implements \ArrayAccess
19
{
20
    /**
21
     * @var string[]
22
     */
23
    private $whiteListFunctions;
24
25
    /**
26
     * @var string[]
27
     */
28
    private $jailedFunctions;
29
30
    /**
31
     * @var Jailable
32
     */
33
    private $object;
34
35
    /**
36
     * JailObject constructor.
37
     *
38
     * @param Jailable $object             The object that will be jailed
39
     * @param array    $whiteListFunctions A list of function names that can be called
40
     * @param array    $jailedFunctions
41
     */
42 28
    public function __construct (&$object, array $whiteListFunctions, array $jailedFunctions = array())
43
    {
44 28
        if (!($object instanceof Jailable) && !($object instanceof \ArrayAccess))
45 28
        {
46
            throw new \InvalidArgumentException('Must implement the ArrayAccess and Jailable interfaces');
47
        }
48
49 28
        $this->object = &$object;
50 28
        $this->whiteListFunctions = $whiteListFunctions;
51 28
        $this->jailedFunctions = $jailedFunctions;
52 28
    }
53
54 2
    public function __call ($name, $arguments)
55
    {
56
        // White listed functions will always be getter functions, so somehow get the name of a possible getter function
57
        // name.
58 2
        $lcName = lcfirst($name);
59 2
        $getFxnCall = ($lcName[0] === 'g' && strpos($lcName, 'get') === 0) ? $lcName : sprintf('get%s', ucfirst($name));
60
61
        // Check if our function call is a jailed call, meaning the function should be mapped to special "jailed"
62
        // jailed version of the function call.
63 2
        if (array_key_exists($getFxnCall, $this->jailedFunctions))
64 2
        {
65
            return call_user_func_array(array($this->object, $this->jailedFunctions[$getFxnCall]), $arguments);
66
        }
67
68
        // Otherwise, test to see if the function call is in our white list and call it
69 2
        if (in_array($getFxnCall, $this->whiteListFunctions))
70 2
        {
71 1
            return call_user_func_array(array($this->object, $getFxnCall), $arguments);
72
        }
73
74
        // Functions should take precedence over __get(), so if it's not a function we'll search to see if the __get()
75
        // handles it
76 1
        if ($this->object->isMagicGet($name))
77 1
        {
78
            return $this->object->$name;
79
        }
80
81 1
        throw new \BadMethodCallException();
82
    }
83
84 1
    public function __get ($name)
85
    {
86 1
        if ($this->object->isMagicGet($name))
87 1
        {
88 1
            return $this->object->$name;
89
        }
90
91
        return NULL;
92
    }
93
94 17
    public function coreInstanceOf ($class)
95
    {
96 17
        return is_subclass_of($this->object, $class);
97
    }
98
99
    //
100
    // ArrayAccess Implementation
101
    //
102
103
    /**
104
     * {@inheritdoc}
105
     */
106 21
    public function offsetExists($offset)
107
    {
108 21
        return $this->object->offsetExists($offset);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 24
    public function offsetGet($offset)
115
    {
116 24
        return $this->object->offsetGet($offset);
117
    }
118
119
    /**
120
     * {@inheritdoc}
121
     */
122
    public function offsetSet($offset, $value)
123
    {
124
        return $this->object->offsetSet($offset, $value);
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function offsetUnset($offset)
131
    {
132
        return $this->object->offsetUnset($offset);
133
    }
134
}