--- a/web/views/xmlrss.py Mon Jan 04 18:40:30 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
-"""base xml and rss views"""
-
-__docformat__ = "restructuredtext en"
-from cubicweb import _
-
-from base64 import b64encode
-from time import timezone
-
-from six.moves import range
-
-from logilab.mtconverter import xml_escape
-
-from cubicweb.predicates import (is_instance, non_final_entity, one_line_rset,
- appobject_selectable, adaptable)
-from cubicweb.view import EntityView, EntityAdapter, AnyRsetView, Component
-from cubicweb.uilib import simple_sgml_tag
-from cubicweb.web import httpcache, component
-
-def encode_bytes(value):
- return '<![CDATA[%s]]>' % b64encode(value.getvalue())
-
-# see cubicweb.sobjects.parser.DEFAULT_CONVERTERS
-SERIALIZERS = {
- 'String': xml_escape,
- 'Bytes': encode_bytes,
- 'Date': lambda x: x.strftime('%Y-%m-%d'),
- 'Datetime': lambda x: x.strftime('%Y-%m-%d %H:%M:%S'),
- 'Time': lambda x: x.strftime('%H:%M:%S'),
- 'TZDatetime': lambda x: x.strftime('%Y-%m-%d %H:%M:%S'), # XXX TZ
- 'TZTime': lambda x: x.strftime('%H:%M:%S'),
- 'Interval': lambda x: x.days * 60*60*24 + x.seconds,
- }
-
-# base xml views ##############################################################
-
-class XMLView(EntityView):
- """xml view for entities"""
- __regid__ = 'xml'
- title = _('xml export (entities)')
- templatable = False
- content_type = 'text/xml'
- xml_root = 'rset'
- item_vid = 'xmlitem'
-
- def cell_call(self, row, col):
- self.wview(self.item_vid, self.cw_rset, row=row, col=col)
-
- def call(self):
- """display a list of entities by calling their <item_vid> view"""
- self.w(u'<?xml version="1.0" encoding="%s"?>\n' % self._cw.encoding)
- self.w(u'<%s size="%s">\n' % (self.xml_root, len(self.cw_rset)))
- for i in range(self.cw_rset.rowcount):
- self.cell_call(i, 0)
- self.w(u'</%s>\n' % self.xml_root)
-
-
-class XMLItemView(EntityView):
- __regid__ = 'xmlitem'
-
- def entity_call(self, entity):
- """element as an item for an xml feed"""
- entity.complete()
- source = entity.cw_metainformation()['source']['uri']
- self.w(u'<%s eid="%s" cwuri="%s" cwsource="%s">\n'
- % (entity.cw_etype, entity.eid, xml_escape(entity.cwuri),
- xml_escape(source)))
- for rschema, attrschema in sorted(entity.e_schema.attribute_definitions()):
- attr = rschema.type
- if attr in ('eid', 'cwuri'):
- continue
- else:
- try:
- value = entity.cw_attr_cache[attr]
- except KeyError:
- # Bytes
- continue
- if value is None:
- self.w(u' <%s/>\n' % attr)
- else:
- try:
- value = SERIALIZERS[attrschema](value)
- except KeyError:
- pass
- self.w(u' <%s>%s</%s>\n' % (attr, value, attr))
- for relstr in self._cw.list_form_param('relation'):
- try:
- rtype, role = relstr.split('-')
- except ValueError:
- self.error('badly formated relation name %r', relstr)
- continue
- if role == 'subject':
- getrschema = entity.e_schema.subjrels
- elif role == 'object':
- getrschema = entity.e_schema.objrels
- else:
- self.error('badly formated relation name %r', relstr)
- continue
- if not rtype in getrschema:
- self.error('unexisting relation %r', relstr)
- continue
- self.w(u' <%s role="%s">\n' % (rtype, role))
- self.wview('xmlrelateditem', entity.related(rtype, role, safe=True), 'null')
- self.w(u' </%s>\n' % rtype)
- self.w(u'</%s>\n' % (entity.e_schema))
-
-
-class XMLRelatedItemView(EntityView):
- __regid__ = 'xmlrelateditem'
- add_div_section = False
-
- def entity_call(self, entity):
- # XXX put unique attributes as xml attribute, they are much probably
- # used to search existing entities in client data feed, and putting it
- # here may avoid an extra request to get those attributes values
- self.w(u' <%s eid="%s" cwuri="%s"/>\n'
- % (entity.e_schema, entity.eid, xml_escape(entity.cwuri)))
-
-
-class XMLRelatedItemStateView(XMLRelatedItemView):
- __select__ = is_instance('State')
-
- def entity_call(self, entity):
- self.w(u' <%s eid="%s" cwuri="%s" name="%s"/>\n'
- % (entity.e_schema, entity.eid, xml_escape(entity.cwuri),
- xml_escape(entity.name)))
-
-
-class XMLRsetView(AnyRsetView):
- """dumps raw rset as xml"""
- __regid__ = 'rsetxml'
- title = _('xml export')
- templatable = False
- content_type = 'text/xml'
- xml_root = 'rset'
-
- def call(self):
- w = self.w
- rset, descr = self.cw_rset, self.cw_rset.description
- eschema = self._cw.vreg.schema.eschema
- labels = self.columns_labels(tr=False)
- w(u'<?xml version="1.0" encoding="%s"?>\n' % self._cw.encoding)
- w(u'<%s query="%s">\n' % (self.xml_root, xml_escape(rset.printable_rql())))
- for rowindex, row in enumerate(self.cw_rset):
- w(u' <row>\n')
- for colindex, val in enumerate(row):
- etype = descr[rowindex][colindex]
- tag = labels[colindex]
- attrs = {}
- if '(' in tag:
- attrs['expr'] = tag
- tag = 'funccall'
- if val is not None and not eschema(etype).final:
- attrs['eid'] = val
- # csvrow.append(val) # val is eid in that case
- val = self._cw.view('textincontext', rset,
- row=rowindex, col=colindex)
- else:
- val = self._cw.view('final', rset, row=rowindex,
- col=colindex, format='text/plain')
- w(simple_sgml_tag(tag, val, **attrs))
- w(u' </row>\n')
- w(u'</%s>\n' % self.xml_root)
-
-
-# RSS stuff ###################################################################
-
-class IFeedAdapter(EntityAdapter):
- __needs_bw_compat__ = True
- __regid__ = 'IFeed'
- __select__ = is_instance('Any')
-
- def rss_feed_url(self):
- """return a URL to the rss feed for this entity"""
- return self.entity.absolute_url(vid='rss')
-
-
-class RSSFeedURL(Component):
- __regid__ = 'rss_feed_url'
- __select__ = non_final_entity()
-
- def feed_url(self):
- return self._cw.build_url(rql=self.cw_rset.limited_rql(), vid='rss')
-
-
-class RSSEntityFeedURL(Component):
- __regid__ = 'rss_feed_url'
- __select__ = one_line_rset() & adaptable('IFeed')
-
- def feed_url(self):
- entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
- return entity.cw_adapt_to('IFeed').rss_feed_url()
-
-
-class RSSIconBox(component.CtxComponent):
- """just display the RSS icon on uniform result set"""
- __regid__ = 'rss'
- __select__ = (component.CtxComponent.__select__
- & appobject_selectable('components', 'rss_feed_url'))
-
- visible = False
- order = 999
-
- def render(self, w, **kwargs):
- try:
- rss = self._cw.uiprops['RSS_LOGO']
- except KeyError:
- self.error('missing RSS_LOGO external resource')
- return
- urlgetter = self._cw.vreg['components'].select('rss_feed_url', self._cw,
- rset=self.cw_rset)
- url = urlgetter.feed_url()
- w(u'<a href="%s"><img src="%s" alt="rss"/></a>\n' % (xml_escape(url), rss))
-
-
-class RSSView(XMLView):
- __regid__ = 'rss'
- title = _('rss export')
- templatable = False
- content_type = 'text/xml'
- http_cache_manager = httpcache.MaxAgeHTTPCacheManager
- cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
- item_vid = 'rssitem'
-
- def _open(self):
- req = self._cw
- self.w(u'<?xml version="1.0" encoding="%s"?>\n' % req.encoding)
- self.w(u'<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">\n')
- self.w(u' <channel>\n')
- self.w(u' <title>%s RSS Feed</title>\n'
- % xml_escape(self.page_title()))
- self.w(u' <description>%s</description>\n'
- % xml_escape(req.form.get('vtitle', '')))
- params = req.form.copy()
- params.pop('vid', None)
- self.w(u' <link>%s</link>\n' % xml_escape(self._cw.build_url(**params)))
-
- def _close(self):
- self.w(u' </channel>\n')
- self.w(u'</rss>')
-
- def call(self):
- """display a list of entities by calling their <item_vid> view"""
- self._open()
- for i in range(self.cw_rset.rowcount):
- self.cell_call(i, 0)
- self._close()
-
- def cell_call(self, row, col):
- self.wview(self.item_vid, self.cw_rset, row=row, col=col)
-
-
-class RSSItemView(EntityView):
- __regid__ = 'rssitem'
- date_format = '%%Y-%%m-%%dT%%H:%%M%+03i:00' % (timezone / 3600)
- add_div_section = False
-
- def cell_call(self, row, col):
- entity = self.cw_rset.complete_entity(row, col)
- self.w(u'<item>\n')
- self.w(u'<guid isPermaLink="true">%s</guid>\n'
- % xml_escape(entity.absolute_url()))
- self.render_title_link(entity)
- self.render_description(entity)
- self._marker('dc:date', entity.dc_date(self.date_format))
- self.render_entity_creator(entity)
- self.w(u'</item>\n')
-
- def render_description(self, entity):
- self._marker('description', entity.dc_description(format='text/html'))
-
- def render_title_link(self, entity):
- self._marker('title', entity.dc_long_title())
- self._marker('link', entity.absolute_url())
-
- def render_entity_creator(self, entity):
- if entity.creator:
- self._marker('dc:creator', entity.dc_creator())
-
- def _marker(self, marker, value):
- if value:
- self.w(u' <%s>%s</%s>\n' % (marker, xml_escape(value), marker))