1- # $Id: client.py,v 1.91 2003-02-18 01:59:10 richard Exp $
1+ # $Id: client.py,v 1.92 2003-02-18 03:58:18 richard Exp $
22
33__doc__ = """
44WWW request handler (also used in the stand-alone server).
@@ -778,16 +778,13 @@ def newItemAction(self):
778778# try:
779779 if 1 :
780780 # create the context here
781- cn = self .classname
782- nid = self ._createnode (cn , props [(cn , None )])
783- del props [(cn , None )]
781+ # cn = self.classname
782+ # nid = self._createnode(cn, props[(cn, None)])
783+ # del props[(cn, None)]
784784
785- extra = self ._editnodes (props , links , {(cn , None ): nid })
786- if extra :
787- extra = '<br>' + extra
785+ # when it hits the None element, it'll set self.nodeid
786+ messages = self ._editnodes (props , links ) #, {(cn, None): nid})
788787
789- # now do the rest
790- messages = '%s %s created' % (cn , nid ) + extra
791788# except (ValueError, KeyError, IndexError), message:
792789# # these errors might just be indicative of user dumbness
793790# self.error_message.append(_('Error: ') + str(message))
@@ -798,7 +795,7 @@ def newItemAction(self):
798795
799796 # redirect to the new item's page
800797 raise Redirect , '%s%s%s?@ok_message=%s' % (self .base , self .classname ,
801- nid , urllib .quote (messages ))
798+ self . nodeid , urllib .quote (messages ))
802799
803800 def newItemPermission (self , props ):
804801 ''' Determine whether the user has permission to create (edit) this
@@ -816,6 +813,119 @@ def newItemPermission(self, props):
816813 return 1
817814 return 0
818815
816+
817+ #
818+ # Utility methods for editing
819+ #
820+ def _editnodes (self , all_props , all_links , newids = None ):
821+ ''' Use the props in all_props to perform edit and creation, then
822+ use the link specs in all_links to do linking.
823+ '''
824+ # figure dependencies and re-work links
825+ deps = {}
826+ links = {}
827+ for cn , nodeid , propname , vlist in all_links :
828+ for value in vlist :
829+ deps .setdefault ((cn , nodeid ), []).append (value )
830+ links .setdefault (value , []).append ((cn , nodeid , propname ))
831+
832+ # figure chained dependencies ordering
833+ order = []
834+ done = {}
835+ # loop detection
836+ change = 0
837+ while len (all_props ) != len (done ):
838+ for needed in all_props .keys ():
839+ if done .has_key (needed ):
840+ continue
841+ tlist = deps .get (needed , [])
842+ for target in tlist :
843+ if not done .has_key (target ):
844+ break
845+ else :
846+ done [needed ] = 1
847+ order .append (needed )
848+ change = 1
849+ if not change :
850+ raise ValueError , 'linking must not loop!'
851+
852+ # now, edit / create
853+ m = []
854+ for needed in order :
855+ props = all_props [needed ]
856+ cn , nodeid = needed
857+
858+ if nodeid is not None and int (nodeid ) > 0 :
859+ # make changes to the node
860+ props = self ._changenode (cn , nodeid , props )
861+
862+ # and some nice feedback for the user
863+ if props :
864+ info = ', ' .join (props .keys ())
865+ m .append ('%s %s %s edited ok' % (cn , nodeid , info ))
866+ else :
867+ m .append ('%s %s - nothing changed' % (cn , nodeid ))
868+ else :
869+ assert props
870+
871+ # make a new node
872+ newid = self ._createnode (cn , props )
873+ if nodeid is None :
874+ self .nodeid = newid
875+ nodeid = newid
876+
877+ # and some nice feedback for the user
878+ m .append ('%s %s created' % (cn , newid ))
879+
880+ # fill in new ids in links
881+ if links .has_key (needed ):
882+ for linkcn , linkid , linkprop in links [needed ]:
883+ props = all_props [(linkcn , linkid )]
884+ cl = self .db .classes [linkcn ]
885+ propdef = cl .getprops ()[linkprop ]
886+ if not props .has_key (linkprop ):
887+ if linkid is None or linkid .startswith ('-' ):
888+ # linking to a new item
889+ if isinstance (propdef , hyperdb .Multilink ):
890+ props [linkprop ] = [newid ]
891+ else :
892+ props [linkprop ] = newid
893+ else :
894+ # linking to an existing item
895+ if isinstance (propdef , hyperdb .Multilink ):
896+ existing = cl .get (linkid , linkprop )[:]
897+ existing .append (nodeid )
898+ props [linkprop ] = existing
899+ else :
900+ props [linkprop ] = newid
901+
902+ return '<br>' .join (m )
903+
904+ def _changenode (self , cn , nodeid , props ):
905+ ''' change the node based on the contents of the form
906+ '''
907+ # check for permission
908+ if not self .editItemPermission (props ):
909+ raise PermissionError , 'You do not have permission to edit %s' % cn
910+
911+ # make the changes
912+ cl = self .db .classes [cn ]
913+ return cl .set (nodeid , ** props )
914+
915+ def _createnode (self , cn , props ):
916+ ''' create a node based on the contents of the form
917+ '''
918+ # check for permission
919+ if not self .newItemPermission (props ):
920+ raise PermissionError , 'You do not have permission to create %s' % cn
921+
922+ # create the node and return its id
923+ cl = self .db .classes [cn ]
924+ return cl .create (** props )
925+
926+ #
927+ # More actions
928+ #
819929 def editCSVAction (self ):
820930 ''' Performs an edit of all of a class' items in one go.
821931
@@ -1023,90 +1133,6 @@ def showAction(self):
10231133 url = '%s%s%s' % (self .db .config .TRACKER_WEB , t , n )
10241134 raise Redirect , url
10251135
1026-
1027- #
1028- # Utility methods for editing
1029- #
1030- def _editnodes (self , all_props , all_links , newids = None ):
1031- ''' Use the props in all_props to perform edit and creation, then
1032- use the link specs in all_links to do linking.
1033- '''
1034- m = []
1035- if newids is None :
1036- newids = {}
1037- for (cn , nodeid ), props in all_props .items ():
1038- if int (nodeid ) > 0 :
1039- # make changes to the node
1040- props = self ._changenode (cn , nodeid , props )
1041-
1042- # and some nice feedback for the user
1043- if props :
1044- info = ', ' .join (props .keys ())
1045- m .append ('%s %s %s edited ok' % (cn , nodeid , info ))
1046- else :
1047- m .append ('%s %s - nothing changed' % (cn , nodeid ))
1048- elif props :
1049- # make a new node
1050- newid = self ._createnode (cn , props )
1051- newids [(cn , nodeid )] = newid
1052- nodeid = newid
1053-
1054- # and some nice feedback for the user
1055- m .append ('%s %s created' % (cn , newid ))
1056-
1057- # handle linked nodes
1058- keys = self .form .keys ()
1059- for cn , nodeid , propname , value in all_links :
1060- cl = self .db .classes [cn ]
1061- property = cl .getprops ()[propname ]
1062- if nodeid is None or nodeid .startswith ('-' ):
1063- if not newids .has_key ((cn , nodeid )):
1064- continue
1065- nodeid = newids [(cn , nodeid )]
1066-
1067- # map the desired classnames to their actual created ids
1068- for link in value :
1069- if not newids .has_key (link ):
1070- continue
1071- linkid = newids [link ]
1072- if isinstance (property , hyperdb .Multilink ):
1073- # take a dupe of the list so we're not changing the cache
1074- existing = cl .get (nodeid , propname )[:]
1075- existing .append (linkid )
1076- cl .set (nodeid , ** {propname : existing })
1077- elif isinstance (property , hyperdb .Link ):
1078- # make the Link set
1079- cl .set (nodeid , ** {propname : linkid })
1080- else :
1081- raise ValueError , '%s %s is not a link or multilink ' \
1082- 'property' % (cn , propname )
1083- m .append ('%s %s linked to <a href="%s%s">%s %s</a>' % (
1084- link [0 ], linkid , cn , nodeid , cn , nodeid ))
1085-
1086- return '<br>' .join (m )
1087-
1088- def _changenode (self , cn , nodeid , props ):
1089- ''' change the node based on the contents of the form
1090- '''
1091- # check for permission
1092- if not self .editItemPermission (props ):
1093- raise PermissionError , 'You do not have permission to edit %s' % cn
1094-
1095- # make the changes
1096- cl = self .db .classes [cn ]
1097- return cl .set (nodeid , ** props )
1098-
1099- def _createnode (self , cn , props ):
1100- ''' create a node based on the contents of the form
1101- '''
1102- # check for permission
1103- if not self .newItemPermission (props ):
1104- raise PermissionError , 'You do not have permission to create %s' % cn
1105-
1106- # create the node and return its id
1107- cl = self .db .classes [cn ]
1108- return cl .create (** props )
1109-
11101136 def parsePropsFromForm (self , num_re = re .compile ('^\d+$' )):
11111137 ''' Pull properties out of the form.
11121138
@@ -1267,6 +1293,13 @@ class <designator> (where <designator> must be
12671293 raise ValueError , \
12681294 'link "%s" value "%s" not a designator' % (key , entry )
12691295 value .append ((m .group (1 ), m .group (2 )))
1296+
1297+ # make sure the link property is valid
1298+ if (not isinstance (propdef , hyperdb .Multilink ) and
1299+ not isinstance (propdef , hyperdb .Link )):
1300+ raise ValueError , '%s %s is not a link or ' \
1301+ 'multilink property' % (cn , propname )
1302+
12701303 all_links .append ((cn , nodeid , propname , value ))
12711304 continue
12721305
@@ -1525,7 +1558,22 @@ class <designator> (where <designator> must be
15251558 if not props .get ('content' , '' ):
15261559 del all_props [(cn , id )]
15271560
1528- return all_props , all_links
1561+ # clean up the links, removing ones that aren't possible
1562+ l = []
1563+ for entry in all_links :
1564+ (cn , nodeid , propname , destlist ) = entry
1565+ source = (cn , nodeid )
1566+ if not all_props .has_key (source ) or not all_props [source ]:
1567+ # nothing to create - don't try to link
1568+ continue
1569+ # nothing to create - don't try to link
1570+ continue
1571+ for dest in destlist [:]:
1572+ if not all_props .has_key (dest ) or not all_props [dest ]:
1573+ destlist .remove (dest )
1574+ l .append (entry )
1575+
1576+ return all_props , l
15291577
15301578def fixNewlines (text ):
15311579 ''' Homogenise line endings.
0 commit comments