From 82a2faf3b2de1b6f7745e79b3a762570210edb5f Mon Sep 17 00:00:00 2001 From: Luca Fabbri Date: Fri, 22 Sep 2017 16:53:41 +0200 Subject: [PATCH] Squashed commit of the following: commit 3f36b4ac590f26696843f7acb36fb037e7520471 Merge: a1387c8 c389777 Author: Luca Fabbri Date: Fri Sep 22 15:41:23 2017 +0200 Merge branch 'fix-165' of https://github.com/abstract-open-solutions/Products.PloneFormGen into fix-165 commit a1387c88309f13a37a551751c2632fb4256c441c Author: Luca Fabbri Date: Wed Nov 9 11:06:41 2016 +0100 Label and descripotion were not copyed on widget change commit b93fb476ffde5e6f5ba662aa4dada28116325490 Author: Luca Fabbri Date: Wed Nov 9 09:47:02 2016 +0100 Restored usage of show_hm field See also https://github.com/smcmahon/Products.PloneFormGen/pull/165 commit 343414c707d621a577ee891f32ed4f029faa4b41 Author: Luca Fabbri Date: Tue Nov 8 18:06:47 2016 +0100 Fixed validation when date is not required (plus tests) commit bebd64b2386c30b2f8357f167b2b86e08169e927 Author: Luca Fabbri Date: Tue Nov 8 18:05:24 2016 +0100 Missing test dependency commit 56b44725669f0739a96a77a477b56fd70da48a8c Author: Tom Gross Date: Mon May 9 13:14:22 2016 +0000 fix date validator to work with new pattern widget output commit f455f348afba2751cb6d9ad847457df287764aab Author: Tom Gross Date: Mon May 9 13:14:04 2016 +0000 ignor pycharm artefacts commit 10987045eb8ab6f89317e3ed072245856706fb32 Author: Tom Gross Date: Mon May 9 10:31:47 2016 +0000 use datepicker widget for datetime input #164 commit f8aa1d7f9ec311bc44283cb81fb2a9861bdbc087 Author: Maurits van Rees Date: Sat Jul 8 20:29:41 2017 +0200 Back to development: 1.8.5 [ci skip] commit 19ac10a92f06cc2d5088e70876cdcffa6b4c8938 Author: Maurits van Rees Date: Sat Jul 8 20:29:01 2017 +0200 Preparing release 1.8.4 [ci skip] commit bf13b48c05674345c689456b63f49d907a41153d Author: Maurits van Rees Date: Sat Jul 8 20:28:39 2017 +0200 Cleanup the changelog a bit. [ci skip] commit b13fbc075d9b78d226169969d6fff30ae882458c Merge: e5163b3 54195c7 Author: Maurits van Rees Date: Sat Jul 8 19:54:26 2017 +0200 Merge pull request #199 from jyukopla/fix-redundant-template-syntax Fix redundant fallback template value commit e5163b3b3d8963ca338a3cf4683a343defef0e51 Merge: 18085c3 9ced974 Author: Maurits van Rees Date: Sat Jul 8 19:39:31 2017 +0200 Merge pull request #200 from jyukopla/fix/ratescalefield-unicode-error Fix/ratescalefield unicode error commit 54195c72176c33c92429ff76b62cb98ced83aef1 Author: Jussi Rajala Date: Fri Jul 7 09:26:32 2017 +0300 Fix integration test to handle missing empty div b10ef37 caused an empty div between
to be absent. For some reasons, current integration test required something (anything) to be between the two elements. This handles the both cases where there is content between them or not. commit 9ced974252b3de4c82fe3e22f6aa43d37f2b206e Author: Valtteri Karppinen Date: Thu Jul 6 11:21:18 2017 +0300 update CHANGES.txt commit 9f2fba21c65544378f36fc6e0670b63fdc48591a Author: Valtteri Karppinen Date: Thu Jul 6 11:20:16 2017 +0300 Fix UnicodeDecodeError on ratescalefield with non-ascii values commit b10ef375762bde619d18b98a91fc5db75d39af8e Author: Jussi Rajala Date: Wed Jul 5 15:56:32 2017 +0300 Fix redundant template fallback value causing errors `|nothing` in conjunction with `structure` or `provider:` (not sure which) caused `ContentProviderLookupError: archetypes.edit.beforefieldsets|nothing` for me in some cases while debugging broken `RichTextField`. It seems that it might not be a valid syntax? In any case, it seems to be redundant, since there is also `tal:on-error="nothing"`, and subsequent equicalent `tal:replace="provider:archetypes.edit.afterfieldsets"` does not have it either. commit 18085c32af00416b3da7f23746287de810351583 Merge: fd2b4a6 82f9062 Author: Maurits van Rees Date: Tue Jun 6 23:20:46 2017 +0200 Merge pull request #195 from rodfersou/issue_194 Remove collective.cover adapter reference commit 82f90627aa9991d23a2024f019e5a6a2e9992ae9 Author: Rodrigo Ferreira de Souza Date: Tue May 23 23:07:11 2017 -0300 Remove collective.cover adapter reference commit fd2b4a63df0443ad1f5b309745fe9cdd3a9ee76b Merge: eb3d189 6ae0258 Author: Maurits van Rees Date: Sat Jun 3 23:35:27 2017 +0200 Merge pull request #197 from smcmahon/fix-bootstrap Fixed bootstrapping. commit 6ae0258981528e4ce47819c0677b9efb64b89a09 Author: Maurits van Rees Date: Sat Jun 3 23:11:42 2017 +0200 Use Plone 5.0.6 for now. 5.0.7 gives failures in the tests. Seems fine in normal usage. commit f2333cb9dcadea32cb9ff151781878304087e4af Author: Maurits van Rees Date: Sat Jun 3 23:01:42 2017 +0200 Tests: set browser.handleErrors to False. That way we get a proper traceback, instead of a general internal server error. commit 06e68fd85c67c98932cbe7331c260d33cb767777 Author: Maurits van Rees Date: Sat Jun 3 21:50:23 2017 +0200 Fixed bootstrapping. Both locally and on Travis. Note that you need to specify the zc.buildout version when bootstrapping: python bootstrap-buildout.py --buildout-version=2.5.3 For setuptools we use the latest that ez_setup.py gives us, which will remain 33.1.1. commit eb3d189a80175caf2a6ae9f17ad0747d0c4deab8 Merge: faa4352 82c18e9 Author: Maurits van Rees Date: Tue Mar 7 18:35:48 2017 +0100 Merge pull request #192 from mikerenfro/fix-column-titles Adding getColumnNames logic to getColumnTitles commit 82c18e97da55ed1777fb8d048bc4f6a92707fd75 Author: Mike Renfro Date: Sun Mar 5 19:03:03 2017 -0600 Adding getColumnNames logic to getColumnTitles commit faa435264098b444ceee7c41f6b6599534ffb5a1 Merge: 10bbf17 c345b27 Author: Maurits van Rees Date: Wed Mar 1 14:12:53 2017 +0100 Merge pull request #191 from datakurre/master Add missing into quickedit.pt commit c345b27a8305d6dd2fef579f1d231180059a8db6 Author: Asko Soukka Date: Fri Feb 24 16:17:25 2017 +0200 Update changelog commit 67f1d49c9c1602c963b572067ba0fab436b608c5 Author: Asko Soukka Date: Fri Feb 24 16:16:15 2017 +0200 Add missing closing into quickedit template commit 10bbf17283c5d380a340e3a3e2444316c46140b5 Author: Maurits van Rees Date: Thu Dec 8 15:45:31 2016 +0100 Fixed UnicodeDecodeError when vocabulary value is a non-ascii string. This could happen in selection and multi selection fields. commit f5fa6950e736709999ad8b1f4b86af941cb689b1 Merge: 6e7018b 7d99f56 Author: Maurits van Rees Date: Fri Dec 16 14:16:02 2016 +0100 Merge pull request #187 from tkimnguyen/master change captcha verification message for #186 commit 7d99f563b9a99cb62074e58a9e0b37fd62cac110 Author: T. Kim Nguyen Date: Wed Dec 14 13:28:16 2016 -0600 change captcha verification message for #186 commit 6e7018b184086d732e4943d5482cfc755df3607c Author: Maurits van Rees Date: Tue Dec 6 15:25:10 2016 +0100 Back to development: 1.8.4 [ci skip] commit 0adae5739f103635fb175e38459cf66f05ddfec8 Author: Maurits van Rees Date: Tue Dec 6 15:24:31 2016 +0100 Preparing release 1.8.3 [ci skip] commit 6829d2fa36f713fda9283175f7b340be3c697a7a Author: Philip Bauer Date: Tue Dec 6 11:27:53 2016 +0100 Transform value to unicode before translating. Fix #182 commit 709f625e6d04080b75201a096e701c9eb07df2da Author: Steve McMahon Date: Tue Nov 22 11:32:04 2016 -0800 Back to development: 1.8.3 commit e13a9dbf08ceaf253ff3e96fa610aa8b2b5a8f70 Author: Steve McMahon Date: Tue Nov 22 11:30:53 2016 -0800 Preparing release 1.8.2 commit b90e67dd17a052df81b6a0e108069b4b1894d1ef Merge: 1cf9556 87a4799 Author: Steve McMahon Date: Tue Nov 22 11:24:53 2016 -0800 Merge pull request #181 from smcmahon/issue-178-helptext-master Fixed showing translations of help text. [master] commit 1cf9556b0db92c48305fc8dfd7465ab10a2f8835 Author: Maurits van Rees Date: Fri Nov 18 18:37:43 2016 +0100 Added commented-out xlwt egg. With this eXceL WriTer you can test the excel export of the Save Data Adapter. commit 70d0bd8a9e17e1093e6890a2bf416acb99341ae2 Merge: c71a53b d8a03a2 Author: Maurits van Rees Date: Fri Nov 18 18:27:47 2016 +0100 Merge remote-tracking branch 'tmog/xls_export' commit 87a47998e9189b55258ee0d968582147e0df624f Author: Maurits van Rees Date: Fri Nov 18 13:00:49 2016 +0100 Fixed showing translations of help text. Since security release 1.78.1, help text was showing up with only the message id, for example `help_placeholder`. This fixes issue #178. commit c71a53bab33f3ea9306013d6e14f7edb21f0001a Author: Harald Friessnegger Date: Thu Sep 3 18:24:52 2015 +0200 use formActionOverride in embedded view if it has been set commit c38977712ae865008a42fc628e8d59942d453c7c Author: Luca Fabbri Date: Wed Nov 9 11:06:41 2016 +0100 Label and descripotion were not copyed on widget change commit 42029d8b9ab4e163fbe5bf86758c4e2be24a8fff Author: Luca Fabbri Date: Wed Nov 9 09:47:02 2016 +0100 Restored usage of show_hm field See also https://github.com/smcmahon/Products.PloneFormGen/pull/165 commit 7e96bd2aa998389ea7e9f77932bcd5729d7b752c Author: Luca Fabbri Date: Tue Nov 8 18:06:47 2016 +0100 Fixed validation when date is not required (plus tests) commit b44b89e91204dc4adbbdd39d202f86d5a9660f76 Author: Luca Fabbri Date: Tue Nov 8 18:05:24 2016 +0100 Missing test dependency commit e920d86e099f054af70d0f48afc18c0c89baa6ab Author: Tom Gross Date: Mon May 9 13:14:22 2016 +0000 fix date validator to work with new pattern widget output commit b283f0c86a43f1949bdce8e26e1fd6e48221842c Author: Tom Gross Date: Mon May 9 13:14:04 2016 +0000 ignor pycharm artefacts commit cf16bef1d43a0eb5198b72cb90863bc060a27374 Author: Tom Gross Date: Mon May 9 10:31:47 2016 +0000 use datepicker widget for datetime input #164 commit af24c55d46f1894b503d3a762e781aa085dcf353 Author: Maurits van Rees Date: Tue May 3 12:05:13 2016 +0200 Back to development: 1.8.2 [ci skip] commit b9590e5573660ee6b8d151430ca2b459f05388ca Author: Steve McMahon Date: Sun May 1 10:43:14 2016 -0700 Eliminate XSS vulnerability in field help field commit d8a03a2d50ca56bacd7b11af47c3976bef360923 Author: Thomas Clement Mogensen Date: Fri Feb 26 14:25:25 2016 +0100 format web links and numbers as such in excel download. Format based on actual data, not field settings. commit c86a891c2492c3db89c1de7b7f8c87149dafd39a Author: Thomas Clement Mogensen Date: Thu Feb 25 13:37:01 2016 +0100 fix encoding issue in excel document creation commit be18ed695e193122318e7d1889fbf073e83d0c92 Author: Thomas Clement Mogensen Date: Wed Feb 24 12:04:35 2016 +0100 Add option to download data from saveDataAdapter in excel format commit fc9592b09292963dc28db74e148186dfa0921679 Author: Steve McMahon Date: Thu Oct 1 09:01:44 2015 -0700 Update README.rst commit cf425b156368465b9e1546cf406fa97a660e24f4 Author: Maurits van Rees Date: Thu Oct 1 04:50:52 2015 +0200 Back to development: 1.8.1 [ci skip] commit 4ba658b3cba1faae7fbddfd9ff70fb3ac8a8ee75 Author: Maurits van Rees Date: Thu Oct 1 04:48:21 2015 +0200 Preparing release 1.8.0 [ci skip] commit 164be3cf3b488ae8ecc1377233eea6f2e5a9352b Author: Maurits van Rees Date: Thu Oct 1 04:47:05 2015 +0200 check-manifest: ignore .gitattributes commit 881063c369bc15bd801761f11098c1bb00470f44 Author: Maurits van Rees Date: Thu Oct 1 04:45:35 2015 +0200 Fixed rst long description. commit 4c4611302f1cd095bc5510a15cba9642ebe32ddb Author: Maurits van Rees Date: Thu Oct 1 02:16:37 2015 +0200 Removed deprecated property use_folder_tabs. commit 26e16d80bebbafea9c32819370e560161af636df Author: Maurits van Rees Date: Thu Oct 1 02:11:59 2015 +0200 Removed unused property typesLinkToFolderContentsInFC. In core Plone this was briefly changed to plone.types_link_to_folder_contents, but it was not actually used. commit cb426ca0789c54c8a6451a50b9a4f7b67c5284b5 Author: Maurits van Rees Date: Thu Oct 1 01:55:29 2015 +0200 Revert "Moved our types_not_searched settings to the registry." This reverts commit 6b4256e5176cb19adf5a3f87dd54c9e399210a15. It needs a fix in plone.app.registry so that typeinfo is loaded before registry.xml, otherwise an install fails. commit 6b4256e5176cb19adf5a3f87dd54c9e399210a15 Author: Maurits van Rees Date: Thu Oct 1 01:11:04 2015 +0200 Moved our types_not_searched settings to the registry. commit 8f3e395c2de1cb1cddf5871424c0cefdef6c3a80 Author: Maurits van Rees Date: Thu Oct 1 01:04:32 2015 +0200 Moved our default_page_types setting to the registry. commit e2e34fb0c2c52ca1c966d1cd4c6e169dce2093a4 Author: Maurits van Rees Date: Wed Sep 30 20:33:39 2015 +0200 Rename UTF-8 and utf8 to lowercase utf-8. They are all the same and this what Plone uses everywhere (or should be). commit 3695500d8b7ad54df61c9177644378ccadb00fa6 Author: Maurits van Rees Date: Wed Sep 30 20:31:41 2015 +0200 Get email settings from registry. Fixes several Plone 5 errors. Do not use ``plone_utils.getSiteEncoding()``, because this is deprecated and always returns ``utf-8''. commit 8375e49b5ce07a2e90e2c6a4fc181a45cc437571 Author: Maurits van Rees Date: Wed Sep 30 20:00:21 2015 +0200 Load widget specific css on quickedit form. We were defining both javascript and css of the addable widgets, but were only adding the javascript, not the css. The calendar widget is still not really working there. But if we are loading this css when viewing a form, we should load it while quickediting the form. On Plone 4.3 it helped. commit 37c2148894aa4f8bc98df00cc2ccd6a176177ac4 Merge: 276df36 3aeb6be Author: Maurits van Rees Date: Fri Sep 11 15:59:36 2015 +0200 Merge remote-tracking branch '4teamwork/fix_embedded_view' commit 276df3653a51439052e0725994a1e6bd88552da0 Author: Maurits van Rees Date: Fri Sep 11 15:59:32 2015 +0200 Tell git to merge CHANGES.txt in union mode. bobtemplates.plone does that. commit 944a6ff5143e7b17b7de4a6fdb35cdfe1a5bc8d8 Author: Maurits van Rees Date: Fri Sep 11 14:55:09 2015 +0200 Removed inline javascript that tried to block inline validation. It had no effect anymore on Plone 5, as no inline validation is done here anyway. And it interferes with themes that load jQuery near the bottom instead of in the head. commit 3aeb6be81347cce5dc21d4a0ecc1b4a771a57fbe Author: Thomas Buchberger Date: Fri Sep 11 11:58:10 2015 +0200 Fix embedded view by removing global_defines macro. commit 5ed163519286f1770fc1d82a77c505c92691be28 Author: Maurits van Rees Date: Wed Sep 9 20:39:55 2015 +0200 Back to development: 1.8.0b5 [ci skip] commit 4cba4e57451f8475d0e6e14856761fcccdf5cb21 Author: Maurits van Rees Date: Wed Sep 9 20:35:02 2015 +0200 Preparing release 1.8.0b4 [ci skip] commit 8499d4804162f4cac2953bdaecdcd1a307ad3ab0 Author: Maurits van Rees Date: Wed Sep 9 20:33:43 2015 +0200 Fixed manifest. commit 2054b2bc126e885d2c2a5bccffd28f241737087c Author: Maurits van Rees Date: Wed Sep 9 20:24:05 2015 +0200 No longer convert long description to ascii. Works fine, at least with any recent zest.releaser version. The current text files are already ascii-only, so there the problem never occurs, but should be fine anyway. commit 03428e880d14ff575f48c230f7ec938aee0c77de Author: Maurits van Rees Date: Tue Sep 8 19:45:26 2015 +0200 Changed our content types to use TinyMCEWidget instead of RichWidget. The old one only showed a plain textarea. Fixes issue #152. --- .gitattributes | 1 + .gitignore | 1 + .travis.yml | 4 +- CHANGES.txt | 102 +++++++++++++++++- MANIFEST.in | 2 +- Products/PloneFormGen/browser/embedded.py | 6 +- Products/PloneFormGen/browser/quickedit.pt | 11 ++ Products/PloneFormGen/configure.zcml | 7 -- Products/PloneFormGen/content/field_utils.py | 43 ++++++++ Products/PloneFormGen/content/fields.py | 69 +++++++----- Products/PloneFormGen/content/fieldsBase.py | 17 +-- Products/PloneFormGen/content/form.py | 22 ++-- .../PloneFormGen/content/formMailerAdapter.py | 28 ++--- .../PloneFormGen/content/saveDataAdapter.py | 90 +++++++++++++--- Products/PloneFormGen/content/thanksPage.py | 6 +- Products/PloneFormGen/content/ya_gpg.py | 2 +- Products/PloneFormGen/events.py | 2 +- .../profiles/default/metadata.xml | 2 +- .../profiles/default/propertiestool.xml | 11 -- .../profiles/default/registry.xml | 5 + .../skins/PloneFormGen/fg_base_view_p3.cpt | 13 +-- .../skins/PloneFormGen/fg_edit_macros_p3.pt | 2 +- .../PloneFormGen/fg_embedded_view_p3.cpt | 1 - .../PloneFormGen/fg_result_embedded_view.pt | 3 +- Products/PloneFormGen/tests/attachment.txt | 3 +- Products/PloneFormGen/tests/browser.txt | 84 ++++++++++++--- .../PloneFormGen/tests/serverside_field.txt | 7 +- Products/PloneFormGen/tests/ssl.txt | 7 +- Products/PloneFormGen/tests/testFunctions.py | 35 ++++-- Products/PloneFormGen/tests/testMailer.py | 4 +- Products/PloneFormGen/tests/testSetup.py | 64 +++++------ Products/PloneFormGen/upgrades.zcml | 10 ++ .../validators/CaptchaValidator.py | 2 +- .../validators/MaxLengthValidator.py | 2 +- Products/PloneFormGen/version.txt | 2 +- README.rst | 4 +- bootstrap-buildout.py | 51 ++++++--- buildout.cfg | 12 ++- setup.cfg | 7 ++ setup.py | 10 +- 40 files changed, 546 insertions(+), 208 deletions(-) create mode 100644 .gitattributes create mode 100644 Products/PloneFormGen/content/field_utils.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..d4ff3632 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +CHANGES.txt merge=union diff --git a/.gitignore b/.gitignore index 6ee7ba9c..80ad24fa 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ parts src var ._* +.idea diff --git a/.travis.yml b/.travis.yml index ac340a0d..ffd31963 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,11 +7,11 @@ cache: - buildout-cache install: - mkdir -p buildout-cache/{eggs,downloads} - - python bootstrap-buildout.py + - python bootstrap-buildout.py --buildout-version=2.5.3 - bin/buildout script: - bin/test notifications: email: - - steve@dcn.org \ No newline at end of file + - steve@dcn.org diff --git a/CHANGES.txt b/CHANGES.txt index 0328472d..e08c2ed4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,9 +1,106 @@ Change History ============== +1.8.5 (unreleased) +------------------ -1.8.0.beta4 (unreleased) ------------------------- +- Use datepicker widget for datetime input + [tomgross] + + +1.8.4 (2017-07-08) +------------------ + +- Fix UnicodeDecodeError: RateScaleField with non-ascii values and without + Thank-you-page. + Fixes `issue #98 `_. + [vkarppinen] + +- Remove collective.cover adapter reference. + (Closes `#194 `_. + [rodfersou] + +- Fixed UnicodeDecodeError when vocabulary value is a non-ascii string. + This could happen in selection and multi selection fields. + [maurits] + +- Change captcha verification message for `#186 `_. + [tkimnguyen] + +- Fix issue where quickedit view caused rendering issues because + of a tag not being closed. + [datakurre] + +- Fix issue where logic in FormSaveDataAdapter's getColumnTitles was + different than the logic for getColumnNames. + [mikerenfro] + +- Fix redundant template fallback value. + [zemm] + + +1.8.3 (2016-12-06) +------------------ + +- Transform value to unicode before translating. Fix #182 + [pbauer] + + +1.8.2 (2016-11-22) +------------------ + +- Fixed showing translations of help text. Since security release + 1.8.1, help text was showing up with only the message id, for + example ``help_placeholder``. + Fixes `issue #178 `_. + [maurits] + +- Use formActionOverride action in embedded view. [fRiSi] + +- Add option to download data from saveDataAdapter in excel format + Excel download depends on the availability of the 'xlwt' python package. + [tmog] + + +1.8.1 (2016-05-01) +------------------ + +- CGI escape field help (description); prevent method call. + Eliminates XSS vulnerability that could be exploited by users with the ability + to create forms. + [smcmahon] + + +1.8.0 (2015-10-01) +------------------ + +- Moved our default_page_types setting to the registry. + [maurits] + +- Get email settings from registry. Fixes several Plone 5 errors. + Do not use ``plone_utils.getSiteEncoding()``, because this is + deprecated and always returns ``utf-8``. + [maurits] + +- Load widget specific css on quickedit form. + [maurits] + +- Fix embedded view by removing deprecated global defines macro. + [buchi] + +- Removed inline javascript that tried to block inline validation. It + had no effect anymore on Plone 5, as no inline validation is done + here anyway. And it interferes with themes that load jQuery near + the bottom instead of in the head. + [maurits] + + +1.8.0b4 (2015-09-09) +-------------------- + +- Changed our content types to use TinyMCEWidget instead of + RichWidget. The old one only showed a plain textarea. Fixes issue + #152. - Fixed ``propertiestool.xml`` to not break importing ``types_not_searched``. @@ -45,3 +142,4 @@ Change History [thet] For previous changes, see docs/HISTORY.txt. + diff --git a/MANIFEST.in b/MANIFEST.in index a27975ef..c248630b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include * +include *cfg *rst *txt recursive-include docs * recursive-include Products/PloneFormGen * global-exclude *.pyc diff --git a/Products/PloneFormGen/browser/embedded.py b/Products/PloneFormGen/browser/embedded.py index eb31353f..d83b8c9e 100644 --- a/Products/PloneFormGen/browser/embedded.py +++ b/Products/PloneFormGen/browser/embedded.py @@ -83,7 +83,11 @@ def __call__(self): if self.action is not None: self.request.set('pfg_form_action', self.action) else: - self.request.set('pfg_form_action', self.request['URL']) + actionOverride = getattr(self.context, 'formActionOverride', None) + if actionOverride: + self.request.set('pfg_form_action', actionOverride) + else: + self.request.set('pfg_form_action', self.request['URL']) self.status = IStatusMessage(self.request) self.request.set('messages', self.status.show()) diff --git a/Products/PloneFormGen/browser/quickedit.pt b/Products/PloneFormGen/browser/quickedit.pt index ffd363de..dff2f65f 100644 --- a/Products/PloneFormGen/browser/quickedit.pt +++ b/Products/PloneFormGen/browser/quickedit.pt @@ -58,6 +58,16 @@ + + + + + @@ -293,6 +303,7 @@ +

diff --git a/Products/PloneFormGen/configure.zcml b/Products/PloneFormGen/configure.zcml index 6a34233e..ce948c3d 100644 --- a/Products/PloneFormGen/configure.zcml +++ b/Products/PloneFormGen/configure.zcml @@ -137,11 +137,4 @@ - - diff --git a/Products/PloneFormGen/content/field_utils.py b/Products/PloneFormGen/content/field_utils.py new file mode 100644 index 00000000..a70ae42f --- /dev/null +++ b/Products/PloneFormGen/content/field_utils.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +from Products.Archetypes.Renderer import renderer +from Products.CMFPlone.utils import safe_unicode +from zope.i18n import translate + +import cgi + + +class ATWidgetWrapper(object): + """ + Wrap a Products.Archetypes.generator.widget.widget class + to intercept the Description method. + """ + + def __init__(self, obj): + self.obj = obj + + def __call__(self, mode, instance, context=None): + return self.obj(mode, instance, context) + + def __getattr__(self, name): + if name == 'Description': + return self.wDescription + return getattr(self.obj, name) + + def wDescription(self, instance, **kwargs): + value = self.obj.description + if value: + value = translate(safe_unicode(value), context=instance.REQUEST) + return cgi.escape(value) + else: + return value + + +def widget(self, field_name, mode="view", field=None, **kwargs): + """Returns the rendered widget. + """ + + if field is None: + field = self.Schema()[field_name] + widget = ATWidgetWrapper(field.widget) + return renderer.render(field_name, mode, widget, self, field=field, + **kwargs) diff --git a/Products/PloneFormGen/content/fields.py b/Products/PloneFormGen/content/fields.py index 389be80b..2dae92a3 100644 --- a/Products/PloneFormGen/content/fields.py +++ b/Products/PloneFormGen/content/fields.py @@ -9,6 +9,8 @@ from Products.Archetypes.public import * from Products.Archetypes.utils import shasattr +from Products.Archetypes.Widget import DateWidget +from Products.Archetypes.Widget import DatetimeWidget from Products.ATContentTypes.content.base import registerATCT from Products.ATContentTypes.content.base import ATCTContent @@ -505,20 +507,37 @@ def __init__(self, oid, **kwargs): self.fgField = DateTimeField('fg_date_field', searchable=0, required=0, + accessor = 'nullAccessor', write_permission = View, - widget=CalendarWidget(), + widget=DatetimeWidget(), ) - security.declareProtected(ModifyPortalContent, 'setFgShowHM') def setFgShowHM(self, value, **kw): """ set show_hm """ - - if type(value) == BooleanType: - self.fgField.widget.show_hm = value + if not type(value) == BooleanType: + value = value == '1' + old_widget = self.fgField.widget + if not value: + # BBB: changing patters options is not working so we re-init the + # inner widget + self.fgField.widget = DateWidget() + self.fgField.widget._properties['pattern_options']['time'] = value + self.fgField.widget.pattern_options['time'] = value else: - self.fgField.widget.show_hm = value == '1' + self.fgField.widget = DatetimeWidget() + try: + del self.fgField.widget.pattern_options['time'] + del self.fgField.widget._properties['pattern_options']['time'] + except KeyError: + pass + + # Copy data from the old widget + self.fgField.__name__ + for attr in ('label', 'description'): + setattr(self.fgField.widget, attr, getattr(old_widget, attr)) + self.fgField.widget.show_hm = value self.fgShowHM = value @@ -571,7 +590,6 @@ def _toLocalizedTime(self, time, long_format=None): tool = getToolByName(self, 'translation_service') return tool.ulocalized_time(time, long_format=long_format) - def htmlValue(self, REQUEST): """ return from REQUEST, this field's value, rendered as XHTML. """ @@ -594,23 +612,16 @@ def htmlValue(self, REQUEST): return cgi.escape(value) - def specialValidator(self, value, field, REQUEST, errors): """ Archetypes isn't validating non-required dates -- so we need to. + BBB: this not seem true anymore on Plone 5 """ - fname = field.getName() - month = REQUEST.form.get('%s_month'%fname, '01') - day = REQUEST.form.get('%s_month'%fname, '01') - - if (month == '00') and (day == '00'): - value = '' - REQUEST.form[fname] = '' - - if value and not field.required: + value = value or REQUEST.form.get(fname) + if value or field.required: try: - dt = DateTime(value) + DateTime(value) except (DateTimeSyntaxError, DateError): return "Validation failed(isValidDate): this is not a valid date." return 0 @@ -768,8 +779,7 @@ def formatVocabDL(self): def htmlValue(self, REQUEST): """ Return value instead of key """ - utils = getToolByName(self, 'plone_utils') - charset = utils.getSiteEncoding() + charset = 'utf-8' value = REQUEST.form.get(self.__name__, '') @@ -780,7 +790,10 @@ def htmlValue(self, REQUEST): vocabulary = self.fgField.Vocabulary(self) v = vocabulary.getValue(vu) or vu - return cgi.escape(v.encode(charset)) + # v might be unicode or string. We need string. + if isinstance(v, unicode): + v = v.encode(charset) + return cgi.escape(v) registerATCT(FGSelectionField, PROJECTNAME) @@ -876,8 +889,7 @@ def formatVocabDL(self): def htmlValue(self, REQUEST): """ Return value instead of key """ - utils = getToolByName(self, 'plone_utils') - charset = utils.getSiteEncoding() + charset = 'utf-8' value = REQUEST.form.get(self.__name__, []) @@ -890,11 +902,14 @@ def htmlValue(self, REQUEST): # so decode the key before lookup ku = k.decode(charset) v = vocabulary.getValue(ku) or ku + # v might be unicode or string. We need string. + if isinstance(v, unicode): + v = v.encode(charset) result.append(v) - value = u', '.join(result) + value = ', '.join(result) - return cgi.escape(value.encode(charset)) + return cgi.escape(value) registerATCT(FGMultiSelectField, PROJECTNAME) @@ -1050,7 +1065,7 @@ def __init__(self, oid, **kwargs): default_content_type = 'text/html', default_output_type = 'text/x-html-safe', allowable_content_types = zconf.ATDocument.allowed_content_types, - widget = RichWidget( + widget = TinyMCEWidget( allow_file_upload = False, ), ) @@ -1104,7 +1119,7 @@ class FGRichLabelField(BaseFormField): default_content_type = 'text/html', default_output_type = 'text/x-html-safe', allowable_content_types = zconf.ATDocument.allowed_content_types, - widget=RichWidget(label=_(u'label_fglabelbody_text', default=u'Label body'), + widget=TinyMCEWidget(label=_(u'label_fglabelbody_text', default=u'Label body'), description=_(u'help_fglabelbody_text', default=u""" The text to display in the form. """), diff --git a/Products/PloneFormGen/content/fieldsBase.py b/Products/PloneFormGen/content/fieldsBase.py index c974763b..863353ce 100644 --- a/Products/PloneFormGen/content/fieldsBase.py +++ b/Products/PloneFormGen/content/fieldsBase.py @@ -39,6 +39,8 @@ from Products.PloneFormGen import PloneFormGenMessageFactory as _ +import field_utils + def finalizeFieldSchema(schema, folderish=True, moveDiscussion=False): """ cleanup typical field schema """ @@ -373,7 +375,7 @@ def finalizeFieldSchema(schema, folderish=True, moveDiscussion=False): default_content_type='text/html', default_output_type='text/x-html-safe', allowable_content_types=zconf.ATDocument.allowed_content_types, - widget=RichWidget(label=_(u'label_fgtextdefault_text', default=u'Default'), + widget=TinyMCEWidget(label=_(u'label_fgtextdefault_text', default=u'Default'), description=_(u'help_fgtextdefault_text', default=u""" The text the field should contain when the form is first displayed. Note that this may be overridden dynamically. @@ -593,8 +595,7 @@ def setTitle(self, value, **kw): if isinstance(value, unicode): uvalue = value else: - utils = getToolByName(self, 'plone_utils') - charset = utils.getSiteEncoding() + charset = 'utf-8' uvalue = unicode(value, charset) self.fgField.widget.label = uvalue @@ -897,16 +898,16 @@ def htmlValue(self, REQUEST): # value may be a string or a unicode string; # it may be an array of string/unicode strings. - # establish a UTF-8 baseline. UTF-8 not because it's right, + # establish a utf-8 baseline. utf-8 not because it's right, # but because it will have backword compatability with previous # versions. if valueType is unicode: - value = value.encode('utf8') + value = value.encode('utf-8') elif valueType is type([]): a = [] for item in value: if type(item) is unicode: - item = item.encode('utf8') + item = item.encode('utf-8') a.append(item) value = a @@ -954,3 +955,7 @@ def manage_afterAdd(self, item, container): id = self.getId() if self.fgField.__name__ != id: self.fgField.__name__ = id + + + def widget(self, field_name, mode="view", field=None, **kwargs): + return field_utils.widget(self, field_name, mode, field, **kwargs) diff --git a/Products/PloneFormGen/content/form.py b/Products/PloneFormGen/content/form.py index 746c1c01..63de779a 100644 --- a/Products/PloneFormGen/content/form.py +++ b/Products/PloneFormGen/content/form.py @@ -42,6 +42,10 @@ from Products.PloneFormGen.content import validationMessages from Products.PloneFormGen import PloneFormGenMessageFactory as _ +from plone.registry.interfaces import IRegistry +from zope.component import getUtility + +import field_utils from types import StringTypes @@ -130,7 +134,7 @@ default_content_type = zconf.ATDocument.default_content_type, default_output_type = 'text/x-html-safe', allowable_content_types = zconf.ATDocument.allowed_content_types, - widget = RichWidget( + widget = TinyMCEWidget( label = _(u'label_prologue_text', default=u"Form Prologue"), description = _(u'help_prologue_text', default=u"This text will be displayed above the form fields."), @@ -149,7 +153,7 @@ default_content_type = zconf.ATDocument.default_content_type, default_output_type = 'text/x-html-safe', allowable_content_types = zconf.ATDocument.allowed_content_types, - widget = RichWidget( + widget = TinyMCEWidget( label = _(u'label_epilogue_text', default=u"Form Epilogue"), description = _(u'help_epilogue_text', default=u"The text will be displayed after the form fields."), @@ -755,10 +759,8 @@ def fgFieldsDisplayList(self, withNone=False, noneValue='', objTypes=None): def thanksPageVocabulary(self): """ returns a DisplayList of contained page-ish documents """ - propsTool = getToolByName(self, 'portal_properties') - siteProperties = getattr(propsTool, 'site_properties') - defaultPageTypes = siteProperties.getProperty('default_page_types') - + registry = getUtility(IRegistry) + defaultPageTypes = registry['plone.default_page_types'] tpages = [('', _(u'vocabulary_none_text', u'None')), ] for obj in self.objectValues(): @@ -770,7 +772,7 @@ def thanksPageVocabulary(self): ### - # A few widgets (TextArea and RichWidget in particular) call the content + # A few widgets (TextArea and TinyMCEWidget in particular) call the content # object rather than the field for this method. IMHO, this is unnecessary, # and should be fixed in the Widget. Meanwhile, this hack ... # @@ -1053,7 +1055,7 @@ def reorderField(self, item_id, target_id, insert_method, **kw): """ move item to target""" plone.protect.CheckAuthenticator(self.REQUEST) - + itemPos = self.getObjectPosition(item_id) targetPos = self.getObjectPosition(target_id) @@ -1112,5 +1114,9 @@ def lastFieldIdFromForm(self, **kw): lastField = myFields[-1].id return lastField + security.declareProtected(View, 'widget') + def widget(self, field_name, mode="view", field=None, **kwargs): + return field_utils.widget(self, field_name, mode, field, **kwargs) + registerATCT(FormFolder, PROJECTNAME) diff --git a/Products/PloneFormGen/content/formMailerAdapter.py b/Products/PloneFormGen/content/formMailerAdapter.py index 4ccf2689..fb997c1a 100644 --- a/Products/PloneFormGen/content/formMailerAdapter.py +++ b/Products/PloneFormGen/content/formMailerAdapter.py @@ -28,6 +28,7 @@ from Products.CMFCore.permissions import View, ModifyPortalContent from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.interfaces import IMailSchema from Products.PloneFormGen.config import * from Products.PloneFormGen.content.actionAdapter import FormActionAdapter, FormAdapterSchema @@ -35,6 +36,8 @@ from Products.TALESField import TALESString from Products.TemplateFields import ZPTField as ZPTField +from plone.registry.interfaces import IRegistry +from zope.component import getUtility from ya_gpg import gpg from email import Encoders @@ -636,8 +639,8 @@ def get_mail_text(self, fields, request, **kwargs): if not isinstance(body, unicode): body = unicode(body, self._site_encoding()) - portal = getToolByName(self, 'portal_url').getPortalObject() - email_charset = portal.getProperty('email_charset', 'utf-8') + registry = getUtility(IRegistry) + email_charset = registry['plone.email_charset'] or 'utf-8' # always use text/plain for encrypted bodies subtype = getattr(self, 'gpg_keyid', False) and 'plain' or self.body_type or 'html' mime_text = MIMEText(body.encode(email_charset, 'replace'), @@ -784,6 +787,8 @@ def get_mail_body(self, fields, **kwargs): security.declarePrivate('secure_header_line') def secure_header_line(self, line): + if line is None: + return '' nlpos = line.find('\x0a') if nlpos >= 0: line = line[:nlpos] @@ -824,11 +829,9 @@ def get_header_body_tuple(self, fields, request, request -- (optional) alternate request object to use """ - pprops = getToolByName(self, 'portal_properties') - site_props = getToolByName(pprops, 'site_properties') - portal = getToolByName(self, 'portal_url').getPortalObject() pms = getToolByName(self, 'portal_membership') - utils = getToolByName(self, 'plone_utils') + registry = getUtility(IRegistry) + mail_settings = registry.forInterface(IMailSchema, prefix='plone') body = self.get_mail_body(fields, **kwargs) @@ -857,8 +860,7 @@ def get_header_body_tuple(self, fields, request, if shasattr(self, 'senderOverride') and self.getRawSenderOverride(): from_addr = self.getSenderOverride().strip() else: - from_addr = from_addr or site_props.getProperty('email_from_address') or \ - portal.getProperty('email_from_address') + from_addr = from_addr or mail_settings.email_from_address # Get To address and full name if shasattr(self, 'recipientOverride') and self.getRawRecipientOverride(): @@ -890,7 +892,8 @@ def get_header_body_tuple(self, fields, request, if userdest is not None: toemail = userdest.getProperty('email', '') if not toemail: - toemail = portal.getProperty('email_from_address') + toemail = mail_settings.email_from_address + assert toemail, """ Unable to mail form input because no recipient address has been specified. Please check the recipient settings of the PloneFormGen "Mailer" within the @@ -908,10 +911,10 @@ def get_header_body_tuple(self, fields, request, headerinfo['Reply-To'] = self.secure_header_line(reply_addr) # transform subject into mail header encoded string - email_charset = portal.getProperty('email_charset', 'utf-8') + email_charset = registry['plone.email_charset'] or 'utf-8' if not isinstance(subject, unicode): - site_charset = utils.getSiteEncoding() + site_charset = 'utf-8' subject = unicode(subject, site_charset, 'replace') msgSubject = self.secure_header_line(subject).encode(email_charset, 'replace') @@ -948,8 +951,7 @@ def send_form(self, fields, request, **kwargs): # translation and encodings def _site_encoding(self): - site_props = self.portal_properties.site_properties - return site_props.default_charset or 'UTF-8' + return 'utf-8' security.declareProtected(View, 'allFieldDisplayList') diff --git a/Products/PloneFormGen/content/saveDataAdapter.py b/Products/PloneFormGen/content/saveDataAdapter.py index 65ad1632..e771a226 100644 --- a/Products/PloneFormGen/content/saveDataAdapter.py +++ b/Products/PloneFormGen/content/saveDataAdapter.py @@ -3,6 +3,14 @@ __author__ = 'Steve McMahon ' __docformat__ = 'plaintext' +try: + import xlwt + has_xls = True +except ImportError: + has_xls = False + +from urlparse import urlparse + from AccessControl import ClassSecurityInfo from BTrees.IOBTree import IOBTree @@ -373,8 +381,10 @@ def getColumnNames(self, excludeServerSide=True): def getColumnTitles(self, excludeServerSide=True): # """Returns a list of column titles""" + showFields = getattr(self, 'showFields', []) names = [field.widget.label for field - in self.fgFields(displayOnly=True, excludeServerSide=excludeServerSide)] + in self.fgFields(displayOnly=True, excludeServerSide=excludeServerSide) + if not showFields or field.getName() in showFields] for f in self.ExtraData: names.append(self.vocabExtraDataDL().getValue(f, '')) @@ -434,6 +444,49 @@ def download_csv(self, REQUEST=None, RESPONSE=None): return '%s%s' % (res, self.getSavedFormInputForEdit()) + security.declareProtected(DOWNLOAD_SAVED_PERMISSION, 'download_xls') + def download_xls(self, REQUEST=None, RESPONSE=None): + # """Download the saved data + # """ + filename = self.id + if filename.find('.') < 0: + filename = '%s.xls' % filename + header_value = contentDispositionHeader('attachment', self.getCharset(), filename=filename) + RESPONSE.setHeader("Content-Disposition", header_value) + RESPONSE.setHeader("Content-Type", 'application/vnd.ms-excel') + + xldoc = xlwt.Workbook(encoding=self.getCharset()) + sheet = xldoc.add_sheet(self.Title()) + + row_num = 0 + + if getattr(self, 'UseColumnNames', False): + col_names = self.getColumnNames(excludeServerSide=False) + for idx, label in enumerate(col_names): + sheet.write(0, idx, label.encode(self.getCharset())) + row_num += 1 + + for row in self.getSavedFormInput(): + for col_num, col in enumerate(row): + if type(col) is unicode: + col = col.encode(self.getCharset()) + + if urlparse(col).scheme in ('http', 'https'): + col = xlwt.Formula('HYPERLINK("%(url)s")' % dict(url=col)) + else: + for format in (int, float): + try: + col = format(col) + break + except ValueError: + pass + + sheet.write(row_num, col_num, col) + row_num += 1 + + string_buffer = StringIO() + xldoc.save(string_buffer) + return string_buffer.getvalue() security.declareProtected(DOWNLOAD_SAVED_PERMISSION, 'download') def download(self, REQUEST=None, RESPONSE=None): @@ -443,6 +496,9 @@ def download(self, REQUEST=None, RESPONSE=None): format = getattr(self, 'DownloadFormat', 'tsv') if format == 'tsv': return self.download_tsv(REQUEST, RESPONSE) + if format == 'xls': + assert has_xls, 'xls download not available' + return self.download_xls(REQUEST, RESPONSE) else: assert format == 'csv', 'Unknown download format' return self.download_csv(REQUEST, RESPONSE) @@ -490,6 +546,8 @@ def formatMIME(self): format = getattr(self, 'DownloadFormat', 'tsv') if format == 'tsv': return 'text/tab-separated-values' + if format == 'xls': + return 'application/vnd.ms-excel' else: assert format == 'csv', 'Unknown download format' return 'text/comma-separated-values' @@ -530,19 +588,27 @@ def vocabExtraDataDL(self): def vocabFormatDL(self): # """ returns vocabulary for format """ - - return DisplayList(( - ('tsv', - self.translate(msgid='vocabulary_tsv_text', - domain='ploneformgen', - default='Tab-Separated Values') - ), - ('csv', - self.translate(msgid='vocabulary_csv_text', + formats = [ + ('tsv', + self.translate(msgid='vocabulary_tsv_text', + domain='ploneformgen', + default='Tab-Separated Values') + ), + ('csv', + self.translate(msgid='vocabulary_csv_text', + domain='ploneformgen', + default='Comma-Separated Values') + ), + ] + if has_xls: + formats.append( + ('xls', + self.translate(msgid='vocabulary_xls_doc', domain='ploneformgen', - default='Comma-Separated Values') + default='Excel document') ), - )) + ) + return DisplayList(formats) diff --git a/Products/PloneFormGen/content/thanksPage.py b/Products/PloneFormGen/content/thanksPage.py index 74d5ea87..3a5808a1 100644 --- a/Products/PloneFormGen/content/thanksPage.py +++ b/Products/PloneFormGen/content/thanksPage.py @@ -78,7 +78,7 @@ default_content_type=zconf.ATDocument.default_content_type, default_output_type='text/x-html-safe', allowable_content_types=zconf.ATDocument.allowed_content_types, - widget=RichWidget( + widget=TinyMCEWidget( label=_(u"label_thanksprologue_text", default=u"Thanks Prologue"), description=_(u"help_thanksprologue_text", default=u"This text will be displayed above the selected field inputs."), rows=8, @@ -95,7 +95,7 @@ default_content_type=zconf.ATDocument.default_content_type, default_output_type='text/x-html-safe', allowable_content_types=zconf.ATDocument.allowed_content_types, - widget=RichWidget( + widget=TinyMCEWidget( label=_(u"label_thanksepilogue_text", default=u"Thanks Epilogue"), description=_(u"help_thanksepilogue_text", default=u"The text will be displayed after the field inputs."), rows=8, @@ -114,7 +114,7 @@

No input was received. Please visit the form.

""", allowable_content_types=zconf.ATDocument.allowed_content_types, - widget=RichWidget( + widget=TinyMCEWidget( label=_(u"label_nosubmit_text", default=u"No Submit Message"), description=_(u"help_nosubmit_text", default=u""" The text to display if the browser reaches this diff --git a/Products/PloneFormGen/content/ya_gpg.py b/Products/PloneFormGen/content/ya_gpg.py index f13158a4..e3e964f7 100644 --- a/Products/PloneFormGen/content/ya_gpg.py +++ b/Products/PloneFormGen/content/ya_gpg.py @@ -94,7 +94,7 @@ def encrypt(self, data, recipient_key_id): PIPE = subprocess.PIPE cmd = '%s --batch --yes --trust-model always --no-secmem-warning --encrypt -a -r %s' % (self.gpg_binary, recipient_key_id) if isinstance(cmd, unicode): - cmd = cmd.encode('utf8') + cmd = cmd.encode('utf-8') cmd = shlex.split(cmd) p = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False) diff --git a/Products/PloneFormGen/events.py b/Products/PloneFormGen/events.py index a3ecad91..24096106 100644 --- a/Products/PloneFormGen/events.py +++ b/Products/PloneFormGen/events.py @@ -1,4 +1,4 @@ -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- from Acquisition import aq_parent, aq_inner from Products.PloneFormGen import interfaces from zope.component import adapter diff --git a/Products/PloneFormGen/profiles/default/metadata.xml b/Products/PloneFormGen/profiles/default/metadata.xml index ff0104be..b4adbdb3 100644 --- a/Products/PloneFormGen/profiles/default/metadata.xml +++ b/Products/PloneFormGen/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 171 + 180 profile-Products.ATContentTypes:base