diff --git a/news/3953.breaking b/news/3953.breaking new file mode 100644 index 000000000..d5550759a --- /dev/null +++ b/news/3953.breaking @@ -0,0 +1,2 @@ +Move plone.app.contenttypes views to plone.app.layout +[frapell] diff --git a/setup.py b/setup.py index 266249480..72fbb4e36 100644 --- a/setup.py +++ b/setup.py @@ -56,7 +56,6 @@ "Products.MimetypesRegistry", "Products.PortalTransforms", "Products.statusmessages", - "plone.app.layout", "plone.app.textfield", "plone.app.uuid", "plone.autoform", diff --git a/src/plone/app/contenttypes/browser/collection.py b/src/plone/app/contenttypes/browser/collection.py index c4f2a4e37..9ac366118 100644 --- a/src/plone/app/contenttypes/browser/collection.py +++ b/src/plone/app/contenttypes/browser/collection.py @@ -1,85 +1,9 @@ -from Acquisition import aq_inner -from plone.app.contenttypes import _ -from plone.app.contenttypes.behaviors.collection import ICollection -from plone.app.contenttypes.behaviors.leadimage import ILeadImage -from plone.app.contenttypes.browser.folder import FolderView -from plone.app.contenttypes.interfaces import IFolder -from plone.app.contenttypes.interfaces import IImage -from plone.memoize.view import memoize +import zope.deferredimport -class CollectionView(FolderView): - @property - def collection_behavior(self): - return ICollection(aq_inner(self.context)) +zope.deferredimport.initialize() - @property - def b_size(self): - return getattr(self, "_b_size", self.collection_behavior.item_count) - - def results(self, **kwargs): - """Return a content listing based result set with results from the - collection query. - - :param **kwargs: Any keyword argument, which can be used for catalog - queries. - :type **kwargs: keyword argument - - :returns: plone.app.contentlisting based result set. - :rtype: ``plone.app.contentlisting.interfaces.IContentListing`` based - sequence. - """ - # Extra filter - contentFilter = dict(self.request.get("contentFilter", {})) - contentFilter.update(kwargs.get("contentFilter", {})) - kwargs.setdefault("custom_query", contentFilter) - kwargs.setdefault("batch", True) - kwargs.setdefault("b_size", self.b_size) - kwargs.setdefault("b_start", self.b_start) - - results = self.collection_behavior.results(**kwargs) - return results - - def batch(self): - # collection is already batched. - return self.results() - - @property - @memoize - def _album_results(self): - """Get results to display an album with subalbums.""" - results = self.results() - images = [] - folders = [] - for it in results: - # TODO: potentially expensive! - ob = it.getObject() - if IFolder.providedBy(ob): - folders.append(it) - elif IImage.providedBy(ob) or ILeadImage.providedBy(ob): - images.append(it) - return {"images": images, "folders": folders} - - @property - def album_images(self): - """Get all images within this collection.""" - return self._album_results["images"] - - @property - def album_folders(self): - """Get all folders within this collection.""" - return self._album_results["folders"] - - def tabular_fields(self): - """Return a list of all metadata fields from the catalog that were - selected. - """ - context = aq_inner(self.context) - wrapped = ICollection(context) - fields = wrapped.selectedViewFields() - fields = [field[0] for field in fields] - return fields - - @property - def no_items_message(self): - return _("description_no_results_found", default="No results were found.") +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.collection import CollectionView instead.", + CollectionView="plone.app.layout.contenttypes.collection:CollectionView", +) diff --git a/src/plone/app/contenttypes/browser/configure.zcml b/src/plone/app/contenttypes/browser/configure.zcml index b3e2c7ba3..1e3c16314 100644 --- a/src/plone/app/contenttypes/browser/configure.zcml +++ b/src/plone/app/contenttypes/browser/configure.zcml @@ -8,7 +8,14 @@ + + + + + + + diff --git a/src/plone/app/contenttypes/browser/file.py b/src/plone/app/contenttypes/browser/file.py index 0a5ffa7c1..681886f68 100644 --- a/src/plone/app/contenttypes/browser/file.py +++ b/src/plone/app/contenttypes/browser/file.py @@ -1,33 +1,9 @@ -from plone.app.contenttypes.browser.utils import Utils -from plone.base.utils import human_readable_size +import zope.deferredimport -import re +zope.deferredimport.initialize() -class FileView(Utils): - def is_videotype(self): - ct = self.context.file.contentType - return "video/" in ct - - def is_audiotype(self): - ct = self.context.file.contentType - return "audio/" in ct - - def human_readable_size(self): - return human_readable_size(self.context.file.getSize()) - - def icon(self): - if "text" in self.context.file.contentType: - return "contenttype-text" - if "html" in self.context.file.contentType: - return "contenttype-text" - if re.search(r"(archive|zip|compressed)", self.context.file.contentType): - return "contenttype-archive" - if "audio" in self.context.file.contentType: - return "contenttype-audio" - if "video" in self.context.file.contentType: - return "contenttype-video" - if "pdf" in self.context.file.contentType: - return "contenttype-pdf" - else: - return "contenttype-file" +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.file import FileView instead.", + FileView="plone.app.layout.contenttypes.file:FileView", +) diff --git a/src/plone/app/contenttypes/browser/folder.py b/src/plone/app/contenttypes/browser/folder.py index 9bdac03b4..b62ba29d6 100644 --- a/src/plone/app/contenttypes/browser/folder.py +++ b/src/plone/app/contenttypes/browser/folder.py @@ -1,278 +1,9 @@ -from Acquisition import aq_base -from Acquisition import aq_inner -from plone.app.contenttypes import _ -from plone.app.contenttypes.behaviors.leadimage import ILeadImage -from plone.app.contenttypes.interfaces import IFolder -from plone.app.contenttypes.interfaces import IImage -from plone.app.vocabularies.metadatafields import get_field_label -from plone.base.batch import Batch -from plone.base.interfaces import ISecuritySchema -from plone.base.interfaces import ISiteSchema -from plone.base.utils import safe_callable -from plone.event.interfaces import IEvent -from plone.memoize.view import memoize -from plone.registry.interfaces import IRegistry -from Products.Five import BrowserView -from zope.component import getMultiAdapter -from zope.component import getUtility -from zope.contentprovider.interfaces import IContentProvider +import zope.deferredimport -import random +zope.deferredimport.initialize() -class FolderView(BrowserView): - text_class = None - _plone_view = None - _portal_state = None - _pas_member = None - - @property - def plone_view(self): - if not self._plone_view: - self._plone_view = getMultiAdapter( - (self.context, self.request), name="plone" - ) - return self._plone_view - - @property - def portal_state(self): - if not self._portal_state: - self._portal_state = getMultiAdapter( - (self.context, self.request), name="plone_portal_state" - ) - return self._portal_state - - @property - def pas_member(self): - if not self._pas_member: - self._pas_member = getMultiAdapter( - (self.context, self.request), name="pas_member" - ) - return self._pas_member - - @property - def b_size(self): - b_size = ( - getattr(self.request, "b_size", None) - or getattr(self.request, "limit_display", None) - or 20 - ) - return int(b_size) - - @property - def b_start(self): - b_start = getattr(self.request, "b_start", None) or 0 - return int(b_start) - - def results(self, **kwargs): - """Return a content listing based result set with contents of the - folder. - - :param **kwargs: Any keyword argument, which can be used for catalog - queries. - :type **kwargs: keyword argument - - :returns: plone.app.contentlisting based result set. - :rtype: ``plone.app.contentlisting.interfaces.IContentListing`` based - sequence. - """ - # Extra filter - kwargs.update(self.request.get("contentFilter", {})) - if "object_provides" not in kwargs: # object_provides is more specific - kwargs.setdefault("portal_type", self.friendly_types) - kwargs.setdefault("batch", True) - kwargs.setdefault("b_size", self.b_size) - kwargs.setdefault("b_start", self.b_start) - kwargs.setdefault("orphan", 1) - - listing = aq_inner(self.context).restrictedTraverse("@@folderListing", None) - if listing is None: - return [] - results = listing(**kwargs) - return results - - def batch(self): - batch = Batch(self.results(), size=self.b_size, start=self.b_start, orphan=1) - return batch - - def normalizeString(self, text): - return self.plone_view.normalizeString(text) - - def toLocalizedTime(self, time, long_format=None, time_only=None): - return self.plone_view.toLocalizedTime(time, long_format, time_only) - - @property - def friendly_types(self): - return self.portal_state.friendly_types() - - @property - def isAnon(self): - return self.portal_state.anonymous() - - @property - def navigation_root_url(self): - return self.portal_state.navigation_root_url() - - @property - def use_view_action(self): - registry = getUtility(IRegistry) - return registry.get("plone.types_use_view_action_in_listings", []) - - @property - def show_about(self): - registry = getUtility(IRegistry) - settings = registry.forInterface(ISecuritySchema, prefix="plone") - show_about = getattr(settings, "allow_anon_views_about", False) - return show_about or not self.isAnon - - @property - def text(self): - textfield = getattr(aq_base(self.context), "text", None) - text = ( - textfield.output_relative_to(self.context) - if getattr(textfield, "output_relative_to", None) - else None - ) - if text: - self.text_class = ( - "stx" - if textfield.mimeType - in ("text/structured", "text/x-rst", "text/restructured") - else "plain" - ) - return text - - @property - def tabular_fields(self): - ret = [] - ret.append("Title") - if self.show_about: - ret.append("Creator") - ret.append("Type") - if self.show_about: - ret.append("ModificationDate") - return ret - - def tabular_field_label(self, field): - """Return the internationalized label (Message object) corresponding - to the field. - """ - return get_field_label(field) - - def tabular_fielddata(self, item, fieldname): - value = getattr(item, fieldname, "") - if safe_callable(value): - value = value() - if fieldname in [ - "CreationDate", - "ModificationDate", - "Date", - "EffectiveDate", - "ExpirationDate", - "effective", - "expires", - "start", - "end", - "created", - "modified", - "last_comment_date", - ]: - value = self.toLocalizedTime(value, long_format=1) - - return { - # 'title': _(fieldname, default=fieldname), - "value": value - } - - def is_event(self, obj): - if getattr(obj, "getObject", False): - obj = obj.getObject() - return IEvent.providedBy(obj) - - def formatted_date(self, item): - provider = getMultiAdapter( - (self.context, self.request, self), IContentProvider, name="formatted_date" - ) - return provider(item) - - @property - @memoize - def album_images(self): - """Get all images within this folder.""" - provides = [ - IImage.__identifier__, - ILeadImage.__identifier__, - ] - images = self.results(batch=False, object_provides=provides) - return images - - @property - @memoize - def album_folders(self): - """Get all folders within this folder.""" - images = self.results(batch=False, object_provides=IFolder.__identifier__) - return images - - @property - def album_random_image(self): - """Get random image from this folder.""" - img = None - images = self.album_images - if images: - img = random.choice(images) - return img - - @property - def album_number_images(self): - """Get number of images from this folder.""" - images = self.album_images - return len(images) - - @property - def no_items_message(self): - return _( - "description_no_items_in_folder", - default="There are currently no items in this folder.", - ) - - @memoize - def get_thumb_scale_table(self): - if getattr(self.context, "suppress_thumbs", False): - return None - thsize = getattr(self.context, "thumb_scale_table", None) - if thsize: - return thsize - registry = getUtility(IRegistry) - settings = registry.forInterface(ISiteSchema, prefix="plone", check=False) - if settings.no_thumbs_tables: - return None - return settings.thumb_scale_table - - @memoize - def get_thumb_scale_list(self): - if getattr(self.context, "suppress_thumbs", False): - return None - thsize = getattr(self.context, "thumb_scale_list", None) - if thsize: - return thsize - registry = getUtility(IRegistry) - settings = registry.forInterface(ISiteSchema, prefix="plone", check=False) - if settings.no_thumbs_lists: - return None - return settings.thumb_scale_listing - - @memoize - def get_thumb_scale_summary(self): - if getattr(self.context, "suppress_thumbs", False): - return None - thsize = getattr(self.context, "thumb_scale_summary", None) - if thsize: - return thsize - registry = getUtility(IRegistry) - settings = registry.forInterface(ISiteSchema, prefix="plone", check=False) - if settings.no_thumbs_summary: - return None - return settings.thumb_scale_summary - - def show_icons(self): - return not getattr(self.context, "suppress_icons", False) +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.folder import FolderView instead.", + FolderView="plone.app.layout.contenttypes.folder:FolderView", +) diff --git a/src/plone/app/contenttypes/browser/full_view.py b/src/plone/app/contenttypes/browser/full_view.py index f2fc191f1..8a39b23a7 100644 --- a/src/plone/app/contenttypes/browser/full_view.py +++ b/src/plone/app/contenttypes/browser/full_view.py @@ -1,30 +1,9 @@ -from plone.registry.interfaces import IRegistry -from Products.Five.browser import BrowserView -from zope.component import getUtility -from zope.publisher.interfaces.browser import IBrowserView +import zope.deferredimport -class FullViewItem(BrowserView): - @property - def default_view(self): - item_layout = self.context.getLayout() - default_view = self.context.restrictedTraverse(item_layout) - return default_view +zope.deferredimport.initialize() - @property - def item_macros(self): - default_view = self.default_view - if IBrowserView.providedBy(default_view): - # IBrowserView - return default_view.index.macros - # FSPageTemplate - return default_view.macros - - @property - def item_url(self): - registry = getUtility(IRegistry) - use_view_action = registry.get("plone.types_use_view_action_in_listings", []) - url = self.context.absolute_url() - if self.context.portal_type in use_view_action: - url = f"{url}/view" - return url +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.full_view import FullViewItem instead.", + FullViewItem="plone.app.layout.contenttypes.full_view:FullViewItem", +) diff --git a/src/plone/app/contenttypes/browser/images/icon_export_ical.png b/src/plone/app/contenttypes/browser/images/icon_export_ical.png deleted file mode 100644 index df034b203..000000000 Binary files a/src/plone/app/contenttypes/browser/images/icon_export_ical.png and /dev/null differ diff --git a/src/plone/app/contenttypes/browser/images/icon_export_vcal.png b/src/plone/app/contenttypes/browser/images/icon_export_vcal.png deleted file mode 100644 index d91f94b92..000000000 Binary files a/src/plone/app/contenttypes/browser/images/icon_export_vcal.png and /dev/null differ diff --git a/src/plone/app/contenttypes/browser/link_redirect_view.py b/src/plone/app/contenttypes/browser/link_redirect_view.py index 1ebc0ea88..fa637dbc6 100644 --- a/src/plone/app/contenttypes/browser/link_redirect_view.py +++ b/src/plone/app/contenttypes/browser/link_redirect_view.py @@ -1,163 +1,13 @@ -from plone.app.contenttypes.utils import replace_link_variables_by_paths -from plone.app.uuid.utils import uuidToObject -from plone.base.interfaces import ITypesSchema -from plone.registry.interfaces import IRegistry -from Products.CMFCore.utils import getToolByName -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from urllib.parse import urlparse -from zope.component import getUtility +import zope.deferredimport -# links starting with these URL scheme should not be redirected to -NON_REDIRECTABLE_URL_SCHEMES = [ - "mailto:", - "tel:", - "callto:", # nonstandard according to RFC 3966. used for skype. - "webdav:", - "caldav:", -] -# links starting with these URL scheme should not be resolved to paths -NON_RESOLVABLE_URL_SCHEMES = NON_REDIRECTABLE_URL_SCHEMES + [ - "file:", - "ftp:", -] +zope.deferredimport.initialize() - -def normalize_uid_from_path(url=None): - """ - Args: - url (string): a path or orl - - Returns: - tuple: tuple of (uid, fragment) a fragment is an anchor id e.g. #head1 - """ - uid = None - fragment = None - - if not url: - return uid, fragment - - # resolve uid - paths = url.split("/") - paths_lower = [_item.lower() for _item in paths] - - if "resolveuid" in paths_lower: - ri = paths_lower.index("resolveuid") - if ri + 1 != len(paths): - uid = paths[ri + 1] - if uid == "": - uid = None - - if not uid: - return uid, fragment - - # resolve fragment - parts = urlparse(uid) - - uid = parts.path - - fragment = f"#{parts.fragment}" if parts.fragment else None - - return uid, fragment - - -class LinkRedirectView(BrowserView): - index = ViewPageTemplateFile("templates/link.pt") - - def _url_uses_scheme(self, schemes, url=None): - url = url or self.context.remoteUrl.strip() - for scheme in schemes: - if url.startswith(scheme): - return True - return False - - @property - def can_edit(self): - context = self.context - mtool = getToolByName(context, "portal_membership") - return mtool.checkPermission("Modify portal content", context) - - def __call__(self): - """Redirect to the Link target URL, if and only if: - - redirect_links property is enabled in - configuration registry - - the link is of a redirectable type (no mailto:, etc) - - AND current user doesn't have permission to edit the Link""" - - registry = getUtility(IRegistry) - settings = registry.forInterface(ITypesSchema, prefix="plone") - redirect_links = settings.redirect_links - - redirect_links = redirect_links and not self._url_uses_scheme( - NON_REDIRECTABLE_URL_SCHEMES - ) - - if redirect_links and not self.can_edit: - return self.request.RESPONSE.redirect(self.absolute_target_url()) - return self.index() - - def url(self): - """Returns the url with link variables replaced.""" - url = replace_link_variables_by_paths( - self.context, self.context.remoteUrl.strip() - ) - return url - - def display_link(self): - """Format the url for display""" - - url = self.url() - if "resolveuid" in url: - uid = url.split("/")[-1] - obj = uuidToObject(uid) - if obj: - title = obj.Title() - meta = obj.absolute_url_path() - return { - "title": title, - "meta": meta, - } - - parsed = urlparse(url) - if parsed.scheme == "mailto": - return { - "title": parsed.path, - "meta": "", - } - - return { - "title": url, - "meta": "", - } - - def absolute_target_url(self): - """Compute the absolute target URL.""" - url = self.url() - - if self._url_uses_scheme(NON_RESOLVABLE_URL_SCHEMES): - # For non http/https url schemes, there is no path to resolve. - return url - - if url.startswith("."): - # we just need to adapt ../relative/links, /absolute/ones work - # anyway -> this requires relative links to start with ./ or - # ../ - context_state = self.context.restrictedTraverse("@@plone_context_state") - url = "/".join([context_state.canonical_object_url(), url]) - else: - if "resolveuid" in url: - uid, fragment = normalize_uid_from_path(url) - obj = uuidToObject(uid) - if obj is None: - # uid can't resolve, return the url - return url - - url = obj.absolute_url() - if fragment is not None: - url = f"{url}{fragment}" - - if not url.startswith(("http://", "https://")): - url = self.request["SERVER_URL"] + url - - return url +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.link_redirect_view import " + "LinkRedirectView, normalize_uid_from_path instead.", + NON_REDIRECTABLE_URL_SCHEMES="plone.app.layout.contenttypes.link_redirect_view:NON_REDIRECTABLE_URL_SCHEMES", + NON_RESOLVABLE_URL_SCHEMES="plone.app.layout.contenttypes.link_redirect_view:NON_RESOLVABLE_URL_SCHEMES", + normalize_uid_from_path="plone.app.layout.contenttypes.link_redirect_view:normalize_uid_from_path", + LinkRedirectView="plone.app.layout.contenttypes.link_redirect_view:LinkRedirectView", +) diff --git a/src/plone/app/contenttypes/browser/migration.py b/src/plone/app/contenttypes/browser/migration.py index ff829623a..4731d96f1 100644 --- a/src/plone/app/contenttypes/browser/migration.py +++ b/src/plone/app/contenttypes/browser/migration.py @@ -1,112 +1,14 @@ -from plone.app.contenttypes.utils import changed_base_classes -from plone.app.contenttypes.utils import get_old_class_name_string -from plone.app.contenttypes.utils import migrate_base_class_to_new_class -from plone.base import PloneMessageFactory as _ -from plone.z3cform.layout import wrap_form -from Products.CMFCore.utils import getToolByName -from Products.statusmessages.interfaces import IStatusMessage -from z3c.form import button -from z3c.form import field -from z3c.form import form -from z3c.form.browser.checkbox import CheckBoxFieldWidget -from zExceptions import NotFound -from zope import schema -from zope.interface import implementer -from zope.interface import Interface -from zope.schema.interfaces import IVocabularyFactory -from zope.schema.vocabulary import SimpleVocabulary +import zope.deferredimport -import logging -logger = logging.getLogger(__name__) +zope.deferredimport.initialize() - -@implementer(IVocabularyFactory) -class ChangedBaseClasses: - def __call__(self, context): - """Return a vocabulary with all changed base classes.""" - terms = [] - for class_name, data in changed_base_classes(context).items(): - title = "{} (➡ {}) - ({} items)".format( - data["old"], data["new"], data["amount"] - ) - term = SimpleVocabulary.createTerm(class_name, class_name, title) - terms.append(term) - return SimpleVocabulary(terms) - - -class IBaseClassMigratorForm(Interface): - changed_base_classes = schema.List( - title="Changed base classes (old class, new class and number of items)", - description="Select changed base classes you want to migrate. " - "If the new types are folderish that change is also applied.", - value_type=schema.Choice( - vocabulary="plone.app.contenttypes.migration.changed_base_classes", - ), - default=[], - required=True, - ) - - -class BaseClassMigratorForm(form.Form): - label = _( - "heading_class_migrator", - default="Update base-classes for content with changed classes", - ) - - fields = field.Fields(IBaseClassMigratorForm) - fields["changed_base_classes"].widgetFactory = CheckBoxFieldWidget - ignoreContext = True - enableCSRFProtection = True - - def updateWidgets(self): - super().updateWidgets() - changed_base_classes = self.widgets["changed_base_classes"] - if not changed_base_classes.terms.terms.by_value: - IStatusMessage(self.request).addStatusMessage( - "No types with changed classes to migrate!", type="warning" - ) - return - - @button.buttonAndHandler("Update", name="update") - def handle_migrate(self, action): - data, errors = self.extractData() - - if errors: - return - - changed_base_classes = data.get("changed_base_classes", []) - messages = IStatusMessage(self.request) - if not changed_base_classes: - messages.addStatusMessage("No types were selected", type="warning") - return - - catalog = getToolByName(self.context, "portal_catalog") - migrated = [] - not_migrated = [] - for brain in catalog(): - try: - obj = brain.getObject() - except (KeyError, NotFound): - continue - old_class_name = get_old_class_name_string(obj) - if old_class_name in changed_base_classes: - if migrate_base_class_to_new_class(obj, migrate_to_folderish=True): - migrated.append(obj) - else: - not_migrated.append(obj) - - info_message_template = "{0} objects were migrated." - warn_message_template = "{0} objects were not migrated." - if migrated: - msg = info_message_template.format(len(migrated)) - messages.addStatusMessage(msg, type="info") - if not_migrated: - msg = warn_message_template.format(len(not_migrated)) - messages.addStatusMessage(msg, type="warning") - self.request.response.redirect(self.request["ACTUAL_URL"]) - - -BaseClassMigrator = wrap_form( - BaseClassMigratorForm, +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.migration import " + "BaseClassMigrator, BaseClassMigratorForm, ChangedBaseClasses, " + "IBaseClassMigratorForm instead.", + ChangedBaseClasses="plone.app.layout.contenttypes.migration:ChangedBaseClasses", + IBaseClassMigratorForm="plone.app.layout.contenttypes.migration:IBaseClassMigratorForm", + BaseClassMigratorForm="plone.app.layout.contenttypes.migration:BaseClassMigratorForm", + BaseClassMigrator="plone.app.layout.contenttypes.migration:BaseClassMigrator", ) diff --git a/src/plone/app/contenttypes/browser/templates/document.pt b/src/plone/app/contenttypes/browser/templates/document.pt deleted file mode 100644 index 5e4da56a3..000000000 --- a/src/plone/app/contenttypes/browser/templates/document.pt +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - -
-
- Text -
-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/file.pt b/src/plone/app/contenttypes/browser/templates/file.pt deleted file mode 100644 index 6da3fc036..000000000 --- a/src/plone/app/contenttypes/browser/templates/file.pt +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - -
- -
- -
- - - - - -
- Filename -
- - - -
- -
- Download -
-
-
- - -

- There is no file uploaded. -

-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/full_view.pt b/src/plone/app/contenttypes/browser/templates/full_view.pt deleted file mode 100644 index dee5d8118..000000000 --- a/src/plone/app/contenttypes/browser/templates/full_view.pt +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - -
-
- -
- -
-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/full_view_item.pt b/src/plone/app/contenttypes/browser/templates/full_view_item.pt deleted file mode 100644 index e17e57900..000000000 --- a/src/plone/app/contenttypes/browser/templates/full_view_item.pt +++ /dev/null @@ -1,90 +0,0 @@ - - - -
- -
- -

- - Title - -

- -
- -

- Description -

- -
- -
- -
- -
- content -
- -
- -
- -
- - - - - -

- - Read More… - -

- -
- - diff --git a/src/plone/app/contenttypes/browser/templates/image.pt b/src/plone/app/contenttypes/browser/templates/image.pt deleted file mode 100644 index cb77820f0..000000000 --- a/src/plone/app/contenttypes/browser/templates/image.pt +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - -
-
- - - -
- -
- Filename -
- - -
- -
- Download - View full-size image -
- - -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/image_view_fullscreen.pt b/src/plone/app/contenttypes/browser/templates/image_view_fullscreen.pt deleted file mode 100644 index 828d0ad92..000000000 --- a/src/plone/app/contenttypes/browser/templates/image_view_fullscreen.pt +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - Title - - - - - - - - diff --git a/src/plone/app/contenttypes/browser/templates/link.pt b/src/plone/app/contenttypes/browser/templates/link.pt deleted file mode 100644 index c7689e210..000000000 --- a/src/plone/app/contenttypes/browser/templates/link.pt +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - -
-
- - - -
- - - -
- - You see this page because you have permission to edit this link. - Others will be immediately redirected to the link's target URL. - -
- -
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/listing.pt b/src/plone/app/contenttypes/browser/templates/listing.pt deleted file mode 100644 index 9ad3df226..000000000 --- a/src/plone/app/contenttypes/browser/templates/listing.pt +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - -
-
The body
-
- - - - - -
- - - - - -
- -
- - - - -
- - - - - — - Oslo - - — - - - - - - by - - Bob Dobalina - - - - - - — - last modified - - August 16, 2001 at 23:35:59 - - - - - - Place custom listing info for custom types here - - - - -
-
- -

- description -

-
- -
- - - -
-
- -
-
-
-
- -
- -
- - -

- There are currently no items in this folder. -

-
- -
-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/listing_album.pt b/src/plone/app/contenttypes/browser/templates/listing_album.pt deleted file mode 100644 index 70561c0e6..000000000 --- a/src/plone/app/contenttypes/browser/templates/listing_album.pt +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - -
-
The body
-
- - - -
- - -
-
-
- -
-
-
Image title
-

Description

- View -
-
-
-
- - -
-
-
- -
-
-
Image title
-

Description

- View -
-
-
-
- -
- -
- - -

- There are currently no items in this folder. -

-
-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/listing_summary.pt b/src/plone/app/contenttypes/browser/templates/listing_summary.pt deleted file mode 100644 index fec35e619..000000000 --- a/src/plone/app/contenttypes/browser/templates/listing_summary.pt +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/plone/app/contenttypes/browser/templates/listing_tabular.pt b/src/plone/app/contenttypes/browser/templates/listing_tabular.pt deleted file mode 100644 index 29b8cdc39..000000000 --- a/src/plone/app/contenttypes/browser/templates/listing_tabular.pt +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - -
-
The body
-
- - - - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Field nameImage
- - - - - - - Item Title - - - - ${name} - - - - - -
- -
- -
- -
- - -

- There are currently no items in this folder. -

-
- -
-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/templates/newsitem.pt b/src/plone/app/contenttypes/browser/templates/newsitem.pt deleted file mode 100644 index 77d7eac23..000000000 --- a/src/plone/app/contenttypes/browser/templates/newsitem.pt +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - -
-
- Text -
-
- -
-
- - - diff --git a/src/plone/app/contenttypes/browser/utils.py b/src/plone/app/contenttypes/browser/utils.py index 307f5ff0c..cbcdd717d 100644 --- a/src/plone/app/contenttypes/browser/utils.py +++ b/src/plone/app/contenttypes/browser/utils.py @@ -1,55 +1,11 @@ -from Acquisition import aq_inner -from plone.memoize.view import memoize -from Products.CMFCore.utils import getToolByName -from Products.Five.browser import BrowserView -from Products.MimetypesRegistry.MimeTypeItem import guess_icon_path -from zope.component import getMultiAdapter -from zope.interface import implementer -from zope.interface import Interface +import zope.deferredimport -PREFIX = "++resource++mimetype.icons/" +zope.deferredimport.initialize() -class IUtils(Interface): - """ """ - - def getMimeTypeIcon(content_file): - """ """ - - -@implementer(IUtils) -class Utils(BrowserView): - def _get_mimes(self, content_file): - # We use 'yield' so iteration can be cut short - # if the calling code is happy. - context = aq_inner(self.context) - mtr = getToolByName(context, "mimetypes_registry") - if content_file.contentType: - # this gives a tuple - yield from mtr.lookup(content_file.contentType) - if content_file.filename: - # this gives a single mime type - yield mtr.lookupExtension(content_file.filename) - yield from mtr.lookup("application/octet-stream") - - @memoize - def getMimeTypeIcon(self, content_file): - # Get possible mime types, and try to find an icon path. - # Keep the first one, in case there is no good match. - first = None - for mime in self._get_mimes(content_file): - if first is None: - first = mime - if hasattr(mime, "icon_path"): - icon_path = mime.icon_path - if not icon_path.startswith("++"): - icon_path = PREFIX + icon_path - return icon_path - - if first is None: - # Probably does not happen in practice. - return "" - context = aq_inner(self.context) - pstate = getMultiAdapter((context, self.request), name="plone_portal_state") - portal_url = pstate.portal_url() - return portal_url + "/" + guess_icon_path(first) +zope.deferredimport.deprecated( + "Please use from plone.app.layout.contenttypes.utils import IUtils, Utils instead.", + PREFIX="plone.app.layout.contenttypes.utils:PREFIX", + IUtils="plone.app.layout.contenttypes.utils:IUtils", + Utils="plone.app.layout.contenttypes.utils:Utils", +) diff --git a/src/plone/app/contenttypes/tests/test_folder.py b/src/plone/app/contenttypes/tests/test_folder.py index 47c048f55..9ddd32f5a 100644 --- a/src/plone/app/contenttypes/tests/test_folder.py +++ b/src/plone/app/contenttypes/tests/test_folder.py @@ -1,6 +1,3 @@ -from datetime import datetime -from datetime import timedelta -from plone.app.contenttypes.browser.folder import FolderView from plone.app.contenttypes.interfaces import IFolder from plone.app.contenttypes.testing import ( # noqa PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING, @@ -8,7 +5,6 @@ from plone.app.contenttypes.testing import ( # noqa PLONE_APP_CONTENTTYPES_INTEGRATION_TESTING, ) -from plone.app.contenttypes.tests.test_image import dummy_image from plone.app.testing import setRoles from plone.app.testing import SITE_OWNER_NAME from plone.app.testing import SITE_OWNER_PASSWORD @@ -50,74 +46,6 @@ def test_adding(self): self.assertTrue(IFolder.providedBy(self.portal["doc1"])) -class FolderViewIntegrationTest(unittest.TestCase): - layer = PLONE_APP_CONTENTTYPES_INTEGRATION_TESTING - - def setUp(self): - self.portal = self.layer["portal"] - self.request = self.layer["request"] - self.request["ACTUAL_URL"] = self.portal.absolute_url() - setRoles(self.portal, TEST_USER_ID, ["Contributor"]) - - def test_result_filtering(self): - """Test, if portal_state's friendly_types and the result method's - keyword arguments are included in the query. - """ - - self.portal.invokeFactory("News Item", "newsitem") - self.portal.invokeFactory("Document", "document") - view = FolderView(self.portal, self.request) - - # Test, if all results are found. - view.portal_state.friendly_types = lambda: ["Document", "News Item"] - res = view.results() - self.assertEqual(len(res), 2) - - # Test, if friendly_types does filter for types. - view.portal_state.friendly_types = lambda: ["Document"] - res = view.results() - self.assertEqual(len(res), 1) - - # Test, if friendly_types does filter for types. - view.portal_state.friendly_types = lambda: ["NotExistingType"] - res = view.results() - self.assertEqual(len(res), 0) - - # Test, if kwargs filtering is applied. - view.portal_state.friendly_types = lambda: ["NotExistingType"] - res = view.results( - object_provides="plone.app.contenttypes.interfaces.IDocument" - ) - self.assertEqual(len(res), 1) - - def test_result_batching(self): - for idx in range(5): - self.portal.invokeFactory("Document", f"document{idx}") - request = self.request.clone() - request.form["b_size"] = 5 - view = FolderView(self.portal, request) - - batch = view.batch() - self.assertEqual(batch.length, 5) - self.assertEqual(len([item for item in batch]), 5) - self.assertFalse(batch.has_next) - - self.portal.invokeFactory("Document", "document5") - - batch = view.batch() - self.assertEqual(batch.length, 6) - self.assertEqual(len([item for item in batch]), 6) - self.assertFalse(batch.has_next) - - self.portal.invokeFactory("Document", "document6") - - batch = view.batch() - self.assertEqual(batch.length, 5) - self.assertEqual(len([item for item in batch]), 5) - self.assertTrue(batch.has_next) - self.assertEqual(batch.next_item_count, 2) - - class FolderFunctionalTest(unittest.TestCase): layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING @@ -158,102 +86,3 @@ def test_add_folder_with_shortname(self): self.browser.getControl(name=widget).value = "my-special-folder" self.browser.getControl("Save").click() self.assertTrue(self.browser.url.endswith("my-special-folder/view")) - - -class FolderViewFunctionalTest(unittest.TestCase): - layer = PLONE_APP_CONTENTTYPES_FUNCTIONAL_TESTING - - def setUp(self): - app = self.layer["app"] - self.portal = self.layer["portal"] - self.request = self.layer["request"] - setRoles(self.portal, TEST_USER_ID, ["Manager"]) - self.portal_url = self.portal.absolute_url() - self.portal.invokeFactory("Folder", id="folder", title="My Folder") - self.folder = self.portal.folder - self.folder_url = self.folder.absolute_url() - self.folder.invokeFactory("Document", id="doc1", title="Document 1") - import transaction - - transaction.commit() - self.browser = Browser(app) - self.browser.handleErrors = False - self.browser.addHeader( - "Authorization", - "Basic {}:{}".format( - SITE_OWNER_NAME, - SITE_OWNER_PASSWORD, - ), - ) - - def test_folder_view(self): - self.browser.open(self.folder_url + "/view") - self.assertIn("My Folder", self.browser.contents) - self.assertIn("Document 1", self.browser.contents) - - def test_folder_summary_view(self): - self.browser.open(self.folder_url + "/summary_view") - self.assertIn("My Folder", self.browser.contents) - self.assertIn("Document 1", self.browser.contents) - - def test_folder_full_view(self): - self.browser.open(self.folder_url + "/full_view") - self.assertIn("My Folder", self.browser.contents) - self.assertIn("Document 1", self.browser.contents) - - def test_folder_tabular_view(self): - self.browser.open(self.folder_url + "/tabular_view") - self.assertIn("My Folder", self.browser.contents) - self.assertIn("Document 1", self.browser.contents) - - def test_folder_album_view(self): - self.folder.invokeFactory("Image", id="image1", title="Image 1") - img1 = self.folder["image1"] - img1.image = dummy_image() - import transaction - - transaction.commit() - self.browser.open(self.folder_url + "/album_view") - self.assertIn("My Folder", self.browser.contents) - self.assertIn( - '