private function getTraits($objectOrClass, $autoload = true): array
    {
        if (is_object($objectOrClass)) {
            $objectOrClass = get_class($objectOrClass);
        }

        if (!is_string($objectOrClass)) {
            throw new \InvalidArgumentException(sprintf('Full qualified class name expected, got: "%s".', gettype($objectOrClass)));
        }

        if (!class_exists($objectOrClass)) {
            throw new \RuntimeException(sprintf('Class "%s" does not exists or it can not be autoloaded.', $objectOrClass));
        }

        $traits = [];
        // Get traits of all parent classes
        do {
            $traits = array_merge(class_uses($objectOrClass, $autoload), $traits);
        } while ($objectOrClass = get_parent_class($objectOrClass));

        $traitsToSearch = $traits;

        while (count($traitsToSearch) > 0) {
            $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
            $traits = array_merge($newTraits, $traits);
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
        }

        foreach ($traits as $trait => $same) {
            $traits = array_merge(class_uses($trait, $autoload), $traits);
        }

        return array_unique(array_map(function ($fqcn) {
            return ltrim($fqcn, '\\');
        }, $traits));
    }