Completed
Push — trunk ( 0e7a2e...6a6c5e )
by SuperNova.WS
07:28
created

oldArrayAccessNd   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 163
ccs 0
cts 71
cp 0
rs 9.6
c 0
b 0
f 0
wmc 32

5 Methods

Rating   Name   Duplication   Size   Complexity  
C offsetSet() 0 39 14
A offsetGet() 0 13 4
C offsetUnset() 0 27 7
B offsetExists() 0 13 6
A __flush() 0 2 1
1
<?php
2
3
namespace Common;
4
use ArrayAccess;
5
6
/**
7
 * Класс упрощает операции с многомерными индексами для ArrayAccess - старая версия
8
 * Многомерные индексы могут передаваться в $offset в виде массива
9
 * Например: array('test', 1, 2, 3) будет соответствовать обращению test[1][2][3]
10
 *
11
 * Таким образом работа с многомерными массивами может быть спроецирована на любой объект, который умеет в пары Ключ-Значение и поддерживает стандартные magic methods __isset, __get, __set и __unset
12
 *
13
 * Если объект-потомок поддерживает отложенную запись - ему нужно реализовать так же функцию __flush()
14
 *
15
 */
16
abstract class oldArrayAccessNd implements ArrayAccess {
17
18
  abstract public function __get($offset);
19
20
  abstract public function __set($offset, $value = null);
21
22
  abstract public function __isset($offset);
23
24
  abstract public function __unset($offset);
25
26
  public function __flush() {
27
    return true;
28
  }
29
30
  /**
31
   * (PHP 5 &gt;= 5.0.0)<br/>
32
   * Whether a offset exists
33
   * @link http://php.net/manual/en/arrayaccess.offsetexists.php
34
   *
35
   * @param mixed $offset <p>
36
   * An offset to check for.
37
   * </p>
38
   *
39
   * @return boolean true on success or false on failure.
40
   * </p>
41
   * <p>
42
   * The return value will be casted to boolean if non-boolean was returned.
43
   */
44
  public function offsetExists($offset) {
45
    !is_array($offset) ? $offset = array($offset) : false;
46
47
    $current_leaf = $this->__get(reset($offset));
48
    while (($leaf_index = next($offset)) !== false) {
49
      if (!isset($current_leaf) || !is_array($current_leaf) || !isset($current_leaf[$leaf_index])) {
50
        unset($current_leaf);
51
        break;
52
      }
53
      $current_leaf = $current_leaf[$leaf_index];
54
    }
55
56
    return isset($current_leaf);
57
  }
58
59
  /**
60
   * (PHP 5 &gt;= 5.0.0)<br/>
61
   * Offset to retrieve
62
   * @link http://php.net/manual/en/arrayaccess.offsetget.php
63
   *
64
   * @param mixed $offset <p>
65
   * The offset to retrieve.
66
   * </p>
67
   *
68
   * @return mixed Can return all value types.
69
   */
70
  public function offsetGet($offset) {
71
    $result = null;
72
73
    !is_array($offset) ? $offset = array($offset) : false;
74
75
    if ($this->offsetExists($offset)) {
76
      $result = $this->__get(reset($offset));
77
      while (($leaf_index = next($offset)) !== false) {
78
        $result = $result[$leaf_index];
79
      }
80
    }
81
82
    return $result;
83
  }
84
85
86
  /**
87
   * (PHP 5 &gt;= 5.0.0)<br/>
88
   * Offset to set
89
   * @link http://php.net/manual/en/arrayaccess.offsetset.php
90
   *
91
   * @param mixed $offset <p>
92
   * The offset to assign the value to.
93
   * </p>
94
   * @param mixed $value <p>
95
   * The value to set.
96
   * </p>
97
   *
98
   * @return void
99
   */
100
  public function offsetSet($offset, $value = null) {
101
    // Если нет никакого индекса - значит нечего записывать
102
    if (!isset($offset) || (is_array($offset) && empty($offset))) {
103
      return;
104
    }
105
106
    // Если в массиве индекса только один элемент - значит это просто индекс
107
    if (is_array($offset) && count($offset) == 1) {
108
      // Разворачиваем его в индекс
109
      $offset = array(reset($offset) => $value);
110
      unset($value);
111
      // Дальше будет использоваться стандартный код для пары $option, $value
112
    }
113
114
    // Адресация многомерного массива через массив индексов в $option
115
    if (is_array($offset) && isset($value)) {
116
      // TODO - а не переделать ли это всё на __isset() ??
117
      // Вытаскиваем корневой элемент
118
      $root = $this->__get(reset($offset));
119
      $current_leaf = &$root;
120
      while (($leaf_index = next($offset)) !== false) {
121
        !is_array($current_leaf[$leaf_index]) ? $current_leaf[$leaf_index] = array() : false;
122
        $current_leaf = &$current_leaf[$leaf_index];
123
      }
124
      if ($current_leaf != $value) {
125
        $current_leaf = $value;
126
        // Сохраняем данные с корня
127
        $this->__set(reset($offset), $root);
128
      }
129
    } else {
130
      // Пакетная запись из массива ключ -> значение
131
      !is_array($offset) ? $offset = array($offset => $value) : false;
132
133
      foreach ($offset as $key => $value) {
134
        $this->__get($key) !== $value ? $this->__set($key, $value) : false;
135
      }
136
    }
137
138
    $this->__flush(); // Сбрасывем кэш - если есть его поддержка
139
  }
140
141
  /**
142
   * (PHP 5 &gt;= 5.0.0)<br/>
143
   * Offset to unset
144
   * @link http://php.net/manual/en/arrayaccess.offsetunset.php
145
   *
146
   * @param mixed $offset <p>
147
   * The offset to unset.
148
   * </p>
149
   *
150
   * @return void
151
   */
152
  public function offsetUnset($offset) {
153
    // Если нет никакого индекса - значит нечего записывать
154
    if (!isset($offset) || (is_array($offset) && empty($offset))) {
155
      return;
156
    }
157
158
    !is_array($offset) ? $offset = array($offset) : false;
159
160
    if ($this->offsetExists($offset)) {
161
      // Перематываем массив в конец
162
      $key_to_delete = end($offset);
163
      $parent_offset = $offset;
164
      array_pop($parent_offset);
165
      if (!count($parent_offset)) {
166
        // В массиве был один элемент - мы удаляем в корне. Просто удаляем элемент
167
        $this->__unset($key_to_delete);
168
      } else {
169
        // Получаем родительское дерево
170
        $parent_element = $this->offsetGet($parent_offset);
171
        // Удаляем из него элемент
172
        unset($parent_element[$key_to_delete]);
173
        // Записываем измененное родительское дерево назад
174
        $this->offsetSet($parent_offset, $parent_element);
175
      }
176
    }
177
178
    $this->__flush(); // Сбрасывем кэш - если есть его поддержка
179
  }
180
}
181