[test] no more __cubicweb_internal_field__ value displayed on password widget
"""The edit controller, handling form submitting.:organization: Logilab:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"fromrql.utilsimportrqlvar_makerfromlogilab.common.textutilsimportsplitstripfromcubicwebimportBinary,ValidationError,typed_eidfromcubicweb.webimportINTERNAL_FIELD_VALUE,RequestError,NothingToEdit,ProcessFormErrorfromcubicweb.web.viewsimportbasecontrollers,autoformclassRqlQuery(object):def__init__(self):self.edited=[]self.restrictions=[]self.kwargs={}definsert_query(self,etype):ifself.edited:rql='INSERT %s X: %s'%(etype,','.join(self.edited))else:rql='INSERT %s X'%etypeifself.restrictions:rql+=' WHERE %s'%','.join(self.restrictions)returnrqldefupdate_query(self,eid):varmaker=rqlvar_maker()var=varmaker.next()whilevarinself.kwargs:var=varmaker.next()rql='SET %s WHERE X eid %%(%s)s'%(','.join(self.edited),var)ifself.restrictions:rql+=', %s'%','.join(self.restrictions)self.kwargs[var]=eidreturnrqlclassEditController(basecontrollers.ViewController):__regid__='edit'defpublish(self,rset=None):"""edit / create / copy / delete entity / relations"""forkeyinself._cw.form:# There should be 0 or 1 actionifkey.startswith('__action_'):cbname=key[1:]try:callback=getattr(self,cbname)exceptAttributeError:raiseRequestError(self._cw._('invalid action %r'%key))else:returncallback()self._default_publish()self.reset()def_default_publish(self):req=self._cwself.errors=[]self.relations_rql=[]form=req.form# so we're able to know the main entity from the repository sideif'__maineid'inform:req.set_shared_data('__maineid',form['__maineid'],querydata=True)# no specific action, generic editionself._to_create=req.data['eidmap']={}self._pending_fields=req.data['pendingfields']=set()try:methodname=req.form.pop('__method',None)foreidinreq.edited_eids():# __type and eidformparams=req.extract_entity_params(eid,minparams=2)ifmethodnameisnotNone:entity=req.entity_from_eid(eid)method=getattr(entity,methodname)method(formparams)eid=self.edit_entity(formparams)except(RequestError,NothingToEdit),ex:if'__linkto'inreq.formand'eid'inreq.form:self.execute_linkto()elifnot('__delete'inreq.formor'__insert'inreq.form):raiseValidationError(None,{None:unicode(ex)})# handle relations in newly created entitiesifself._pending_fields:forform,fieldinself._pending_fields:self.handle_formfield(form,field)# execute rql to set all relationsforquerydefinself.relations_rql:self._cw.execute(*querydef)# XXX this processes *all* pending operations of *all* entitiesifreq.form.has_key('__delete'):todelete=req.list_form_param('__delete',req.form,pop=True)iftodelete:autoform.delete_relations(self._cw,todelete)ifreq.form.has_key('__insert'):warn('[3.6] stop using __insert, support will be removed',DeprecationWarning)toinsert=req.list_form_param('__insert',req.form,pop=True)iftoinsert:autoform.insert_relations(self._cw,toinsert)self._cw.remove_pending_operations()ifself.errors:errors=dict((f.name,unicode(ex))forf,exinself.errors)raiseValidationError(form.get('__maineid'),errors)def_insert_entity(self,etype,eid,rqlquery):rql=rqlquery.insert_query(etype)try:# get the new entity (in some cases, the type might have# changed as for the File --> Image mutation)entity=self._cw.execute(rql,rqlquery.kwargs).get_entity(0,0)neweid=entity.eidexceptValidationError,ex:self._to_create[eid]=ex.entityifself._cw.json_request:# XXX (syt) why?ex.entity=eidraiseself._to_create[eid]=neweidreturnneweiddef_update_entity(self,eid,rqlquery):self._cw.execute(rqlquery.update_query(eid),rqlquery.kwargs)defedit_entity(self,formparams,multiple=False):"""edit / create / copy an entity and return its eid"""etype=formparams['__type']entity=self._cw.vreg['etypes'].etype_class(etype)(self._cw)entity.eid=formparams['eid']is_main_entity=self._cw.form.get('__maineid')==formparams['eid']# let a chance to do some entity specific stuffentity.pre_web_edit()# create a rql query from parametersrqlquery=RqlQuery()# process inlined relations at the same time as attributes# this will generate less rql queries and might be useful in# a few dark cornersformid=self._cw.form.get('__form_id','edition')form=self._cw.vreg['forms'].select(formid,self._cw,entity=entity)eid=form.actual_eid(entity.eid)form.formvalues={}# init fields value cachetry:editedfields=formparams['_cw_edited_fields']exceptKeyError:raiseRequestError(self._cw._('no edited fields specified for entity %s'%entity.eid))foreditedfieldinsplitstrip(editedfields):try:name,role=editedfield.split('-')except:name=editedfieldrole=Noneifform.field_by_name.im_func.func_code.co_argcount==4:# XXXfield=form.field_by_name(name,role,eschema=entity.e_schema)else:field=form.field_by_name(name,role)forfieldinfield.actual_fields(form):iffield.has_been_modified(form):self.handle_formfield(form,field,rqlquery)ifself.errors:errors=dict((f.role_name(),unicode(ex))forf,exinself.errors)raiseValidationError(entity.eid,errors)ifeidisNone:# creation or copyentity.eid=self._insert_entity(etype,formparams['eid'],rqlquery)elifrqlquery.edited:# edition of an existant entityself._update_entity(eid,rqlquery)ifis_main_entity:self.notify_edited(entity)ifformparams.has_key('__delete'):# XXX deprecate?todelete=self._cw.list_form_param('__delete',formparams,pop=True)autoform.delete_relations(self._cw,todelete)ifformparams.has_key('__cloned_eid'):entity.copy_relations(typed_eid(formparams['__cloned_eid']))ifis_main_entity:# only execute linkto for the main entityself.execute_linkto(entity.eid)returneiddefhandle_formfield(self,form,field,rqlquery=None):eschema=form.edited_entity.e_schematry:forfield,valueinfield.process_posted(form):ifnot((field.role=='subject'andfield.nameineschema.subjrels)or(field.role=='object'andfield.nameineschema.objrels)):continuerschema=self._cw.vreg.schema.rschema(field.name)ifrschema.final:rqlquery.kwargs[field.name]=valuerqlquery.edited.append('X %s%%(%s)s'%(rschema,rschema))else:ifform.edited_entity.has_eid():origvalues=set(entity.eidforentityinform.edited_entity.related(field.name,field.role,entities=True))else:origvalues=set()ifvalueisNoneorvalue==origvalues:continue# not edited / not modified / to do laterifrschema.inlinedandrqlqueryisnotNoneandfield.role=='subject':self.handle_inlined_relation(form,field,value,origvalues,rqlquery)elifform.edited_entity.has_eid():self.handle_relation(form,field,value,origvalues)else:self._pending_fields.add((form,field))exceptProcessFormError,exc:self.errors.append((field,exc))defhandle_inlined_relation(self,form,field,values,origvalues,rqlquery):"""handle edition for the (rschema, x) relation of the given entity """attr=field.nameifvalues:rqlquery.kwargs[attr]=iter(values).next()rqlquery.edited.append('X %s%s'%(attr,attr.upper()))rqlquery.restrictions.append('%s eid %%(%s)s'%(attr.upper(),attr))elifform.edited_entity.has_eid():self.handle_relation(form,field,values,origvalues)defhandle_relation(self,form,field,values,origvalues):"""handle edition for the (rschema, x) relation of the given entity """etype=form.edited_entity.e_schemarschema=self._cw.vreg.schema.rschema(field.name)iffield.role=='subject':desttype=rschema.objects(etype)[0]card=rschema.rdef(etype,desttype).cardinality[0]subjvar,objvar='X','Y'else:desttype=rschema.subjects(etype)[0]card=rschema.rdef(desttype,etype).cardinality[1]subjvar,objvar='Y','X'eid=form.edited_entity.eidiffield.role=='object'ornotrschema.inlinedornotvalues:# this is not an inlined relation or no values specified,# explicty remove relationsrql='DELETE %s%s%s WHERE X eid %%(x)s, Y eid %%(y)s'%(subjvar,rschema,objvar)forreidinorigvalues.difference(values):self.relations_rql.append((rql,{'x':eid,'y':reid},('x','y')))seteids=values.difference(origvalues)ifseteids:rql='SET %s%s%s WHERE X eid %%(x)s, Y eid %%(y)s'%(subjvar,rschema,objvar)forreidinseteids:self.relations_rql.append((rql,{'x':eid,'y':reid},('x','y')))def_action_apply(self):self._default_publish()self.reset()def_action_cancel(self):errorurl=self._cw.form.get('__errorurl')iferrorurl:self._cw.cancel_edition(errorurl)self._cw.message=self._cw._('edit canceled')returnself.reset()def_action_delete(self):self.delete_entities(self._cw.edited_eids(withtype=True))returnself.reset()