private function pickStepsByTags(Exercise $exercise, array $previousExercise = null)
    {
        $pickConfig = $exercise->getPick();

        // Retrieve the list of items to use
        $items = [];

        if (!empty($previousExercise) && Recurrence::ALWAYS !== $exercise->getRandomPick()) {
            // Just get the list of items from the previous paper
            foreach ($previousExercise['steps'] as $pickedStep) {
                foreach ($pickedStep['items'] as $pickedItem) {
                    $items[] = $exercise->getQuestion($pickedItem['id']);
                }
            }
        } else {
            // Get the list of items from exercise
            foreach ($exercise->getSteps() as $step) {
                $items = array_merge($items, $step->getQuestions());
            }
        }

        // Serialize items (we will automatically get items tags for filtering)
        $serializedItems = array_map(function (Item $pickedItem) {
            return $this->itemSerializer->serialize($pickedItem, [
                Transfer::SHUFFLE_ANSWERS,
                Transfer::INCLUDE_SOLUTIONS,
            ]);
        }, $items);

        $pickedItems = [];

        if (!empty($previousExercise) && Recurrence::ALWAYS !== $exercise->getRandomPick()) {
            // items are already filtered
            $pickedItems = $serializedItems;
        } else {
            // Only pick wanted tags (format : ['tagName', itemCount])
            foreach ($pickConfig['tags'] as $pickedTag) {
                $taggedItems = array_filter($serializedItems, function ($serializedItem) use ($pickedTag) {
                    return !empty($serializedItem['tags']) && in_array($pickedTag[0], $serializedItem['tags']);
                });

                // Get the correct number of items with the current tag
                // There is no error if we want more items than there are in the quiz,
                // we just stop to pick when there are no more available items
                $pickedItems = array_merge($pickedItems, static::pick($taggedItems, $pickedTag[1], true));
            }
        }

        // Shuffle items according to config
        if ((empty($previousExercise) && Recurrence::ONCE === $exercise->getRandomOrder())
            || Recurrence::ALWAYS === $exercise->getRandomOrder()) {
            shuffle($pickedItems);
        }

        // Create steps and fill it with the correct number of questions
        $pickedSteps = [];
        while (!empty($pickedItems)) {
            $pickedStep = $this->stepSerializer->serialize(new Step());
            $pickedStep['items'] = array_splice($pickedItems, 0, $pickConfig['pageSize']);
            $pickedSteps[] = $pickedStep;
        }

        return $pickedSteps;
    }