Browse Source

Added a first implementation of the set_rank method in LeRelation

Roland Haroutiounian 9 years ago
parent
commit
4af1606b04
2 changed files with 68 additions and 0 deletions
  1. 43
    0
      DataSource/MySQL/leapidatasource.py
  2. 25
    0
      leapi/lerelation.py

+ 43
- 0
DataSource/MySQL/leapidatasource.py View File

320
     # @param letype LeType(class) : We want related LeObject of this LeType child class (not instance)
320
     # @param letype LeType(class) : We want related LeObject of this LeType child class (not instance)
321
     # @param get_sub bool : If True leo is the superior and we want subordinates, else its the opposite
321
     # @param get_sub bool : If True leo is the superior and we want subordinates, else its the opposite
322
     # @return a list of dict { 'id_relation':.., 'rank':.., 'lesup':.., 'lesub'.., 'rel_attrs': dict() }
322
     # @return a list of dict { 'id_relation':.., 'rank':.., 'lesup':.., 'lesub'.., 'rel_attrs': dict() }
323
+    # TODO A conserver , utilisé par la nouvelle méthode update_rank
323
     def get_related(self, leo, letype, get_sub=True):
324
     def get_related(self, leo, letype, get_sub=True):
324
         if LeCrud.name2class('LeType') not in letype.__bases__:
325
         if LeCrud.name2class('LeType') not in letype.__bases__:
325
             raise ValueError("letype argument should be a LeType child class, but got %s" % type(letype))
326
             raise ValueError("letype argument should be a LeType child class, but got %s" % type(letype))
397
         self._check_rank(rank)
398
         self._check_rank(rank)
398
         self._set_relation_rank(id_relation, rank)
399
         self._set_relation_rank(id_relation, rank)
399
 
400
 
401
+    ## @brief Sets a new rank on a relation
402
+    # @param id_relation int: relation ID
403
+    # @param rank int|str|tuple : 'first', 'last', an integer value or a (operator, value) tuple (for the shifting)
404
+    # @throw leapi.leapi.LeObjectQueryError if id_relation doesn't exist
405
+    #
406
+    # TODO Conserver cette méthode dans le datasource du fait des requêtes SQL. Elle est appelée par le set_rank de LeRelation
407
+    def update_rank(self, id_relation, rank):
408
+        ret = self.get_relation(id_relation, no_attr=True)
409
+        if not ret:
410
+            raise leapi.leapi.LeObjectQueryError("No relation with id_relation = %d" % id_relation)
411
+        lesup = ret['lesup']
412
+        lesub = ret['lesub']
413
+        current_rank = ret['rank']
414
+
415
+        # In case we passed an (operator, value) tuple, we will recalculate the new rank
416
+        if isinstance(rank, tuple):
417
+            operator = rank[0]
418
+            step_value = rank[1]
419
+            rank = current_rank + step_value if operator == '+' else current_rank - step_value
420
+
421
+        rank = 1 if rank == 'first' or rank < 1 else rank
422
+        if current_rank == rank:
423
+            return True
424
+
425
+        relations = self.get_related(lesup, lesub.__class__, get_sub=True)
426
+
427
+        if rank == 'last' or rank > len(relations):
428
+            rank = len(relations)
429
+            if current_rank == rank:
430
+                return True
431
+
432
+        # insert the relation at the right position considering its new rank
433
+        our_relation = relations.pop(current_rank)
434
+        relations.insert(our_relation, rank)
435
+
436
+        # rebuild now the list of relations from the resorted list and recalculating the ranks
437
+        rdatas = [(attrs['relation_id'], new_rank+1) for new_rank, (sup, sub, attrs) in enumerate(relations)]
438
+
439
+        sql = insert(MySQL.relations_table_name, columns=(MySQL.relations_pkname, 'rank'), values=rdatas, on_duplicate_key_update={'rank', mosql.util.raw('VALUES(`rank`)')})
440
+
441
+
400
     ## @brief Set the rank of a relation identified by its ID
442
     ## @brief Set the rank of a relation identified by its ID
401
     #
443
     #
402
     # @note this solution is not the more efficient solution but it
444
     # @note this solution is not the more efficient solution but it
492
     # @return a dict{'id_relation':.., 'lesup':.., 'lesub':..,'rank':.., 'depth':.., #if not none#'nature':.., #if exists#'dict_attr':..>}
534
     # @return a dict{'id_relation':.., 'lesup':.., 'lesub':..,'rank':.., 'depth':.., #if not none#'nature':.., #if exists#'dict_attr':..>}
493
     #
535
     #
494
     # @todo TESTS
536
     # @todo TESTS
537
+    # TODO conserver, appelé par la méthode update_rank
495
     def get_relation(self, id_relation, no_attr=False):
538
     def get_relation(self, id_relation, no_attr=False):
496
         relation = dict()
539
         relation = dict()
497
         with self.connection as cur:
540
         with self.connection as cur:

+ 25
- 0
leapi/lerelation.py View File

6
 import EditorialModel.fieldtypes.leo as ft_leo
6
 import EditorialModel.fieldtypes.leo as ft_leo
7
 from . import lecrud
7
 from . import lecrud
8
 from . import leobject
8
 from . import leobject
9
+from . import lefactory
9
 
10
 
10
 ## @brief Main class for relations
11
 ## @brief Main class for relations
11
 class _LeRelation(lecrud._LeCrud):
12
 class _LeRelation(lecrud._LeCrud):
82
         ret = cls._datasource.delete(target_class, filters)
83
         ret = cls._datasource.delete(target_class, filters)
83
         return True if ret == 1 else False
84
         return True if ret == 1 else False
84
 
85
 
86
+    ## @brief move to the first rank
87
+    # @return True in case of success, False in case of failure
88
+    def move_first(self):
89
+        return self.set_rank('first')
90
+
91
+    ## @brief move to the last rank
92
+    # @return True in case of success, False in case of failure
93
+    def move_last(self):
94
+        return self.set_rank('last')
95
+
96
+    ## @brief move to the given rank defined by a shift step
97
+    # @param step str|int Step of the rank shift. Can be a string containing an operator and the value (i.e. "+6"
98
+    #                                               or "-6"), or can be an integer (the operator will then be "+")
99
+    # @return True in case of success, False in case of failure
100
+    def shift_rank(self, step):
101
+        return self.set_rank(step)
102
+
103
+    ## @brief sets a new rank
104
+    # @return True in case of success, False in case of failure
105
+    def set_rank(self, rank):
106
+        parsed_rank = self.__class__._parse_rank(rank)
107
+        return self._datasource.update_rank(self.id_relation, rank)
108
+
109
+
85
     @classmethod
110
     @classmethod
86
     ## @brief checks if a rank value is valid
111
     ## @brief checks if a rank value is valid
87
     # @param rank str|int
112
     # @param rank str|int

Loading…
Cancel
Save