Esempio n. 1
0
def get_content_links(obj):
    refs = set()
    if ILayoutAware.providedBy(obj):
        behavior_data = ILayoutAware(obj)
        # get data from tile data
        annotations = IAnnotations(obj)
        for key in annotations.keys():
            if key.startswith(ANNOTATIONS_KEY_PREFIX):
                data = annotations[key]
                refs |= get_tile_data_links(obj, data)
        if not behavior_data.contentLayout and behavior_data.content:
            dom = fromstring(behavior_data.content)
            for el in dom.cssselect('.mosaic-text-tile .mosaic-tile-content'):
                links = extractLinks(tostring(el))
                refs |= li.getObjectsFromLinks(obj, links)
    try:
        # scan more than just this we probably should...
        value = obj.text.raw
        links = extractLinks(value)
        refs |= li.getObjectsFromLinks(obj, links)
    except AttributeError:
        pass

    if getattr(obj, 'image'):
        if IReferenceNamedImage.providedBy(obj.image):
            sub_obj = uuidToObject(obj.image.reference)
            if sub_obj:
                objid = get_ref(obj)
                if objid:
                    refs.add(RelationValue(objid))
    return refs
Esempio n. 2
0
    def get_layout_name(self, context, default_layout='index.html'):
        adapted = ILayoutAware(context, None)
        selected = None
        if adapted is not None:
            selected = adapted.pageSiteLayout
            if selected is None:
                context = aq_parent(context)
                while not ISiteRoot.providedBy(context):
                    adapted = ILayoutAware(context, None)
                    if adapted and adapted.sectionSiteLayout:
                        selected = adapted.sectionSiteLayout
                        break
                    context = aq_parent(context)

        if selected is None:
            if ISiteRoot.providedBy(context):
                # check if a default layout is set
                try:
                    selected = context.portal_registry[
                        'castle.cms.default_layout'] or default_layout  # noqa
                except (AttributeError, KeyError):
                    selected = default_layout
            else:
                selected = default_layout
        return selected
Esempio n. 3
0
def onLayoutEdited(obj, event):
    """
    need to get the layout because you need to know what are
    acceptible storage values
    """
    lookup = ILayoutAware(obj)
    layout = lookup.content_layout()

    if not layout:
        return

    tree = fromstring(layout)
    tile_keys = []
    for el in utils.bodyTileXPath(tree):
        tile_url = el.attrib.get('data-tile', '')
        if 'plone.app.standardtiles.field' in tile_url:
            continue
        tile_keys.append(
            ANNOTATIONS_KEY_PREFIX +
            '.' +
            tile_url.split('?')[0].split('/')[-1]
        )

    annotations = IAnnotations(obj)
    for key in list(annotations.keys()):
        if key.startswith(ANNOTATIONS_KEY_PREFIX) and key not in tile_keys:
            del annotations[key]
Esempio n. 4
0
    def deletelayout(self):
        layout_resources = queryResourceDirectory(
            CONTENT_LAYOUT_RESOURCE_NAME, 'custom')

        # find directory
        layout_path = self.request.form.get('layout')
        filename = layout_path.split('/')[-1]
        directory = layout_resources
        for part in layout_path.replace('custom/', '').split('/')[:-1]:
            directory = directory[part]
        del directory[filename]

        # now to modify manifest to not include
        if MANIFEST_FILENAME in directory.listDirectory():
            manifest = loadManifest(directory.readFile(MANIFEST_FILENAME))
            removeLayout(manifest, filename)
            directory.writeFile(MANIFEST_FILENAME, dumpManifest(manifest))

        # now reassign if provided
        replacement = self.request.form.get('replacement')
        if replacement:
            replacement = self._get_layout_path(replacement)
            catalog = api.portal.get_tool('portal_catalog')
            for brain in catalog(layout=self._get_layout_path(layout_path)):
                obj = brain.getObject()
                layout_data = ILayoutAware(obj, None)
                if layout_data:
                    layout_data.contentLayout = replacement
                    obj.reindexObject(idxs=['layout'])

        return json.dumps({
            'success': True,
            'user_layouts': getUserContentLayoutsForType(self.context.portal_type),
            'available_layouts': getContentLayoutsForType(self.context.portal_type)
        })
Esempio n. 5
0
def setDefaultLayoutForNewPage(obj, event):
    """When a new page is created, set its layout based on the default in
    the FTI
    """
    
    layoutAware = ILayoutAware(obj, None)
    if layoutAware is None:
        return
    
    # Initialise object
    layoutAware.content = ILayoutAware['content'].missing_value
    layoutAware.pageSiteLayout = ILayoutAware['pageSiteLayout'].missing_value
    layoutAware.sectionSiteLayout = ILayoutAware['sectionSiteLayout'].missing_value
    
    portal_type = obj.portal_type
    template = getDefaultPageLayout(portal_type)
    
    if template is None:
        raise ValueError("Cannot find layout template for %s" % portal_type)
    
    templatePath = urlparse.urljoin(obj.absolute_url_path(), template)
    
    try:
        layoutAware.content = resolveResource(templatePath)
    except:
        LOGGER.exception("Could not resolve default page layout %s" % portal_type)
Esempio n. 6
0
    def get(self):
        available = dict([(t.value, t.title)
                          for t in AvailableSiteLayouts(self.context)])
        applied = 'index.html'
        applied_context = getSite()

        context = self.context
        adapted = context_adapted = ILayoutAware(context)
        selected = adapted.pageSiteLayout
        if selected is None:
            context = aq_parent(context)
            while not ISiteRoot.providedBy(context):
                adapted = ILayoutAware(context, None)
                if adapted and adapted.sectionSiteLayout:
                    selected = adapted.sectionSiteLayout
                    break
                context = aq_parent(context)

        if selected:
            applied = selected
            applied_context = context

        return {
            'success': True,
            'available': available,
            'applied': applied,
            'context': utils.get_path(self.context),
            'applied_context': utils.get_path(applied_context),
            'page_layout': context_adapted.pageSiteLayout,
            'section_layout': context_adapted.sectionSiteLayout,
            'folder': IDexterityContainer.providedBy(self.context)
        }
Esempio n. 7
0
    def handleAdd(self, action):

        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        typeName = self.tileType.__name__

        context = self.context

        # Look up if our context supports tiles, if not
        # pick default view instead
        if not ILayoutAware(context, None):
            default_page_view = getMultiAdapter((context, self.request),
                                                name='default_page')
            default_page = default_page_view.getDefaultPage()
            context = default_page and context[default_page] or context
            context = ILayoutAware(context, None)

        # Traverse to a new tile in the context, with no data
        tile = context.restrictedTraverse(
            '@@%s/%s' % (typeName, self.tileId,))

        dataManager = ITileDataManager(tile)
        dataManager.set(data)

        # Look up the URL - we need to do this after we've set the data to
        # correctly account for transient tiles
        tileURL = absoluteURL(tile, self.request)
        contextURL = absoluteURL(tile.context, self.request)
        tileRelativeURL = tileURL

        if tileURL.startswith(contextURL):
            tileRelativeURL = '.' + tileURL[len(contextURL):]

        notify(ObjectCreatedEvent(tile))
        notify(ObjectAddedEvent(tile, self.context, self.tileId))

        IStatusMessage(self.request).addStatusMessage(
                _(u"Tile created at ${url}",
                  mapping={'url': tileURL}),
                type=u'info',
            )

        # Calculate the edit URL and append some data in a JSON structure,
        # to help the UI know what to do.

        url = getEditTileURL(tile, self.request)

        tileDataJson = {}
        tileDataJson['action'] = "save"
        tileDataJson['mode'] = "add"
        tileDataJson['url'] = tileRelativeURL
        tileDataJson['tile_type'] = typeName
        tileDataJson['id'] = tile.id

        url = appendJSONData(url, 'tiledata', tileDataJson)
        self.request.response.redirect(url)
Esempio n. 8
0
def recursive_create_path(path):
    if path in ('/', ''):
        folder = site
    else:
        path = path.lstrip('/')
        folder = traverse(path)
        if folder is not None and not IFolder.providedBy(folder):
            api.content.delete(folder)
            folder = None
        if folder is None:
            # Need to create folders up to where we want content
            # we'll walk it up create folders as needed
            folder = site
            for part in path.split('/'):
                try:
                    ob = folder[part]
                    if not IFolder.providedBy(ob):
                        api.content.delete(ob)
                        raise KeyError()
                    else:
                        folder = ob
                except (KeyError, AttributeError):
                    fpath = os.path.join(args.export_directory,
                                         relpath(folder), part, '__folder__')

                    if os.path.exists(fpath):
                        fi = open(fpath)
                        data = mjson.loads(fi.read())
                        fi.close()
                        importtype = get_import_type(
                            data, fpath[len(args.export_directory):], None)
                        creation_data = importtype.get_data()
                        creation_data['container'] = folder
                        creation_data['id'] = part
                        try:
                            folder = api.content.create(**creation_data)
                        except api.exc.InvalidParameterError:
                            logger.error(
                                'Error creating content {}'.format(fpath),
                                exc_info=True)
                            return
                        importtype.post_creation(folder)
                        if data['state']:
                            try:
                                api.content.transition(folder,
                                                       to_state=data['state'])
                            except:
                                # maybe workflows do not match up
                                pass
                        folder.reindexObject()
                    else:
                        folder = api.content.create(type='Folder',
                                                    id=part,
                                                    title=part.capitalize(),
                                                    container=folder)
                        bdata = ILayoutAware(folder)
                        bdata.contentLayout = '++contentlayout++castle/folder-query.html'
    return folder
Esempio n. 9
0
 def save(self):
     adapted = ILayoutAware(self.context)
     data = self.request.form.get('data')
     if not data:
         return
     data = json.loads(data)
     adapted.pageSiteLayout = data['page_layout']
     adapted.sectionSiteLayout = data['section_layout']
     return {'success': True}
Esempio n. 10
0
    def add_body_classes(self,
                         original_context,
                         context,
                         request,
                         tree,
                         result,
                         raw=False):
        '''
        Dynamically add useful body classes for theming and JS.
        '''
        body_classes = ''
        if raw:
            # this is a content layout likely
            plone_layout = queryMultiAdapter((original_context, request),
                                             name='plone_layout')
            if plone_layout:
                body_classes += ' ' + plone_layout.bodyClass(None, None)
        else:
            content_body = body_xpath(result)
            if len(content_body) > 0:
                body_classes += ' ' + content_body[0].attrib.get('class', '')

        body = body_xpath(tree)[0]
        from plone.app.blocks.layoutbehavior import ILayoutAware
        if ILayoutAware.providedBy(context):
            body_classes += ' template-layout'
            adapted = ILayoutAware(context, None)
            if adapted is not None:
                layout = getattr(adapted, 'contentLayout', None)
                if layout:
                    # Transform ++contentlayout++default/document.html
                    # into layout-default-document
                    names = LAYOUT_NAME.findall(layout)
                    if len(names) == 1:
                        body_classes += ' layout-' + names[0].replace('/', '-')
                else:
                    body_classes += ' layout-custom'

        try:
            body_classes += ' selected-layout-%s ' % original_context.getLayout(
            )  # noqa
        except Exception:
            pass
        classes = '%s %s' % (body.attrib.get('class', ''), body_classes)
        body.attrib['class'] = classes

        plone_view = queryMultiAdapter((original_context, request),
                                       name='plone')
        if plone_view:
            try:
                body.attrib.update(plone_view.patterns_settings())
            except AttributeError:
                plone_view = queryMultiAdapter((context, request),
                                               name='plone')
                if plone_view:
                    body.attrib.update(plone_view.patterns_settings())
Esempio n. 11
0
    def deletelayout(self):
        layout_resources = queryResourceDirectory(
            CONTENT_LAYOUT_RESOURCE_NAME, 'custom')
        layout_path = self.request.form.get('layout')

        if len(layout_path.split('/')) <= 2:
            sm = getSecurityManager()
            # this is a global layout, need to check permissions
            if not sm.checkPermission('Plone: Manage Content Layouts',
                                      api.portal.get()):
                raise Unauthorized("User not allowed to delete global layout")
        else:
            # check this user is allowed to delete this template
            user_dir = 'custom/user-layouts/{0:s}'.format(
                api.user.get_current().getId())
            if not layout_path.startswith(user_dir):
                raise Unauthorized("You are not allowed to delete this layout")

        # find directory
        filename = layout_path.split('/')[-1]
        directory = layout_resources
        for part in layout_path.replace('custom/', '').split('/')[:-1]:
            directory = directory[part]
        del directory[filename]

        # now to modify manifest to not include
        if MANIFEST_FILENAME in directory.listDirectory():
            manifest = loadManifest(directory.readFile(MANIFEST_FILENAME))
            removeLayout(manifest, filename)
            directory.writeFile(MANIFEST_FILENAME, dumpManifest(manifest))

        # now reassign if provided
        replacement = self.request.form.get('replacement')
        if replacement:
            replacement = self._get_layout_path(replacement)
            catalog = api.portal.get_tool('portal_catalog')
            for brain in catalog(layout=self._get_layout_path(layout_path)):
                obj = brain.getObject()
                layout_data = ILayoutAware(obj, None)
                if layout_data:
                    layout_data.contentLayout = replacement
                    obj.reindexObject(idxs=['layout'])

        return json.dumps(
            {
                'success': True,
                'user_layouts': getUserContentLayoutsForType(
                    self.context.portal_type
                ),
                'available_layouts': getContentLayoutsForType(
                    self.context.portal_type,
                    self.context
                )
            }
        )
Esempio n. 12
0
    def deletelayout(self):
        layout_resources = queryResourceDirectory(
            CONTENT_LAYOUT_RESOURCE_NAME, 'custom')
        layout_path = self.request.form.get('layout')

        if len(layout_path.split('/')) <= 2:
            sm = getSecurityManager()
            # this is a global layout, need to check permissions
            if not sm.checkPermission('Plone: Manage Content Layouts',
                                      api.portal.get()):
                raise Unauthorized("User not allowed to delete global layout")
        else:
            # check this user is allowed to delete this template
            user_dir = 'custom/user-layouts/{}'.format(
                api.user.get_current().getId())
            if not layout_path.startswith(user_dir):
                raise Unauthorized("You are not allowed to delete this layout")

        # find directory
        filename = layout_path.split('/')[-1]
        directory = layout_resources
        for part in layout_path.replace('custom/', '').split('/')[:-1]:
            directory = directory[part]
        del directory[filename]

        # now to modify manifest to not include
        if MANIFEST_FILENAME in directory.listDirectory():
            manifest = loadManifest(directory.readFile(MANIFEST_FILENAME))
            removeLayout(manifest, filename)
            directory.writeFile(MANIFEST_FILENAME, dumpManifest(manifest))

        # now reassign if provided
        replacement = self.request.form.get('replacement')
        if replacement:
            replacement = self._get_layout_path(replacement)
            catalog = api.portal.get_tool('portal_catalog')
            for brain in catalog(layout=self._get_layout_path(layout_path)):
                obj = brain.getObject()
                layout_data = ILayoutAware(obj, None)
                if layout_data:
                    layout_data.contentLayout = replacement
                    obj.reindexObject(idxs=['layout'])

        return json.dumps(
            {
                'success': True,
                'user_layouts': getUserContentLayoutsForType(
                    self.context.portal_type
                ),
                'available_layouts': getContentLayoutsForType(
                    self.context.portal_type
                )
            }
        )
Esempio n. 13
0
 def create_plain_folder(self, id, container):
     logger.info("Creating plain Folder (no __folder__ file found), %s" %
                 id)
     folder = api.content.create(type='Folder',
                                 id=id,
                                 title=id.capitalize(),
                                 container=container)
     bdata = ILayoutAware(folder)
     bdata.contentLayout = '++contentlayout++castle/folder-query.html'
     if not args.skip_transitioning:
         api.content.transition(folder, to_state='published')
     return folder
Esempio n. 14
0
    def transform(self, result, encoding):
        context = getContext(self.published)
        layout = queryMultiAdapter(
            (context, self.request),
            name='plone_layout'
        )
        root = result.tree.getroot()
        body = root.body

        if layout is None or body is None:
            return result

        body_class = body.attrib.get('class', '')
        body_classes = body_class.split()

        # Get default body classes
        if 'template-' not in body_class and 'site-' not in body_class:
            body_classes.extend([
                n for n in layout.bodyClass(None, self.published).split()
                if n not in body_classes
            ])

        # Get contentLayout body class
        if (
            'template-layout' in body_classes or
            'template-layout_view' in body_classes
        ):
            adapted = ILayoutAware(context, None)
            if adapted is not None:
                layout = None
                if getattr(adapted, 'content_layout_path', False):
                    # plone.app.blocks > 4.0.0rc1
                    layout = adapted.content_layout_path()
                else:
                    layout = getattr(adapted, 'contentLayout', None)
                if layout:
                    # Transform ++contentlayout++default/document.html
                    # into layout-default-document
                    names = LAYOUT_NAME.findall(layout)
                    if len(names) == 1:
                        body_classes.append('layout-' +
                                            names[0].replace('/', '-'))
                else:
                    body_classes.append('layout-custom')

        body_classes.append('mosaic-grid')

        # Set body class
        body.attrib['class'] = ' '.join(body_classes)

        return result
Esempio n. 15
0
def migrate_content_to_customContentLayout(context):
    pc = getToolByName(context, 'portal_catalog')
    brains = []
    brains.extend(pc.unrestrictedSearchResults(
        object_provides=ILayoutAware.__identifier__))
    brains.extend(pc.unrestrictedSearchResults(
        object_provides=ILayoutBehaviorAdaptable.__identifier__))
    for brain in brains:
        ob = brain._unrestrictedGetObject()
        adapted = ILayoutAware(ob)
        if all([
            not getattr(adapted, 'customContentLayout', None),
            getattr(adapted, 'content', None)
        ]):
            adapted.customContentLayout = adapted.content
            adapted.content = None
def findall_tiles(context, spec):
    if not isinstance(spec, list):
        spec = [spec]
    request = context.REQUEST
    la = ILayoutAware(context)
    layout = (
        la.customContentLayout
        if la.customContentLayout is not None
        else la.contentLayout
        if la.contentLayout is not None
        else la.content
    )
    if layout is None:
        return []
    possible_urls = re.findall(r"(@@[\w\.]+/\w+)", layout)
    urls = []
    for name in spec:
        urls += [url for url in possible_urls if url.startswith("@@{}".format(name))]
    # TODO: maybe better to get tile data? using ITileDataManager(id)?
    our_tile = request.response.headers.get("x-tile-url")
    tiles = [context.unrestrictedTraverse(str(url)) for url in urls]
    # mosaic get confused if we are doing this while creating a filter tile
    if request.response.headers.get("x-tile-url"):
        if our_tile:
            request.response.headers["x-tile-url"] = our_tile
        else:
            del request.response.headers["x-tile-url"]
    return tiles
    def transformIterable(self, result, encoding):
        if (
            self.published is None or
            not self.request.get('plone.app.blocks.enabled', False) or
            not isinstance(result, XMLSerializer)
        ):
            return None

        context = aq_parent(aq_base(self.published)) or api.portal.get()
        layout = queryMultiAdapter(
            (context, self.request),
            name='plone_layout'
        )
        root = result.tree.getroot()
        body = root.body

        if layout is None or body is None:
            return result

        body_class = body.attrib.get('class', '')
        body_classes = body_class.split()

        # Get default body classes
        if 'template-' not in body_class and 'site-' not in body_class:
            body_classes.extend([
                n for n in layout.bodyClass(None, self.published).split()
                if n not in body_classes
            ])

        # Get contentLayout body class
        if 'template-layout' in body_classes:
            adapted = ILayoutAware(context, None)
            if adapted is not None:
                layout = getattr(adapted, 'contentLayout', None)
                if layout:
                    # Transform ++contentlayout++default/document.html
                    # into layout-default-document
                    names = LAYOUT_NAME.findall(layout)
                    if len(names) == 1:
                        body_classes.append('layout-' +
                                            names[0].replace('/', '-'))
                else:
                    body_classes.append('layout-custom')

        # Enable mosaic-grid when no grid system is defined
        gridSystem = xpath1(gridXPath, result.tree)
        if gridSystem is None:
            registry = queryUtility(IRegistry)
            if registry:
                settings = registry.forInterface(IBlocksSettings, check=False)
                gridSystem = getattr(
                    settings, 'default_grid_system', None) or None
        if gridSystem is None:
            body_classes.append('mosaic-grid')

        # Set body class
        body.attrib['class'] = ' '.join(body_classes)

        return result
Esempio n. 18
0
 def is_deco_enabled(self):
     try:
         from plone.app.blocks.layoutbehavior import ILayoutAware
         if ILayoutAware.providedBy(self.context):
             return True
     except:
         pass
     return False
Esempio n. 19
0
 def is_deco_enabled(self):
     try:
         from plone.app.blocks.layoutbehavior import ILayoutAware
         if ILayoutAware.providedBy(self.context):
             return True
     except:
         pass
     return False
Esempio n. 20
0
def recursive_create_path(path):
    if path in ('/', ''):
        folder = site
    else:
        path = path.lstrip('/')
        folder = traverse(path)
        if folder is not None and not IFolder.providedBy(folder):
            api.content.delete(folder)
            folder = None
        if folder is None:
            # Need to create folders up to where we want content
            # we'll walk it up create folders as needed
            folder = site
            for part in path.split('/'):
                try:
                    ob = folder[part]
                    if not IFolder.providedBy(ob):
                        logger.warn(
                            'Existing object in traversal path is not folderish. Removing it.'
                        )
                        api.content.delete(ob)
                        raise KeyError()
                    else:
                        folder = ob
                except (KeyError, AttributeError):
                    fpath = os.path.join(args.export_directory,
                                         relpath(folder), part, '__folder__')
                    imported = False
                    if os.path.exists(fpath):
                        imported = import_object(fpath)
                    if not imported:
                        logger.info(
                            "Creating plain Folder (no __folder__ file found), %s"
                            % part)
                        folder = api.content.create(type='Folder',
                                                    id=part,
                                                    title=part.capitalize(),
                                                    container=folder)
                        bdata = ILayoutAware(folder)
                        bdata.contentLayout = '++contentlayout++castle/folder-query.html'
                        if not args.skip_transitioning:
                            api.content.transition(folder,
                                                   to_state='published')
    return folder
Esempio n. 21
0
 def _context_selected_layout(self):
     """Return the current layout for the layout aware context if we
     are on the layout aware context
     """
     if not ILayoutAware(self.context, None):
         return ''
     selectable_layout = ISelectableBrowserDefault(self.context, None)
     if not selectable_layout:
         return ''
     return selectable_layout.getLayout()
Esempio n. 22
0
def is_mosaic_edit_form(request):
    try:
        if (ILayoutAware.providedBy(request.PUBLISHED.context)
                and IDexterityEditForm.providedBy(request.PUBLISHED)
                and request.PUBLISHED.context.getLayout() == 'layout_view'
                and request.PUBLISHED.__name__ == 'edit'):
            return True
    except:
        pass
    return False
Esempio n. 23
0
    def get_field_data(self):
        from plone.dexterity.interfaces import IDexterityFTI
        from plone.behavior.interfaces import IBehaviorAssignable

        data = {}

        schema = getUtility(IDexterityFTI,
                            name=self.obj.portal_type).lookupSchema()
        for name, field in getFieldsInOrder(schema):
            data[name] = getattr(self.obj, name, None)

        behavior_assignable = IBehaviorAssignable(self.obj)
        for behavior in behavior_assignable.enumerateBehaviors():
            binst = behavior.interface(self.obj)
            bdata = {}
            for name, field in getFieldsInOrder(behavior.interface):
                bdata[name] = getattr(binst, name, None)
            data[behavior.interface.__identifier__] = bdata

        if ILayoutAware.providedBy(self.obj):
            from plone.tiles.data import ANNOTATIONS_KEY_PREFIX
            from plone.app.blocks.utils import getLayout
            from repoze.xmliter.utils import getHTMLSerializer
            from plone.app.blocks import tiles
            from plone.app.blocks import gridsystem
            from lxml.html import tostring
            tdata = {}
            annotations = IAnnotations(self.obj, {})
            for key in annotations.keys():
                if key.startswith(ANNOTATIONS_KEY_PREFIX):
                    adata = annotations[key]
                    tdata[key] = adata
            data['tile_data'] = tdata

            req = site.REQUEST
            layout = getLayout(self.obj)
            dom = getHTMLSerializer(layout)

            try:
                tiles.renderTiles(req,
                                  dom.tree,
                                  site=site,
                                  baseURL=self.obj.absolute_url() +
                                  '/layout_view')
            except TypeError:
                tiles.renderTiles(req,
                                  dom.tree,
                                  baseURL=self.obj.absolute_url() +
                                  '/layout_view')
            gridsystem.merge(req, dom.tree)

            data['rendered_layout'] = tostring(dom.tree)

        return data
Esempio n. 24
0
 def save(self):
     adapted = ILayoutAware(self.context)
     data = self.request.form.get('data')
     if not data:
         return
     data = json.loads(data)
     adapted.pageSiteLayout = data['page_layout']
     adapted.sectionSiteLayout = data['section_layout']
     parent = aq_parent(self.context)
     if ISiteRoot.providedBy(parent):
         # check if default page...
         if getDefaultPage(parent) == self.context.id:
             # also set site wide global layout setting...
             registry = getUtility(IRegistry)
             field = registry_field.TextLine(title=u'Default layout',
                                             required=False)
             new_record = Record(field)
             registry.records['castle.cms.default_layout'] = new_record
             registry['castle.cms.default_layout'] = data['section_layout']
     return {'success': True}
Esempio n. 25
0
    def deletelayout(self):
        layout_resources = queryResourceDirectory(
            CONTENT_LAYOUT_RESOURCE_NAME, 'custom')

        # find directory
        layout_path = self.request.form.get('layout')
        filename = layout_path.split('/')[-1]
        directory = layout_resources
        for part in layout_path.replace('custom/', '').split('/')[:-1]:
            directory = directory[part]
        del directory[filename]

        # now to modify manifest to not include
        if MANIFEST_FILENAME in directory.listDirectory():
            manifest = loadManifest(directory.readFile(MANIFEST_FILENAME))
            removeLayout(manifest, filename)
            directory.writeFile(MANIFEST_FILENAME, dumpManifest(manifest))

        # now reassign if provided
        replacement = self.request.form.get('replacement')
        if replacement:
            replacement = self._get_layout_path(replacement)
            catalog = api.portal.get_tool('portal_catalog')
            for brain in catalog(layout=self._get_layout_path(layout_path)):
                obj = brain.getObject()
                layout_data = ILayoutAware(obj, None)
                if layout_data:
                    layout_data.contentLayout = replacement
                    obj.reindexObject(idxs=['layout'])

        return json.dumps(
            {
                'success': True,
                'user_layouts': getUserContentLayoutsForType(
                    self.context.portal_type
                ),
                'available_layouts': getContentLayoutsForType(
                    self.context.portal_type
                )
            }
        )
Esempio n. 26
0
def getLayoutAwareSiteLayout(context):
    """Get the path to the site layout for a page. This is generally only
    appropriate for the view of this page. For a generic template or view, use
    getDefaultSiteLayout(context) instead.
    """

    layoutAware = ILayoutAware(context, None)
    if layoutAware is not None:
        if getattr(layoutAware, 'pageSiteLayout', None):
            return layoutAware.pageSiteLayout

    return getDefaultSiteLayout(context)
Esempio n. 27
0
def on_content_created(obj, event):
    if obj.portal_type == 'Dashboard':
        return
    metadata = IPublication(obj, None)
    if metadata is not None:
        if metadata.effective is None:
            metadata.effective = localized_now(obj)
    _touch_contributors(obj)

    if obj.portal_type == 'Collection':
        # enable syndication on type by default
        settings = FeedSettings(obj)
        settings.enabled = True

    adapted = ILayoutAware(obj, None)
    if adapted:
        if not adapted.content and not adapted.contentLayout:
            registry = getUtility(IRegistry)
            try:
                default_layout = registry['%s.%s' %
                                          (DEFAULT_CONTENT_LAYOUT_REGISTRY_KEY,
                                           obj.portal_type.replace(' ', '-'))]
                adapted.contentLayout = default_layout
            except (KeyError, AttributeError):
                pass
            try:
                default_layout = registry['%s.%s' %
                                          (DEFAULT_SITE_LAYOUT_REGISTRY_KEY,
                                           obj.portal_type.replace(' ', '-'))]
                adapted.pageSiteLayout = default_layout
            except (KeyError, AttributeError):
                pass

    try:
        tasks.scan_links.delay('/'.join(obj.getPhysicalPath()))
    except CannotGetPortalError:
        pass

    obj.reindexObject()
    def test_page_site_layout_is_not_acquired(self):
        self.registry[DEFAULT_SITE_LAYOUT_REGISTRY_KEY] = \
            b'/++sitelayout++testlayout1/site.html'

        a1 = ILayoutAware(self.portal['f1'])
        a2 = ILayoutAware(self.portal['f1']['d1'])

        self.assertEqual(a1.site_layout(), a2.site_layout())

        a1.pageSiteLayout = '/++sitelayout++testlayout2/mylayout.html'

        self.assertNotEqual(a1.site_layout(), a2.site_layout())
Esempio n. 29
0
    def render(self):
        context, request = self.context, self.request
        tile = getMultiAdapter((context, request), name=u'plone.deco_toolbar')

        tile_body = ''
        tree = html.fromstring(tile.index())
        for el in tree.body.getchildren():
            tile_body += html.tostring(el)

        if ILayoutAware.providedBy(self.context):
            return u'<div style="display:none;" ' + \
                    u'data-iframe="toolbar">%s</div>' % (tile_body)
        else:
            return u''
Esempio n. 30
0
    def render(self):
        context, request = self.context, self.request
        tile = getMultiAdapter((context, request), name=u'plone.deco_toolbar')

        tile_body = ''
        tree = html.fromstring(tile.index())
        for el in tree.body.getchildren():
            tile_body += html.tostring(el)

        if ILayoutAware.providedBy(self.context):
            return u'<div style="display:none;" ' + \
                    u'data-iframe="toolbar">%s</div>' % (tile_body)
        else:
            return u''
Esempio n. 31
0
def getDefaultSiteLayout(context):
    """Get the path to the site layout to use by default for the given content
    object
    """

    # Note: the sectionSiteLayout on context is for pages *under* context, not
    # necessarily context itself

    parent = aq_parent(aq_inner(context))
    while parent is not None:
        layoutAware = ILayoutAware(parent, None)
        if layoutAware is not None:
            if getattr(layoutAware, 'sectionSiteLayout', None):
                return layoutAware.sectionSiteLayout
        parent = aq_parent(aq_inner(parent))

    registry = queryUtility(IRegistry)
    if registry is None:
        return None

    return registry.get(DEFAULT_SITE_LAYOUT_REGISTRY_KEY)
Esempio n. 32
0
    def field_tiles(self, tree=None):
        if tree is None:
            layout = ILayoutAware(self).content
            tree = etree.HTML(layout)

        for tileNode in tileXPath(tree):
            tileId = tileNode.get('target', None)
            tileHref = tileNode.get('href', None)
            if tileHref is not None:
                if tileHref.startswith('./'):
                    tileHref = tileHref[2:]
                try:
                    tile = self.restrictedTraverse(tileHref)
                except Exception:
                    logger.exception('Could not render tile %s' % tileHref)
                else:
                    if IFieldTile.providedBy(tile):
                        yield tileId, tile

                        # remove the tile link from the head
                        tileNode.getparent().remove(tileNode)
 def layout(self):
     published = self.request.get('PUBLISHED')
     if isinstance(published, DefaultAddView):
         # Handle the special case of DX add form of layout aware context
         layout = None
         adapter = ILayoutAware(self.context, None)
         if adapter is not None:
             if getattr(adapter, 'sectionSiteLayout', None):
                 layout = adapter.sectionSiteLayout
         if layout:
             layout = urljoin(self.context.absolute_url_path(), layout)
             layout = resolveResource(layout)
         if not layout:
             layout = getMultiAdapter((self.context, self.request),
                                      name='default-site-layout').index()
     else:
         layout = getMultiAdapter((self.context, self.request),
                                  name='page-site-layout').index()
     cooked = cook_layout(layout, self.request.get('ajax_load'))
     pt = ViewPageTemplateString(cooked)
     bound_pt = pt.__get__(self, type(self))
     return bound_pt
Esempio n. 34
0
def layoutFieldDefaultValue(context, request):
    if context and ILayoutAware(context, None):
        return getPortalTypeDefaultContentLayoutContent(context.portal_type)

    # XXX: Context cannot be used yet, because plone.dexterity does not
    # bound fields to support context aware default factories
    layout = absolute_path(CONTENT_LAYOUT_DEFAULT_LAYOUT)

    # XXX: This is a workaround for a subrequest bug, where parent_app
    # ends up being a view with publishTraverse returning always NotFound.
    try:
        parent_app = request.PARENTS[-1]
        if IWidgetsView.providedBy(parent_app):
            return u''
    except AttributeError:
        pass
    except IndexError:
        pass

    try:
        return resolveResource(layout)
    except NotFound:
        return u''
Esempio n. 35
0
    def render(self):
        # Render fields by iterating over the form field tiles, rendering
        # each one, and replacing the tile with the result.
        layout = ILayoutAware(self.context).content
        layoutTree = getHTMLSerializer(layout,
                                       pretty_print=True,
                                       encoding='utf8')

        for tileId, tile in self.context.field_tiles(layoutTree.tree):
            # XXX need to include the full Plone view of the field
            widget = self.widgets[tile.id]
            widgetRenderer = getMultiAdapter((widget, self.request),
                                             name=u'ploneform-render-widget')
            widgetHtml = widgetRenderer()
            tileTree = html.fromstring(widgetHtml).getroottree()
            tileTarget = xpath1("//*[@id='%s']" % tileId, layoutTree.tree)

            if tileTarget is None:
                continue

            # clear children, but keep attributes
            oldAttrib = dict(tileTarget.attrib)
            tileTarget.clear()
            tileTarget.attrib.update(oldAttrib)

            # insert tile target with tile body
            tileBody = tileTree.find('body')
            if tileBody is not None:
                tileTarget.text = tileBody.text
                for tileBodyChild in tileBody:
                    tileTarget.append(tileBodyChild)

        # TODO:
        # - create form tag
        # - fill in status message
        return str(layoutTree)
Esempio n. 36
0
def tiles(site, req, tiles_data=_tiles_data):

    alsoProvides(req, ICastleLayer)

    # Sitewide slot tiles
    for meta_id, tiles in tiles_data.items():
        meta_tile = MetaTile(site, req)
        alsoProvides(meta_tile, IGlobalTile)
        meta_tile.id = 'meta-' + meta_id
        meta_tile.__name__ = 'castle.cms.meta'
        meta_data_manager = ITileDataManager(meta_tile)
        meta_data = meta_data_manager.get()
        meta_tiles = []

        for tile_data in tiles:
            meta_tiles.append(tile_data['meta'])
            tile = getMultiAdapter((site, req), name=tile_data['meta']['type'])
            alsoProvides(tile, IPersistentTile)
            tile.id = tile_data['meta']['id']
            tile.__name__ = tile_data['meta']['type']
            data_manager = ITileDataManager(tile)
            data_manager.set(tile_data['data'])

        meta_data['tiles'] = meta_tiles
        meta_data_manager.set(meta_data)

    frontpage = site['front-page']
    adapted = ILayoutAware(frontpage, None)
    if adapted:
        adapted.pageSiteLayout = 'frontpage.html'

    # Tiles only for the front-page
    frontpage_tiles = getTileData()

    for tile in frontpage_tiles:
        fp_tile = getMultiAdapter((frontpage, req), name=tile['meta']['type'])

        meta = tile['meta']
        fp_tile.id = meta['id']
        alsoProvides(fp_tile, IPersistentTile)
        data_manager = ITileDataManager(fp_tile)
        data_manager.set(tile['data'])

        if 'slot' in tile:
            meta_tile = MetaTile(frontpage, req)
            alsoProvides(meta_tile, IGlobalTile)
            meta_tile.id = 'meta-' + tile['slot']
            meta_tile.__name__ = 'castle.cms.meta'
            meta_data_manager = ITileDataManager(meta_tile)
            meta_data = meta_data_manager.get()

            existing_tiles = meta_data.get('tiles') or []
            new_tile_id = tile['meta']['id']

            if new_tile_id in [x['id'] for x in existing_tiles]:
                # check if the tile we're trying to install is already there.
                continue

            existing_tiles.append(meta)
            meta_data['tiles'] = existing_tiles
            meta_data['mode'] = 'show'

            meta_data_manager.set(meta_data)

    frontpageLayout = ILayoutAware(frontpage, None)
    if frontpageLayout:
        frontpageLayout.contentLayout = '/++contentlayout++castle/frontpage-layout.html'  # noqa
Esempio n. 37
0
 def _getLayout(self):
     layout_adapter = ILayoutAware(self.context)
     if self.request.form.get('ajax_load'):
         return layout_adapter.ajax_site_layout()
     return layout_adapter.site_layout()
Esempio n. 38
0
    def post_creation(self,
                      obj,
                      pdb_if_exception=False,
                      post_creation_data=None):
        if obj is None:
            return
        field_data = self.field_data
        bdata = ILayoutAware(obj, None)
        if bdata:
            try:
                bdata.contentLayout = self.layout
            except Exception:
                bdata.contentLayout = '++contentlayout++default/document.html'
        bdata = IRichText(obj, None)
        if bdata:
            try:
                bdata.text = RichTextValue(field_data['text'], 'text/html',
                                           'text/html')
            except Exception:
                try:
                    bdata.text = RichTextValue(
                        field_data[
                            'plone.app.contenttypes.behaviors.richtext.IRichText']
                        ['text'],  # noqa
                        'text/html',
                        'text/html').raw
                except Exception:
                    bdata.text = ''

        bdata = IBasic(obj, None)
        if bdata:
            try:
                bdata.title = field_data['title']
            except Exception:
                try:
                    bdata.title = field_data[
                        'plone.app.content.interfaces.INameFromTitle']['title']
                except Exception:
                    bdata.description = field_data[dublin]['title']
            try:
                bdata.description = field_data['description']
            except Exception:
                try:
                    bdata.description = field_data[dublin]['description']
                except Exception:
                    bdata.description = field_data[basic]['description']
        else:
            try:
                obj.title = field_data['title']
                obj.description = field_data['description']
            except Exception:
                obj.title = field_data[dublin]['title']
                obj.description = field_data[dublin]['description']

        bdata = ICategorization(obj, None)
        if bdata:
            try:
                bdata.subjects = field_data['subject']
            except Exception:
                try:
                    bdata.subjects = self.field_data[dublin]['subjects']
                except Exception:
                    try:
                        bdata.subjects = self.field_data[categorization][
                            'subjects']
                    except Exception:
                        pass  # no keywords found

            bdata = IPublication(obj)
            try:
                if field_data['effectiveDate']:
                    bdata.effective = pydt(field_data['effectiveDate'])
            except Exception:
                try:
                    if field_data[dublin]['effective']:
                        bdata.effective = pydt(field_data[dublin]['effective'])
                except Exception:
                    try:
                        if field_data[publication]['effective']:
                            bdata.effective = pydt(
                                field_data[publication]['effective'])
                    except Exception:
                        bdata.effective = None

        ldata = ILocation(obj, None)
        if ldata:
            if field_data.get('location'):
                ldata.locations = [field_data['location']]

            if field_data.get('newsLocation'):
                if ldata.locations:
                    ldata.locations.append(field_data['newsLocation'])
                else:
                    ldata.locations = [field_data['newsLocation']]

        try:
            obj.modification_date = field_data['modification_date']
        except Exception:
            try:
                obj.modification_date = obj.modified()
            except Exception:
                obj.modification_date = None
        try:
            obj.creation_date = field_data['creation_date']
        except Exception:
            try:
                obj.creation_date = obj.created()
            except Exception:
                obj.creation_date = None

        bdata = IDublinCore(obj, None)
        if bdata:
            if IDublinCore.__identifier__ in field_data:
                dublin_core = field_data[IDublinCore.__identifier__]
                bdata.expires = dublin_core['expires']
                bdata.rights = dublin_core['rights']
                bdata.creators = tuple(dublin_core['creators'])
                bdata.language = dublin_core['language']
                bdata.effective = pydt(dublin_core['effective'])
                bdata.subjects = dublin_core['subjects']
                bdata.contributors = tuple(dublin_core['contributors'])
            else:
                bdata.expires = pydt(field_data.get('expirationDate'))
                bdata.rights = field_data.get('rights')
                creators = field_data.get('creators')
                bdata.creators = tuple(creators) if creators else ()
                language = field_data.get('language')
                bdata.language = language if language is not None else ""
                bdata.effective = pydt(field_data.get('effectiveDate'))
                bdata.subjects = field_data.get('subject')
                contributors = field_data.get('contributors')
                bdata.contributors = tuple(contributors) if contributors else (
                )

        bdata = ILayoutAware(obj, None)
        if bdata:
            if self.data['portal_type'] == 'Folder' and (
                    self.field_data.get('text') or '').strip():
                bdata.content = FOLDER_DEFAULT_PAGE_LAYOUT % self.field_data[
                    'text']
                # need to explicitly reset contentLayout value because this data
                # could be overwritten
                bdata.contentLayout = None
            elif self.layout:
                if layoutaware in field_data and 'contentLayout' in field_data[
                        layoutaware]:
                    bdata.contentLayout = field_data[layoutaware][
                        'contentLayout']
                if layoutaware in field_data and 'content' in field_data[
                        layoutaware]:
                    bdata.content = field_data[
                        'plone.app.blocks.layoutbehavior.ILayoutAware'][
                            'content']
                if 'rendered_layout' in self.data['data']:
                    bdata.rendered_layout = self.data['data'][
                        'rendered_layout']

        inv_field_mapping = {v: k for k, v in self.fields_mapping.iteritems()}
        for IBehavior, field_name in self.behavior_data_mappers:

            original_field_name = inv_field_mapping.get(field_name, field_name)

            if original_field_name not in self.field_data:
                # data not here...
                continue

            behavior = IBehavior(obj, None)
            if behavior is None:
                # behavior not valid for obj type
                continue

            val = self.field_data[original_field_name]

            if field_name in self.data_converters:
                val = self.data_converters[field_name](val)

            setattr(behavior, field_name, val)

        # handle lead images
        for field_name in self.lead_image_field_names:
            if self.field_data.get(field_name):
                if field_name == 'plone.app.contenttypes.behaviors.leadimage.ILeadImage':
                    im_obj = self.field_data.get(field_name)['image']
                else:
                    im_obj = self.field_data.get(field_name)
                if hasattr(im_obj, 'read'):
                    im_data = im_obj.read()
                else:
                    im_data = im_obj

                if not im_data:
                    continue

                filename = self.field_data.get('image_filename')
                if not filename:
                    if hasattr(im_obj, 'filename'):
                        filename = im_obj.filename
                    else:
                        filename = self.field_data['id']
                obj.image = im_data

                if not isinstance(obj.image, NamedBlobImage):
                    is_stringio = isinstance(im_obj, StringIO)
                    if is_stringio:
                        namedblobimage_data = im_data
                    elif isinstance(im_obj, Image):
                        namedblobimage_data = im_data.data
                    else:
                        if pdb_if_exception:
                            pdb.set_trace()
                        logger.info("    lead image is type %s" % type(im_obj))
                    obj.image = NamedBlobImage(data=namedblobimage_data,
                                               contentType='',
                                               filename=filename)

                if hasattr(obj.image, 'contentType') and isinstance(
                        obj.image.contentType, unicode):
                    obj.image.contentType = obj.image.contentType.encode(
                        'ascii')
                else:
                    if isinstance(im_obj, Image):
                        data = im_obj.data
                    elif hasattr(im_obj, 'buf'):
                        data = im_obj.buf
                    elif hasattr(im_obj, '_blob'):
                        if hasattr(im_obj._blob, '_p_blob_uncommitted'):
                            f = open(im_obj._blob._p_blob_uncommitted, 'r')
                            data = f.read()
                            f.close()
                        else:
                            raise Exception(
                                "no _p_blob_uncommitted attr in im_obj._blob")
                    else:
                        raise Exception("no _blob attr in im_obj")

                    if data == '' or data is None:
                        data = base64.b64decode(
                            'R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
                        )

                    image_type = what('', h=data)
                    if image_type in [
                            'png', 'bmp', 'jpeg', 'xbm', 'tiff', 'gif'
                    ]:
                        obj.image.contentType = 'image/%s' % image_type
                    elif image_type == 'rast':
                        obj.image.contentType = 'image/cmu-raster'
                    elif image_type == 'ppm':
                        obj.image.contentType = 'image/x-portable-pixmap'
                    elif image_type == 'pgm':
                        obj.image.contentType = 'image/x-portable-greymap'
                    elif image_type == 'pbm':
                        obj.image.contentType = 'image/x-portable-bitmap'
                    elif image_type == 'rgb':
                        obj.image.contentType = 'image/x-rgb'
                    else:
                        # look at filename extension
                        contentType, encoding = guess_type(obj.image.filename,
                                                           strict=False)
                        if contentType:
                            obj.image.contentType = contentType
                        else:
                            logger.info(
                                "Unknown image type {};"
                                " defaulting to jpeg".format(image_type))
                            pdb.set_trace()
                            obj.image.contentType = 'image/jpeg'  # default
                for caption_field_name in self.lead_image_caption_field_names:
                    if caption_field_name in self.field_data:
                        obj.imageCaption = self.field_data.get(
                            caption_field_name)
Esempio n. 39
0
 def has_layout(self):
     return ILayoutAware.providedBy(self.context)