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