Completed
Push — master ( 375f27...3b6ceb )
by Todd
02:03
created

Config::gettok()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 3
crap 1
1
<?php
2
3
namespace Logikos\Util;
4
5
/**
6
 * This is largely inspired by \Phalcon\Config - https://docs.phalconphp.com/hr/3.2/api/Phalcon_Config
7
 * NOTICE: \Phalcon\Config will be much faster than this class and you are encouraged to use it
8
 * @see ../docs/config/README.md
9
 */
10
abstract class Config implements \ArrayAccess, \Countable, \Iterator {
11
  private $locked   = false;
12
  private $values   = [];
13
14 49
  public function __construct(array $arrayConfig = []) {
15 49
    foreach($arrayConfig as $key => $value)
16 44
      $this->offsetSet($key, $value);
17
18 49
    $this->onConstruct();
19 49
  }
20
21
  // override this if you want to
22
  protected function onConstruct() {}
23
24 44
  public function isLocked() {
25 44
    return $this->locked;
26
  }
27
28 7
  public function get($key, $default = null) {
29 7
    return $this->offsetExists($key) ? $this->offsetGet($key) : $default;
30
  }
31
32 1
  public function has($key) {
33 1
    return $this->offsetExists($key);
34
  }
35
36 6
  public function toArray() {
37 6
    return array_map(
38 6
        function ($value) {
39 6
          return $this->hasToArray($value) ? $value->toArray() : $value;
40 6
        },
41 6
        $this->values
42
    );
43
  }
44
45 6
  private function hasToArray($value): bool {
46 6
    return is_object($value) && method_exists($value, 'toArray');
47
  }
48
49 4
  public function path($path, $default = null, $delimiter = '.') {
50 4
    if ($this->pathStartsWithConfig($path, $delimiter))
51 2
      return $this->evalSubPath($path, $delimiter, $default);
52
53 4
    return $this->get($this->getFirstToken($path, $delimiter), $default);
54
  }
55
56 4
  private function pathStartsWithConfig($path, $delimiter) {
57 4
    return $this->getFirstTokenValue($path, $delimiter) instanceof self;
58
  }
59
60 4
  private function getFirstTokenValue($path, $delimiter) {
61 4
    return $this->get($this->getFirstToken($path, $delimiter));
62
  }
63
64 4
  private function getFirstToken($path, $delimiter) {
65 4
    return $this->gettok($path, $delimiter,0);
66
  }
67
68 2
  private function evalSubPath($path, $delimiter, $default) {
69 2
    return $this->getFirstTokenValue($path, $delimiter)->path(
70 2
        $this->subtok($path, $delimiter, 1),
71 2
        $default,
72 2
        $delimiter
73
    );
74
  }
75
76
  /**
77
   * subtok(string, delimiter, offset, length)
78
   *
79
   * Usage:
80
   *  subtok('a.b.c.d.e','.',0)     = 'a.b.c.d.e'
81
   *  subtok('a.b.c.d.e','.',0,2)   = 'a.b'
82
   *  subtok('a.b.c.d.e','.',2,1)   = 'c'
83
   *  subtok('a.b.c.d.e','.',2,-1)  = 'c.d'
84
   *  subtok('a.b.c.d.e','.',-4)    = 'b.c.d.e'
85
   *  subtok('a.b.c.d.e','.',-4,2)  = 'b.c'
86
   *  subtok('a.b.c.d.e','.',-4,-1) = 'b.c.d'
87
   *
88
   * @param  string   $string    The input string
89
   * @param  string   $delimiter The boundary string
90
   * @param  int      $offset    starting position, like in substr
91
   * @param  int|null $length    length, like in substr
92
   * @return string
93
   */
94 2
  private function subtok($string, $delimiter, $offset, $length = NULL) {
95 2
    return implode($delimiter, array_slice(explode($delimiter, $string), $offset, $length));
96
  }
97
98 4
  private function gettok($string, $delimiter, $offset) {
99 4
    return explode($delimiter, $string)[$offset];
100
  }
101
102
  # Countable
103 3
  public function count() {
104 3
    return count($this->values);
105
  }
106
107
108
  # ArrayAccess
109 30
  public function offsetExists($offset) {
110 30
    return array_key_exists($offset, $this->values);
111
  }
112
113 18
  public function offsetGet($offset) {
114 18
    if (!$this->offsetExists($offset))
115 2
      throw new \OutOfBoundsException("offset '{$offset}' does not exist");
116 16
    return $this->values[$offset];
117
  }
118
119 44
  public function offsetSet($offset, $value) {
120 44
    $this->blockIfLocked();
121 44
    $this->values[strval($offset)] = is_array($value)
122 10
        ? new static($value)
123 44
        : $value;
124 44
  }
125
126 4
  public function offsetUnset($offset) {
127 4
    $this->blockIfLocked();
128 2
    unset($this->values[strval($offset)]);
129 2
  }
130
131
132
  # Iterator
133
  public function rewind()  { return reset($this->values);        }
134
  public function key()     { return key($this->values);          }
135
  public function current() { return current($this->values);      }
136
  public function next()    { return next($this->values);         }
137
  public function valid()   { return key($this->values) !== null; }
138
139
140
  # Magic Property Access
141
  public function __set($offset, $value) { $this->offsetSet($offset, $value);   }
142
  public function __unset($offset)       { $this->offsetUnset($offset);         }
143
  public function __get($offset)         { return $this->offsetGet($offset);    }
144
  public function __isset($offset)       { return $this->offsetExists($offset); }
145
146
  /**
147
   * @param array $data
148
   * @return static
149
   */
150 1
  public static function __set_state(array $data): Config {
151 1
    return new static($data);
152
  }
153
154 12
  public function lock() {
155 12
    $this->locked = true;
156 12
  }
157
158 5
  protected function rawValues() {
159 5
    return $this->values;
160
  }
161
162 5
  protected function isConfigObject($value) {
163 5
    return $value instanceof Config;
164
  }
165
166 44
  private function blockIfLocked() {
167 44
    if ($this->isLocked())
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->isLocked() targeting Logikos\Util\Config::isLocked() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
168 6
      throw new CanNotMutateException();
169
  }
170
}