observe_import_resource/2

Import a prepared external resource instead of its default importer.

Type: first. The first observer returning anything other than undefined handles the item. This is a replacement hook, not a property transformation fold.

Declare -behaviour(zotonic_observer) and export observe_import_resource/2 or pid_observe_import_resource/3. Both callbacks are optional. The behaviour does not define records: include zotonic_core/include/zotonic.hrl in every module using #import_resource{}.

-behaviour(zotonic_observer).
-include_lib("zotonic_core/include/zotonic.hrl").
-export([observe_import_resource/2]).

observe_import_resource(#import_resource{
    source = #{importer := mod_import_feed, feed := Feed},
    item = Item
}, Context) ->
    my_importer:import(Item, Feed, Context);
observe_import_resource(_, _) ->
    undefined.

Payload

  • item: a map with binary source uri and binary-keyed resource props. Optional edges contains {Predicate, Object} pairs; references can be local IDs, names, source URIs or remote resource-reference maps. medium is a source URL, a media description map, or undefined. Importers may add fields, such as id, media_aliases, or the native feed's zotonic_export and native_options.
  • related: known related item maps, not a fully fetched recursive graph. Entries marked is_reference => true have only identity information. Their presence does not imply ownership or is_dependent on the imported resource.
  • source: importer metadata. importer identifies the producer. Feeds use #{importer => mod_import_feed, feed => Settings}; native imports use #{importer => m_rsc_import, uri => Uri}. Feed settings omit lease tokens and saved ACL groups.
  • options: native import options when applicable, otherwise an empty list. Feed-specific policy is in the source's feed settings.
  • raw: original parsed input. For feeds this is XML, optionally accompanied by WordPress JSON; for native imports it is the decoded resource export.

Timing and permissions

Feed entries notify after preparation and unchanged/deleted checks, inside their entry transaction. Native resource imports notify after category eligibility is checked but before reference mapping can create resources. Local-URI lookups do not notify. Resource properties and raw input remain untrusted; handlers must use normal resource/media APIs, sanitize input and enforce import policies.

The supplied context retains the importing user's permissions. No automatic sudo or transaction is introduced by z_import_resource:import/3. Reuse the supplied context for delegation and writes. Delegating the same URI to another participating importer does not notify again; different URIs do. Thus native feed roots notify once and recursively imported resources can notify separately.

Results

  • undefined: continue to other observers, then the default importer.
  • {ok, Id}: the observer has completed the import. The resource must be editable by the importing user.
  • {ok, Id, UriToIdMap}: additionally return imported related resources. Keys must be binary source URIs and values integer IDs visible to the importing user.
  • {skip, Reason}: deliberately skip. Feeds record the skip; m_rsc_import returns {error, {skipped, Reason}} to preserve its public result contract.
  • {error, Reason}: fail. Feeds roll back their entry transaction; other importers retain their own transaction policy. External effects cannot be rolled back.

Malformed results return {error, invalid_observer_result} and inaccessible IDs return {error, eacces}. Do not return success before asynchronous writes finish. The caller retains import history and completion handling: native imports save import options and emit #rsc_import_done{} even when an observer handles them.

This notification is emitted by the feed and native resource importers. CSV/XLSX, WordPress WXR/datamodel imports and ordinary media uploads do not yet emit it.

Edit on GitHub