Не смотрели порядок обхода?
if (! isset($resultsId[$parentId])) {
return false;
}
В этом месте он может пропустить приличное количество подпапок (в том числе все).
Даже отсортированные Group не гарантируют, что получится скопировать дерево целиком, ведь если родитель появился после потомка, то начнёт с потомка.
То есть предложенный алгоритм в принципе плохо справится с этой задачей. Нужно или хранить в виде дерева (то есть в памяти), или хранить флаг о том, что этот элемент уже прошли (с инкрементными айди можно использовать в качестве костыля-флага значение id, больше или меньше старого максимального).
Другие адекватные решения в голову не приходят :)