/** * Рекурсивно соединить два массива без повторения одинаковых элементов * * @param array $array1 * @param array $array2 * @return array */ function &arrayMergeUniqueRecursive(&$array1, &$array2) { $result = $array1; foreach ($array2 as $key2 => &$value2) { if (!is_array($value2) && in_array($value2, $result)) { continue; } if (isset($result[$key2])) { if (is_array($result[$key2]) && is_array($value2)) { $result[$key2] = arrayMergeUniqueRecursive($result[$key2], $value2); } else { if (!is_array($result[$key2]) && is_array($value2)) { $temp = array($result[$key2]); $result[$key2] = arrayMergeUniqueRecursive($temp, $value2); } else { if (is_array($result[$key2]) && !is_array($value2)) { $temp = array($value2); $result[$key2] = arrayMergeUniqueRecursive($result[$key2], $temp); } else { $result[] = $value2; } } } } else { $result[$key2] = $value2; } } return $result; }
/** * Получить список разрешения доступа с уже вычтеным из него списком запрещения доступа * Метод вызывается рекурсивно и способна свалиться в цикл, если существует цикл в исходных массивах * * @param mixed $role * @return array */ private function getAllow($role) { $storageKey = __CLASS__ . '_' . __METHOD__ . '_' . $role; /** * Если в сессии не сохранён список, то вычисляем и сохраняем в сессию */ if (($allow = $this->storage()->get($storageKey)) === FALSE) { /** * Получение прямых списков разрешения и запрещения доступа для переданной роли */ $allow = isset($this->allow[$role]) ? $this->allow[$role] : array(); $deny = isset($this->deny[$role]) ? $this->deny[$role] : array(); /** * Разворачивание всей иерархии, если она есть */ if (isset($this->hierarchy[$role])) { foreach ($this->hierarchy[$role] as &$parent) { $temp = $this->getAllow($parent); $allow = arrayMergeUniqueRecursive($allow, $temp); } } /** * Вычитание из списка разрешения доступа списка запрета доступа */ $allow = arrayDiffRecursive($allow, $deny); /** * Сохранение списка разрешения доступа в сессию */ $this->storage()->set($storageKey, $allow); } return $allow; }