Skip to content

Commit

Permalink
Merge branch 'master' into dxcontainer-siteroot
Browse files Browse the repository at this point in the history
  • Loading branch information
jaroel committed Jun 22, 2018
2 parents c905972 + c5ecfaf commit 512acec
Show file tree
Hide file tree
Showing 32 changed files with 488 additions and 206 deletions.
80 changes: 78 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Changelog
=========

1.4.7 (unreleased)
------------------
1.4.12 (unreleased)
-------------------

Breaking changes:

Expand All @@ -17,6 +17,82 @@ Bug fixes:
- *add item here*


1.4.11 (2018-06-18)
-------------------

Bug fixes:

- Fix SearchableText in Python 3
[pbauer]

- Skip migration tests if ATContentTypes is not installed.
[davisagli]


1.4.10 (2018-04-03)
-------------------

New features:

- Set the ``plone.app.contenttypes_migration_running`` key while running a migration.
Other addons can check for that and handle accordingly.
[thet]

Bug fixes:

- Implement better human readable file size logic.
[hvelarde]

- Do not encode query strings on internal link redirections;
fixes `issue 457 <https://github.com/plone/plone.app.contenttypes/issues/457>`_.
[hvelarde]

- Migrations:
- Handle ignore catalog errors where a brain can't find it's object.
- Try to delete the layout attribute before setting the layout.
Rework parts where the layout is set by always setting the layout.
[thet]

- In folder listings, when a content object has no title show it's id instead of an empty title.
[thet]

- Fix upgrades steps when the catalog is inconsistent
[ale-rt]


1.4.9 (2018-02-11)
------------------

New features:

- Members folder made permanently private. Fixes https://github.com/plone/Products.CMFPlone/issues/2259
[mrsaicharan1]


1.4.8 (2018-02-05)
------------------

Bug fixes:

- Do not use ``portal_quickinstaller`` in the migration form.
Use ``get_installer`` to check if ``plone.app.contenttypes`` is
installed or installable. Use ``portal_setup`` directly for
blacklisting the ``type_info`` step when installing our profile.
[maurits]

- Add Python 2 / 3 compatibility
[pbauer]


1.4.7 (2017-12-14)
------------------

Bug fixes:

- Rename post_handlers. Fixes https://github.com/plone/Products.CMFPlone/issues/2238
[pbauer]


1.4.6 (2017-11-26)
------------------

Expand Down
2 changes: 1 addition & 1 deletion plone/app/contenttypes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from zope.i18nmessageid import MessageFactory

import permissions # noqa
from . import permissions


permissions # pyflakes
Expand Down
4 changes: 4 additions & 0 deletions plone/app/contenttypes/browser/file.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from plone.app.contenttypes.browser.utils import Utils
from plone.app.contenttypes.utils import human_readable_size


class FileView(Utils):
Expand All @@ -14,3 +15,6 @@ def is_audiotype(self):

def get_mimetype_icon(self):
return super(FileView, self).getMimeTypeIcon(self.context.file)

def human_readable_size(self):
return human_readable_size(self.context.file.getSize())
4 changes: 2 additions & 2 deletions plone/app/contenttypes/browser/link_redirect_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def absolute_target_url(self):
url
])
else:
if not (url.startswith('http://') or url.startswith('https://')):
url = self.request.physicalPathToURL(url)
if not url.startswith(('http://', 'https://')):
url = self.request['SERVER_URL'] + url

return url
5 changes: 1 addition & 4 deletions plone/app/contenttypes/browser/templates/file.pt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
alt content_type;" border="0" />
<tal:name tal:content="context/file/filename" >Filename</tal:name>
</a>
<span class="discreet"
tal:define="size context/file/getSize;
kb python:size/1024">
&mdash; <span tal:replace="kb" /> KB</span>
<span class="discreet">&mdash; <span tal:replace="view/human_readable_size" /></span>
</p>

<video tal:condition="view/is_videotype" controls="controls">
Expand Down
1 change: 1 addition & 0 deletions plone/app/contenttypes/browser/templates/listing.pt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
item_url item/getURL;
item_id item/getId;
item_title item/Title;
item_title python:item_title or item_id;
item_description item/Description;
item_type item/PortalType;
item_modified item/ModificationDate;
Expand Down
2 changes: 2 additions & 0 deletions plone/app/contenttypes/browser/templates/listing_tabular.pt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
image_scale portal/@@image_scale">
<tal:entries tal:repeat="item batch">
<tal:block tal:define="item_url item/getURL;
item_id item/getId;
item_title item/Title;
item_title python:item_title or item_id;
item_description item/Description;
item_type item/PortalType;
item_type_class python:'contenttype-' + view.normalizeString(item_type) if showicons else '';
Expand Down
7 changes: 5 additions & 2 deletions plone/app/contenttypes/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
from zope.lifecycleevent import modified


import six


@implementer(ICollection)
class Collection(Item):
"""Convenience subclass for ``Collection`` portal type
Expand Down Expand Up @@ -91,7 +94,7 @@ def PUT(self, REQUEST=None, RESPONSE=None):
infile = request.get('BODYFILE', None)
filename = request['PATH_INFO'].split('/')[-1]
self.file = NamedBlobFile(
data=infile.read(), filename=unicode(filename))
data=infile.read(), filename=six.text_type(filename))

modified(self)
return response
Expand Down Expand Up @@ -125,7 +128,7 @@ def PUT(self, REQUEST=None, RESPONSE=None):
infile = request.get('BODYFILE', None)
filename = request['PATH_INFO'].split('/')[-1]
self.image = NamedBlobImage(
data=infile.read(), filename=unicode(filename))
data=infile.read(), filename=six.text_type(filename))

modified(self)
return response
Expand Down
23 changes: 17 additions & 6 deletions plone/app/contenttypes/indexers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
from ZODB.POSException import ConflictError


import six


logger = getLogger(__name__)

FALLBACK_CONTENTTYPE = 'application/octet-stream'
Expand All @@ -28,13 +31,18 @@
def _unicode_save_string_concat(*args):
"""
concats args with spaces between and returns utf-8 string, it does not
matter if input was unicode or str
matter if input was text or bytes
"""
result = ''
for value in args:
if isinstance(value, unicode):
value = value.encode('utf-8', 'replace')
if value:
if six.PY2:
if isinstance(value, six.text_type):
value = value.encode('utf-8', 'replace')
if value:
result = ' '.join((result, value))
else:
if isinstance(value, six.binary_type):
value = safe_unicode(value)
result = ' '.join((result, value))
return result

Expand All @@ -49,9 +57,12 @@ def SearchableText(obj):
# Before you think about switching raw/output
# or mimeType/outputMimeType, first read
# https://github.com/plone/Products.CMFPlone/issues/2066
raw = safe_unicode(textvalue.raw)
if six.PY2:
raw = raw.encode('utf-8', 'replace')
text = transforms.convertTo(
'text/plain',
safe_unicode(textvalue.raw).encode('utf-8'),
raw,
mimetype=textvalue.mimeType,
).getData().strip()

Expand Down Expand Up @@ -116,7 +127,7 @@ def SearchableText_file(obj):
return SearchableText(obj)
except (ConflictError, KeyboardInterrupt):
raise
except Exception, msg:
except Exception as msg:
logger.exception(
'exception while trying to convert blob contents to "text/plain" '
'for {0}. Error: {1}'.format(obj, str(msg)),
Expand Down
47 changes: 28 additions & 19 deletions plone/app/contenttypes/migration/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
from plone.app.contenttypes.content import NewsItem
from plone.app.contenttypes.migration import dxmigration
from plone.app.contenttypes.migration import migration
from plone.app.contenttypes.migration.patches import patch_before_migration
from plone.app.contenttypes.migration.patches import undo_patch_after_migration
from plone.app.contenttypes.migration.utils import installTypeIfNeeded
from plone.app.contenttypes.migration.utils import isSchemaExtended
from plone.app.contenttypes.migration.utils import restore_references
from plone.app.contenttypes.migration.utils import store_references
from plone.app.contenttypes.migration.vocabularies import ATCT_LIST
from plone.app.contenttypes.migration.patches import patch_before_migration
from plone.app.contenttypes.migration.patches import undo_patch_after_migration
from plone.app.contenttypes.upgrades import use_new_view_names
from plone.app.contenttypes.utils import DEFAULT_TYPES
from plone.browserlayer.interfaces import ILocalBrowserLayerType
Expand All @@ -25,6 +25,7 @@
from pprint import pformat
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory as _
from Products.CMFPlone.utils import get_installer
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.statusmessages.interfaces import IStatusMessage
Expand All @@ -33,6 +34,7 @@
from z3c.form import form
from z3c.form.browser.checkbox import CheckBoxFieldWidget
from z3c.form.interfaces import HIDDEN_MODE
from zExceptions import NotFound
from zope import schema
from zope.component import getMultiAdapter
from zope.component import queryUtility
Expand Down Expand Up @@ -79,7 +81,11 @@ def __call__(self):
query['portal_type'] = portal_type
results = catalog(query)
for brain in results:
obj = brain.getObject()
try:
obj = brain.getObject()
except (KeyError, NotFound):
logger.exception('Can not resolve object from brain.')
continue
if IDexterityContent.providedBy(obj):
object_class_name = obj.__class__.__name__
target_class_name = portal_type_class.__name__
Expand Down Expand Up @@ -136,6 +142,8 @@ def __call__(self,
stats_before = self.stats()
starttime = datetime.now()

self.request['plone.app.contenttypes_migration_running'] = True

msg = 'Starting Migration\n\n'
msg += '\n-----------------------------\n'
msg += 'Content statictics:\n'
Expand Down Expand Up @@ -259,7 +267,10 @@ def stats(self):
results = {}
catalog = self.context.portal_catalog
for brain in catalog():
classname = brain.getObject().__class__.__name__
try:
classname = brain.getObject().__class__.__name__
except (KeyError, NotFound):
continue
results[classname] = results.get(classname, 0) + 1
return results

Expand Down Expand Up @@ -428,7 +439,10 @@ def handle_migrate(self, action):
migrated = []
not_migrated = []
for brain in catalog():
obj = brain.getObject()
try:
obj = brain.getObject()
except (KeyError, NotFound):
continue
old_class_name = dxmigration.get_old_class_name_string(obj)
if old_class_name in changed_base_classes:
if dxmigration.migrate_base_class_to_new_class(
Expand Down Expand Up @@ -574,31 +588,26 @@ class PACInstaller(form.Form):

@property
def pac_installable(self):
qi = getToolByName(self.context, 'portal_quickinstaller')
pac_installed = qi.isProductInstalled('plone.app.contenttypes')
pac_installable = qi.isProductInstallable('plone.app.contenttypes')
qi = get_installer(self.context)
pac_installed = qi.is_product_installed('plone.app.contenttypes')
pac_installable = qi.is_product_installable('plone.app.contenttypes')
return pac_installable and not pac_installed

@property
def pac_installed(self):
qi = getToolByName(self.context, 'portal_quickinstaller')
return qi.isProductInstalled('plone.app.contenttypes')
qi = get_installer(self.context)
return qi.is_product_installed('plone.app.contenttypes')

@button.buttonAndHandler(_(u'Install'), name='install')
def handle_install(self, action):
""" install p.a.c
"""
url = self.context.absolute_url()
qi = getToolByName(self.context, 'portal_quickinstaller')
fail = qi.installProduct(
'plone.app.contenttypes',
profile='plone.app.contenttypes:default',
blacklistedSteps=['typeinfo'],
portal_setup = getToolByName(self.context, 'portal_setup')
portal_setup.runAllImportStepsFromProfile(
'profile-plone.app.contenttypes:default',
blacklisted_steps=['typeinfo'],
)
if fail:
messages = IStatusMessage(self.request)
messages.addStatusMessage(fail, type='error')
self.request.response.redirect(url)

# For types without any instances we want to instantly
# replace the AT-FTI's with DX-FTI's.
Expand Down
Loading

0 comments on commit 512acec

Please sign in to comment.