FlexibleContainer   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 4
dl 0
loc 159
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A hydrate() 0 6 1
A fields() 0 24 5
A extract() 0 4 1
A getIterator() 0 4 1
B __call() 0 24 6
A checkAttribute() 0 14 3
A extractMethodName() 0 10 2
1
<?php
2
/*
3
 * This file is part of the PommProject/ModelManager package.
4
 *
5
 * (c) 2014 - 2015 Grégoire HUBERT <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PommProject\ModelManager\Model\FlexibleEntity;
11
12
use PommProject\Foundation\Inflector;
13
use PommProject\ModelManager\Exception\ModelException;
14
15
/**
16
 * FlexibleContainerTrait
17
 *
18
 * Trait for being a flexible data container.
19
 *
20
 * @package   ModelManager
21
 * @copyright 2014 - 2015 Grégoire HUBERT
22
 * @author    Grégoire HUBERT
23
 * @license   X11 {@link http://opensource.org/licenses/mit-license.php}
24
 */
25
abstract class FlexibleContainer implements FlexibleEntityInterface, \IteratorAggregate
26
{
27
    use StatefulEntityTrait;
28
29
    use ModifiedColumnEntityTrait;
30
31
    protected $container = [];
32
33
    /**
34
     * hydrate
35
     *
36
     * @see FlexibleEntityInterface
37
     */
38
    public function hydrate(array $values)
39
    {
40
        $this->container = array_merge($this->container, $values);
41
42
        return $this;
43
    }
44
45
    /**
46
     * fields
47
     *
48
     * Return the fields array. If a given field does not exist, an exception
49
     * is thrown.
50
     *
51
     * @throws  \InvalidArgumentException
52
     * @see     FlexibleEntityInterface
53
     */
54
    public function fields(array $fields = null)
55
    {
56
        if ($fields === null) {
57
            return $this->container;
58
        }
59
60
        $output = [];
61
62
        foreach ($fields as $name) {
63
            if (isset($this->container[$name]) || array_key_exists($name, $this->container)) {
64
                $output[$name] = $this->container[$name];
65
            } else {
66
                throw new \InvalidArgumentException(
67
                    sprintf(
68
                        "No such field '%s'. Existing fields are {%s}",
69
                        $name,
70
                        join(', ', array_keys($this->container))
71
                    )
72
                );
73
            }
74
        }
75
76
        return $output;
77
    }
78
79
80
    /**
81
     * extract
82
     *
83
     * @see FlexibleEntityInterface
84
     */
85
    public function extract()
86
    {
87
        return $this->fields();
88
    }
89
90
    /**
91
     * getIterator
92
     *
93
     * @see FlexibleEntityInterface
94
     */
95
    public function getIterator()
96
    {
97
        return new \ArrayIterator($this->extract());
98
    }
99
100
    /**
101
     * __call
102
     *
103
     * Allows dynamic methods getXxx, setXxx, hasXxx or clearXxx.
104
     *
105
     * @access public
106
     * @throws ModelException if method does not exist.
107
     * @param  mixed $method
108
     * @param  mixed $arguments
109
     * @return mixed
110
     */
111
    public function __call($method, $arguments)
112
    {
113
        list($operation, $attribute) = $this->extractMethodName($method);
114
115
        switch ($operation) {
116
        case 'set':
117
            $this->container[$attribute] = $arguments[0];
118
119
            return $this;
120
        case 'get':
121
            return $this
122
                ->checkAttribute($attribute)
123
                ->container[$attribute]
124
                ;
125
        case 'has':
126
            return isset($this->container[$attribute]) || array_key_exists($attribute, $this->container);
127
        case 'clear':
128
            unset($this->checkAttribute($attribute)->container[$attribute]);
129
130
            return $this;
131
        default:
132
            throw new ModelException(sprintf('No such method "%s:%s()"', get_class($this), $method));
133
        }
134
    }
135
136
    /**
137
     * checkAttribute
138
     *
139
     * Check if the attribute exist. Throw an exception if not.
140
     *
141
     * @access protected
142
     * @param  string $attribute
143
     * @return FlexibleContainer    $this
144
     * @throws ModelException
145
     */
146
    protected function checkAttribute($attribute)
147
    {
148
        if (!(isset($this->container[$attribute]) || array_key_exists($attribute, $this->container))) {
149
            throw new ModelException(
150
                sprintf(
151
                    "No such attribute '%s'. Available attributes are {%s}",
152
                    $attribute,
153
                    join(", ", array_keys($this->fields()))
154
                )
155
            );
156
        }
157
158
        return $this;
159
    }
160
161
    /**
162
     * extractMethodName
163
     *
164
     * Get container field name from method name.
165
     * It returns an array with the operation (get, set, etc.) as first member
166
     * and the name of the attribute as second member.
167
     *
168
     * @access protected
169
     * @param  string   $argument
170
     * @return array
171
     * @throws ModelException
172
     */
173
    protected function extractMethodName($argument)
174
    {
175
        $split = preg_split('/(?=[A-Z])/', $argument, 2);
176
177
        if (count($split) !== 2) {
178
            throw new ModelException(sprintf('No such argument "%s:%s()"', get_class($this), $argument));
179
        }
180
181
        return [$split[0], Inflector::underscore($split[1])];
182
    }
183
}
184