public function hierarchy($prefix = '', &$ignore = [], $index = false)
    {
        $hash = spl_object_hash($this);
        if (isset($ignore[$hash])) {
            return false;
        }
        $ignore[$hash] = true;

        $tree = array_fill_keys($this->schema()->relations(), true);

        $result = [];
        $habtm = [];

        foreach ($tree as $field => $value) {
            $rel = $this->schema()->relation($field);
            if ($rel->type() === 'hasManyThrough') {
                $habtm[$field] = $rel;
                continue;
            }
            if (!isset($this->{$field})) {
                continue;
            }
            $entity = $this->__get($field); // Too Many Magic Kill The Magic.
            if ($entity) {
                $path = $prefix ? $prefix . '.' . $field : $field;
                if ($children = $entity->hierarchy($path, $ignore, true)) {
                    $result += $children;
                } elseif ($children !== false) {
                    $result[$path] = $path;
                }
            }
        }

        foreach ($habtm as $field => $rel) {
            $using = $rel->through() . '.' . $rel->using();
            $path = $prefix ? $prefix . '.' . $using : $using;
            foreach ($result as $key) {
                if (strpos($key, $path) === 0) {
                    $path = $prefix ? $prefix . '.' . $field : $field;
                    $result[$path] = $path;
                }
            }
        }
        return $index ? $result : array_values($result);
    }