{"id":2434,"date":"2021-06-14T15:52:37","date_gmt":"2021-06-14T14:52:37","guid":{"rendered":"https:\/\/www.jurecuhalev.com\/blog\/?p=2434"},"modified":"2021-06-14T15:52:38","modified_gmt":"2021-06-14T14:52:38","slug":"first-spike-for-roam-to-wp-plugin","status":"publish","type":"post","link":"https:\/\/www.jurecuhalev.com\/blog\/first-spike-for-roam-to-wp-plugin\/","title":{"rendered":"First spike for Roam to WP plugin"},"content":{"rendered":"\n<p>Status update on getting the first &#8220;spike\/prototype&#8221; of code working.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scaffolding initial plugin code<\/h3>\n\n\n\n<p>I&#8217;ve looked into a number of scaffolding solutions:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>@wordpress\/create-block<\/li><li><a href=\"https:\/\/github.com\/roots\/acorn\">Roots acorn<\/a><\/li><li><a href=\"https:\/\/developer.wordpress.org\/cli\/commands\/scaffold\/plugin\/\">wp scaffold plugin<\/a><\/li><li>A number of WordPress Plugin Boilerplate plugins<\/li><\/ul>\n\n\n\n<p>I&#8217;ve initially tried to use <a href=\"https:\/\/github.com\/WPBP\/WordPress-Plugin-Boilerplate-Powered\">WordPress Plugin Boilerplate Powered<\/a> but it generated so much boilerplate code that it was just too much work to actually write my own code.<\/p>\n\n\n\n<p>So I ended up using <code>wp scaffold<\/code> that produced a very nice skeleton that I could start writing code into.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Settings Screen<\/h3>\n\n\n\n<p>I first needed to build a screen where I could upload my exported data. Final result looks like this for now:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"643\" src=\"https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/Screenshot-2021-06-14-at-16.35.20-1-1024x643.png\" alt=\"\" class=\"wp-image-2436\" srcset=\"https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/Screenshot-2021-06-14-at-16.35.20-1-1024x643.png 1024w, https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/Screenshot-2021-06-14-at-16.35.20-1-550x345.png 550w, https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/Screenshot-2021-06-14-at-16.35.20-1-768x482.png 768w, https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/Screenshot-2021-06-14-at-16.35.20-1.png 1035w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>What was really useful in this research was article by <a href=\"https:\/\/deliciousbrains.com\/create-wordpress-plugin-settings-page\/\">Delicious Brains &#8211; 5 Ways to Create a WordPress Plugin Settings\u00a0Page<\/a>. I ended up using Carbon Fields as I didn&#8217;t want to invest too much time into scaffolding my own HTML Form code just to process a few fields.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Processing the data export<\/h3>\n\n\n\n<p>For now the general idea is that I only need to look at the first level of blocks inside Roam. So I&#8217;ll have structure like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\n  \"create-time\": 1621153344466,\n  \"title\": \"!Resources\/BASB\/Reviews\",\n..\n\"children\": [\n  {\n  \"string\": \"Wordpress:: #publish\",\n  ..\n  \":create\/user\": {\n    \":user\/uid\": \"D9GErGIgWMcqL1SJ9egralKACQ62\"\n  },\n  ..\n},\n..\n]\n}<\/pre>\n\n\n\n<p>and I need to find all blocks that have somewhere in the first level of children a <code>string<\/code> that matches <code>\"Wordpress:: #publish\"<\/code>. The problem is that tree searching libraries like jsonq only return the matching child node but not the parent structure.<\/p>\n\n\n\n<p>No problem we just need to write a single node depth search:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n&lt;?php \nfunction extract_nodes_to_publish( array $data ): array {\n\t$rules = \\preg_split( &quot;\/\\r\\n|\\n|\\r\/&quot;, carbon_get_theme_option( 'rtw_import_rules' ) );\n\tif ( ! $rules ) {\n\t\treturn &#x5B;];\n\t}\n\n\t$matching_pages = &#x5B;];\n\tforeach ( array_splice( $data, 0 ) as $page ) {\n\t\tif ( isset( $page&#x5B;'children'] ) ) {\n\t\t\tforeach ( $page&#x5B;'children'] as $block ) {\n\t\t\t\tif ( in_array( $block&#x5B;'string'], $rules ) ) {\n\t\t\t\t\tray( $block&#x5B;'string'] );\n\t\t\t\t\t$matching_pages&#x5B;] = $page;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn $matching_pages;\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Rendering whole content tree<\/h3>\n\n\n\n<p>After we have a list of pages that match we need to render whole Roam content page that is in Markdown strings into HTML. Since I&#8217;ve been inspired by &#8220;Roam Blocks&#8221; plugin I&#8217;ve decided to reuse their function that does that: https:\/\/github.com\/artpi\/wp-roam-block\/blob\/main\/endpoints.php#L82<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">First rendered page<\/h3>\n\n\n\n<p>With a bit more glue code I can already see how this plugin creates a new <strong>Note<\/strong> custom post types and inserts a page that I tagged with #publish:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"954\" src=\"https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/note-preview-1024x954.png\" alt=\"\" class=\"wp-image-2438\" srcset=\"https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/note-preview-1024x954.png 1024w, https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/note-preview-550x512.png 550w, https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/note-preview-768x716.png 768w, https:\/\/www.jurecuhalev.com\/blog\/wp-content\/uploads\/2021\/06\/note-preview.png 1099w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Next steps<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li>Figure out how to grab <code>Title::<\/code> attribute if present so I don&#8217;t need to expose internal Roam page titles<\/li><li>Figure out what should be a bullet and what should be just a paragraph.<\/li><li>Publish to Github so maybe some other brave soul could give it a try<\/li><\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Status update on getting the first &#8220;spike\/prototype&#8221; of code working. Scaffolding initial plugin code I&#8217;ve looked into a number of scaffolding solutions: @wordpress\/create-block Roots acorn wp scaffold plugin A number of WordPress Plugin Boilerplate plugins I&#8217;ve initially tried to use WordPress Plugin Boilerplate Powered but it generated so much boilerplate code that it was just [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[946,947],"tags":[],"class_list":["post-2434","post","type-post","status-publish","format-standard","hentry","category-dev-logs","category-roam-to-wp"],"acf":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts\/2434","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/comments?post=2434"}],"version-history":[{"count":2,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts\/2434\/revisions"}],"predecessor-version":[{"id":2439,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/posts\/2434\/revisions\/2439"}],"wp:attachment":[{"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/media?parent=2434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/categories?post=2434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jurecuhalev.com\/blog\/wp-json\/wp\/v2\/tags?post=2434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}