-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow opt-in to recursive unpublish #23
Comments
Actually I'm not sure if this is a good idea: Even for a straightforward |
If we were relying on has_one or has_many to implicitly control this, it would be dangerous, but if it's explicitly related to using the $owns static then developers are opting-in already. $owns may need documentation around its power. Alternatively, you could create multiple static owns_publishes, owns_unpublishes, but I suspect people will just use onAfters to write more complex custom code and avoid owns altogether. |
So I did have a think about it, and there are two kinds of exclusive relationships:
We probably need an unpublish control similar to below class MyObject extends DataObject {
/**
* Determine when to unpublish this object:
* - Versioned::EXCLUSIVE_OWNER - Unpublished when only the exclusive owner is unpublished via has_many to this object (default)
* - Versioned::SINGLE_OWNER - Unpublished when the last owner is unpublished
* - Versioned::EXPLICIT - Object must be explicitly unpublished
*/
private static $unpublished_by = Versioned::EXCLUSIVE_OWNER;
} We would set this to EXPLICIT for files, but the default for other dataobjects is exclusive_owner. We could also use this to replace the unlinkDisownedObjects (doesn't unpublish has_many objects, but sets the has_one on the object to 0 when doing a partial publish). Essentially we would be auto-implement staging of deleted has_many. Existing code below: /**
* Set foreign keys of has_many objects to 0 where those objects were
* disowned as a result of a partial publish / unpublish.
* I.e. this object and its owned objects were recently written to $targetStage,
* but deleted objects were not.
*
* Note that this operation does not create any new Versions
*
* @param string $sourceStage Objects in this stage will not be unlinked.
* @param string $targetStage Objects which exist in this stage but not $sourceStage
* will be unlinked.
*/
public function unlinkDisownedObjects($sourceStage, $targetStage) {} |
There's something pretty important there: Auto-unpublish cascade === Auto-delete cascade I think that focusing on unpublish in isolation is going to lead to an inconsistent model. "unpublish" really just mean "delete from live", after all. Because of this I think that My preference is that the config goes on the parent object and not the child objects (so "cascade_deletes" and not "cascade_deletes_from") because the latter is too much like aspect-oriented programming. If cascade_deletes isn't set, then the current behaviour of clearing the has_one record makes sense. The behaviour of cascade_deletes on a many-many relationship would be a little tricky: my interpretation would be that if you set cascade_deletes on a many-many relationship, then the foreign object would be deleted when the it was linked to no more records on that relationship. I think as long as we're clear about the semantics, developers can decide whether to enable it. |
Do you want it to apply to non-versioned objects? I had thought of moving ownership out of versioned, and making it something that all objects can use. |
I don't see that we have a choice without creating a fundamentally inconsistent model. Strictly speaking, "cascade_deletes" could be on the base ORM and "owns" could still be part of versioned, as owns controls the cascade of publications, which is a creation even and "cascade_create" doesn't mean any thing outside of a multi-stage data structure.
Not really an option, and I don't think it's necessary. |
It's starting to feel like what we really want to do isn't going to be a non-breaking API. |
I don't see how something can (or should) cascade delete if it isn't owned. |
By writing code that does it. :-P If i understand your comment correctly, you mean more "it would seem inconsistent to have an owns property in our schema and not use it to control the behaviour of cascade deletes". To which I'd say, sure, but:
|
What I mean is, I don't know why an object should cascade delete but not cascade publish. I thought cascades would be a subset of owns. But back to what you are suggesting, you mean owns for publishing, cascade for deletes, and these are independent? |
I agree that it would be more logical, but it's not worth breaking the API for.
Yes, as a way of introducing the required functionality without breaking APIs, I was suggesting that. If you can come up with something that ties owns and cascade-deletes together, and doesn't break APIs, I'd support that. |
ok, I think that sounds like a safe direction; One that doesn't need to rely on versioned right? Could it be a CasecadeDeleteExtension? (so it's not baked into dataobject) |
It could be an extension I supposed - would it be pulled in automatically by Versioned? However I kind of see it as part of relational integrity and as such it could go into DataObject if needs be. |
Yeah it could be a part of versioned, maybe, or just SilverStripe\ORM? |
Question for @chillu We have looked at two possible directions:
I don't see either feature being significantly more difficult than one another; Recursive delete may be more useful in more cases, but will have a more significant effect on framework. Given that it'll be opt-in, it shouldn't have any unexpected consequences. My preference is recursive delete, and we have a @chillu if you are happy with this direction, I'll write up the new A/C in the body of this issue and write up tasks. Otherwise discuss. :) |
I think we should clearly separate "ACs" (which is what's already there) and "recommended implementation" (something new to write). I think that we risk losing context of why when we replace ACs with specific technical implementations. |
I've added new ACs reflecting the state of discussion. Hopefully I haven't put too much implementation detail in there. In broad strokes, I think it should be opt-in, there should no inferring of cascades based on relationship/ownership type, and that we don't need to introduce a concept of "exclusive ownership" to make this work. Original ACs for reference:
|
Acceptance Criteria
Notes
ChangeSet
model trackingTasks
PRs
Related
The text was updated successfully, but these errors were encountered: