# HG changeset patch # User Denis Laxalde <denis.laxalde@logilab.fr> # Date 1439804067 -7200 # Mon Aug 17 11:34:27 2015 +0200 # Node ID a729d4376e9660a2b595a3ba4ec3ef70aef3e910 # Parent 6402bd623407c747d8f624e682e29f5bdc123396 [views] Add a controller to handle cloning This can be an alternative to the 'clone' action, in particular when the 'edition' form of the entity to be cloned is not readily usable (e.g. needs tweaking to hide inlined sub-forms, etc.). diff --git a/i18n/en.po b/i18n/en.po --- a/i18n/en.po +++ b/i18n/en.po @@ -9,3 +9,7 @@ msgid "clone" msgstr "" + +#, python-format +msgid "clone of entity #%d created" +msgstr "" diff --git a/i18n/fr.po b/i18n/fr.po --- a/i18n/fr.po +++ b/i18n/fr.po @@ -9,3 +9,7 @@ msgid "clone" msgstr "cloner" + +#, python-format +msgid "clone of entity #%d created" +msgstr "un clone de l'entité #%d a été crée" diff --git a/test/test_compound.py b/test/test_compound.py --- a/test/test_compound.py +++ b/test/test_compound.py @@ -340,14 +340,20 @@ rset=entity.as_rset()) self.assertIsInstance(action, CloneAction) + @staticmethod + def _clone_setup(cnx): + """Setup a graph of entities to be cloned.""" + agent = cnx.create_entity('Agent', name=u'bob') + cnx.create_entity('OnlineAccount', reverse_account=agent) + bio = cnx.create_entity('Biography', reverse_biography=agent) + cnx.create_entity('Event', reverse_event=bio) + cnx.create_entity('Anecdote', reverse_event=bio) + cnx.create_entity('Anecdote', reverse_event=bio, narrated_by=agent) + return agent + def test_clone_hook(self): with self.admin_access.repo_cnx() as cnx: - agent = cnx.create_entity('Agent', name=u'bob') - cnx.create_entity('OnlineAccount', reverse_account=agent) - bio = cnx.create_entity('Biography', reverse_biography=agent) - cnx.create_entity('Event', reverse_event=bio) - cnx.create_entity('Anecdote', reverse_event=bio) - cnx.create_entity('Anecdote', reverse_event=bio, narrated_by=agent) + self._clone_setup(cnx) cnx.commit() with self.new_access(u'georges').repo_cnx() as cnx: bob = cnx.find('Agent', name=u'bob').one() @@ -360,6 +366,17 @@ ' B event E, E is Event, B event A, A narrated_by X') self.assertTrue(rset) + def test_clone_controller(self): + with self.admin_access.repo_cnx() as cnx: + original_eid = self._clone_setup(cnx).eid + cnx.commit() + with self.new_access(u'georges').web_request() as req: + req.form['eid'] = original_eid + self.app_handle_request(req, 'compound.clone') + rset = req.execute( + 'Any X WHERE X clone_of O, O eid %s' % original_eid) + self.assertTrue(rset) + if __name__ == '__main__': from logilab.common.testlib import unittest_main diff --git a/views.py b/views.py --- a/views.py +++ b/views.py @@ -15,9 +15,14 @@ # with this program. If not, see <http://www.gnu.org/licenses/>. """cubicweb-compound views/forms/actions/components for web ui""" -from cubicweb.predicates import one_line_rset, adaptable, has_permission +from cubicweb.web import Redirect +from cubicweb.predicates import (one_line_rset, adaptable, has_permission, + match_form_params) +from cubicweb.web.controller import Controller from cubicweb.web.views.actions import CopyAction +from cubes.compound.entities import copy_entity + _ = unicode @@ -36,3 +41,22 @@ CopyAction.__select__ &= ~adaptable('IClonable') + + +class CloneController(Controller): + """Controller handling cloning of the original entity (with `eid` passed + in form parameters). Redirects to the cloned entity primary view. + """ + __regid__ = 'compound.clone' + __select__ = Controller.__select__ & match_form_params('eid') + + def publish(self, rset=None): + eid = int(self._cw.form['eid']) + original = self._cw.entity_from_eid(eid) + iclone = original.cw_adapt_to('IClonable') + rtype = (iclone.rtype if iclone.role == 'object' + else 'reverse_' + iclone.rtype) + kwargs = {rtype: eid} + clone = copy_entity(original, **kwargs) + msg = self._cw._('clone of entity #%d created' % eid) + raise Redirect(clone.absolute_url(__message=msg))