{"result":{"depiction_url":null,"edges":{"references":{"objects":[{"created":"2020-05-30T05:47:44Z","object_id":{"id":1274,"is_a":["text","documentation","developerguide"],"name":"doc_developerguide_notifications","title":{"_type":"trans","tr":{"en":"Respond to a notification"}},"uri":"https:\/\/zotonic.com\/id\/1274"},"seq":1000000}],"predicate":{"id":332,"is_a":["meta","predicate"],"name":"references","title":{"_type":"trans","tr":{"en":"References"}},"uri":"https:\/\/zotonic.com\/id\/references"}},"subject":{"objects":[{"created":"2026-09-09T13:47:33Z","object_id":{"id":2555,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_reference","title":"Reference","uri":"https:\/\/zotonic.com\/id\/2555"},"seq":1},{"created":"2026-09-09T13:47:33Z","object_id":{"id":2564,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_backend_developer","title":"Backend developer","uri":"https:\/\/zotonic.com\/id\/2564"},"seq":2},{"created":"2026-09-09T13:47:33Z","object_id":{"id":2600,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_import_and_migration","title":"Import and migration","uri":"https:\/\/zotonic.com\/id\/2600"},"seq":3},{"created":"2026-09-09T13:47:33Z","object_id":{"id":2627,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_notification","title":"Notification","uri":"https:\/\/zotonic.com\/id\/2627"},"seq":4},{"created":"2026-09-09T13:47:33Z","object_id":{"id":2650,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_import","title":"Import","uri":"https:\/\/zotonic.com\/id\/2650"},"seq":5}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":1780,"is_a":["text","documentation","reference","notification"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1780"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_notification_import_resource","page_url":{"en":"https:\/\/zotonic.com\/docs\/1780\/observe_import_resource-2","x-default":"https:\/\/zotonic.com\/docs\/1780\/observe_import_resource-2"},"preview_url":null,"resource":{"version":3395,"pivot_location_lat":null,"title":"observe_import_resource\/2","is_authoritative":true,"body":"<p>Import a prepared external resource instead of its default importer.<\/p>\n<p>Type: <a href=\"\/id\/doc_developerguide_notifications#notification-first\">first<\/a>. The first\nobserver returning anything other than <code>undefined<\/code> handles the item. This is a\nreplacement hook, not a property transformation fold.<\/p>\n<p>Declare <code>-behaviour(zotonic_observer)<\/code> and export <code>observe_import_resource\/2<\/code> or\n<code>pid_observe_import_resource\/3<\/code>. Both callbacks are optional. The behaviour does\nnot define records: <strong>include <code>zotonic_core\/include\/zotonic.hrl<\/code><\/strong> in every module\nusing <code>#import_resource{}<\/code>.<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-erlang\">-behaviour(zotonic_observer).\n-include_lib(&quot;zotonic_core\/include\/zotonic.hrl&quot;).\n-export([observe_import_resource\/2]).\n\nobserve_import_resource(#import_resource{\n    source = #{importer := mod_import_feed, feed := Feed},\n    item = Item\n}, Context) -&gt;\n    my_importer:import(Item, Feed, Context);\nobserve_import_resource(_, _) -&gt;\n    undefined.\n<\/code><\/pre>\n<h2>Payload<\/h2>\n<ul><li><code>item<\/code>: a map with binary source <code>uri<\/code> and binary-keyed resource <code>props<\/code>.\nOptional <code>edges<\/code> contains <code>{Predicate, Object}<\/code> pairs; references can be local\nIDs, names, source URIs or remote resource-reference maps. <code>medium<\/code> is a source\nURL, a media description map, or <code>undefined<\/code>. Importers may add fields, such as\n<code>id<\/code>, <code>media_aliases<\/code>, or the native feed&#39;s <code>zotonic_export<\/code> and <code>native_options<\/code>.<\/li><li><code>related<\/code>: known related item maps, not a fully fetched recursive graph. Entries\nmarked <code>is_reference =&gt; true<\/code> have only identity information. Their presence\ndoes not imply ownership or <code>is_dependent<\/code> on the imported resource.<\/li><li><code>source<\/code>: importer metadata. <code>importer<\/code> identifies the producer. Feeds use\n<code>#{importer =&gt; mod_import_feed, feed =&gt; Settings}<\/code>; native imports use\n<code>#{importer =&gt; m_rsc_import, uri =&gt; Uri}<\/code>. Feed settings omit lease tokens and\nsaved ACL groups.<\/li><li><code>options<\/code>: native import options when applicable, otherwise an empty list.\nFeed-specific policy is in the source&#39;s <code>feed<\/code> settings.<\/li><li><code>raw<\/code>: original parsed input. For feeds this is XML, optionally accompanied by\nWordPress JSON; for native imports it is the decoded resource export.<\/li><\/ul>\n<h2>Timing and permissions<\/h2>\n<p>Feed entries notify after preparation and unchanged\/deleted checks, inside their\nentry transaction. Native resource imports notify after category eligibility is\nchecked but before reference mapping can create resources. Local-URI lookups do\nnot notify. Resource properties and raw input remain untrusted; handlers must use\nnormal resource\/media APIs, sanitize input and enforce import policies.<\/p>\n<p>The supplied context retains the importing user&#39;s permissions. No automatic\n<code>sudo<\/code> or transaction is introduced by <code>z_import_resource:import\/3<\/code>. Reuse the\nsupplied context for delegation and writes. Delegating the same URI to another\nparticipating importer does not notify again; different URIs do. Thus native feed\nroots notify once and recursively imported resources can notify separately.<\/p>\n<h2>Results<\/h2>\n<ul><li><code>undefined<\/code>: continue to other observers, then the default importer.<\/li><li><code>{ok, Id}<\/code>: the observer has completed the import. The resource must be editable\nby the importing user.<\/li><li><code>{ok, Id, UriToIdMap}<\/code>: additionally return imported related resources. Keys must\nbe binary source URIs and values integer IDs visible to the importing user.<\/li><li><code>{skip, Reason}<\/code>: deliberately skip. Feeds record the skip; <code>m_rsc_import<\/code>\nreturns <code>{error, {skipped, Reason}}<\/code> to preserve its public result contract.<\/li><li><code>{error, Reason}<\/code>: fail. Feeds roll back their entry transaction; other importers\nretain their own transaction policy. External effects cannot be rolled back.<\/li><\/ul>\n<p>Malformed results return <code>{error, invalid_observer_result}<\/code> and inaccessible IDs\nreturn <code>{error, eacces}<\/code>. Do not return success before asynchronous writes finish.\nThe caller retains import history and completion handling: native imports save\nimport options and emit <code>#rsc_import_done{}<\/code> even when an observer handles them.<\/p>\n<p>This notification is emitted by the feed and native resource importers. CSV\/XLSX,\nWordPress WXR\/datamodel imports and ordinary media uploads do not yet emit it.<\/p>","slug":"observe_import_resource-2","is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"1faef0718b2d31fa09e1727e58abe5c52b01d45e99ba424ed86a07afc18cfad4","is_featured":false,"notification":{"arity":2,"callbacks":[{"arity":2,"name":"observe_import_resource","signature":"observe_import_resource\/2","variation":"observe"},{"arity":3,"name":"pid_observe_import_resource","signature":"pid_observe_import_resource\/3","variation":"pid_observe"}],"name":"import_resource","record":{"item":"undefined","options":"[]","raw":"undefined","related":"[]","source":"#{}"}},"content_group_id":{"id":2551,"is_a":["meta","content_group"],"name":"content_group_imported_docs","title":"Imported documentation","uri":"https:\/\/zotonic.com\/id\/content_group_imported_docs"},"category_id":{"id":1122,"is_a":["meta","category"],"name":"notification","title":"Notifications","uri":"https:\/\/test.zotonic.com\/id\/1122"},"doc_source_path":"apps\/zotonic_core\/src\/behaviours\/zotonic_observer.erl","publication_start":"2023-01-30T19:23:59Z","github_url":"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/apps\/zotonic_core\/src\/behaviours\/zotonic_observer.erl","pivot_location_lng":null,"doc_source_kind":"notification","name":"doc_notification_import_resource","is_unfindable":false,"is_published":true,"pivot_geocode":null,"created":"2020-05-30T05:47:35Z","uri":null,"doc_status":"current","is_dependent":false,"publication_end":"9999-06-01T00:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_source_commit":"9542d51dd051382bb67b08e5659311d8bb2b37e0\n","creator_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"modified":"2026-10-20T16:40:19Z","title_slug":"observe_import_resource-2"},"uri":"https:\/\/zotonic.com\/id\/1780","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1780"}},"status":"ok"}