1# -*- coding: utf-8 -*-
2from django.utils.six.moves import zip
3
4
5def copy_plugins_to(old_plugins, to_placeholder,
6                    to_language=None, parent_plugin_id=None, no_signals=False):
7    """
8    Copies a list of plugins to a placeholder to a language.
9    """
10    # TODO: Refactor this and copy_plugins to cleanly separate plugin tree/node
11    # copying and remove the need for the mutating parameter old_parent_cache.
12    old_parent_cache = {}
13    # For subplugin copy, top-level plugin's parent must be nulled
14    # before copying.
15    if old_plugins:
16        old_parent = old_plugins[0].parent
17        for old_plugin in old_plugins:
18            if old_plugin.parent == old_parent:
19                old_plugin.parent = old_plugin.parent_id = None
20    new_plugins = []
21    for old in old_plugins:
22        new_plugins.append(
23            old.copy_plugin(to_placeholder, to_language or old.language,
24                            old_parent_cache, no_signals))
25
26    if new_plugins and parent_plugin_id:
27        from cms.models import CMSPlugin
28        parent_plugin = CMSPlugin.objects.get(pk=parent_plugin_id)
29        for idx, plugin in enumerate(new_plugins):
30            if plugin.parent_id is None:
31                plugin.parent_id = parent_plugin_id
32                # Always use update fields to avoid side-effects.
33                # In this case "plugin" has invalid values for internal fields
34                # like numchild.
35                # The invalid value is only in memory because the instance
36                # was never updated.
37                plugin.save(update_fields=['parent'])
38                new_plugins[idx] = plugin.move(parent_plugin, pos="last-child")
39
40    plugins_ziplist = list(zip(new_plugins, old_plugins))
41
42    # this magic is needed for advanced plugins like Text Plugins that can have
43    # nested plugins and need to update their content based on the new plugins.
44    for new_plugin, old_plugin in plugins_ziplist:
45        new_instance = new_plugin.get_plugin_instance()[0]
46        if new_instance:
47            new_instance._no_reorder = True
48            new_instance.post_copy(old_plugin, plugins_ziplist)
49
50    # returns information about originals and copies
51    return plugins_ziplist
52