90 self.datadir_url = vreg.config.https_datadir_url |
90 self.datadir_url = vreg.config.https_datadir_url |
91 else: |
91 else: |
92 self.uiprops = vreg.config.uiprops |
92 self.uiprops = vreg.config.uiprops |
93 self.datadir_url = vreg.config.datadir_url |
93 self.datadir_url = vreg.config.datadir_url |
94 # raw html headers that can be added from any view |
94 # raw html headers that can be added from any view |
95 self.html_headers = HTMLHead() |
95 self.html_headers = HTMLHead(self.datadir_url) |
96 # form parameters |
96 # form parameters |
97 self.setup_params(form) |
97 self.setup_params(form) |
98 # dictionnary that may be used to store request data that has to be |
98 # dictionnary that may be used to store request data that has to be |
99 # shared among various components used to publish the request (views, |
99 # shared among various components used to publish the request (views, |
100 # controller, application...) |
100 # controller, application...) |
212 if param in self.no_script_form_params and val: |
212 if param in self.no_script_form_params and val: |
213 val = self.no_script_form_param(param, val) |
213 val = self.no_script_form_param(param, val) |
214 if param == '_cwmsgid': |
214 if param == '_cwmsgid': |
215 self.set_message_id(val) |
215 self.set_message_id(val) |
216 elif param == '__message': |
216 elif param == '__message': |
|
217 warn('[3.13] __message in request parameter is deprecated (may ' |
|
218 'only be given to .build_url). Seeing this message usualy ' |
|
219 'means your application hold some <form> where you should ' |
|
220 'replace use of __message hidden input by form.set_message, ' |
|
221 'so new _cwmsgid mechanism is properly used', |
|
222 DeprecationWarning) |
217 self.set_message(val) |
223 self.set_message(val) |
218 else: |
224 else: |
219 self.form[param] = val |
225 self.form[param] = val |
220 |
226 |
221 def no_script_form_param(self, param, value): |
227 def no_script_form_param(self, param, value): |
254 |
260 |
255 def reset_headers(self): |
261 def reset_headers(self): |
256 """used by AutomaticWebTest to clear html headers between tests on |
262 """used by AutomaticWebTest to clear html headers between tests on |
257 the same resultset |
263 the same resultset |
258 """ |
264 """ |
259 self.html_headers = HTMLHead() |
265 self.html_headers = HTMLHead(self.datadir_url) |
260 return self |
266 return self |
261 |
267 |
262 # web state helpers ####################################################### |
268 # web state helpers ####################################################### |
263 |
269 |
264 @property |
270 @property |
265 def message(self): |
271 def message(self): |
266 try: |
272 try: |
267 return self.session.data.pop(self._msgid, '') |
273 return self.session.data.pop(self._msgid, u'') |
268 except AttributeError: |
274 except AttributeError: |
269 try: |
275 try: |
270 return self._msg |
276 return self._msg |
271 except AttributeError: |
277 except AttributeError: |
272 return None |
278 return None |
281 @cached |
287 @cached |
282 def redirect_message_id(self): |
288 def redirect_message_id(self): |
283 return make_uid() |
289 return make_uid() |
284 |
290 |
285 def set_redirect_message(self, msg): |
291 def set_redirect_message(self, msg): |
|
292 # TODO - this should probably be merged with append_to_redirect_message |
286 assert isinstance(msg, unicode) |
293 assert isinstance(msg, unicode) |
287 msgid = self.redirect_message_id() |
294 msgid = self.redirect_message_id() |
288 self.session.data[msgid] = msg |
295 self.session.data[msgid] = msg |
289 return msgid |
296 return msgid |
290 |
297 |
291 def append_to_redirect_message(self, msg): |
298 def append_to_redirect_message(self, msg): |
292 msgid = self.redirect_message_id() |
299 msgid = self.redirect_message_id() |
293 currentmsg = self.session.data.get(msgid) |
300 currentmsg = self.session.data.get(msgid) |
294 if currentmsg is not None: |
301 if currentmsg is not None: |
295 currentmsg = '%s %s' % (currentmsg, msg) |
302 currentmsg = u'%s %s' % (currentmsg, msg) |
296 else: |
303 else: |
297 currentmsg = msg |
304 currentmsg = msg |
298 self.session.data[msgid] = currentmsg |
305 self.session.data[msgid] = currentmsg |
299 return msgid |
306 return msgid |
300 |
307 |
413 |
420 |
414 # web edition helpers ##################################################### |
421 # web edition helpers ##################################################### |
415 |
422 |
416 @cached # so it's writed only once |
423 @cached # so it's writed only once |
417 def fckeditor_config(self): |
424 def fckeditor_config(self): |
418 self.add_js('fckeditor/fckeditor.js') |
425 fckeditor_url = self.build_url('fckeditor/fckeditor.js') |
|
426 self.add_js(fckeditor_url, localfile=False) |
419 self.html_headers.define_var('fcklang', self.lang) |
427 self.html_headers.define_var('fcklang', self.lang) |
420 self.html_headers.define_var('fckconfigpath', |
428 self.html_headers.define_var('fckconfigpath', |
421 self.data_url('cubicweb.fckcwconfig.js')) |
429 self.data_url('cubicweb.fckcwconfig.js')) |
422 def use_fckeditor(self): |
430 def use_fckeditor(self): |
423 return self.vreg.config.fckeditor_installed() and self.property_value('ui.fckeditor') |
431 return self.vreg.config.fckeditor_installed() and self.property_value('ui.fckeditor') |
452 form = self.form |
460 form = self.form |
453 for param in form: |
461 for param in form: |
454 try: |
462 try: |
455 name, peid = param.split(':', 1) |
463 name, peid = param.split(':', 1) |
456 except ValueError: |
464 except ValueError: |
457 if not param.startswith('__') and param != "eid": |
465 if not param.startswith('__') and param not in ('eid', '_cw_fields'): |
458 self.warning('param %s mis-formatted', param) |
466 self.warning('param %s mis-formatted', param) |
459 continue |
467 continue |
460 if peid == eid: |
468 if peid == eid: |
461 value = form[param] |
469 value = form[param] |
462 if value == INTERNAL_FIELD_VALUE: |
470 if value == INTERNAL_FIELD_VALUE: |
615 # quote or other special characters that will break the js expression. |
623 # quote or other special characters that will break the js expression. |
616 extraparams.setdefault('fname', 'view') |
624 extraparams.setdefault('fname', 'view') |
617 url = self.build_url('json', **extraparams) |
625 url = self.build_url('json', **extraparams) |
618 cbname = build_cb_uid(url[:50]) |
626 cbname = build_cb_uid(url[:50]) |
619 # think to propagate pageid. XXX see https://www.cubicweb.org/ticket/1753121 |
627 # think to propagate pageid. XXX see https://www.cubicweb.org/ticket/1753121 |
620 jscode = 'function %s() { $("#%s").%s; }' % ( |
628 jscode = u'function %s() { $("#%s").%s; }' % ( |
621 cbname, nodeid, js.loadxhtml(url, {'pageid': self.pageid}, |
629 cbname, nodeid, js.loadxhtml(url, {'pageid': self.pageid}, |
622 'get', replacemode)) |
630 'get', replacemode)) |
623 self.html_headers.add_post_inline_script(jscode) |
631 self.html_headers.add_post_inline_script(jscode) |
624 return "javascript: %s()" % cbname |
632 return "javascript: %s()" % cbname |
625 |
633 |
626 # urls/path management #################################################### |
634 # urls/path management #################################################### |
|
635 |
|
636 def build_url(self, *args, **kwargs): |
|
637 """return an absolute URL using params dictionary key/values as URL |
|
638 parameters. Values are automatically URL quoted, and the |
|
639 publishing method to use may be specified or will be guessed. |
|
640 """ |
|
641 if '__message' in kwargs: |
|
642 msg = kwargs.pop('__message') |
|
643 kwargs['_cwmsgid'] = self.set_redirect_message(msg) |
|
644 return super(CubicWebRequestBase, self).build_url(*args, **kwargs) |
627 |
645 |
628 def url(self, includeparams=True): |
646 def url(self, includeparams=True): |
629 """return currently accessed url""" |
647 """return currently accessed url""" |
630 return self.base_url() + self.relative_path(includeparams) |
648 return self.base_url() + self.relative_path(includeparams) |
631 |
649 |
888 return 1./score, value |
906 return 1./score, value |
889 |
907 |
890 def _parse_accept_header(raw_header, value_parser=None, value_sort_key=None): |
908 def _parse_accept_header(raw_header, value_parser=None, value_sort_key=None): |
891 """returns an ordered list accepted types |
909 """returns an ordered list accepted types |
892 |
910 |
893 returned value is a list of 2-tuple (value, score), ordered |
911 :param value_parser: a function to parse a raw accept chunk. If None |
894 by score. Exact type of `value` will depend on what `value_parser` |
912 is provided, the function defaults to identity. If a function is provided, |
895 will reutrn. if `value_parser` is None, then the raw value, as found |
913 it must accept 2 parameters ``value`` and ``other_params``. ``value`` is |
896 in the http header, is used. |
914 the value found before the first ';', `other_params` is a dictionary |
|
915 built from all other chunks after this first ';' |
|
916 |
|
917 :param value_sort_key: a key function to sort values found in the accept |
|
918 header. This function will be passed a 3-tuple |
|
919 (raw_value, parsed_value, score). If None is provided, the default |
|
920 sort_key is 1./score |
|
921 |
|
922 :return: a list of 3-tuple (raw_value, parsed_value, score), |
|
923 ordered by score. ``parsed_value`` will be the return value of |
|
924 ``value_parser(raw_value)`` |
897 """ |
925 """ |
898 if value_sort_key is None: |
926 if value_sort_key is None: |
899 value_sort_key = lambda infos: 1./infos[-1] |
927 value_sort_key = lambda infos: 1./infos[-1] |
900 values = [] |
928 values = [] |
901 for info in raw_header.split(','): |
929 for info in raw_header.split(','): |
926 (type, subtype, type_params) corresponding to the mimetype definition |
954 (type, subtype, type_params) corresponding to the mimetype definition |
927 e.g. : for 'text/*', `mimetypeinfo` will be ('text', '*', {}), for |
955 e.g. : for 'text/*', `mimetypeinfo` will be ('text', '*', {}), for |
928 'text/html;level=1', `mimetypeinfo` will be ('text', '*', {'level': '1'}) |
956 'text/html;level=1', `mimetypeinfo` will be ('text', '*', {'level': '1'}) |
929 """ |
957 """ |
930 try: |
958 try: |
931 media_type, media_subtype = value.strip().split('/') |
959 media_type, media_subtype = value.strip().split('/', 1) |
932 except ValueError: # safety belt : '/' should always be present |
960 except ValueError: # safety belt : '/' should always be present |
933 media_type = value.strip() |
961 media_type = value.strip() |
934 media_subtype = '*' |
962 media_subtype = '*' |
935 return (media_type, media_subtype, other_params) |
963 return (media_type, media_subtype, other_params) |
936 |
964 |