示例#1
0
def renderTiles(request, tree):
    """Find all tiles in the given response, contained in the lxml element
    tree `tree`, and insert them into the ouput.

    Assumes panel merging has already happened.
    """

    # Optionally enable ESI rendering in tiles that support this
    if not request.getHeader(ESI_HEADER):
        registry = queryUtility(IRegistry)
        if registry is not None:
            if registry.forInterface(IBlocksSettings).esi:
                request.environ[ESI_HEADER_KEY] = 'true'

    root = tree.getroot()
    headNode = root.find('head')
    baseURL = request.getURL()
    if request.getVirtualRoot():
        # plone.subrequest deals with VHM requests
        baseURL = ''
    for tileNode in utils.headTileXPath(tree):
        tileHref = tileNode.attrib[utils.tileAttrib]
        if not tileHref.startswith('/'):
            tileHref = urljoin(baseURL, tileHref)
        try:
            tileTree = utils.resolve(tileHref)
        except NotFound:
            continue
        if tileTree is not None:
            tileRoot = tileTree.getroot()
            utils.replace_content(tileNode, tileRoot.find('head'))

    for tileNode in utils.bodyTileXPath(tree):
        tileHref = tileNode.attrib[utils.tileAttrib]
        if not tileHref.startswith('/'):
            tileHref = urljoin(baseURL, tileHref)
        try:
            tileTree = utils.resolve(tileHref)
        except NotFound:
            continue
        if tileTree is not None:
            tileRoot = tileTree.getroot()
            tileHead = tileRoot.find('head')
            if tileHead is not None:
                for tileHeadChild in tileHead:
                    headNode.append(tileHeadChild)
            utils.replace_with_children(tileNode, tileRoot.find('body'))

    return tree
示例#2
0
def renderTiles(request, tree):
    """Find all tiles in the given response, contained in the lxml element
    tree `tree`, and insert them into the ouput.

    Assumes panel merging has already happened.
    """

    # Optionally enable ESI rendering in tiles that support this
    if not request.getHeader(ESI_HEADER):
        registry = queryUtility(IRegistry)
        if registry is not None:
            if registry.forInterface(IBlocksSettings).esi:
                request.environ[ESI_HEADER_KEY] = 'true'

    root = tree.getroot()
    headNode = root.find('head')
    baseURL = request.getURL()
    if request.getVirtualRoot():
        # plone.subrequest deals with VHM requests
        baseURL = ''
    for tileNode in utils.headTileXPath(tree):
        tileHref = tileNode.attrib[utils.tileAttrib]
        if not tileHref.startswith('/'):
            tileHref = urljoin(baseURL, tileHref)
        try:
            tileTree = utils.resolve(tileHref)
        except NotFound:
            continue
        if tileTree is not None:
            tileRoot = tileTree.getroot()
            utils.replace_content(tileNode, tileRoot.find('head'))

    for tileNode in utils.bodyTileXPath(tree):
        tileHref = tileNode.attrib[utils.tileAttrib]
        if not tileHref.startswith('/'):
            tileHref = urljoin(baseURL, tileHref)
        try:
            tileTree = utils.resolve(tileHref)
        except NotFound:
            continue
        if tileTree is not None:
            tileRoot = tileTree.getroot()
            tileHead = tileRoot.find('head')
            if tileHead is not None:
                for tileHeadChild in tileHead:
                    headNode.append(tileHeadChild)
            utils.replace_content(tileNode, tileRoot.find('body'))

    return tree
示例#3
0
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True):
    """Perform panel merging for the given page.

    Returns None if the page has no layout.
    """

    # Find layout node
    layoutHref = utils.xpath1(utils.layoutXPath, pageTree)
    if layoutHref is None:
        return None

    # Resolve layout tree
    baseURL = request.getURL()
    if request.getVirtualRoot():
        # plone.subrequest deals with VHM requests
        baseURL = ''
    layoutHref = parse.urljoin(baseURL, layoutHref)  # noqa: turn the link absolute
    # Pass special ajax_load parameter forward to allow layout indirection
    # views to select, for example, default AJAX layout instead of full layout.
    if request.form.get('ajax_load'):
        parts = list(parse.urlparse(layoutHref))
        query = parse.parse_qs(parts[4])
        query['ajax_load'] = request.form.get('ajax_load')
        parts[4] = parse.urlencode(query)
        layoutHref = parse.urlunparse(parts)
    layoutTree = utils.resolve(layoutHref)
    if layoutTree is None:
        return None

    # Map page panels onto the layout

    pagePanels = dict(
        (node.attrib['data-panel'], node)
        for node in utils.panelXPath(pageTree)
    )

    layoutPanels = dict(
        (node.attrib['data-panel'], node)
        for node in utils.panelXPath(layoutTree)
    )

    # Site layout should always have element with data-panel="content"
    # Note: This could be more generic, but that would empower editors too much
    if 'content' in pagePanels and 'content' not in layoutPanels:
        for node in layoutTree.xpath('//*[@id="content"]'):
            node.attrib['data-panel'] = 'content'
            layoutPanels['content'] = node
            break

    for panelId, layoutPanelNode in layoutPanels.items():
        pagePanelNode = pagePanels.get(panelId, None)
        if pagePanelNode is not None:
            utils.replace_content(layoutPanelNode, pagePanelNode)
        if removePanelLinks:
            del layoutPanelNode.attrib['data-panel']

    if removeLayoutLink:
        del pageTree.getroot().attrib[utils.layoutAttrib]

    return layoutTree
示例#4
0
    def test_resolve_utf8_unicode(self):
        content_layout = u"""
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html data-layout="./@@default-site-layout">
  <body>
    <h1>Ä</h1>
  </body>
</html>"""
        text = resolve('', content_layout).xpath('//h1')[0].text
        self.assertEqual(u'Ä', text)
示例#5
0
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True):
    """Perform panel merging for the given page.

    Returns None if the page has no layout.
    """

    # Find layout node
    layoutHref = utils.xpath1(utils.layoutXPath, pageTree)
    if layoutHref is None:
        return None

    # Resolve layout tree
    baseURL = request.getURL()
    if request.getVirtualRoot():
        # plone.subrequest deals with VHM requests
        baseURL = ''
    layoutHref = urljoin(baseURL, layoutHref)  # turn the link absolute
    if request.form.get('ajax_load'):
        parts = list(urlparse(layoutHref))
        query = parse_qs(parts[4])
        query['ajax_load'] = request.form.get('ajax_load')
        parts[4] = urlencode(query)
        layoutHref = urlunparse(parts)
    layoutTree = utils.resolve(layoutHref)
    if layoutTree is None:
        return None

    # Map page panels onto the layout

    pagePanels = dict((node.attrib['data-panel'], node)
                      for node in utils.panelXPath(pageTree))

    layoutPanels = dict((node.attrib['data-panel'], node)
                        for node in utils.panelXPath(layoutTree))

    # Site layout should always have element with data-panel="content"
    # Note: This could be more generic, but that would empower editors too much
    if 'content' in pagePanels and 'content' not in layoutPanels:
        for node in layoutTree.xpath('//*[@id="content"]'):
            node.attrib['data-panel'] = 'content'
            layoutPanels['content'] = node
            break

    for panelId, layoutPanelNode in layoutPanels.items():
        pagePanelNode = pagePanels.get(panelId, None)
        if pagePanelNode is not None:
            utils.replace_content(layoutPanelNode, pagePanelNode)
        if removePanelLinks:
            del layoutPanelNode.attrib['data-panel']

    if removeLayoutLink:
        del pageTree.getroot().attrib[utils.layoutAttrib]

    return layoutTree
示例#6
0
    def test_resolve_utf8_bytestring(self):
        """Test fix for issue where layouts with non-ascii characters were
        not properly parsed resulting in double encoding
        """
        content_layout = u"""
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html data-layout="./@@default-site-layout">
  <body>
    <h1>Ä</h1>
  </body>
</html>""".encode('utf-8')
        text = resolve('', content_layout).xpath('//h1')[0].text
        self.assertEqual(u'Ä', text)
def applyTilePersistent(path, resolved):
    """Append X-Tile-Persistent into resolved layout's tile URLs to allow
    context specific tile configuration overrides.

    (Path is required for proper error message when lxml parser fails.)
    """
    from plone.app.blocks.utils import tileAttrib
    from plone.app.blocks.utils import bodyTileXPath
    from plone.app.blocks.utils import resolve
    tree = resolve(path, resolved=resolved)
    for node in bodyTileXPath(tree):
        url = node.attrib[tileAttrib]
        if 'X-Tile-Persistent' not in url:
            if '?' in url:
                url += '&X-Tile-Persistent=yes'
            else:
                url += '?X-Tile-Persistent=yes'
        node.attrib[tileAttrib] = url
    return html.tostring(tree)
示例#8
0
    def tiles_instances(self):
        tiles = {}
        baseURL = self.request.getURL()
        tree = lxml.html.fromstring(self.content)

        for panelNode in utils.panelXPath(tree):
            panelName = panelNode.attrib['data-panel']

            for tileNode in utils.bodyTileXPath(panelNode):
                tileName = tileNode.attrib['data-tile']

                tileTree = utils.resolve(urljoin(baseURL, tileName))
                tile = tileTree.find('body')

                if panelName not in tiles.keys():
                    tiles[panelName] = {}

                tiles[panelName][tileName] = (tile.text or '') + \
                    ''.join([lxml.html.tostring(child) for child in tile])

        return json.dumps(tiles)
示例#9
0
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True):
    """Perform panel merging for the given page.

    Returns None if the page has no layout.
    """

    # Find layout node
    layoutHref = utils.xpath1(utils.layoutXPath, pageTree)
    if layoutHref is None:
        return None

    # Resolve layout tree
    baseURL = request.getURL()
    if request.getVirtualRoot():
        # plone.subrequest deals with VHM requests
        baseURL = ''
    layoutHref = urljoin(baseURL, layoutHref)  # turn the link absolute
    layoutTree = utils.resolve(layoutHref)
    if layoutTree is None:
        return None

    # Map page panels onto the layout

    pagePanels = dict(
        (node.attrib['data-panel'], node)
        for node in utils.panelXPath(pageTree)
    )

    for layoutPanelNode in utils.panelXPath(layoutTree):
        panelId = layoutPanelNode.attrib['data-panel']
        pagePanelNode = pagePanels.get(panelId, None)
        if pagePanelNode is not None:
            utils.replace_content(layoutPanelNode, pagePanelNode)
        if removePanelLinks:
            del layoutPanelNode.attrib['data-panel']

    if removeLayoutLink:
        del pageTree.getroot().attrib[utils.layoutAttrib]

    return layoutTree
def resolveTiles(request, tree):
    """Given a request and an lxml tree with the body, find all tile
    placehodlers and resolve them to actual tiles.
    """

    # renderView = None
    # renderedRequestKey = None

    # Optionally enable ESI rendering
    # registry = queryUtility(IRegistry)
    # if registry is not None:
    #    if registry.forInterface(IBlocksSettings).esi:
    #        renderView = 'plone.app.blocks.esirenderer'
    #        renderedRequestKey = 'plone.app.blocks.esi'

    baseURL = request.getURL()

    root = tree.getroot()
    headNode = root.find('head')

    # Find all tile placeholders
    for tilePlaceholderNode in root.cssselect('img.mceTile'):

        try:
            tileHref = tilePlaceholderNode.get('alt', None)
            if not tileHref:
                log.error('Could not render tile at %s', tileHref)
                continue
            tileHref = urljoin(baseURL, tileHref)
            tileTree = utils.resolve(tileHref)

            resolveTile(tilePlaceholderNode, tileHref, tileTree, headNode)
        except ConflictError:
            raise
        except Exception:
            log.exception('Could not render tile at %s', tileHref)
            continue

    return tree
示例#11
0
def merge(request, pageTree, removePanelLinks=False, removeLayoutLink=True):
    """Perform panel merging for the given page.

    Returns None if the page has no layout.
    """

    # Find layout node
    layoutHref = utils.xpath1(utils.layoutXPath, pageTree)
    if layoutHref is None:
        return None

    # Resolve layout tree
    baseURL = request.getURL()
    layoutHref = urljoin(baseURL, layoutHref)  # turn the link absolute
    layoutTree = utils.resolve(layoutHref)
    if layoutTree is None:
        return None

    # Map page panels onto the layout

    pagePanels = dict(
        (node.attrib['data-panel'], node)
        for node in utils.panelXPath(pageTree)
        )

    for layoutPanelNode in utils.panelXPath(layoutTree):
        panelId = layoutPanelNode.attrib['data-panel']
        pagePanelNode = pagePanels.get(panelId, None)
        if pagePanelNode is not None:
            utils.replace_content(layoutPanelNode, pagePanelNode)
        if removePanelLinks:
            del layoutPanelNode.attrib['data-panel']

    if removeLayoutLink:
        del pageTree.getroot().attrib[utils.layoutAttrib]

    return layoutTree
示例#12
0
def renderTiles(request, tree):
    """Find all tiles in the given response, contained in the lxml element
    tree `tree`, and insert them into the output.

    Assumes panel merging has already happened.
    """
    # Optionally enable ESI rendering in tiles that support this
    if not request.getHeader(ESI_HEADER):
        registry = queryUtility(IRegistry)
        if registry is not None:
            if registry.forInterface(IBlocksSettings, check=False).esi:
                request.environ[ESI_HEADER_KEY] = 'true'

    root = tree.getroot()
    headNode = root.find('head')
    baseURL = request.getURL()
    if request.getVirtualRoot():
        # plone.subrequest deals with VHM requests
        baseURL = ''
    for tileNode in utils.headTileXPath(tree):
        tileHref = tileNode.attrib[utils.tileAttrib]
        if not tileHref.startswith('/'):
            tileHref = urljoin(baseURL, tileHref)
        try:
            tileTree = utils.resolve(tileHref)
        except RuntimeError:
            tileTree = None
        except NotFound:
            logger.warn(
                'NotFound while trying to render tile: {0}'.format(
                    tileHref
                )
            )
            continue
        if tileTree is not None:
            tileRoot = tileTree.getroot()
            utils.replace_with_children(tileNode, tileRoot.find('head'))

    for tileNode in utils.bodyTileXPath(tree):
        tileHref = tileNode.attrib[utils.tileAttrib]
        tileRulesHref = tileNode.attrib.get(utils.tileRulesAttrib)

        if not tileHref.startswith('/'):
            tileHref = urljoin(baseURL, tileHref)
        try:
            tileTree = utils.resolve(tileHref)
        except RuntimeError:
            tileTree = errorTile(request)
        except NotFound:
            continue

        if tileRulesHref:
            if not tileRulesHref.startswith('/'):
                tileRulesHref = urljoin(baseURL, tileRulesHref)
            try:
                tileTransform = resolve_transform(tileRulesHref, tileNode)
            except NotFound:
                tileTransform = None
            del tileNode.attrib[utils.tileRulesAttrib]
        else:
            tileTransform = None

        if tileTree is not None:
            tileRoot = tileTree.getroot()

            tileHead = tileRoot.find('head')
            tileBody = tileRoot.find('body')

            if tileHead is None and tileBody is None:
                tileBody = tileRoot

            if tileTransform is not None:
                result = tileTransform(tileBody).getroot()
                del tileBody[:]
                tileBody.append(result)

            if tileHead is not None:
                for tileHeadChild in tileHead:
                    headNode.append(tileHeadChild)
            utils.replace_with_children(tileNode, tileBody)

    return tree