docs: def perform_request_add_comment_or_remark(recID=0,
                                            uid=-1,
                                            action='DISPLAY',
                                            ln=CFG_SITE_LANG,
                                            msg=None,
                                            score=None,
                                            note=None,
                                            priority=None,
                                            reviews=0,
                                            comID=0,
                                            client_ip_address=None,
                                            editor_type='textarea',
                                            can_attach_files=False,
                                            subscribe=False,
                                            req=None,
                                            attached_files=None,
                                            warnings=None):
      """
      Add a comment/review or remark
      :param recID: record id
      :param uid: user id
      :param action:  'DISPLAY' to display add form
                      'SUBMIT' to submit comment once form is filled
                      'REPLY' to reply to an existing comment
      :param ln: language
      :param msg: the body of the comment/review or remark
      :param score: star score of the review
      :param note: title of the review
      :param priority: priority of remark (int)
      :param reviews: boolean, if enabled will add a review, if disabled will add a comment
      :param comID: if replying, this is the comment id of the comment we are replying to
      :param editor_type: the kind of editor/input used for the comment: 'textarea', 'ckeditor'
      :param can_attach_files: if user can attach files to comments or not
      :param subscribe: if True, subscribe user to receive new comments by email
      :param req: request object. Used to register callback to send email notification
      :param attached_files: newly attached files to this comment, mapping filename to filepath
      :type attached_files: dict
      :param warnings: list of warning tuples (warning_text, warning_color) that should be considered
      :return:
               - html add form if action is display or reply
               - html successful added form if action is submit
      """
      _ = gettext_set_language(ln)
      if warnings is None:
          warnings = []
  
      _ = gettext_set_language(ln)
  
      # check arguments
      check_recID_is_in_range(recID, warnings, ln)
      if uid <= 0:
          try:
              raise InvenioWebCommentError(
                  _('%(uid)s is an invalid user ID.', uid=uid))
          except InvenioWebCommentError as exc:
              register_exception()
              body = webcomment_templates.tmpl_error(exc.message, ln)
              return body
          #errors.append(('ERR_WEBCOMMENT_UID_INVALID', uid))
          return ''
  
      if attached_files is None:
          attached_files = {}
  
      user_contact_info = query_get_user_contact_info(uid)
      nickname = ''
      if user_contact_info:
          if user_contact_info[0]:
              nickname = user_contact_info[0]
      # show the form
      if action == 'DISPLAY':
          if reviews and CFG_WEBCOMMENT_ALLOW_REVIEWS:
              return webcomment_templates.tmpl_add_comment_form_with_ranking(
                  recID,
                  uid,
                  nickname,
                  ln,
                  msg,
                  score,
                  note,
                  warnings,
                  can_attach_files=can_attach_files)
          elif not reviews and CFG_WEBCOMMENT_ALLOW_COMMENTS:
              return webcomment_templates.tmpl_add_comment_form(
                  recID,
                  uid,
                  nickname,
                  ln,
                  msg,
                  warnings,
                  can_attach_files=can_attach_files)
          else:
              try:
                  raise InvenioWebCommentError(
                      _('Comments on records have been disallowed by the administrator.'))
              except InvenioWebCommentError as exc:
                  register_exception(req=req)
                  body = webcomment_templates.tmpl_error(exc.message, ln)
                  return body
              # errors.append(('ERR_WEBCOMMENT_COMMENTS_NOT_ALLOWED',))
  
      elif action == 'REPLY':
          if reviews and CFG_WEBCOMMENT_ALLOW_REVIEWS:
              try:
                  raise InvenioWebCommentError(_('Cannot reply to a review.'))
              except InvenioWebCommentError as exc:
                  register_exception(req=req)
                  body = webcomment_templates.tmpl_error(exc.message, ln)
                  return body
              # errors.append(('ERR_WEBCOMMENT_REPLY_REVIEW',))
              return webcomment_templates.tmpl_add_comment_form_with_ranking(
                  recID,
                  uid,
                  nickname,
                  ln,
                  msg,
                  score,
                  note,
                  warnings,
                  can_attach_files=can_attach_files)
          elif not reviews and CFG_WEBCOMMENT_ALLOW_COMMENTS:
              textual_msg = msg
              if comID > 0:
                  comment = query_get_comment(comID)
                  if comment:
                      user_info = UserInfo(comment[2])
                      if user_info:
                          date_creation = convert_datetext_to_dategui(
                              str(comment[4]))
                          # Build two msg: one mostly textual, the other one with
                          # HTML markup, for the CkEditor.
                          msg = _("%(x_name)s wrote on %(x_date)s:") % {
                              'x_name': user_info[2],
                              'x_date': date_creation}
                          textual_msg = msg
                          # 1 For CkEditor input
                          msg += '\n\n'
                          msg += comment[3]
                          msg = email_quote_txt(text=msg)
                          # Now that we have a text-quoted version, transform into
                          # something that CkEditor likes, using <blockquote> that
                          # do still enable users to insert comments inline
                          msg = email_quoted_txt2html(
                              text=msg,
                              indent_html=(
                                  '<blockquote><div>',
                                  '&nbsp;&nbsp;</div></blockquote>'),
                              linebreak_html="&nbsp;<br/>",
                              indent_block=False)
                          # Add some space for users to easily add text
                          # around the quoted message
                          msg = '<br/>' + msg + '<br/>'
                          # Due to how things are done, we need to
                          # escape the whole msg again for the editor
                          msg = cgi.escape(msg)
  
                          # 2 For textarea input
                          textual_msg += "\n\n"
                          textual_msg += comment[3]
                          textual_msg = email_quote_txt(text=textual_msg)
              return webcomment_templates.tmpl_add_comment_form(
                  recID,
                  uid,
                  nickname,
                  ln,
                  msg,
                  warnings,
                  textual_msg,
                  can_attach_files=can_attach_files,
                  reply_to=comID)
          else:
              try:
                  raise InvenioWebCommentError(
                      _('Comments on records have been disallowed by the administrator.'))
              except InvenioWebCommentError as exc:
                  register_exception(req=req)
                  body = webcomment_templates.tmpl_error(exc.message, ln)
                  return body
              # errors.append(('ERR_WEBCOMMENT_COMMENTS_NOT_ALLOWED',))
  
      # check before submitting form
      elif action == 'SUBMIT':
          if reviews and CFG_WEBCOMMENT_ALLOW_REVIEWS:
              if note.strip() in [
                      "", "None"] and not CFG_WEBCOMMENT_ALLOW_SHORT_REVIEWS:
                  try:
                      raise InvenioWebCommentWarning(
                          _('You must enter a title.'))
                  except InvenioWebCommentWarning as exc:
                      register_exception(stream='warning', req=req)
                      warnings.append((exc.message, ''))
                  # warnings.append(('WRN_WEBCOMMENT_ADD_NO_TITLE',))
              if score == 0 or score > 5:
                  try:
                      raise InvenioWebCommentWarning(
                          _('You must choose a score.'))
                  except InvenioWebCommentWarning as exc:
                      register_exception(stream='warning', req=req)
                      warnings.append((exc.message, ''))
                  # warnings.append(("WRN_WEBCOMMENT_ADD_NO_SCORE",))
          if msg.strip() in [
                  "", "None"] and not CFG_WEBCOMMENT_ALLOW_SHORT_REVIEWS:
              try:
                  raise InvenioWebCommentWarning(_('You must enter a text.'))
              except InvenioWebCommentWarning as exc:
                  register_exception(stream='warning', req=req)
                  warnings.append((exc.message, ''))
              # warnings.append(('WRN_WEBCOMMENT_ADD_NO_BODY',))
          # if no warnings, submit
          if len(warnings) == 0:
              if reviews:
                  if check_user_can_review(recID, client_ip_address, uid):
                      success = query_add_comment_or_remark(
                          reviews,
                          recID=recID,
                          uid=uid,
                          msg=msg,
                          note=note,
                          score=score,
                          priority=0,
                          client_ip_address=client_ip_address,
                          editor_type=editor_type,
                          req=req,
                          reply_to=comID)
                  else:
                      try:
                          raise InvenioWebCommentWarning(
                              _('You already wrote a review for this record.'))
                      except InvenioWebCommentWarning as exc:
                          register_exception(stream='warning', req=req)
                          warnings.append((exc.message, ''))
                      # warnings.append('WRN_WEBCOMMENT_CANNOT_REVIEW_TWICE')
                      success = 1
              else:
                  if check_user_can_comment(recID, client_ip_address, uid):
                      success = query_add_comment_or_remark(
                          reviews,
                          recID=recID,
                          uid=uid,
                          msg=msg,
                          note=note,
                          score=score,
                          priority=0,
                          client_ip_address=client_ip_address,
                          editor_type=editor_type,
                          req=req,
                          reply_to=comID,
                          attached_files=attached_files)
                      if success > 0 and subscribe:
                          subscribe_user_to_discussion(recID, uid)
                  else:
                      try:
                          raise InvenioWebCommentWarning(
                              _('You already posted a comment short ago. Please retry later.'))
                      except InvenioWebCommentWarning as exc:
                          register_exception(stream='warning', req=req)
                          warnings.append((exc.message, ''))
                      # warnings.append('WRN_WEBCOMMENT_TIMELIMIT')
                      success = 1
              if success > 0:
                  if CFG_WEBCOMMENT_ADMIN_NOTIFICATION_LEVEL > 0:
                      notify_admin_of_new_comment(comID=success)
                  return webcomment_templates.tmpl_add_comment_successful(
                      recID, ln, reviews, warnings, success)
              else:
                  try:
                      raise InvenioWebCommentError(
                          _('Failed to insert your comment to the database. Please try again.'))
                  except InvenioWebCommentError as exc:
                      register_exception(req=req)
                      body = webcomment_templates.tmpl_error(exc.message, ln)
                      return body
                  # errors.append(('ERR_WEBCOMMENT_DB_INSERT_ERROR'))
          # if are warnings or if inserting comment failed, show user where
          # warnings are
          if reviews and CFG_WEBCOMMENT_ALLOW_REVIEWS:
              return webcomment_templates.tmpl_add_comment_form_with_ranking(
                  recID,
                  uid,
                  nickname,
                  ln,
                  msg,
                  score,
                  note,
                  warnings,
                  can_attach_files=can_attach_files)
          else:
              return webcomment_templates.tmpl_add_comment_form(
                  recID,
                  uid,
                  nickname,
                  ln,
                  msg,
                  warnings,
                  can_attach_files=can_attach_files)
      # unknown action send to display
      else:
          try:
              raise InvenioWebCommentWarning(
                  _('Unknown action --> showing you the default add comment form.'))
          except InvenioWebCommentWarning as exc:
              register_exception(stream='warning', req=req)
              warnings.append((exc.message, ''))
          # warnings.append(('WRN_WEBCOMMENT_ADD_UNKNOWN_ACTION',))
          if reviews and CFG_WEBCOMMENT_ALLOW_REVIEWS:
              return webcomment_templates.tmpl_add_comment_form_with_ranking(
                  recID,
                  uid,
                  ln,
                  msg,
                  score,
                  note,
                  warnings,
                  can_attach_files=can_attach_files)
          else:
              return webcomment_templates.tmpl_add_comment_form(
                  recID,
                  uid,
                  ln,
                  msg,
                  warnings,
                  can_attach_files=can_attach_files)
  
      return ''