Projet

Général

Profil

0001-formdef-add-internal-identifier-attribute-separated-.patch

Frédéric Péters, 19 juillet 2017 23:39

Télécharger (10,8 ko)

Voir les différences:

Subject: [PATCH 1/2] formdef: add internal identifier attribute, separated
 from url_name (#15663)

This will allow changing url name behaviour without impacting on storage
matters.
 tests/test_admin_pages.py | 18 +++++++++------
 tests/test_formdef.py     |  8 ++++---
 tests/test_sql.py         |  2 +-
 wcs/admin/forms.py        |  5 ++--
 wcs/formdef.py            | 59 +++++++++++++++++++++++++++++++++++------------
 5 files changed, 64 insertions(+), 28 deletions(-)
tests/test_admin_pages.py
328 328
    assert resp.location == 'http://example.net/backoffice/forms/1/'
329 329
    resp = resp.follow()
330 330
    assert FormDef.get(1).name == 'new title'
331
    assert FormDef.get(1).url_name == 'new-title'
331
    assert FormDef.get(1).url_name == 'form-title'
332
    assert FormDef.get(1).internal_identifier == 'new-title'
332 333

  
333 334
def test_form_category(pub):
334 335
    create_superuser(pub)
......
745 746
    resp = resp.forms[0].submit()
746 747
    assert FormDef.count() == 1
747 748

  
748
    # import the same formdef a second time, make sure the urlname is not
749
    # reused
749
    # import the same formdef a second time, make sure url name and internal
750
    # identifier are not reused
750 751
    resp = app.get('/backoffice/forms/')
751 752
    resp = resp.click(href='import')
752 753
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
......
754 755
    assert FormDef.count() == 2
755 756
    assert FormDef.get(1).url_name == 'form-title'
756 757
    assert FormDef.get(2).url_name == 'form-title-1'
758
    assert FormDef.get(1).internal_identifier == 'form-title'
759
    assert FormDef.get(2).internal_identifier == 'form-title-1'
757 760

  
758
    # import a formdef with an url_name that doesn't match its title,
759
    # it should be updated to match.
761
    # import a formdef with an url name that doesn't match its title,
762
    # it should be kept intact.
760 763
    formdef.url_name = 'xxx-other-form-title'
761 764
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
762 765

  
......
764 767
    resp = resp.click(href='import')
765 768
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
766 769
    resp = resp.forms[0].submit()
767
    assert FormDef.get(3).url_name == 'form-title-2'
770
    assert FormDef.get(3).url_name == 'xxx-other-form-title'
771
    assert FormDef.get(3).internal_identifier == 'form-title-2'
768 772

  
769 773
    # import an invalid file
770 774
    resp = app.get('/backoffice/forms/')
......
1418 1422

  
1419 1423
    app = login(get_app(pub))
1420 1424
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
1421
    resp = resp.click(href='overwrite')
1425
    resp = resp.click(href='overwrite', index=0)
1422 1426
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
1423 1427
    resp = resp.forms[0].submit()
1424 1428
    assert 'The form removes and changes fields' in resp.body
tests/test_formdef.py
83 83
    formdef.store()
84 84
    assert FormDef.get(formdef.id).name == 'foo'
85 85
    assert FormDef.get(formdef.id).url_name == 'foo'
86
    assert FormDef.get(formdef.id).internal_identifier == 'foo'
86 87

  
87 88
    formdef.name = 'bar'
88 89
    formdef.store()
89 90
    assert FormDef.get(formdef.id).name == 'bar'
90
    assert FormDef.get(formdef.id).url_name == 'bar'
91
    assert FormDef.get(formdef.id).url_name == 'foo'
92
    assert FormDef.get(formdef.id).internal_identifier == 'bar'
91 93

  
92
    # makes sure the url_name doesn't change if there are submitted forms
94
    # makes sure the internal_name doesn't change if there are submitted forms
93 95
    formdef.data_class()().store()
94 96
    formdef.name = 'baz'
95 97
    formdef.store()
96 98
    assert FormDef.get(formdef.id).name == 'baz'
97
    assert FormDef.get(formdef.id).url_name == 'bar' # didn't change
99
    assert FormDef.get(formdef.id).internal_identifier == 'bar' # didn't change
98 100

  
99 101
def test_substitution_variables():
100 102
    formdef = FormDef()
tests/test_sql.py
569 569

  
570 570
    formdef.name = 'tests2'
571 571
    formdef.store()
572
    assert formdef.url_name == 'tests2'
572
    assert formdef.url_name == 'tests'
573 573

  
574 574
    formdef.name = 'tests'
575 575
    formdef.store()
wcs/admin/forms.py
949 949
        return redirect('.')
950 950

  
951 951
    def overwrite_by_formdef(self, new_formdef):
952
        # keep current formdef id, url_name and sql table name
952
        # keep current formdef id, url_name, internal identifier and sql table name
953 953
        new_formdef.id = self.formdef.id
954
        new_formdef.internal_identifier = self.formdef.internal_identifier
954 955
        new_formdef.url_name = self.formdef.url_name
955 956
        new_formdef.table_name = self.formdef.table_name
956 957
        # keep currently assigned category and workflow
......
1552 1553
                form.set_error('file', msg)
1553 1554
            raise ValueError()
1554 1555

  
1555
        formdef.url_name = None # a new one will be set in .store()
1556
        formdef.internal_identifier = None # a new one will be set in .store()
1556 1557
        formdef.disabled = True
1557 1558
        formdef.store()
1558 1559
        get_session().message = ('info',
wcs/formdef.py
69 69
    description = None
70 70
    keywords = None
71 71
    url_name = None
72
    internal_identifier = None # mostly for pickle
72 73
    table_name = None # for SQL only
73 74
    fields = None
74 75
    category_id = None
......
101 102

  
102 103
    # declarations for serialization
103 104
    TEXT_ATTRIBUTES = ['name', 'url_name', 'description', 'keywords',
104
            'publication_date', 'expiration_date',
105
            'publication_date', 'expiration_date', 'internal_identifier',
105 106
            'disabled_redirection',]
106 107
    BOOLEAN_ATTRIBUTES = ['discussion', 'detailed_emails', 'disabled',
107 108
            'only_allow_one', 'enable_tracking_codes', 'confirmation',
......
173 174
            self.table_name = sql.get_formdef_table_name(self)
174 175
            changed = True
175 176

  
177
        if not self.internal_identifier:
178
            self.internal_identifier = self.url_name
179

  
176 180
        if self.max_field_id is None and self.fields:
177 181
            self.max_field_id = max([lax_int(x.id) for x in self.fields])
178 182
            changed = True
......
238 242
            actions = sql.do_formdef_tables(self)
239 243
        else:
240 244
            cls = new.classobj(self.url_name.title(), (FormData,),
241
                        {'_names': 'form-%s' % self.url_name,
245
                        {'_names': 'form-%s' % self.internal_identifier,
242 246
                         '_formdef': self})
243 247
            actions = []
244 248
        setattr(sys.modules['formdef'], self.url_name.title(), cls)
......
259 263
        return str(field_id)
260 264

  
261 265
    def get_new_url_name(self):
262
        new_url_name = simplify(self.name)
266
        new_url_name = simplify(self.name, space='-')
263 267
        base_new_url_name = new_url_name
264 268
        suffix_no = 0
265 269
        while True:
266 270
            try:
267
                formdef = self.get_by_urlname(new_url_name, ignore_migration=True)
271
                obj = self.get_on_index(new_url_name, 'url_name', ignore_migration=True)
268 272
            except KeyError:
269 273
                break
270
            if formdef.id == self.id:
274
            if obj.id == self.id:
271 275
                break
272 276
            suffix_no += 1
273 277
            new_url_name = '%s-%s' % (base_new_url_name, suffix_no)
274 278
        return new_url_name
275 279

  
280
    def get_new_internal_identifier(self):
281
        new_internal_identifier = simplify(self.name)
282
        base_new_internal_identifier = new_internal_identifier
283
        suffix_no = 0
284
        while True:
285
            try:
286
                formdef = self.get_by_urlname(new_internal_identifier, ignore_migration=True)
287
            except KeyError:
288
                break
289
            if formdef.id == self.id:
290
                break
291
            suffix_no += 1
292
            new_internal_identifier = '%s-%s' % (base_new_internal_identifier, suffix_no)
293
        return new_internal_identifier
294

  
276 295
    @classmethod
277 296
    def get_new_id(cls, create=False):
278 297
        keys = cls.keys()
......
303 322
            sql.formdef_wipe()
304 323

  
305 324
    def store(self):
306
        new_url_name = self.get_new_url_name()
307
        if not self.url_name:
308
            self.url_name = new_url_name
309
        if new_url_name != self.url_name:
310
            # title changed, url will be changed only if the formdef is
311
            # currently being imported (self.id is None) or if there are not
312
            # yet any submitted forms
313
            data_class = self.data_class()
314
            if self.id is None or data_class().count() == 0:
315
                self.url_name = new_url_name
325
        if self.url_name is None:
326
            # set url name if it's not yet there
327
            self.url_name = self.get_new_url_name()
328
        new_internal_identifier = self.get_new_internal_identifier()
329
        if not self.internal_identifier:
330
            self.internal_identifier = new_internal_identifier
331
        if new_internal_identifier != self.internal_identifier:
332
            # title changed, internal identifier will be changed only if
333
            # the formdef is currently being imported (self.id is None)
334
            # or if there are not yet any submitted forms
335
            if self.id is None or self.data_class().count() == 0:
336
                self.internal_identifier = new_internal_identifier
316 337
        self.last_modification_time = time.localtime()
317 338
        if get_request() and get_request().user:
318 339
            self.last_modification_user_id = str(get_request().user.id)
......
846 867
        formdef = cls.import_from_xml_tree(tree, charset=charset,
847 868
                include_id=include_id)
848 869

  
870
        if formdef.url_name:
871
            try:
872
                obj = cls.get_on_index(formdef.url_name, 'url_name', ignore_migration=True)
873
            except KeyError:
874
                pass
875
            else:
876
                formdef.url_name = formdef.get_new_url_name()
877

  
849 878
        # fix max_field_id if necessary
850 879
        if formdef.max_field_id is not None:
851 880
            max_field_id = max([lax_int(x.id) for x in formdef.fields])
852
-