512 'SET E %s P WHERE X %s P, X eid %%(x)s, E eid %%(e)s, NOT E %s P' |
516 'SET E %s P WHERE X %s P, X eid %%(x)s, E eid %%(e)s, NOT E %s P' |
513 % (self.main_rtype, self.main_rtype, self.main_rtype), |
517 % (self.main_rtype, self.main_rtype, self.main_rtype), |
514 {'x': meid, 'e': seid}) |
518 {'x': meid, 'e': seid}) |
515 |
519 |
516 |
520 |
517 class PropagateSubjectRelationAddHook(Hook): |
521 class PropagateRelationAddHook(Hook): |
518 """propagate to entities at the end of watched relations when a `main_rtype` |
522 """Propagate to entities at the end of watched relations when a `main_rtype` |
519 relation is added |
523 relation is added. |
|
524 |
|
525 `subject_relations` and `object_relations` attributes should be specified on |
|
526 subclasses and are usually shared references with attributes of the same |
|
527 name on :class:`PropagateRelationHook`. |
|
528 |
|
529 Because of those shared references, you can use `skip_subject_relations` and |
|
530 `skip_object_relations` attributes when you don't want to propagate to |
|
531 entities linked through some particular relations. |
520 """ |
532 """ |
521 events = ('after_add_relation',) |
533 events = ('after_add_relation',) |
522 |
534 |
523 # to set in concrete class |
535 # to set in concrete class (mandatory) |
524 subject_relations = None |
536 subject_relations = None |
525 object_relations = None |
537 object_relations = None |
|
538 # to set in concrete class (optionaly) |
|
539 skip_subject_relations = () |
|
540 skip_object_relations = () |
526 |
541 |
527 def __call__(self): |
542 def __call__(self): |
528 eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0]) |
543 eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0]) |
529 execute = self._cw.execute |
544 execute = self._cw.execute |
530 for rel in self.subject_relations: |
545 for rel in self.subject_relations: |
531 if rel in eschema.subjrels: |
546 if rel in eschema.subjrels and not rel in self.skip_subject_relations: |
532 execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
547 execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
533 'X %s R, NOT R %s P' % (self.rtype, rel, self.rtype), |
548 'X %s R, NOT R %s P' % (self.rtype, rel, self.rtype), |
534 {'x': self.eidfrom, 'p': self.eidto}) |
549 {'x': self.eidfrom, 'p': self.eidto}) |
535 for rel in self.object_relations: |
550 for rel in self.object_relations: |
536 if rel in eschema.objrels: |
551 if rel in eschema.objrels and not rel in self.skip_object_relations: |
537 execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
552 execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
538 'R %s X, NOT R %s P' % (self.rtype, rel, self.rtype), |
553 'R %s X, NOT R %s P' % (self.rtype, rel, self.rtype), |
539 {'x': self.eidfrom, 'p': self.eidto}) |
554 {'x': self.eidfrom, 'p': self.eidto}) |
540 |
555 |
541 |
556 |
542 class PropagateSubjectRelationDelHook(Hook): |
557 class PropagateRelationDelHook(PropagateRelationAddHook): |
543 """propagate to entities at the end of watched relations when a `main_rtype` |
558 """Propagate to entities at the end of watched relations when a `main_rtype` |
544 relation is deleted |
559 relation is deleted. |
|
560 |
|
561 This is the opposite of the :class:`PropagateRelationAddHook`, see its |
|
562 documentation for how to use this class. |
545 """ |
563 """ |
546 events = ('after_delete_relation',) |
564 events = ('after_delete_relation',) |
547 |
|
548 # to set in concrete class |
|
549 subject_relations = None |
|
550 object_relations = None |
|
551 |
565 |
552 def __call__(self): |
566 def __call__(self): |
553 eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0]) |
567 eschema = self._cw.vreg.schema.eschema(self._cw.describe(self.eidfrom)[0]) |
554 execute = self._cw.execute |
568 execute = self._cw.execute |
555 for rel in self.subject_relations: |
569 for rel in self.subject_relations: |
556 if rel in eschema.subjrels: |
570 if rel in eschema.subjrels and not rel in self.skip_subject_relations: |
557 execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
571 execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
558 'X %s R' % (self.rtype, rel), |
572 'X %s R' % (self.rtype, rel), |
559 {'x': self.eidfrom, 'p': self.eidto}) |
573 {'x': self.eidfrom, 'p': self.eidto}) |
560 for rel in self.object_relations: |
574 for rel in self.object_relations: |
561 if rel in eschema.objrels: |
575 if rel in eschema.objrels and not rel in self.skip_object_relations: |
562 execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
576 execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
563 'R %s X' % (self.rtype, rel), |
577 'R %s X' % (self.rtype, rel), |
564 {'x': self.eidfrom, 'p': self.eidto}) |
578 {'x': self.eidfrom, 'p': self.eidto}) |
|
579 |
|
580 |
|
581 PropagateSubjectRelationHook = class_renamed( |
|
582 'PropagateSubjectRelationHook', PropagateRelationHook, |
|
583 '[3.9] PropagateSubjectRelationHook has been renamed to PropagateRelationHook') |
|
584 PropagateSubjectRelationAddHook = class_renamed( |
|
585 'PropagateSubjectRelationAddHook', PropagateRelationAddHook, |
|
586 '[3.9] PropagateSubjectRelationAddHook has been renamed to PropagateRelationAddHook') |
|
587 PropagateSubjectRelationDelHook = class_renamed( |
|
588 'PropagateSubjectRelationDelHook', PropagateRelationDelHook, |
|
589 '[3.9] PropagateSubjectRelationDelHook has been renamed to PropagateRelationDelHook') |
565 |
590 |
566 |
591 |
567 # abstract classes for operation ############################################### |
592 # abstract classes for operation ############################################### |
568 |
593 |
569 class Operation(object): |
594 class Operation(object): |