protected function flattenInvoiceLines(array $lines)
    {
        $result = array();

        foreach ($lines as $line) {
            $children = null;
            // Ignore children if we do not want to show them.
            // If it has children, flatten them and determine how to add them.
            if (array_key_exists(Meta::ChildrenLines, $line)) {
                $children = $this->flattenInvoiceLines($line[Meta::ChildrenLines]);
                // Remove children from parent.
                unset($line[Meta::ChildrenLines]);
                // Determine whether to add them at all and if so whether
                // to add them as a single line or as separate lines.
                if ($this->keepSeparateLines($line, $children)) {
                    // Keep them separate but perform the following actions:
                    // - Allow for some web shop specific corrections.
                    // - Add meta data to relate parent and children.
                    // - Indent product descriptions.
                    $this->correctInfoBetweenParentAndChildren($line, $children);
                } else {
                    // Merge the children into the parent product:
                    // - Allow for some web shop specific corrections.
                    // - Add meta data about removed children.
                    // - Add text from children, eg. chosen variants, to parent.
                    $line = $this->collectInfoFromChildren($line, $children);
                    // Delete children as their info is merged into the parent.
                    $children = null;
                }
            }

            // Add the line and its children, if any.
            $result[] = $line;
            if (!empty($children)) {
                $result = array_merge($result, $children);
            }
        }

        return $result;
    }