-
Notifications
You must be signed in to change notification settings - Fork 24
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
Add 'forceDelete' setting to CouplerBehavior #59
base: cake-2.0
Are you sure you want to change the base?
Conversation
If set to true, record deletion will proceed even if original media file was not found in baseDirectory.
Could you also add tests for this? Generally the whole delete stuff really needs some specific tests, wish I had some time for this. I think having the possibility to force a delete would generally be useful, and I think it should be disabled by default as it would otherwise break backwards compatibility. The default behavior is generally debatable, but I'd say currently compatibility should be more important.
Generally issuing a notice, or maybe even a warning for missing files might be an idea, personally, as a developer, I'd like to know about such problems, so I can see how being able to log these kind of problems can be useful even when forcing deletes. Are you sure the |
You're right, I really lack experience in building test cases, but I'll try to make some time for this
True. Perhaps to be revised when we'll need a cake 3.0 rewrite
Sorry, I meant the opposite, 'File' does not, 'unlink()' does. Rephrased the above for clarification |
I have a little bit of free time, so I can add tests for this if you want. I'll add some coupler behavior specific delete tests anyways... Back to the warning, I think the So I'd say when file deletion fails it should trigger a warning ( |
There are actually a few more possible scenarios : deletion may not work because the file no longer exists or by lack of permission. There's also the problem of race conditions. Depending on user-scenario you might, or might not, want to alert the user or prompt for his confirmation that the record is to be deleted. (parts of that would probably best be done at validation stage though) So I think it's best not to make assumptions, but I'm really banging my head on how to impliment a flexible solution. On a hunch I would go for throwing Exceptions — but am lost as to where these should be caught so as to be useable by the app but not stopping execution: public function beforeDelete(Model $Model, $cascade = true) {
// .... //
$file = $baseDirectory;
$file .= $result[$Model->alias]['dirname'];
$file .= DS . $result[$Model->alias]['basename'];
try {
if (!@unlink($file)) {
$error = error_get_last();
if (strpos($error['message'], 'No such file or directory')) {
throw new MediaNotFoundException(array('file' => $file));
} elseif (strpos($error['message'], 'Permission denied')) {
throw new MediaDeletePermissionException(array('file' => $file));
}
}
} catch (Exception $e) {
if (!$this->settings[$Model->alias]['forceDelete']) {
return false;
}
// How to send Exception $e to the controller
// while continuing the record deletion ??
}
return true;
} … so I guess the most elegant, albeit not the most convenient, solution would be to let Or would there be any other way to let the controller know that the file deletion failed ? Other thought : @bmcclure created the |
You can't pass data back to the controller directly, at least not with the default With 2.x, exposing details would for example be possible using events, callback functions, or methods/properties that return/hold information about the errors that occoured, however I'm not sure if I would use exceptions for this, as they seem to be more appropriate for severe problems where something goes so wrong that it's not possible to continue without errors anymore (Printer On Fire 🔥 anyone? ;)). When passing them around like that, then it's not really exception handling anymore, but more like simply error handling where error codes would do it too. Personally I'm all for exposing details, the question is how much information do you really need in the controller? Permissions, open-base-dir restrictions, file doesn't exist, path isn't a file, etc, wouldn't it maybe be enough to know that the file couldn't not be/wasn't deleted because of a problem whichs details can be found in the logs? Also what about file creation/transfer when creating a record, it's more or less the same problem as it also doesn't return any details about why it failed (apart from validation), but will only trigger errors (in some cases). I think when implementing a more detailed error reporting then it should be as consistent as possible throughout the whole plugin. |
Ah, I've overlooked your latest commit, sorry :) I kinda like it, though properties on behaviors aren't accessible directly via the model, so one would have to access The exception is pretty drastic, though I can see how it would be helpful to for example halt the process of deleting associated records, and in that case also the deletion of the record itself, that way one wouldn't be left with orphaned associated records, which would be pretty nice actually. However, I'm not sure whether there might be any side effects, at the very last it's not backwards compatible when thrown by default? |
I still like the general idea, however there are still some questions left... |
Current behavior :
When deleting the record for a media, if the original file is not found in the transfer directory, record deletion is interrupted without any warning
Proposed fix:
A $forceDelete setting is added to CouplerBeharvior. If set to true, record deletion will proceed even if original media file was not found in baseDirectory. Defaults to false (but does this make sense, see bullet point)
Further thinking:
Should a warning be issued when the file is not found instead or in addition to this behavior ? Would the best approach to this be to use php's unlink() method instead of File::delete() (as unlink() issues an E_WARNING when the file is not found whereas File::delete() doesn't ) ?