Completed
Pull Request — master (#41)
by Vladimir
02:32
created

JailObject::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 2
nop 3
dl 0
loc 11
ccs 6
cts 7
cp 0.8571
crap 3.0261
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright 2017 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
class JailObject implements \ArrayAccess
17
{
18
    /**
19
     * @var string[]
20
     */
21
    private $whiteListFunctions;
22
23
    /**
24
     * @var string[]
25
     */
26
    private $jailedFunctions;
27
28
    /**
29
     * @var Jailable
30
     */
31
    private $object;
32
33
    /**
34
     * JailObject constructor.
35
     *
36
     * @param Jailable $object             The object that will be jailed
37
     * @param array    $whiteListFunctions A list of function names that can be called
38
     * @param array    $jailedFunctions
39
     */
40 49
    public function __construct(&$object, array $whiteListFunctions, array $jailedFunctions = array())
41
    {
42 49
        if (!($object instanceof Jailable) && !($object instanceof \ArrayAccess))
43
        {
44
            throw new \InvalidArgumentException('Must implement the ArrayAccess and Jailable interfaces');
45
        }
46
47 49
        $this->object = &$object;
48 49
        $this->whiteListFunctions = $whiteListFunctions;
49 49
        $this->jailedFunctions = $jailedFunctions;
50 49
    }
51
52 10
    public function __call($name, $arguments)
53
    {
54
        // White listed functions will always be getter functions, so somehow get the name of a possible getter function
55
        // name.
56 10
        $lcName = lcfirst($name);
57 10
        $getFxnCall = ($lcName[0] === 'g' && strpos($lcName, 'get') === 0) ? $lcName : sprintf('get%s', ucfirst($name));
58
59
        // Check if our function call is a jailed call, meaning the function should be mapped to special "jailed"
60
        // jailed version of the function call.
61 10
        if (array_key_exists($getFxnCall, $this->jailedFunctions))
62
        {
63 3
            return call_user_func_array(array($this->object, $this->jailedFunctions[$getFxnCall]), $arguments);
64
        }
65
66
        // Otherwise, test to see if the function call is in our white list and call it
67 7
        if (in_array($getFxnCall, $this->whiteListFunctions))
68
        {
69 6
            return call_user_func_array(array($this->object, $getFxnCall), $arguments);
70
        }
71
72 1
        throw new \BadMethodCallException();
73
    }
74
75 4
    public function coreInstanceOf($class)
76
    {
77 4
        return is_subclass_of($this->object, $class);
78
    }
79
80
    //
81
    // ArrayAccess Implementation
82
    //
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 22
    public function offsetExists($offset)
88
    {
89 22
        return $this->object->offsetExists($offset);
90
    }
91
92
    /**
93
     * {@inheritdoc}
94
     */
95 33
    public function offsetGet($offset)
96
    {
97 33
        return $this->object->offsetGet($offset);
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function offsetSet($offset, $value)
104
    {
105
        return $this->object->offsetSet($offset, $value);
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function offsetUnset($offset)
112
    {
113
        return $this->object->offsetUnset($offset);
114
    }
115
}
116