Importers are only allowed to throw ImporterException. Each particular importer should throw a subclassed exception in order to make it easier to know where the exception comes from.
Any exception that happens inside the importer should be wrapped in an ImporterException, or one of the subclasses. For example, if a FileNotFoundException happens inside the share importer, the share importer should wrap the exception in a ShareImporterException or in a subclass such as ShareImporterFileException.
Exporter and extractor will behave the same as the importers for the error handling: each particular component will throw its own exception.
The OCA\DataExporter\Importer will only catch ImporterException. Specific subclasses might be catched and handled if needed, although most of this work should be done already by the MetadataImporter (which is acting as the root component)
The OCA\DataExporter\Exporter will behave the same as the importer.
Each command is expected to catch only either ImporterException (for the "import:user" command) and ExporterException (for the "export:user" and "export:migrate:share" commands), mainly to show the exception class and the message. This should allow easier debugging of known errors.
Unhandled exceptions are expected to show a full stack trace. Commands mustn't catch these exceptions. The intention here is to debug what's happening as this should be considered as an unknown scenario that shouldn't happen. Proper fix is to either convert the exception to an ImporterException or ExporterException if it can't be handled (this should be done in either the OCA\DataExporter\Importer or OCA\DataExporter\Exporter classes) or handle it properly wherever it can be handled.
In addition:
Models musn't throw exceptions.
Utility classes might throw exceptions.
If the exception is originated in the utility class, throw a custom exception. Do NOT throw default exception, and NEVER EVER \Exception
If there are exception thrown by any dependant component that can't be handled by the utility class, document properly the exception. There is no need to wrap the exceptions in this case.
Classes using these utilities are expected to handled (or rethrow) the exceptions defined in the PHPDoc for the specific method of the utility class. If any other kind of exception leaks from the utility class, it's something that utility class need to fix, either handling the exception or updating the PHPDoc
ALWAYS indicate in the doc the conditions that can trigger each particular exception. (I've seen some \OCP\PreConditionNotMetException being thrown and I don't want to spend more than 1 day figuring out how to trigger that exception or where that exception comes from)
Several things to notice:
ImporterException
. Each particular importer should throw a subclassed exception in order to make it easier to know where the exception comes from.ImporterException
, or one of the subclasses. For example, if aFileNotFoundException
happens inside the share importer, the share importer should wrap the exception in aShareImporterException
or in a subclass such asShareImporterFileException
.OCA\DataExporter\Importer
will only catchImporterException
. Specific subclasses might be catched and handled if needed, although most of this work should be done already by theMetadataImporter
(which is acting as the root component)OCA\DataExporter\Exporter
will behave the same as the importer.ImporterException
(for the "import:user" command) andExporterException
(for the "export:user" and "export:migrate:share" commands), mainly to show the exception class and the message. This should allow easier debugging of known errors.ImporterException
orExporterException
if it can't be handled (this should be done in either theOCA\DataExporter\Importer
orOCA\DataExporter\Exporter
classes) or handle it properly wherever it can be handled.In addition:
\Exception
\OCP\PreConditionNotMetException
being thrown and I don't want to spend more than 1 day figuring out how to trigger that exception or where that exception comes from)