Completed
Pull Request — master (#41)
by Vladimir
02:46
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 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 43
    public function __construct (&$object, array $whiteListFunctions, array $jailedFunctions = array())
43
    {
44 43
        if (!($object instanceof Jailable) && !($object instanceof \ArrayAccess))
45
        {
46
            throw new \InvalidArgumentException('Must implement the ArrayAccess and Jailable interfaces');
47
        }
48
49 43
        $this->object = &$object;
50 43
        $this->whiteListFunctions = $whiteListFunctions;
51 43
        $this->jailedFunctions = $jailedFunctions;
52 43
    }
53
54 10
    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 10
        $lcName = lcfirst($name);
59 10
        $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 10
        if (array_key_exists($getFxnCall, $this->jailedFunctions))
64
        {
65 3
            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 7
        if (in_array($getFxnCall, $this->whiteListFunctions))
70
        {
71 6
            return call_user_func_array(array($this->object, $getFxnCall), $arguments);
72
        }
73
74 1
        throw new \BadMethodCallException();
75
    }
76
77 4
    public function coreInstanceOf ($class)
78
    {
79 4
        return is_subclass_of($this->object, $class);
80
    }
81
82
    //
83
    // ArrayAccess Implementation
84
    //
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 22
    public function offsetExists($offset)
90
    {
91 22
        return $this->object->offsetExists($offset);
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 33
    public function offsetGet($offset)
98
    {
99 33
        return $this->object->offsetGet($offset);
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function offsetSet($offset, $value)
106
    {
107
        return $this->object->offsetSet($offset, $value);
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function offsetUnset($offset)
114
    {
115
        return $this->object->offsetUnset($offset);
116
    }
117
}