tag:blogger.com,1999:blog-19515429260241085642024-03-16T12:12:28.202+11:00The Map Guy(de)Need directions?Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.comBlogger568125tag:blogger.com,1999:blog-1951542926024108564.post-15326803603082583552023-12-18T22:14:00.000+11:002023-12-18T22:14:14.878+11:00Minor change of plans<p>There will be a slight change of plans in the MapGuide Open Source 4.0 release timeline.</p><p>Namely, the next release will not be the Release Candidate, but rather a 2nd beta release.</p><p>The main driver behind this decision is because of my intention to remove the <a href="https://themapguyde.blogspot.com/2020/10/mapguide-40-showcase-supercharged-tile.html" rel="nofollow" target="_blank">recently introduced support for Mapbox Vector Tiles</a>. While I initially had high hopes with this implementation, additional testing with data outside of the example Sheboygan dataset has revealed <a href="https://trac.osgeo.org/mapguide/ticket/2836" rel="nofollow" target="_blank">rendering issues</a> I do not have the capability to address. Rather than ship a half-baked implementation that may never bake fully, I'd rather bow out while we still can, remove this immature implementation, and leave MVT tile generation to <a href="https://github.com/mapbox/awesome-vector-tiles?tab=readme-ov-file#parsers--generators" rel="nofollow" target="_blank">dedicated external tools</a>.</p><p>A 2nd beta release will also mean that the other changes I want to get in will also have some time to bake before the Release Candidate stage.</p><p>I am hoping the 2nd beta release will be out late January in the new year.</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-991242561992699082023-12-04T21:30:00.005+11:002023-12-04T21:30:58.194+11:00Announcing: mapguide-rest 1.0 RC6<p><a href="https://themapguyde.blogspot.com/2017/01/announcing-mapguide-rest-10-rc5.html" rel="nofollow" target="_blank">6 years later</a>, I have finally put out another release of <a href="https://github.com/jumpinjackie/mapguide-rest" rel="nofollow" target="_blank">mapguide-rest</a>!</p><p>The reason for finally putting out a new release (besides being long overdue!), is that I needed a solid verification of the vanilla SWIG API binding work for MapGuide Open Source 4.0 and mapguide-rest was just the ideal project that touches almost every nook and cranny of the MapGuide API. So if mapguide-rest still works with the PHP binding in MapGuide Open Source 4.0, that is as good of an endorsement to the reliability and readiness of these bindings.</p><p>For this release of mapguide-rest, it is compatible with the version of PHP that comes with:</p><p></p><ul style="text-align: left;"><li>MapGuide Open Source 3.1.2 (PHP 5.6)</li><li>MapGuide Open Source 4.0 Beta 1 (PHP 8.1)</li></ul><div>Besides being compatible with the upcoming MapGuide Open Source release (and the current stable one), this release also adds a new series of APIs to perform various geo-processing tasks. All of which are available to try out in the interactive swagger API reference.</div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgQxlhLgxTEjSusyOajw2yKtCFOYUA7-bI_ThJe5sSVHBC_Y6EpuCXBqKCzaDgUuaXiu50_g5-MdpZLEc4amSjKnXiiOh6hkwveq5-e_jp1eOh7tMhxXE-Fke9hmB65hDb6vHNakWJZAFea9wa41evVVbzOcDILgVbJQqPk7bjclYPq2TsuAPAZZJRX4Z4" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="444" data-original-width="1010" height="282" src="https://blogger.googleusercontent.com/img/a/AVvXsEgQxlhLgxTEjSusyOajw2yKtCFOYUA7-bI_ThJe5sSVHBC_Y6EpuCXBqKCzaDgUuaXiu50_g5-MdpZLEc4amSjKnXiiOh6hkwveq5-e_jp1eOh7tMhxXE-Fke9hmB65hDb6vHNakWJZAFea9wa41evVVbzOcDILgVbJQqPk7bjclYPq2TsuAPAZZJRX4Z4=w640-h282" width="640" /></a></div><br /><br /></div><div><a href="https://github.com/jumpinjackie/mapguide-rest/releases/tag/1.0rc6" rel="nofollow" target="_blank">Download</a></div><div><br /></div><div>Special thanks to <a href="https://mapguide.wordpress.com/" rel="nofollow" target="_blank">Gordon Luckett</a> and Scott Hamiester for assistance in internal testing of many internal builds of mapguide-rest that finally culminated in this long-overdue release.</div><div><br /></div><div>Now that this is out of the way, it is back to MapGuide development proper and getting closer to the 4.0 release.</div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-40026527616155783892023-09-13T03:54:00.007+10:002023-09-13T04:07:20.969+10:00Announcing: vscode-map-preview 0.6.0<p><a href="https://marketplace.visualstudio.com/items?itemName=jumpinjackie.vscode-map-preview" rel="nofollow" target="_blank">This impromptu update</a> fixes up Stamen tiles support to point to the new infrastructure managed by <a href="https://stadiamaps.com/news/stamen-design-and-stadia-maps/" rel="nofollow" target="_blank">Stadia Maps</a>.</p><p>Since we have to do this, we've taken this migration as an opportunity to add support for many more base layer types. </p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzMGNj56sN5SGPEY6nYYeRHk_hM7XCiOI6TMSqnUUZ9cjEldCA1CZwMxGy1sbawK6XhLIdNrCW2sEElskFl0Q' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<p>The full list of base layers supported is now:</p><p></p><ul style="text-align: left;"><li><a href="https://www.openstreetmap.org/" rel="nofollow" target="_blank">OpenStreetMap</a></li><li>Stamen tiles (by Stadia Maps)</li><li><a href="https://stadiamaps.com/themes/" rel="nofollow" target="_blank">Stadia Maps</a></li><li><a href="https://www.bing.com/maps" rel="nofollow" target="_blank">Bing Maps</a></li></ul><p></p><p>However, certain Bing and Stadia Maps layers will only be available in the base layer switcher if you provide respective API keys for these services through new configuration properties.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim-MIk5jSub-o9Wp73jnNYpycf9AMPuWlE4rWubi54zNepiaKisMhWNACTt3EY2SToecwNR_JfTbM9XEkXyTi6c_5ysmjCselAS3XB4rYpzvxYBgZDR7W2kKAruUQ32eRQcXScLORIf6hJo2Mseqi7C-l8In18iuUmqv1XdXisJTuMa0_W9aBWyUfXRAk/s1032/2023_09_13_03_22_09_Settings_Untitled_Workspace_Visual_Studio_Code.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="440" data-original-width="1032" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim-MIk5jSub-o9Wp73jnNYpycf9AMPuWlE4rWubi54zNepiaKisMhWNACTt3EY2SToecwNR_JfTbM9XEkXyTi6c_5ysmjCselAS3XB4rYpzvxYBgZDR7W2kKAruUQ32eRQcXScLORIf6hJo2Mseqi7C-l8In18iuUmqv1XdXisJTuMa0_W9aBWyUfXRAk/w640-h272/2023_09_13_03_22_09_Settings_Untitled_Workspace_Visual_Studio_Code.png" width="640" /></a></div><p>Don't like these base layers and want to bring your own? You can do that now too! If you have an XYZ tile set or WMTS service you want as a backdrop for your map previews, you can define such layers in your settings.json like so:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwJj-NyeqdfspHxcyE73RNeKfmriHPoPM7ypV7G9VHhIaazE3afk-KX4Zt2oiXf05-t7fh43aRB5fbuiS_0geQaje3AWEXVN69bK6gJ3nLkQHleM5qpgYOYQkpUykcLF_o0r0qyL77i5znu4CaZzPoOQsKam_UCo6RV7ZGEVBPQ5_x-RDUVZBi8ox1zZU/s1417/2023-09-13%2003_32_50-%E2%97%8F%20settings.json%20-%20Untitled%20(Workspace)%20-%20Visual%20Studio%20Code.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="696" data-original-width="1417" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwJj-NyeqdfspHxcyE73RNeKfmriHPoPM7ypV7G9VHhIaazE3afk-KX4Zt2oiXf05-t7fh43aRB5fbuiS_0geQaje3AWEXVN69bK6gJ3nLkQHleM5qpgYOYQkpUykcLF_o0r0qyL77i5znu4CaZzPoOQsKam_UCo6RV7ZGEVBPQ5_x-RDUVZBi8ox1zZU/w640-h314/2023-09-13%2003_32_50-%E2%97%8F%20settings.json%20-%20Untitled%20(Workspace)%20-%20Visual%20Studio%20Code.png" width="640" /></a></div><p>And they shall appear in the base layer switcher as layers you can switch to</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgKQ_mP-omRLf0zPr7IpedM-zKjOyCiylZdxcE49SKt9C3crK97e5LBwP3672t-2nAKzn-IY9jlrHenJz8CtwEZH2mtvHqBlI5OlIuFjKU8aS3rOjh81xk8MEseQVA3_T1gOREzr7FcblAvry_QNbrEtB58ADsSjxB6e0UKXpATSz6h6wKNS9sabvyjyk/s933/2023-09-13%2003_38_15-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="851" data-original-width="933" height="584" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgKQ_mP-omRLf0zPr7IpedM-zKjOyCiylZdxcE49SKt9C3crK97e5LBwP3672t-2nAKzn-IY9jlrHenJz8CtwEZH2mtvHqBlI5OlIuFjKU8aS3rOjh81xk8MEseQVA3_T1gOREzr7FcblAvry_QNbrEtB58ADsSjxB6e0UKXpATSz6h6wKNS9sabvyjyk/w640-h584/2023-09-13%2003_38_15-Window.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBVQsfElvH6x9JvbNSNvsJUXvxA5x6NZkiqUJeaG_1rxe1vxmLaNr_vDM2bbDYPGBEmYKowhQDS7vVJ0tvmmqerLunILImlWnp1cUQrkzOO7e9ZY2VFOhSOuLkLLCQ8IP1q20NjAagsE9kGzQw_0_-KsA2Ik-UuvfqnIMAB5wOtUBaWyhJQAEY-RiMfeU/s933/2023-09-13%2003_38_31-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="846" data-original-width="933" height="580" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBVQsfElvH6x9JvbNSNvsJUXvxA5x6NZkiqUJeaG_1rxe1vxmLaNr_vDM2bbDYPGBEmYKowhQDS7vVJ0tvmmqerLunILImlWnp1cUQrkzOO7e9ZY2VFOhSOuLkLLCQ8IP1q20NjAagsE9kGzQw_0_-KsA2Ik-UuvfqnIMAB5wOtUBaWyhJQAEY-RiMfeU/w640-h580/2023-09-13%2003_38_31-Window.png" width="640" /></a></div><br /><p>This update also refactors the viewer HTML preparation by fetching the document (to be previewed) content on viewer init instead of embedding its content into the viewer HTML. This should improve responsiveness when previewing larger files, to the point that you can make out the new preview preparation message.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXQTMsVtc691zd7iA1ErMH9Nr2WCSuHv-zmgKNh0-_aOeXSw8R-jycmKYT7qpwxKsyFMgujFb4MgbLB5bRuJW1RCsRVxCFInJ-cdlaDe9r6GXayWnl5UdRSQVL698UshUWsYzMyQ_-L6XTqSwlaelrSZecF2TOzg7QfrPvkCMsj5sKk7107QwWKRUTgYI/s1853/2023-09-13%2003_44_46-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="847" data-original-width="1853" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXQTMsVtc691zd7iA1ErMH9Nr2WCSuHv-zmgKNh0-_aOeXSw8R-jycmKYT7qpwxKsyFMgujFb4MgbLB5bRuJW1RCsRVxCFInJ-cdlaDe9r6GXayWnl5UdRSQVL698UshUWsYzMyQ_-L6XTqSwlaelrSZecF2TOzg7QfrPvkCMsj5sKk7107QwWKRUTgYI/w640-h292/2023-09-13%2003_44_46-Window.png" width="640" /></a></div><p>However, as I started to test this with bigger and bigger files, I eventually found a limit where the VSCode APIs will not cooperate with us. This limit is the<a href="https://github.com/microsoft/vscode/issues/31078" rel="nofollow" target="_blank"> point where VSCode will either not do syntax highlighting or tokenization or both</a> and when we try to preview such a file, it will silently fail.</p><p>For this update, we will show a better error message on such files.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvJ-PrMtbqs-YgvzADe1wngW9pE0ojTBMbESQ48j11c84VZHs5GtuIOIoVlbEdHpL62bsbvXF7jBKQWRfJ44g-y6089-nrzheVJem2ddEhbg1Rn8QH3hbHyrB_0ujCeV2w11qQdGmBDJxbsi7QJd-kDtOrxAOgwIi9FWfut8uMgmWoislhS8ltfnhp9xI/s1848/2023-09-13%2003_49_07-parcels.geojson%20-%20Untitled%20(Workspace)%20-%20Visual%20Studio%20Code.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="962" data-original-width="1848" height="334" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvJ-PrMtbqs-YgvzADe1wngW9pE0ojTBMbESQ48j11c84VZHs5GtuIOIoVlbEdHpL62bsbvXF7jBKQWRfJ44g-y6089-nrzheVJem2ddEhbg1Rn8QH3hbHyrB_0ujCeV2w11qQdGmBDJxbsi7QJd-kDtOrxAOgwIi9FWfut8uMgmWoislhS8ltfnhp9xI/w640-h334/2023-09-13%2003_49_07-parcels.geojson%20-%20Untitled%20(Workspace)%20-%20Visual%20Studio%20Code.png" width="640" /></a></div><p>So for those who are <a href="https://github.com/jumpinjackie/vscode-map-preview/issues/28" rel="nofollow" target="_blank">hoping to use this extension to preview GeoJSON files whose size is in the range of gigabytes</a>, sorry there's nothin I can do here 🤷♂️🤷♂️🤷♂️🤷♂️ I think at that point you are better served by using actual GIS tools/software for this purpose.</p><p>Now this this update is out the door, it's back to mapguide-rest development.</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-2974473424937738022023-09-12T00:50:00.000+10:002023-09-12T00:50:10.759+10:00Another temporary detour<p>While I was deep into reviving <a href="https://github.com/jumpinjackie/mapguide-rest" rel="nofollow" target="_blank">mapguide-rest</a> to make sure it works with the PHP 8.1 bundled with MapGuide Open Source 4.0, I missed the memo that <a href="http://maps.stamen.com/#toner/12/37.7706/-122.3782" rel="nofollow" target="_blank">Stamen Maps</a> is now under new management: <a href="https://stadiamaps.com/" rel="nofollow" target="_blank">Stadia Maps</a>.</p><p>The most important aspect of <a href="http://maps.stamen.com/stadia-partnership/" rel="nofollow" target="_blank">this announcement</a> was that come October 2023 (a month from now), current stamen tile URLs may stop redirecting/working and you should have migrated over to Stadia Maps by then.</p><p>Because Stamen tiles carried the same role as <a href="https://www.openstreetmap.org/" rel="nofollow" target="_blank">OpenStreetMap</a> as a freely accessible base tiled layer for various open source projects of mine, this announcement has thrown a spanner in my works because come next month, Stamen tiles may not work and for continued support for these layers would require migration over to Stadia Maps.</p><p>So I have momentarily suspended my work on mapguide-rest to give focus to one of my other projects affected by this announcement: <a href="https://marketplace.visualstudio.com/items?itemName=jumpinjackie.vscode-map-preview" rel="nofollow" target="_blank">My VSCode map preview extension</a>.</p><p>Because continued support for stamen map tiles requires migrating the extension over to use Stadia Maps, we might as well take this opportunity to add support in the extension for <a href="https://docs.stadiamaps.com/themes/" rel="nofollow" target="_blank">other base layers</a> that Stadia Maps offers. And while we're at it, we might as well go all the way and add in <a href="https://www.bing.com/maps" rel="nofollow" target="_blank">Bing Maps</a>, XYZ and WMTS base layers as well.</p><p>Or, just have a gander at this clip for a taste of what the next version of the VSCode map preview extension can do!</p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxSyJ3C390T-iGIYF-0kzENYF8iAKrxfUXbomWK_M5LMhyH1Ef6poCeYFiwCecdOtV03y5Ih0d9huZ289_XPg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><br /><p>The next version of the extension will drop real soon and then it is back to mapguide-rest development.</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-55063746436018208012023-08-12T20:47:00.001+10:002023-08-12T20:47:21.429+10:00MapGuide Maestro 6.0m12 nuget packages now available on nuget.org<p><a href="http://nuget.org">nuget.org</a> support finally provided a resolution on my account issue and I was able to regenerate my publishing keys.</p><p>As a result, the 6.0m12 release (6.0.0-pre500) nuget packages are now finally available on nuget.org</p><p></p><ul style="text-align: left;"><li><a href="https://www.nuget.org/packages/OSGeo.MapGuide.ObjectModels/6.0.0-pre500">OSGeo.MapGuide.ObjectModels</a></li><li><a href="https://www.nuget.org/packages/OSGeo.FDO.Expressions/6.0.0-pre500">OSGeo.FDO.Expressions</a></li><li><a href="https://www.nuget.org/packages/OSGeo.MapGuide.MaestroAPI/6.0.0-pre500">OSGeo.MapGuide.MaestroAPI</a></li></ul><div>We now return to your regularly scheduled programming ...</div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-39948886921928176732023-08-07T09:34:00.002+10:002023-08-07T09:34:40.689+10:00Where's the new Maestro API nuget packages?<p>There were a few things I left out of <a href="https://themapguyde.blogspot.com/2023/08/announcing-mapguide-maestro-60m12.html" rel="nofollow" target="_blank">the previous announcement</a> that I'll use this post to address.</p><p>Firstly, the 6.0m12 release of MapGuide Maestro formally drops all Fusion editor support for integration with Google Maps tiles and services. We no longer support Google Maps integration in Fusion and the editor in previous releases gave the false impression that this is still possible. That is no longer the case with this release.</p><p>Secondly, the more important thing (and the subject of this post) is that if you are using the Maestro API and consume this through nuget packages from <a href="http://nuget.org">nuget.org</a> you may be wondering why there are no new versions?</p><p>The answer to that one is simply: My nuget package publishing keys have expired and something in the nuget.org website or something with my nuget.org account is preventing me from regenerating these keys or to generate a fresh set. As a result, I currently cannot upload any new nuget packages to nuget.org</p><p>But do not fret, because there is an alternative solution.</p><p>As part of the MapGuide Maestro release on GitHub, the nuget .nupkg files are also included</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGXw1tFomNCH4k0RwUl2VSqMuu85rjpSj5iYLeOF1uoruyeAby6Bv4VXIqCeNrb7AV-fmMcAIZp9mmO4sJ4pbqbD4S-dx_yUM2L7YuTW5aXO-b0Fv4c7AGG8pfR_ve7X8WJxLI9k_kMCZ3cMCtoOQrZ9REoCHeRP9iDhfRXXi62DLVwDV0JVnJ2W8EgcA/s1336/2023-08-07%2009_18_39-Release%206.0m12%20%C2%B7%20jumpinjackie_mapguide-maestro%20-%20Brave.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="1336" height="69" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGXw1tFomNCH4k0RwUl2VSqMuu85rjpSj5iYLeOF1uoruyeAby6Bv4VXIqCeNrb7AV-fmMcAIZp9mmO4sJ4pbqbD4S-dx_yUM2L7YuTW5aXO-b0Fv4c7AGG8pfR_ve7X8WJxLI9k_kMCZ3cMCtoOQrZ9REoCHeRP9iDhfRXXi62DLVwDV0JVnJ2W8EgcA/w640-h69/2023-08-07%2009_18_39-Release%206.0m12%20%C2%B7%20jumpinjackie_mapguide-maestro%20-%20Brave.png" width="640" /></a></div><br /><p>From here, you can set up a <a href="https://learn.microsoft.com/en-us/nuget/hosting-packages/local-feeds" rel="nofollow" target="_blank">local directory-based nuget package source</a>, drop the .nupkg files into it and the this version of the package is available to install in your Visual Studio solution.</p><p>If/when I get a resolution on this publishing key matter, I will upload the .nupkg files for this release and make another announcement. Until then, this local package source is a suitable workaround.</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-29420387567963420222023-08-02T06:41:00.002+10:002023-08-02T06:41:12.430+10:00Announcing: MapGuide Maestro 6.0m12<p>Next stop on the <a href="https://themapguyde.blogspot.com/2023/05/the-i-havent-forgotten-about-you.html" rel="nofollow" target="_blank">tour</a>: A new release of MapGuide Maestro</p><p>This release includes the following notable changes.</p><h2 style="text-align: left;">Improved MapGuide Open Source 4.0 authoring support</h2><p>This release improves the MapGuide Open Source 4.0 authoring experience with support for the new label justification setting for basic stylization labels.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCmIl4g2K-MN4ULxfrNXhmfPt1iC-HYZnHpwMA9FAOqo_TSjgiSYRK_cQxNJ9uzg0CjRr8-Z6pbUg5aa5KPyCAfZ7bHGY5nGfudE7yYmQNnjstkbXWT2W3LyHfaNTrpNkGx6imdIZtcrlZkMknZo8WWddczlZECE2GG41tuOlRtrYM6SB0j6yol_N4EJU/s668/2023-08-01%2004_49_44-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="668" data-original-width="419" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCmIl4g2K-MN4ULxfrNXhmfPt1iC-HYZnHpwMA9FAOqo_TSjgiSYRK_cQxNJ9uzg0CjRr8-Z6pbUg5aa5KPyCAfZ7bHGY5nGfudE7yYmQNnjstkbXWT2W3LyHfaNTrpNkGx6imdIZtcrlZkMknZo8WWddczlZECE2GG41tuOlRtrYM6SB0j6yol_N4EJU/w251-h400/2023-08-01%2004_49_44-Window.png" width="251" /></a></div><br /><p>This setting is part of the new v4.0.0 Layer Definition XML schema, whose .xsd file is now also included with this release (so XML validation against this schema will work)</p><h2 style="text-align: left;">Fusion editor enhancements for mapguide-react-layout features</h2><p>This release includes several enhancements to the Fusion Flexible Layout editor to support various features that can be taken advantage of when loaded into a mapguide-react-layout viewer. These new enhancements are accessible from the layout settings panel and require <a href="https://themapguyde.blogspot.com/2023/07/announcing-mapguide-react-layout-0149.html" rel="nofollow" target="_blank">the latest release of mapguide-react-layout</a> to leverage these new features.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgATzjLoua74WEZVchFsdNrHOXLxG8QaAop5PedL0xpgtCyTanQlA6nWGi-nuGCpqDPHLw_Nm5ERoOHO9MzoqnA6T8W48iybOb_2NusmRe1QHB-v62gb0IQLVuaVaNkwbJ1RMNx_7MZjnaHcOIqlZxLg3AfxKZ1Wk7V_4Zs1864Cw-6a6sAvztbh4iabkA/s588/2023-08-01%2004_53_59-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="321" data-original-width="588" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgATzjLoua74WEZVchFsdNrHOXLxG8QaAop5PedL0xpgtCyTanQlA6nWGi-nuGCpqDPHLw_Nm5ERoOHO9MzoqnA6T8W48iybOb_2NusmRe1QHB-v62gb0IQLVuaVaNkwbJ1RMNx_7MZjnaHcOIqlZxLg3AfxKZ1Wk7V_4Zs1864Cw-6a6sAvztbh4iabkA/s16000/2023-08-01%2004_53_59-Window.png" /></a></div><br /><p>The <b>Manage Custom Projections</b> button opens up a new dialog that lets you manage and pre-register custom proj4 definitions for your application. By pre-registering these definitions in the Flexible Layout document itself, you can avoid needing to perform a epsg.io lookup for any projections found in the viewer init process that is not EPSG:4326 or EPSG:3857</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj05IFxMB_zuexqR_Tj4j3n9Tt34T-M31MrAScNNxfPSl4nDKPpIw9bsWPCc6R8aaydV_pBr8L7trBkfwIWx-kdMVb1f_F98_4FUBXNfn2ZNhv7nj5HR2ZYI6edligjZba9kPvvik4LnDDfLI1cBS5O6URNgfRBK0e0wpAIX74F8VquwhlwGA4lKshNiy0/s970/2023-08-01%2004_55_46-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="595" data-original-width="970" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj05IFxMB_zuexqR_Tj4j3n9Tt34T-M31MrAScNNxfPSl4nDKPpIw9bsWPCc6R8aaydV_pBr8L7trBkfwIWx-kdMVb1f_F98_4FUBXNfn2ZNhv7nj5HR2ZYI6edligjZba9kPvvik4LnDDfLI1cBS5O6URNgfRBK0e0wpAIX74F8VquwhlwGA4lKshNiy0/w640-h392/2023-08-01%2004_55_46-Window.png" width="640" /></a></div>The <b>Manage Settings</b> button opens up a different dialog that lets you managed the app settings in the Flexible Layout document. These are arbitrary key/value pairs that your mapguide-react-layout viewer will be initialized with and your viewer code can read such settings at runtime to control and drive whatever custom functionality you may have.<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilGt_vkn7GgWpzsCjRrA6lJbYl8RUjZISfaMhL7vh0xUbJyAjLob7te0G8Egk7_1O8yCgp8c0XzA9lPQVZ3UsjF4m_ViML3hG6a8Cbgb7uwdCaeihdurmaI7tl0_2wOzdsrLjUDNSkqLP6BSBQIjTwUZJwCyKxCkN4XeN9mUUCFSrN7KdGd-UnfePegcc/s838/2023-08-01%2004_58_11-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="510" data-original-width="838" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilGt_vkn7GgWpzsCjRrA6lJbYl8RUjZISfaMhL7vh0xUbJyAjLob7te0G8Egk7_1O8yCgp8c0XzA9lPQVZ3UsjF4m_ViML3hG6a8Cbgb7uwdCaeihdurmaI7tl0_2wOzdsrLjUDNSkqLP6BSBQIjTwUZJwCyKxCkN4XeN9mUUCFSrN7KdGd-UnfePegcc/w640-h390/2023-08-01%2004_58_11-Window.png" width="640" /></a></div><br /><div><h2 style="text-align: left;">Other Changes</h2><p></p><ul style="text-align: left;"><li>Improved layer editor UI responsiveness when layer points to a feature source with a really large schema</li><li>Increased schema walk/describe timeout to handle really large schemas</li><li>Fix: Connection error dialog buttons are no longer cut off</li><li>Fix: Transactional package drag-and-drop loading works again</li><li>Fix: Broken rest addin due to missing RestSharp dependency</li><li>Fix: Fill/line pattern dropdowns in layer editor are working again</li><li>Fix: MgTileSeeder will now accept bounding boxes outside the [-90, -180, 90, 180] lat/long domain by clamping any outside coordinates to be within this domain.</li></ul><div>Now onto the next stop: Finally giving mapguide-rest some long deserved attention!</div><div><br /></div><div><a href="https://github.com/jumpinjackie/mapguide-maestro/releases/tag/6.0m12" rel="nofollow" target="_blank">Download</a></div><p></p></div>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-51429376146609897362023-07-19T20:50:00.000+10:002023-07-19T20:50:18.501+10:00Announcing: mapguide-react-layout 0.14.9<p><a href="https://themapguyde.blogspot.com/2023/05/the-i-havent-forgotten-about-you.html" rel="nofollow" target="_blank">Our journey</a> needed to make a temporary detour, with another release of mapguide-react-layout.</p><p>This release has the following notable changes</p><h2 style="text-align: left;">Legend layer and group customization support</h2><div>This release provides a new viewer init option to allow layer and group elements of the Legend component to be augmented with additional HTML content. For example, we can use this to add a download link for specific layers (how to actually implement the download link is an exercise left to you the reader)</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzZgeDQslozCLhW5llHH2Ok9SIyMj9GFAz1z3mIo9q7h7jes8nhBN3kGTf7Wk3g372hA1L3xv1dswyXg9X9QYypzzKQ9nu5q7MM5Z9I41qJiYi0viqiQWPttQQeK-HEJg-EIH-j0E34ORJ4E3Mz_pGQSCes8tAobIhutkayNbLLlALK73U9u8Fk5zzY3k/s338/2023-07-19%2020_32_05-Window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="298" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzZgeDQslozCLhW5llHH2Ok9SIyMj9GFAz1z3mIo9q7h7jes8nhBN3kGTf7Wk3g372hA1L3xv1dswyXg9X9QYypzzKQ9nu5q7MM5Z9I41qJiYi0viqiQWPttQQeK-HEJg-EIH-j0E34ORJ4E3Mz_pGQSCes8tAobIhutkayNbLLlALK73U9u8Fk5zzY3k/s320/2023-07-19%2020_32_05-Window.png" width="282" /></a></div><br /><div><br /><a href="https://github.com/jumpinjackie/mapguide-react-layout/issues/1441#issuecomment-1591196725" rel="nofollow" target="_blank">See this comment</a> for an example of how to customize the layer and group elements.</div><h2 style="text-align: left;">Reduced excessive re-rendering</h2><div>In the process of implementing the above feature, we discovered that some components (the Legend component in particular) did a lot of pointless re-rendering which contributes to sluggishness in viewer performance.</div><div><br /></div><div>For this release, great efforts were made to ensure that component re-rendering is the result of <b>legitimate changes</b> to component state and not from pointless re-rendering from bogus shallow state "changes"</div><div><br /></div><h2 style="text-align: left;">Removed IE-specific polyfills and workarounds</h2><div>Internet Explorer ceased to be a supported browser by Microsoft for some time now. This release formally removes our various IE-specific workarounds and polyfills that were only there to support this ancient browser.</div><div><br /></div><h2 style="text-align: left;">Other changes</h2><div><ul style="text-align: left;"><li>The urlPropsIgnore setting is now considered when the viewer updates the URL state</li><li>The viewer bundle patches OpenLayers to log a console warning and abort rendering when attempting to render a map overlay image with a width/height/scale/dpi of 0</li><li>Fixed an issue where no map images are rendered if the browser zoom is below 100%</li></ul></div><div><br /></div><div><a href="https://github.com/jumpinjackie/mapguide-react-layout/releases/tag/v0.14.9" rel="nofollow" target="_blank">Download</a></div>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-30812250872863468352023-06-02T23:02:00.004+10:002023-06-02T23:02:58.321+10:00Announcing: mapguide-react-layout 0.14.8<p>We've arrived at the next stop on the <a href="https://themapguyde.blogspot.com/2023/05/the-i-havent-forgotten-about-you.html" rel="nofollow" target="_blank">tour</a>, a new release of mapguide-react-layout</p><p>This release has the following notable changes</p><h3 style="text-align: left;">Map Definition with XYZ tileset restriction lifted</h3><div>MapGuide Open Source 4.0 removed the restriction that Map Definitions cannot link to a XYZ tileset definition. This release of mapguide-react-layout takes advantage of this removed restriction by now supporting loading of a Map Definition that links to a XYZ tileset.</div><h3 style="text-align: left;">Support for loading custom projections and app settings from an Application Definition</h3><div>The beauty of the Extension element in an Application Definition document (and why its XML schema has not required a revision since its introduction) is that we can put any content in there.</div><div><br /></div><div>With this release, we are taking advantage of this fact by supporting the ability to read custom projections and app settings from an Application Definition if the right elements are present in the root Extension element of the Application Definition.</div><div><br /></div><div>By registering custom projections in the Application Definitions, we can register custom projections with the viewer without requiring an epsg.io lookup.</div><div><br /></div><div>The next release of Maestro (the next stop on this tour) will have dedicated editors for specifying custom projections and app settings. So stay tuned to see how this feature can be used.</div><h3 style="text-align: left;">Modal dialog size/positioning now preserved</h3><div>The redux state around modal dialogs has been reworked so that size/positioning is now preserved. This means that if you close a modal dialog and re-open it later on, it will retain the previous size/positioning it had previously, as demonstrated in this video.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dw-YIBjCWa8lmQbohWXHlDYzThqtSt-4QgJ-5jUCYF0dwPQry-Hrb1atvZlLPm4I0IF15ZKmToL3xWupRT8zw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><br /><h3 style="text-align: left;">MapGuide Base Layers now has its own opacity</h3><div>Previously the opacity of MapGuide Base Layers was coupled to the opacity of the MapGuide Map. With this release, MapGuide Base Layers now has its own opacity setting.</div><div><br /><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEE0heJBW1QCMgaZPHW_6bgQx63x8UHPBUnvFryxd1-4RFBUk85_seeOoNa5pV4kCI3ExMARSvqXzRdk8sYbYP9aaaRxb-jFtikTNd1WcBJbZYmn5DtHex_-qm689U8qwcY0m1h8d17SqqljVZicgs794Bz5wvB_muB90hpIxov5gqKaXxjrePHZ7m/s433/2023-06-02%2022_52_42-Sheboygan%20Map%20-%20Brave.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="422" data-original-width="433" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEE0heJBW1QCMgaZPHW_6bgQx63x8UHPBUnvFryxd1-4RFBUk85_seeOoNa5pV4kCI3ExMARSvqXzRdk8sYbYP9aaaRxb-jFtikTNd1WcBJbZYmn5DtHex_-qm689U8qwcY0m1h8d17SqqljVZicgs794Bz5wvB_muB90hpIxov5gqKaXxjrePHZ7m/s320/2023-06-02%2022_52_42-Sheboygan%20Map%20-%20Brave.png" width="320" /></a></div><br /><h3 style="text-align: left;">Other Changes</h3><p></p><ul style="text-align: left;"><li></li><li>OpenLayers updated to 6.15.1</li><li>Support disabling custom cursors through a new DISABLE_CURSORS app setting (1 to enable, 0 to disable)</li><li>Fix potential stale legend state from dispatched update action</li><li>Fix epsg.io lookup</li><li>Support Coordinate Tracker with only one projection specified</li><li>Un-break viewer API drawing example</li><li>Restore selection appending while holding down SHIFT key</li><li>Fix viewer state not pushing to url</li></ul><p></p><p><br /></p><p><a href="https://github.com/jumpinjackie/mapguide-react-layout/releases/tag/v0.14.8" rel="nofollow" target="_blank">Download</a></p><p><br /></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-17505749826988939212023-05-17T23:40:00.000+10:002023-05-17T23:40:54.500+10:00Announcing: FDO Toolbox 1.5.3<p>Here's the <a href="https://themapguyde.blogspot.com/2023/05/the-i-havent-forgotten-about-you.html" rel="nofollow" target="_blank">first stop of the tour</a>, a new release of FDO Toolbox.</p><p>I knew that a new release of FDO Toolbox would be coming when I was using the previous 1.5.2 release and it spectacularly failed in my <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food" rel="nofollow" target="_blank">dogfooding</a> of trying to load some <a href="https://www.icsm.gov.au/gda2020" rel="nofollow" target="_blank">GDA2020</a> SHP files to SQL Server. The actual problem was <a href="https://github.com/jumpinjackie/fdotoolbox/issues/80#issuecomment-1542076983" rel="nofollow" target="_blank">actually pretty minor</a>, but this inevitably started a chain of dealing with many other annoyances and reported issues, culminating in this release you see here.</p><p>Here's a summary of notable changes in this release.</p><p>The configuration support check has been fixed so that the configuration doc field is enabled based on actual provider capability check instead of the previously (dumb) approach of checking the provider name. This means the configuration document field is no longer disabled when connecting to PostgreSQL/PostGIS databases and one can finally supply a XML configuration document to <a href="https://themapguyde.blogspot.com/2010/08/using-fdo-schema-overrides.html" rel="nofollow" target="_blank">apply schema overrides</a>!</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUL9ceX5VK7TQOdXfVxjkHr_Ps95XJNgDvsonGhZqY1C2HHMdk5rLw86qYOnMyCFMvo--Hs0AcuEY7jTR5Bl3TMdkpzckD-uBSfc2zbm49EoiXqla16RYRL8eWpb4IS4ywox2TCuDAz0FVcneA2hFU72yBC80C6tj41Ls1OGMX8aNKbfJkPb38OobK/s557/2023-05-17%2022_24_22-Connect%20to%20PostgreSQL%20_%20PostGIS.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="308" data-original-width="557" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUL9ceX5VK7TQOdXfVxjkHr_Ps95XJNgDvsonGhZqY1C2HHMdk5rLw86qYOnMyCFMvo--Hs0AcuEY7jTR5Bl3TMdkpzckD-uBSfc2zbm49EoiXqla16RYRL8eWpb4IS4ywox2TCuDAz0FVcneA2hFU72yBC80C6tj41Ls1OGMX8aNKbfJkPb38OobK/s16000/2023-05-17%2022_24_22-Connect%20to%20PostgreSQL%20_%20PostGIS.png" /></a></div><br /><p>The data store editor in standalone mode now supports deleting schemas, to support the common FDO schema override use case of trimming out extraneous schemas and feature classes.</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEWALV-Iw3eM8zLH8tuhOs2aI6lPqL3WX8U3KpQDt0e1gICafpnrfioafCt1pLrkMztxficI4byIBvBvURqshHa4qPSfGKB-n9duIaBhxdpdXI7fopWg_kfeJ5mdlb1y8OQ8iHza09mvdH0Z6im_EnbC9dE3cj4zL690sGjLlw5tQ1SknJTyuNyXuA/s547/2023-05-17%2022_56_02-FDO%20Toolbox.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="211" data-original-width="547" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEWALV-Iw3eM8zLH8tuhOs2aI6lPqL3WX8U3KpQDt0e1gICafpnrfioafCt1pLrkMztxficI4byIBvBvURqshHa4qPSfGKB-n9duIaBhxdpdXI7fopWg_kfeJ5mdlb1y8OQ8iHza09mvdH0Z6im_EnbC9dE3cj4zL690sGjLlw5tQ1SknJTyuNyXuA/s16000/2023-05-17%2022_56_02-FDO%20Toolbox.png" /></a></div><br /><p></p><p>The annoyance of loading a saved bulk copy definition file and a whole bunch of connections with "Connection1/Connection2/Connection3" names being created is now fixed. We will now try to use the original name on the definition file if there is no open connection using the same name.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNQbuYl4KF8RoqpYZB_SAOj1mBaU5X7RfJbFXd4Ch6B6jV1Tb6rpwd6Jrbq4G8VBKiUAn0KZbqblkWqBOBfP2vkkGsWEJXgzeJ3TgFPXk4s2_F2gy8EgfnbP0LR1gX9C33yRYxTwmYUzvJJVIsZSF3nUDoPKQJm74QF6qJJLzW2Dtwt4XkEQpuAYF9/s933/fdo_bcp_dragdrop.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="621" data-original-width="933" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNQbuYl4KF8RoqpYZB_SAOj1mBaU5X7RfJbFXd4Ch6B6jV1Tb6rpwd6Jrbq4G8VBKiUAn0KZbqblkWqBOBfP2vkkGsWEJXgzeJ3TgFPXk4s2_F2gy8EgfnbP0LR1gX9C33yRYxTwmYUzvJJVIsZSF3nUDoPKQJm74QF6qJJLzW2Dtwt4XkEQpuAYF9/s16000/fdo_bcp_dragdrop.gif" /></a></div><br /><p>Also did you know that FDO Toolbox has a neat little feature to help you easily visualize <a href="https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry" rel="nofollow" target="_blank">geometry WKT</a>?</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKYCGM7LurHfsAbghDWCw1Mn_FhH_CfQMB9tnkHaXjcnisO6I3LXSnsJ4N8VnJjh6mB7NWbaWO06CljeaT7j3CxDKhxFfXQoQIy4P7Xk3G0HEg27LyADR48oBfZ0Z4jlT1paX0KYrCQZv__u2kV_9qYoTyDtWuYil37oB6GD_NfzSW9GYID_6elEf4/s383/2023-05-17%2023_34_21-Geometry%20Visualizer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="298" data-original-width="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKYCGM7LurHfsAbghDWCw1Mn_FhH_CfQMB9tnkHaXjcnisO6I3LXSnsJ4N8VnJjh6mB7NWbaWO06CljeaT7j3CxDKhxFfXQoQIy4P7Xk3G0HEg27LyADR48oBfZ0Z4jlT1paX0KYrCQZv__u2kV_9qYoTyDtWuYil37oB6GD_NfzSW9GYID_6elEf4/s16000/2023-05-17%2023_34_21-Geometry%20Visualizer.png" /></a></div><br /><p>You probably didn't know because this feature was hidden in the depths of the FDO Expression Editor when editing FDO expressions or filters and could not be accessed on its own.</p><p>That's why in this release, the Geometry Visualizer is now also accessible from the Tools menu.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvnfkly1jglfRAat-FAB856uNf_DXGPSUuf4boEvzswxzZQGfrSKTUMxiQ60E6pglRMU9_gRhGF2j2njpGG4MO-VrktfOC7xPgXDLmjyXrQLup6ti9sZhwUR5tHCv3hOEDaNUOi_z4QgOf3WOtsbAynUgau5A4Q0jY2SzN5Bre_4bPH_kF_iqGBaLI/s380/2023-05-17%2023_37_20-FDO%20Toolbox.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="264" data-original-width="380" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvnfkly1jglfRAat-FAB856uNf_DXGPSUuf4boEvzswxzZQGfrSKTUMxiQ60E6pglRMU9_gRhGF2j2njpGG4MO-VrktfOC7xPgXDLmjyXrQLup6ti9sZhwUR5tHCv3hOEDaNUOi_z4QgOf3WOtsbAynUgau5A4Q0jY2SzN5Bre_4bPH_kF_iqGBaLI/s16000/2023-05-17%2023_37_20-FDO%20Toolbox.png" /></a></div><p>Finally, to return back to the original issue motivating the production of this new release, the <b>ExtendedCoordSys.txt</b> support file for the SQL Server FDO provider has been updated to match the copy from current FDO trunk and has been updated with a CS alias mapping for GDA2020, allowing one to create spatial contexts on a SQL Server data store with this particular coordinate system (and many others!)</p><p>Now onto the next tour stop!</p><p><a href="https://github.com/jumpinjackie/fdotoolbox/releases/tag/v1.5.3" rel="nofollow" target="_blank">Download</a></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-22733558284265732023-05-05T01:23:00.001+10:002023-05-05T01:23:19.515+10:00The "I haven't forgotten about you $PROJECT" tour<p>As I said near the end of my <a href="https://themapguyde.blogspot.com/2023/04/announcing-mapguide-open-source-40-beta.html" rel="nofollow" target="_blank">MGOS 4.0 Beta 1 announcement</a>, I will be momentarily stepping away from MapGuide development/maintenance to give some of my sibling projects in the MapGuide/FDO space some long-overdue attention.</p><p>So for the next few weeks, I will be embarking on the "I haven't forgotten about you $PROJECT" tour with stopovers at the following projects:</p><h2 style="text-align: left;">mapguide-react-layout</h2><div>Next Release: 0.14.8</div><div><br /></div><div>Objectives: This will be the last release in the 0.14.x series and the last release to officially support Internet Explorer.</div><h2 style="text-align: left;">MapGuide Maestro</h2><div>Next Release: 6.0m12</div><div><br /></div><div>Primary Objective: This release will have authoring parity with MapGuide Open Source 4.0 Beta 1</div><div>Secondary Objective: Assorted fixes and minor enhancements</div><h2 style="text-align: left;">FDO Toolbox</h2><div>Next Release: 1.5.3</div><div><br /></div><div>Objective: Some fixes for bugs and usability problems reported since 1.5.2</div><h2 style="text-align: left;">mapguide-rest</h2><div>Next Release: 1.0 RC6</div><div><br /></div><div>Yes! I am finally giving this project some very-overdue attention!</div><div><br /></div><div>Primary Objective: Make sure it is compatible with PHP 8.1 that is bundled with MapGuide Open Source 4.0 Beta 1. Also doubles as a secondary sanity test of the new vanilla SWIG-generated PHP bindings, which is my main motivator for revisiting this project.</div><div><br /></div><div>Secondary Objective: See if we can do this will still being able to support older PHP versions bundled with older MapGuide versions. If this is not tenable, we may need to branch codebases and make separate releases. I hope that this is not the case.</div><div><br /></div><div><br /></div><div>When I finish this tour, then I will be returning to get MapGuide Open Source 4.0 to the final release finish line</div><div><br /></div><div><br /></div><div><br /></div>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-15018034918511333462023-04-05T22:27:00.000+10:002023-04-05T22:27:04.720+10:00Announcing: MapGuide Open Source 4.0 Beta 1<p>Due to real life priorities and commitments, this release look longer than expected to finally come to fruition, but that's all in the past because we're finally here! The first (and probably only) beta release of MapGuide Open Source 4.0 is finally available for the following platforms:</p><p></p><ul style="text-align: left;"><li>Windows</li><li>Ubuntu Linux 22.04</li><li>CentOS Linux 7.0</li></ul><div>Some notable changes / improvements over the <a href="https://themapguyde.blogspot.com/2022/11/announcing-mapguide-open-source-40.html" rel="nofollow" target="_blank">previous Preview 4 release</a> are detailed below.</div><h3 style="text-align: left;">GeoJSON output improvements</h3><div>The GeoJSON output support has several improvements in this release:</div><div><ul style="text-align: left;"><li>Where possible, the GeoJSON will now always include the <span style="font-family: courier;">crs</span> property (if the source data's coordinate system has an EPSG code representation), allowing for the GeoJSON content to self-identify its coordinate system.</li><li>GeoJSON from WFS <span style="font-family: courier;">GetFeature</span> requests will now properly transform feature data if a different SRS/CRS is specified in the query parameters</li><li>Such requests that return GeoJSON content now properly return a <span style="font-family: courier;">application/json</span> mime type</li></ul></div><h3 style="text-align: left;">Additional security options for mapagent hardening</h3><div>Currently, an <span style="font-family: courier;">Anonymous</span> (guest) user or session can read any resource in a MapGuide Server's repository via the mapagent HTTP endpoint. While this capability is required for certain client applications to work properly (for example, <a href="https://github.com/jumpinjackie/mapguide-react-layout" rel="nofollow" target="_blank">mapguide-react-layout</a> needs to be able to read WebLayout/ApplicationDefinition/MapDefinition resources as part of viewer initialization), it doesn't mean that *<b>every*</b> resource should be allowed to be read by anonymous users/sessions.</div><div><br /></div><div>In particular, Feature Sources rarely need to be read by anonymous users/sessions and it may be considered a security risk to some that connection settings in such Feature Sources (especially ones that connect to relational databases) can be read by anonymous users/sessions, exposing names of internal db servers in the process.</div><div><br /></div><div>The current resource permission model in MapGuide does allow for read access certain resources to be denied (in their resource headers), but this model is a sledgehammer approach. (ie. It will break rendering operations that need to query data from a feature source you just denied access to in their resource header).</div><div><br /></div><div>We need a more fine-grained approach where we can deny direct resource API access operations to things like feature sources, but still allow resource API access operations to such resources in the context of things like map rendering.</div><div><br /></div><div>This release introduces several new webconfig.ini properties to help reduce the attack surface of the mapagent in this regard.</div><div><div><ul style="text-align: left;"><li><span style="font-family: courier;">AnonymousDenyGetResourceContent</span></li><li><span style="font-family: courier;">AnonymousDenyGetResourceData</span></li><li><span style="font-family: courier;">AnonymousDenyGetResourceHeader</span></li></ul><div><span style="font-family: inherit;">These properties accept a comma-delimited list of resource ids or resource id prefixes and when set, if an anonymous user/session attempts a GETRESOURCECONTENT, GETRESOURCEHEADER or GETRESOURCEDATA with a resource id that matches any id or prefix specified, the mapagent will deny them access to that resource.</span></div></div></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">With this feature, you can reduce the attack surface of your mapagent by reducing anonymous resource access to only resources needed for a MapGuide client application to function.</span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">Please note that this feature only covers the mapagent and not your custom application code.</span></div><h3 style="text-align: left;">Web Tier Component updates</h3><div>This release bundles updated web tier components:</div><div><ul style="text-align: left;"><li>PHP 8.1.17</li><li>Apache httpd 2.4.56</li><li>Apache Tomcat 9.0.73</li></ul><h3 style="text-align: left;">Some long-standing bugs/limitations finally fixed!</h3></div><div><a href="https://trac.osgeo.org/mapguide/ticket/979" rel="nofollow" target="_blank">A 14-year old bug</a> where un-formatted WebLayout XML cannot be loaded has finally been fixed.</div><div><br /></div><div><a href="https://trac.osgeo.org/mapguide/ticket/772" rel="nofollow" target="_blank">Another 14-year old limitation</a> where labels under basic stylization is always left-justified has been addressed with new options in the 4.0.0 Layer Definition schema allowing you to control the feature label justification.</div><div><br /></div><div>Sorry for the long turnaround on such issues. Sadly, one person can only do so much.</div><h3 style="text-align: left;">What's next?</h3><div>Before we begin the journey to Release Candidate (and then Final release). I will be stepping away from MapGuide development/maintenance work for a few weeks to give some of the surrounding projects like Maestro and mapguide-react-layout some long needed attention, and I expect new releases of MapGuide Maestro and mapguide-react-layout during this period as a result.</div><div><br /></div><div>Once that is out of the way, then it is back onto the 4.0 release train, driving it to its final destination.</div><div><br /></div><div><a href="https://trac.osgeo.org/mapguide/wiki/Release/4.0.0/Beta1/Notes" rel="nofollow" target="_blank">Download</a></div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-77511016668948680792022-11-04T21:33:00.000+11:002022-11-04T21:33:18.372+11:00Announcing: MapGuide Open Source 4.0 Preview 4<p><a href="https://themapguyde.blogspot.com/2022/09/mapguide-dev-diary-it-is-done.html" rel="nofollow">After a long an arduous development journey</a>, it is finally here! The 4th preview release of MapGuide Open Source 4.0 is now available for the following platforms:</p><p></p><ul style="text-align: left;"><li>Windows</li><li>Ubuntu Linux 22.04</li><li>CentOS Linux 7.0</li></ul><div>The main feature new to the preview 4 release is the one feature that took the longest time to finish, but was something that needed to be done: We have overhauled all of our MapGuide API language bindings to now be generated with the <a href="https://swig.org/" rel="nofollow">official version of SWIG</a> instead of our ancient and heavily modified version.</div><div><br /></div><div>It is through this work that are finally able to drop PHP 5.6 and bundle a newer version of PHP, which for this release is PHP 8.1.11.</div><div><br /></div><div>On the .net front, this release now offers the .net bindings as a series of <b>netstandard2.0</b> nuget packages. These packages can be found in the <b>Web/nuget</b> directory of your preview 4 installation. Come the final release of MapGuide Open Source 4.0, we will publish these packages to the <a href="https://www.nuget.org/" rel="nofollow">official NuGet gallery</a> and will replace the existing <a href="https://www.nuget.org/packages/mapguide-api-web-x64" rel="nofollow">MapGuide API nuget</a> package going forward.</div><div><br /></div><div>On the Java front, we no longer ship MapGuideJavaApi.jar (the "crufty" wrapper) and <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc129">MapGuideJavaApiEx.jar</a> (the "non-crufty" wrapper) together. We now just ship a single MapGuideJavaApi.jar, which is based on the "non-crufty" wrapper. If your Java MapGuide application has been working against MapGuideJavaApiEx.jar, then migration back to MapGuideJavaApi.jar is 99.9% seamless.</div><div><br /></div><div>While this release is not deemed production ready, you should use this release as a means to start getting your MapGuide applications ready for the 4.0 final release. For all 3 languages, refer to <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc185#ImpactsummaryofAPIchanges" rel="nofollow">the RFC</a> for an overview of what migration you will need to perform on your codebase.</div><div><br /></div><div>After this release, I'm not intending to introduce or implement any new features in the 4.0 timeframe. It will be all bug fixes and library updates (where required) going forward, so I'm expecting a relatively short Beta > RC > Final cycle.</div><div><br /></div><div><a href="https://trac.osgeo.org/mapguide/wiki/Release/4.0.0/Preview4/Notes" rel="nofollow">Download</a></div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-26920458669578674342022-09-10T03:48:00.003+10:002022-09-10T03:56:33.057+10:00MapGuide dev diary: It is done!<p>In the <a href="https://themapguyde.blogspot.com/2022/05/mapguide-dev-diary-and-now-we-begin.html" rel="nofollow" target="_blank">previous</a> installment, we had gotten a test MapGuide installation with bundled PHP 8.1 up and running, and we were able to successfully produce a PHP error when hitting the Site Administrator.</p><p>This PHP error referenced previously was a milestone because it meant that our PHP 8.1 setup (FastCGI on Apache via mod_fcgid) was working, our PHP code was actually running and so the actual errors is the result of the vast swaths of our current PHP web tier applications needing to be migrated across to work against this new PHP 8.1 binding for the MapGuide API.</p><p>And so for the next few months I did just that, not just for PHP, but also for Java and .net. You can consider this post to be a preview of what you'll need to do yourself if you want to migrate your PHP/Java/.net MapGuide applications to MGOS 4.0.</p><p><span style="font-size: x-large;">PHP Migration Overview</span></p><p><span>The PHP binding was the one I expect to be the most work because besides finally supporting PHP 8.1, the major feature of this new PHP binding is that constants.php is no longer required! This is because with vanilla SWIG we now can bake all the constants of the MapGuide API into the PHP binding extension itself! So I expect a lot of "include 'constants.php'" references needing to be removed.</span></p><p>Once all the constants.php references are removed, we found the prime issue with this new PHP binding. PHP didn't like some of our C++ classes had overloaded methods whose signatures did not exist in the parent class. This manifested in the form of fatal PHP errors like the following:</p><p><span style="font-family: courier;">PHP Fatal error: Declaration of MgCoordinateSystemMeasure::GetDistance(MgCoordinate|float|null $arg1, MgCoordinate|float|null $arg2, float $arg3, float $arg4): float must be compatible with MgMeasure::GetDistance(?MgCoordinate $arg1, ?MgCoordinate $arg2): float in Unknown on line 0</span></p><p>In this case, our <b>MgMeasure</b> class has a <b>GetDistance</b> method of the following signature:</p><p style="text-align: center;"><span style="font-family: courier;">double GetDistance(MgCoordinate* coord1, MgCoordinate* coord2)</span></p><p>In the derived <b>MgCoordinateSystemMeasure</b>, it has a new overload of <b>GetDistance</b> that has this signature:</p><p style="text-align: center;"><span style="font-family: courier;">double GetDistance(double x1, double y1, double x2, double y2)</span></p><p>However, when this converted to PHP proxy classes by SWIG, PHP doesn't like this class setup because under its inheritance model, it is expecting the <b>GetDistance</b> overload with 4 double parameters to also exist in the base <b>MgMeasure</b> class. This is not the case, and thus PHP throws the above fatal error.</p><p>To workaround this problem, we had to use the SWIG %rename directive to rename the conflicting overload signature in <b>MgCoordinateSystemMeasure</b> in PHP to the following:</p><p style="text-align: center;"><span style="font-family: courier;">double GetDistanceSimple(double x1, double y1, double x2, double y2)</span></p><p>With this rename, there is no longer a signature conflict in the generated proxy class and PHP no longer throws a fatal error. Fortunately, only 2 classes in the MapGuide API have this problem, so the amount of method renaming is minimal.</p><p>Once this issue was addressed, I tried firing up the PHP implementation of the AJAX viewer and I got an interactive map! Everything seemed to be working until I tried to generate a map plot, and found my second problem. I was getting PHP fatal errors like this:</p><p><span style="font-family: courier;">PHP Fatal error: Uncaught TypeError: No matching function for overloaded 'MgRenderingService_RenderMap' in quickplotgeneratepicture.php:115</span></p><p>Fortunately, this one was easier to explain and fix. In PHP 8.1 (maybe even earlier in the PHP 7.x series), the type checking became more stricter which meant <b>int</b> parameters must take integers, <b>double</b> parameters must take doubles, etc, etc, you couldn't pass ints as doubles or vice versa, and for a method like RenderMap of MgRenderingService, there are lots of overloads that take many different combinations of int and double parameters.</p><p>Our map plotting code was passing in strings where int/double parameters were expected. In PHP 5.6 this was allowed because the type checking was evidently more lax. Now such cases cause the above PHP fatal error. This was easy enough to fix, we just use the <a href="https://www.php.net/manual/en/function.intval.php" rel="nofollow">intval</a> and <a href="https://www.php.net/manual/en/function.doubleval.php" rel="nofollow">doubleval</a> functions to make sure ints are being passed into int parameters and doubles are being passed into double parameters.</p><p>And with that, the rest of the changes involving fixing up our exception handling code due to a major change with how MapGuide applications should be handling exceptions from the MapGuide API. As part of this SWIG binding work, we've flattened the MapGuide exception hierarchy into a single MgException class, and introduced a new exception code property to allow handling MapGuide exceptions on a case-by-case basis.</p><p>So if you were handling specific MapGuide exceptions like this:</p>
<!--HTML generated using hilite.me--><div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2
3
4
5
6
7
8</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #d0d0d0;">try</span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;"> //Some code that could throw</span>
<span style="color: #d0d0d0;">} </span>
<span style="color: #d0d0d0;">catch (MgUnauthorizedAccessException $e) </span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;"> ...</span>
<span style="color: #d0d0d0;">}</span>
</pre></td></tr></tbody></table></div>
<p>You would now rewrite them like this:</p>
<!--HTML generated using hilite.me--><div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;"> 1
2
3
4
5
6
7
8
9
10</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #d0d0d0;">try</span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;"> //Some code that could throw</span>
<span style="color: #d0d0d0;">} </span>
<span style="color: #d0d0d0;">catch (MgException $e) </span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;"> if ($e->GetExceptionCode() == MgExceptionCodes::MgUnauthorizedAccessException) {</span>
<span style="color: #d0d0d0;"> ...</span>
<span style="color: #d0d0d0;"> }</span>
<span style="color: #d0d0d0;">}</span>
</pre></td></tr></tbody></table></div>
<p>The reason for flattening the exception hierarchy was:</p><p></p><ul style="text-align: left;"><li>To make wrapping exceptions simpler (we now only need to wrap the sole MgException class in SWIG) and not have to handle exception class inheritance chains in a consistent manner across all 3 language bindings.</li><li>Most of the example MapGuide API code pretty much only caught MgException anyways and rarely catches any of its derived exception classes (and I imagine that this is the case in your MapGuide applications as well). Any code that cared to handle specific exception cases, we can just include the relevant sub-classification as a property of MgException itself as the above code example shows.</li></ul><div>Once this final change was made, the AJAX viewer was fully functional. Porting Fusion to PHP 8 was a similar process.</div><p></p>
<p><span style="font-size: x-large;">Java Migration Overview</span></p><div style="text-align: left;">This migration I expect to be a cakewalk because although this binding is now also being generated by vanilla SWIG, it is 99% identical to the existing <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc129">MapGuideJavaApiEx.jar</a> that we have been generating and shipping for many releases of MapGuide.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">So all I expect is just to:</div><div style="text-align: left;"><ul style="text-align: left;"><li>Fix up references to MapGuideJavaApiEx and rename them to MapGuideJavaApi</li><li>Update exception handling blocks to take action based on the captured exception code in the caught MgException instead of catching for specific subclasses of MgException</li><li>Replace MapGuideApiEx.jar with MapGuideApi.jar (we're using the old jar name for the new binding) in our MG installation (and effectively, going back full circle to the way things were for Java in MapGuide)</li></ul><div>And ... it went just exactly what I said above! This was by far the easiest migration effort of the lot.</div></div><p><span style="font-size: x-large;">.net Migration Overview</span></p><p>This migration was the one I had been dreading the most. Not because I feared this binding was going to be fragile, because we already had an exhaustive test suite which this binding passed with flying colors.</p><p>But rather, I had been dreading this one because all of our .net code that is going to use this binding (AJAX viewer, code samples, etc) are all <b>legacy pre-historic aspx webforms</b> and I wasn't sure if such code would accept the brand new .net development story I had planned for it.</p><p>Consider the current .net development story.</p><p></p><ol style="text-align: left;"><li>You would reference the 5 OSGeo.MapGuide.* assemblies from mapviewernet/bin in your MapGuide application.</li><li>You would then have to manually copy the remaining dlls from mapviewernet/bin to your MapGuide application's output directory so that the .net MapGuide API binding doesn't fail due to missing native dll dependencies</li></ol><div>The alternative to this is to use the <a href="https://www.nuget.org/packages/mapguide-api-web-x64" rel="nofollow">NuGet package</a>, which make this story more seamless, but the process to build this NuGet package was a bespoke affair, with hand-crafted powershell scripts that trigger on nuget package installation to set up the necessary project build events to copy the native dlls needed by the OSGeo.MapGuide.* assemblies to the right location. Such functionality is tightly-coupled to Visual Studio, so if you were installing this NuGet package and building your MapGuide application outside of Visual Studio, none of the required post-build events would fire and the result is a broken MapGuide .net application because the native dll dependencies were not being copied to your application's output directory.</div><div><br /></div><div>For this new .net binding, we build each OSGeo.MapGuide.* assembly as a separate <a href="https://docs.microsoft.com/en-us/dotnet/core/project-sdk/overview" rel="nofollow">SDK-style</a> csproj project files. This new csproj file format has several benefits:</div><div><ul style="text-align: left;"><li>You don't have to reference individual C# source files that need to be compiled. Any C# source fil in the same directory as the csproj file is implied to be compiled as part of the project. This is great because it means we can run SWIG to generate the .cs files straight into the project and build that project straight away afterwards.</li><li>This csproj file format supports NuGet packages as first-class project output</li><li>The NuGet packages produced have first-class support for native dependencies. This is the real killer feature because it means in terms of packaging, we just have to include these native dlls in a well known location and they will be bundled up automatically as part of NuGet package creation. Such a package when consumed will have its native dependencies automatically copied to the right place and loaded from the right spot without any custom post-build events to set this stuff up!</li><li>And finally, it means instead of targeting .net Framework, we can target <b>netstandard2.0</b></li></ul></div><p></p><p>What does netstandard2.0 support imply? It implies your MapGuide application using these packages can work on <a href="https://github.com/dotnet/standard/blob/v2.1.0/docs/versions/netstandard2.0.md#platform-support" rel="nofollow" target="_blank">all of these platforms</a>. Now practically speaking, despite now being netstandard2.0 packages, these packages will only work on platforms where the underlying OS is Windows and <a href="https://themapguyde.blogspot.com/2018/07/introducing-new-experimental-bindings.html" rel="nofollow" target="_blank">(maybe) Linux</a> as those are the platforms where we can actually compile the underlying supporting native libraries needed by these nuget packages. So no Mac OSX, no Xamarin, etc. </p><p>In practical terms, it means you are no longer shackled to <b>legacy .net framework</b> for building MapGuide .net applications. You can now use <b>.net core</b> from its earliest netstandard2.0-supported iterations all the way to the latest <b>.net 6.0</b> (as of this post). </p><p>That's great and all, but going back to the original issue: Can the current suite of <b>aspx webforms</b> code accept this new way of consuming the .net MapGuide API and come along for the ride? I hope so! Because the alternative is to rewrite all of this code with more modern .net web technologies (razor pages maybe?), and while such a rewrite has merit and probably warranted, it is not warranted <b>right now</b> because that would add many more months of dev work to my already time-poor schedule. We have bigger fish to fry! We just hope this current codebase will cooperate with our new .net packaging paradigm with minimal effort.</p><p>So let's start with the basic facts.</p><p></p><ul style="text-align: left;"><li>MapGuide's .net integration requires IIS and .net framework to already be installed</li><li>We can assume that for the purpose of being able to use this netstandard2.0 library, that the installed .net framework version must <b>.net framework 4.8</b>.<b> </b>Building your own MapGuide applications for .net core and .net 5.0+ is something you can opt-in to, but it is not something to be demanded by our existing .net web tier code.</li></ul><div>With these facts established we have our first hurdle, and it is one of setup/deployment.</div><div><br /></div><div>The AJAX viewer and sample code have no Visual Studio solution/project files! How do these things ever get built?</div><div><br /></div><div>The AJAX viewer for .net is a series of raw .aspx files, will be "compiled" to .net assemblies on first request to IIS. As part of this compilation, it will check its respective "bin" directory for any references. That's why the mapviewernet/bin has the OSGeo.MapGuide.* assemblies in there because that is what is being referenced when the .aspx files get compiled. The .net sample code also follows the same pattern.</div><div><br /></div><div>So we have a bunch of folders of .aspx files and we need to get the correct set of dlls from inside our brand new shiny nuget packages into these folders. How would we go about this without needing to disruptively set up solution/project files for them?</div><div><br /></div><div>Here's my approach. We setup a stub SDK-style project that targets net4.8 and references the 5 OSGeo.MapGuide.* nuget packages produced from our new .net binding project setup.</div><div><br /></div><div>As part of the main build, we perform a framework-dependent publish of this project. Because of the first-class native dependency support, the publish output of this project would be the project's assembly, the 5 OSGeo.MapGuide.* assemblies and (importantly) all of their native dll dependencies in one single output directory. Once we done the framework-dependent publish, we can then copy all the dll files in this publish output folder (except for the stub project) into the bin directory of our AJAX viewer and sample directories.</div><div><br /></div><div>It turns out this approach does result in a functional .net AJAX viewer and code samples. What was needed in addition to using a stub project to setup the required dll file list, is that the .net AJAX viewer and code samples need <a href="https://github.com/dotnet/standard/issues/542#issuecomment-339328208" rel="nofollow">a web.config file that references the netstandard assembly</a> due to our OSGeo.MapGuide.* assemblies now target netstandard2.0</div><div><br /></div><div>Is this a complete and utter hack? Totally!</div><div><br /></div><div>But this approach gives us a functional .net AJAX viewer and code samples. Considering the alternative solutions and my current timelines, this is a workable approach and sometimes ...</div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgVOaB-TNMCMzzi8yMiA2dAnklmkHmSUIcqWWUlhkUzSMIrvc9VLkEwoPAfgdwkr4_dFROMzqLhKu10fRkdabvUiWIvuEMTE5VrD3jxCUevjCvFl0ntwWE0CGctocItuRjkp9joPoiBC5ajfIiMOZf9vnOzMIje8dMmPnMqnUtSFiUBIgePH3LAiopO" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="320" data-original-width="270" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEgVOaB-TNMCMzzi8yMiA2dAnklmkHmSUIcqWWUlhkUzSMIrvc9VLkEwoPAfgdwkr4_dFROMzqLhKu10fRkdabvUiWIvuEMTE5VrD3jxCUevjCvFl0ntwWE0CGctocItuRjkp9joPoiBC5ajfIiMOZf9vnOzMIje8dMmPnMqnUtSFiUBIgePH3LAiopO" width="203" /></a></div><br />So that was the ugly setup/deployment aspect, but what about the code itself? Well that was relatively simple. Like PHP and Java before it, we only needed to fix up the exception handling code to match to our new pattern of checking for specific exception codes in the caught MgException to handle for certain error cases.</div><p></p><p><span style="font-size: x-large;">Getting this to work on Linux</span></p><p><span>With the bindings now all being generated by vanilla SWIG and all working on Windows, it was a case of getting the build system fully working again on Linux with these new bindings and updated web tier components.</span></p><p>Fortunately, on the binding front, most of the CMake configurations added in the initial phases of this work only needed minor adjustments, so the bulk of the work was actually building PHP 8.1 and integrating this into the Apache httpd server, which we are also building from source and updating our various httpd/php config file templates to work with this new version of PHP.</p><p><span style="font-size: x-large;">Where we stand now</span></p><p>We now finally have MapGuide API bindings generated with vanilla, unmodified SWIG that work on both Windows and Linux. This has been a long and arduous journey and I can finally see the light at the end of this tunnel!</p><p><a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc185" rel="nofollow">A new RFC</a> has been posted for PSC discussion/voting. I hope there isn't strong opposition/dissent on these changes, because I truly believe that this work is absolutely necessary for MapGuide going forward. Newer versions of .net/Java/PHP will always get released and inevitably we will need our MapGuide API bindings to work on these newer versions. Our current infrastructure to keep up with newer .net/Java/PHP versions is just not maintainable or tenable.</p><p>If/when this RFC is adopted, the long overdue Preview 4 release should drop not too long after!</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-25186563190410733602022-08-24T00:06:00.006+10:002022-08-24T00:06:56.441+10:00MapGuide Site Administrator XSS security fix available<p>A security fix is now available for MapGuide Open Source.</p><p>This fix mitigates several XSS vulnerabilities reported in the MapGuide Site Administrator tool.</p><p><a href="https://download.osgeo.org/mapguide/patches/mapadmin_xss_fix/mapadmin_xss_fix.zip" rel="nofollow" target="_blank">Download the fix here</a></p><p>To apply, simply extract the zip contents to the <b>www/mapadmin</b> folder of your MapGuide installation and overwrite all existing files.</p><p>This fix can be applied to the following versions of MapGuide Open Source:</p><p></p><ul style="text-align: left;"><li>2.6.1</li><li>3.0.0</li><li>3.1.0</li><li>3.1.1</li><li>3.1.2</li><li>Any preview release of 4.0.0</li></ul><p></p><p>Special thanks to Eitan Shav of <a href="https://www.mend.io/">mend.io</a> who found and reported this vulnerability</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-9639771657375536112022-08-03T00:33:00.001+10:002022-08-04T03:10:19.751+10:00Announcing: MapGuide Maestro 6.0m11<p>In the interest of getting back into the habit of releasing things again and to line up authoring expectations/experience for another upcoming MapGuide Open Source 4.0 preview release, here's a long overdue release of MapGuide Maestro. Here's a summary of what's changed since <a href="https://themapguyde.blogspot.com/2018/08/announcing-mapguide-maestro-60m10-and.html" rel="nofollow" target="_blank">the last release</a> (Wow! It really has been 4 years since the last one?)</p><h2 style="text-align: left;">MapGuide Open Source 4.0 authoring support</h2><div>This release of Maestro takes advantage of features/capabilities introduced in the upcoming MapGuide Open Source 4.0. For all these demonstrated features, we assume you have the current <a href="https://themapguyde.blogspot.com/2021/06/announcing-mapguide-open-source-40.html" rel="nofollow" target="_blank">Preview 3</a> release of MGOS 4.0 installed or newer.</div><div><br /></div><div>A new Layer Definition resource template based on <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc178" rel="nofollow" target="_blank">the v4.0.0 schema</a> is now available.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtTRuAY3xWa84c_8BbgsMI-s1olSEJ-QGP-D6TmA1ae5tvmPZq9boXx6UBT0OjiV4kwvyevJU8wySd9JhPk_uXfQF8d-EU0gLIGglCs_33A4uKRmffqaluhYm64xogyH9q14KjvLYtGFBeh7nBhBbwLNeb4zD-D-e1IczcR5WjqC2xvV8fi8N_AcNP/s826/2022-07-25%2022_52_42-MapGuide%20Maestro.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="578" data-original-width="826" height="448" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtTRuAY3xWa84c_8BbgsMI-s1olSEJ-QGP-D6TmA1ae5tvmPZq9boXx6UBT0OjiV4kwvyevJU8wySd9JhPk_uXfQF8d-EU0gLIGglCs_33A4uKRmffqaluhYm64xogyH9q14KjvLYtGFBeh7nBhBbwLNeb4zD-D-e1IczcR5WjqC2xvV8fi8N_AcNP/w640-h448/2022-07-25%2022_52_42-MapGuide%20Maestro.png" width="640" /></a></div><br /><div><br /></div><div>What features/capabilities does this offer? A new toggle option to determine if QUERYMAPFEATURES requests that hit this layer should include bounding box information or not. When bounding box data is not included, client-side viewer tools like zooming to selection will not work due to the lack of this information.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzqTw_XzN9-ELOiqDrrMOD_x946OFMrsRato7DsxntIdcNcfLDzROgATBiuD8Sp34fklacWg-VegvRIWNi-LhcA1ROJy5xdwi0A9yY2o0Hzf1SPUebLhJmicrvnKeGz_jtU8H3WmSwbdLS05Klik0MtObEt0xKsXw7mLkIWWpvjbhN4iyq-6QMEDZq/s741/2022-07-25%2022_54_03-MapGuide%20Maestro.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="237" data-original-width="741" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzqTw_XzN9-ELOiqDrrMOD_x946OFMrsRato7DsxntIdcNcfLDzROgATBiuD8Sp34fklacWg-VegvRIWNi-LhcA1ROJy5xdwi0A9yY2o0Hzf1SPUebLhJmicrvnKeGz_jtU8H3WmSwbdLS05Klik0MtObEt0xKsXw7mLkIWWpvjbhN4iyq-6QMEDZq/w640-h204/2022-07-25%2022_54_03-MapGuide%20Maestro.png" width="640" /></a></div><br /><div><br /></div><div><br /></div><div>The WMS metadata UI now has support for exposing or hiding <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc163" rel="nofollow" target="_blank">the geometry field data from WMS GetFeatureInfo responses</a>.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPhOuyWjtrqMMiyWR3xi5nYbPufFUuNUIXwlygi7IlLJA9VAiTGq-Cglxor_7s4KE27DlMjjetTo4oYVye5-ty_IX8R4WJ3ZwR0reWek3pmWA72jCgUIwhhz6CYcX8ZEiKYKjh1LPI_RBwZgbh5tV5Pi5kZmn3K8RiHrP-0QJl4jYPsckN0MY-iYzU/s504/2022-07-25%2022_56_13-Library___Samples_Sheboygan_Layers_Parcels.LayerDefinition.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="504" height="389" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPhOuyWjtrqMMiyWR3xi5nYbPufFUuNUIXwlygi7IlLJA9VAiTGq-Cglxor_7s4KE27DlMjjetTo4oYVye5-ty_IX8R4WJ3ZwR0reWek3pmWA72jCgUIwhhz6CYcX8ZEiKYKjh1LPI_RBwZgbh5tV5Pi5kZmn3K8RiHrP-0QJl4jYPsckN0MY-iYzU/w400-h389/2022-07-25%2022_56_13-Library___Samples_Sheboygan_Layers_Parcels.LayerDefinition.png" width="400" /></a></div><br /><div><br /></div><div>The basic label style editor finally has the missing support for editing advanced placement settings</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYxlc0z-FSjzcwYuBjZgvWfEYfJ0HVAVOaIZO9eFHeKoECw_YYtKH1m6YEXdM5eCi0mT9MTZj4a75r2N-6N5-nUuexchxf0Z4OYmTFQNCR5JVgyYnO6ed53i0At4UCb4bLY2ZCX7cj5Dthp-SPtD5jVgbfsvhK3ZjbGSUjlS2WLIv0lDMZ1KkEQiCL/s382/2022-07-25%2022_57_26-Edit%20the%20style.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="218" data-original-width="382" height="229" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYxlc0z-FSjzcwYuBjZgvWfEYfJ0HVAVOaIZO9eFHeKoECw_YYtKH1m6YEXdM5eCi0mT9MTZj4a75r2N-6N5-nUuexchxf0Z4OYmTFQNCR5JVgyYnO6ed53i0At4UCb4bLY2ZCX7cj5Dthp-SPtD5jVgbfsvhK3ZjbGSUjlS2WLIv0lDMZ1KkEQiCL/w400-h229/2022-07-25%2022_57_26-Edit%20the%20style.png" width="400" /></a></div><br /><div><br /></div><div>MapGuide Open Source 4.0 introduced <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc162" rel="nofollow" target="_blank">bulk coordinate transformation capabilities in the mapagent</a> and Maestro will now take advantage of this feature for places in the UI that require transforming coordinates, such as setting the map extents for example</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYZ8eyPrthh92JIdWi46MaxgZwmqpxe2qiLTvwVzi6uUZScj8XU9EW8Fef4R3NSBy1ll0qPwDfHpzDkkWJem__00GJK7li3hp-NxM9cxvOidGo6AE9ZBEmKRGFTG0AzA3h1-yW3n2QyEQ40iTt2IbyIpsRKZSkJN_1haolJWCpjq0ch0k4JMh-9oaH/s919/2022-07-25%2022_58_45-Calculating%20Extents.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="462" data-original-width="919" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYZ8eyPrthh92JIdWi46MaxgZwmqpxe2qiLTvwVzi6uUZScj8XU9EW8Fef4R3NSBy1ll0qPwDfHpzDkkWJem__00GJK7li3hp-NxM9cxvOidGo6AE9ZBEmKRGFTG0AzA3h1-yW3n2QyEQ40iTt2IbyIpsRKZSkJN_1haolJWCpjq0ch0k4JMh-9oaH/w640-h322/2022-07-25%2022_58_45-Calculating%20Extents.png" width="640" /></a></div><br /><div><br /></div><div>MapGuide Open Source 4.0 now also <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc173" rel="nofollow" target="_blank">removes the restriction</a> that you cannot CREATERUNTIMEMAP or MgMap.Create() a Map Definition that links to a XYZ tileset, so the Map Definition editor will no longer throw this warning and block you from linking to a XYZ tile set definition if you are connected to a MGOS 4.0 instance.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTqWP7CWFHCNAEZllM6lUpItOHr5mTXVvKPag3EAUUG0MC9dpC4qVvkxqoCJNqk7sdHJuwmB14tNGdR9gNk5RjVHj5-zqRgoZOXYufpOdWfe-OI3l8614qktxM1G4ZGfcHeJS-VQx-AGV9MOAxV0OLDXPmjT1TuFU8cp2gvBtjVpLMVxUvjoq6_hth/s417/2022-07-25%2023_37_04-MapGuide%20Maestro.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="152" data-original-width="417" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTqWP7CWFHCNAEZllM6lUpItOHr5mTXVvKPag3EAUUG0MC9dpC4qVvkxqoCJNqk7sdHJuwmB14tNGdR9gNk5RjVHj5-zqRgoZOXYufpOdWfe-OI3l8614qktxM1G4ZGfcHeJS-VQx-AGV9MOAxV0OLDXPmjT1TuFU8cp2gvBtjVpLMVxUvjoq6_hth/w400-h146/2022-07-25%2023_37_04-MapGuide%20Maestro.png" width="400" /></a></div><div><br /></div><h2 style="text-align: left;">Notable UI Changes</h2><div>Your published WFS and WMS layers are now visible as top-level nodes in the Site Explorer! This allows for quick visual verification that you have correctly applied the appropriate WFS/WMS publishing metadata to your Feature Source or Layer Definition.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkB448DwqHU67gLhkiEifduQ-WjCvCvHMX4Ihe6FzJ-5el9j9TEwOft4ERzfF6caHZ1nNDf7m3TpFseqJCAxSIPsAjG3M8Ids5hloKIySJ42qqzxoJDu2GbLVFahjqQd_9upl0ujWz0rxG7S2QoF44YAYYVGg2nq4-MFB_4kskdvR7F629UhxnHflb/s420/2022-07-25%2023_38_04-MapGuide%20Maestro.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="320" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkB448DwqHU67gLhkiEifduQ-WjCvCvHMX4Ihe6FzJ-5el9j9TEwOft4ERzfF6caHZ1nNDf7m3TpFseqJCAxSIPsAjG3M8Ids5hloKIySJ42qqzxoJDu2GbLVFahjqQd_9upl0ujWz0rxG7S2QoF44YAYYVGg2nq4-MFB_4kskdvR7F629UhxnHflb/w305-h400/2022-07-25%2023_38_04-MapGuide%20Maestro.png" width="305" /></a></div><br /><div>These new nodes aren't just for show. For the published WMS layers, there are context menu actions to follow back to the source Layer Definition or for the more exciting option, the ability to preview this WMS layer through <a href="https://trac.osgeo.org/mapguide/wiki/MapGuideRfc181" rel="nofollow" target="_blank">the new OpenLayers-driven content representation</a> for WMS layers</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoZ_w-ZRqskAbaWwAapy3K1fJtpICA7-fGg_R_swzY_omMEokUHmM6NSpxqMrjLPwkq-dA2MF4k7Zz18gVMV_4zRLMf8UmTDYzQVE2S8BTI3z95ZisIRHsg2QeyvJT3G6kbaDKYuiZ3Vp79yFjwdSzClOXHWjKmSfDWoN89H4GrLBO7sLqlo0m_AbE/s425/2022-07-25%2023_40_47-MapGuide%20Maestro.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="198" data-original-width="425" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoZ_w-ZRqskAbaWwAapy3K1fJtpICA7-fGg_R_swzY_omMEokUHmM6NSpxqMrjLPwkq-dA2MF4k7Zz18gVMV_4zRLMf8UmTDYzQVE2S8BTI3z95ZisIRHsg2QeyvJT3G6kbaDKYuiZ3Vp79yFjwdSzClOXHWjKmSfDWoN89H4GrLBO7sLqlo0m_AbE/w400-h186/2022-07-25%2023_40_47-MapGuide%20Maestro.png" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrxlgPDQm1n4RGF24H1BsqBHH_qqC03uyM47oyV5ZwSeVXVbxdIRM_tAa3kwYNTRRgxxT-ZGjLf4MB2b9UuV4g3GB5Es_Z4vUVTwgIDYpMuHImRH6kGLgA6_CrjKE2YFzjSyxxNSjH4s8ZMFkLCfpkNSbNqQH6oEgXweA-Vsnm7HeD-Vzo50fxaMwR/s1134/2022-07-25%2023_48_31-localhost_8018_mapguide_mapagent_mapagent.fcgi_REQUEST=GETMAP&SERVICE=WMS&VERSIO.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="440" data-original-width="1134" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrxlgPDQm1n4RGF24H1BsqBHH_qqC03uyM47oyV5ZwSeVXVbxdIRM_tAa3kwYNTRRgxxT-ZGjLf4MB2b9UuV4g3GB5Es_Z4vUVTwgIDYpMuHImRH6kGLgA6_CrjKE2YFzjSyxxNSjH4s8ZMFkLCfpkNSbNqQH6oEgXweA-Vsnm7HeD-Vzo50fxaMwR/w640-h248/2022-07-25%2023_48_31-localhost_8018_mapguide_mapagent_mapagent.fcgi_REQUEST=GETMAP&SERVICE=WMS&VERSIO.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">The local map viewer component (used for local map previews) now has a panel to show selection attributes</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEfJ0DlwTvN17G8mQwkQnLA0k7BMaF3oK5CVuX5HYvs06I6ycnuZJ1BRTjpqttCguPjGoRYS36s2DPm-bwgxWaVIY_qp2XAfEJ8i9d2_24sVCb0OW4ZJQ6hnsSmw9v5514l7yqADMzY66vMud3nkT_Dc6oU6Z0jzktSxzHiQ6281hS13QsKVZZVEoC/s985/2022-07-25%2023_50_47-MapGuide%20Maestro.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="699" data-original-width="985" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEfJ0DlwTvN17G8mQwkQnLA0k7BMaF3oK5CVuX5HYvs06I6ycnuZJ1BRTjpqttCguPjGoRYS36s2DPm-bwgxWaVIY_qp2XAfEJ8i9d2_24sVCb0OW4ZJQ6hnsSmw9v5514l7yqADMzY66vMud3nkT_Dc6oU6Z0jzktSxzHiQ6281hS13QsKVZZVEoC/w640-h454/2022-07-25%2023_50_47-MapGuide%20Maestro.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: left;"><br /></div><h2 style="text-align: left;">MgCooker is no more. Replaced with MgTileSeeder</h2><div>The venerable MgCooker tool for pre-seeding tilesets in MapGuide has been removed. <a href="https://themapguyde.blogspot.com/2017/11/an-introduction-to-mgtileseeder.html" rel="nofollow" target="_blank">MgTileSeeder</a> is now the full replacement for MgCooker and is capable of more things than MgCooker (like being a generic XYZ tileset seeder). All existing Maestro UI integrations with the MgCooker tool have also been removed as a result.</div><h2 style="text-align: left;">Maestro API package is now SourceLink-enabled</h2><div>If you use the Maestro API to build your own MapGuide client applications, the Maestro API nuget package is now built with <a href="https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/sourcelink" rel="nofollow" target="_blank">SourceLink</a> support meaning that when you go to a definition of any class/type of the Maestro API, you will now see the <b>full source code</b> of that class/type instead of the class/type outline from inferred .net metadata.</div><div><br /></div><div>Similarly, when debugging you can now step into the source code for any method in the Maestro API!</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dx4SBMaysBjxUMrU3A33Z2XdwIoK1Q1xtKvdsJbHcI20PHOHHHiMOKLoeUpdSH9lthvFUsxtadc-_a5vJdTqg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><br /><div>To take advantage of SourceLink requires some small Visual Studio settings changes, which are covered in detail <a href="https://jumpinjackie.github.io/mapguide-maestro/devguide/gettingstarted.html#enabling-sourcelink" rel="nofollow" target="_blank">here</a>.</div><h2 style="text-align: left;">Maestro is now a self-contained .net 6.0 windows application</h2><div>Aside from being able to take advantage of the new capabilities and performance improvements of .net 6.0, the other upside of this move is that this means that you no longer have to download/install the .net Framework first before installing Maestro. Being a self-contained application means that the support files needed to run a .net 6.0 application are now included with the installer itself.</div><div><br /></div><div><br /></div><div><a href="https://github.com/jumpinjackie/mapguide-maestro/releases/tag/6.0m11" rel="nofollow" target="_blank">Download MapGuide Maestro</a></div>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-29134256432924803162022-05-23T19:13:00.002+10:002022-05-23T19:13:29.796+10:00MapGuide dev diary: ... and now we begin the great migration<p><a href="https://themapguyde.blogspot.com/2022/04/mapguide-dev-diary-another-tangential.html" rel="nofollow">Previously</a>, we made some important breakthroughs on the PHP8 binding for MapGuide. Our sanity PHP tests passed (meaning that the core essentials of the MapGuide API were working), but the main PHP test suite itself had a large amount of failures.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB6M2ILuE8MbMi3MdOFeVcM8t0v6umT4vm2FRLQ2pz5gV1v_bPzFQjAq4CKAxb6jpOaVFoWoyB8hiAW64J0ZWb-maVYCSwDk4R5rAZE0qT-EtJKVhclykzXnrq8WmZNLs7djju3RMUpGYXuHvavBSHDm66zizt1HM9fKiJfZw5sicuLiJbkx91Htju/s596/2022-04-22%2001_34_46-Window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="52" data-original-width="596" height="56" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB6M2ILuE8MbMi3MdOFeVcM8t0v6umT4vm2FRLQ2pz5gV1v_bPzFQjAq4CKAxb6jpOaVFoWoyB8hiAW64J0ZWb-maVYCSwDk4R5rAZE0qT-EtJKVhclykzXnrq8WmZNLs7djju3RMUpGYXuHvavBSHDm66zizt1HM9fKiJfZw5sicuLiJbkx91Htju/w640-h56/2022-04-22%2001_34_46-Window.png" width="640" /></a></div><br /><p>Thanks to dead-easy PHP debugging in VSCode, I was able to step into the PHP test code line-by-line and was able to discover that most of these failures was due to a change in how we're meant to be reading out expected test results from our test fixture SQLite databases. We were reading out test results as SQLite BLOBs which broke test result comparison in PHP8. Switching over to reading out these test results as strings instead fixed up along with updating how we check for exceptions thrown by the MapGuide API fixed up all but one test case.</p><p>That one remaining test case failure is due deleting a resource created in a preceding test that doesn't exist. While I could spend more time finding out why, the fact of the matter is that 99.9% of the current test suite is now passing on Windows, and it would be more fruitful now to sort out the revised bundling and configuration story with PHP 8 and try to get a working MapGuide installation with the PHP 8 bundled installation, fixing up whatever code and configurations along the way until we have all of our PHP-based MapGuide applications fully functional, which for reference is the following:</p><p></p><ul style="text-align: left;"><li>The Site Administrator</li><li>The Feature Source schema report/preview</li><li>The AJAX viewer with PHP backend</li><li>Fusion</li></ul><div>In the process of getting a new MapGuide installation with bundled PHP 8 setup, I've changed how Apache httpd is set up to talk to PHP. Previously, we actually did something incorrect. We previously bundled the <b>thread-safe</b> build of PHP and used that for both Apache and IIS setups. It turns out we bundled the wrong kind of build for the IIS configuration, as we should have actually been using the <b>NTS (non-thread-safe)</b> build of PHP if setting up a MapGuide Web Tier with IIS and FastCGI.</div><div><br /></div><div>In the interest of getting things right this time round and not have to bundle <b>2 copies</b> of PHP (TS and NTS builds), I've decided to go all in on using the NTS build of PHP for both IIS and Apache. This means that setting up IIS will now use the correct binaries for FastCGI, but means that we can no longer use <b>mod_php</b> when setting up Apache httpd as that can only be used with the thread-safe builds of PHP. Instead, for Apache httpd we will now set up FastCGI for use with PHP as well via <a href="https://httpd.apache.org/mod_fcgid/" rel="nofollow">mod_fcgid</a>.</div><div><br /></div><div>So I grabbed a compatible copy of mod_fcgid.so from <a href="https://www.apachelounge.com/" rel="nofollow">apachelounge</a> and dropped it into my httpd installation, updated httpd.conf to use FastCGI for PHP, flipped <b>display_errors = On</b> in php.ini, spun up both the MapGuide Server and httpd, opened the MapGuide Site Administrator and was greeted with the following.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMccHvVXgceqd0tO3vxYuNjeKjxaBWXdspbVmDVGJtVkbP8UOv2Af7GeoXCC4e2MavNGR9Wc2wYCvqIbjoK2XIQ2hVMaMoMoKq4zvSBBxvNxqhBCA07hYgfTxW37S-RSjzNcbGtxmz67r3qx0tNXgp6bE_4Rtjd-HGjJUHQtPFSgi1b7B8MrNYjzYm/s1706/2022-05-23%2018_27_21-localhost_8018_mapguide_mapadmin_login.php%20-%20Brave.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="227" data-original-width="1706" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMccHvVXgceqd0tO3vxYuNjeKjxaBWXdspbVmDVGJtVkbP8UOv2Af7GeoXCC4e2MavNGR9Wc2wYCvqIbjoK2XIQ2hVMaMoMoKq4zvSBBxvNxqhBCA07hYgfTxW37S-RSjzNcbGtxmz67r3qx0tNXgp6bE_4Rtjd-HGjJUHQtPFSgi1b7B8MrNYjzYm/w640-h86/2022-05-23%2018_27_21-localhost_8018_mapguide_mapadmin_login.php%20-%20Brave.png" width="640" /></a></div><br /><div>And I am so glad to see this error message :)</div><div><br /></div><div>Because that is an error message reported by PHP, so we know PHP itself (via FastCGI) is working.</div><div><br /></div><div>Also the error is about a missing <b>constants.php</b> file, which if you've been following my previous posts is a file that is no longer necessary as our new PHP 8 bindings defines the constants within the binary extension itself.</div><div><br /></div><div>This error is one of who-knows-how-many things in our PHP applications that will need fixing up to be PHP 8 compatible.</div><div><br /></div><div>Time to start a-fixing!</div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-64061046002421041622022-04-22T02:21:00.000+10:002022-04-22T02:21:09.493+10:00MapGuide dev diary: Another (tangential) breakthrough!<p><a href="https://themapguyde.blogspot.com/2022/04/mapguide-dev-diary-important.html" rel="nofollow">Since I got the basic sanity checking PHP script running</a> without crashing, there was one problem remaining around MgByteReader contents being read incorrectly. This turned out to be another out-of-date SWIG typemap around byte arrays. Once that got fixed we are able to read out the contents of the MgByteReader without content corruption. This is an important thing to test because a lot of results from the MapGuide API (XML results, rendered map images, map plots, etc) come in the form of MgByteReaders. If we can't read content out of these readers without data corruption we have major problems, but that is fortunately not the case (so far!).</p><p>With that out of the way, it was onto to the current PHP test suite for the MapGuide API and getting it fixed up and passing.</p><p>But before we go there, I wanted to check if our new PHP binding was leaking memory in the most obvious cases. To that effect, I built our PHP binding with reference counting diagnostics enabled and wrote this PHP script.</p>
<!--HTML generated using hilite.me--><div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #cd2828; font-weight: bold;"><?php</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">exceptionTest</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> Expected release book-keeping:</span>
<span style="color: #999999; font-style: italic;"> MgException - 1</span>
<span style="color: #999999; font-style: italic;"> */</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #40ffff;">$rid</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgResourceIdentifier(</span><span style="color: #ed9d13;">"iamnotvalid"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">throwingFunction</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #40ffff;">$agfRw</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgAgfReaderWriter();</span>
<span style="color: #40ffff;">$wktRw</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgWktReaderWriter();</span>
<span style="color: #40ffff;">$rid</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgResourceIdentifier(</span><span style="color: #ed9d13;">"iamnotvalid"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">exceptionTest2</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> Expected release book-keeping:</span>
<span style="color: #999999; font-style: italic;"> MgAgfReaderWriter - 1</span>
<span style="color: #999999; font-style: italic;"> MgWktReaderWriter - 1</span>
<span style="color: #999999; font-style: italic;"> MgException - 1</span>
<span style="color: #999999; font-style: italic;"> */</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">throwingFunction();</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">exceptionTest3</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> Expected release book-keeping:</span>
<span style="color: #999999; font-style: italic;"> MgAgfReaderWriter - 1</span>
<span style="color: #999999; font-style: italic;"> MgWktReaderWriter - 1</span>
<span style="color: #999999; font-style: italic;"> MgException - 2</span>
<span style="color: #999999; font-style: italic;"> */</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #40ffff;">$rid</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgResourceIdentifier(</span><span style="color: #ed9d13;">"iamnotvalid"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">throwingFunction();</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">//Previous iterations of the binding would leak the previous $ex when</span>
<span style="color: #999999; font-style: italic;">//reusing the variable in this catch block</span>
<span style="color: #999999; font-style: italic;">//If the release book-keeping for MgException is 2, then this is no</span>
<span style="color: #999999; font-style: italic;">//longer the case</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">geometryXformTest</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> Expected release book-keeping:</span>
<span style="color: #999999; font-style: italic;"> MgCoordinateSystemFactory - 1</span>
<span style="color: #999999; font-style: italic;"> MgCoordinateSystem - 2</span>
<span style="color: #999999; font-style: italic;"> MgTransform - 1</span>
<span style="color: #999999; font-style: italic;"> MgWktReaderWriter - 1</span>
<span style="color: #999999; font-style: italic;"> MgPoint - 2</span>
<span style="color: #999999; font-style: italic;"> MgCoordinateXY - 2</span>
<span style="color: #999999; font-style: italic;"> */</span>
<span style="color: #40ffff;">$csFactory</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgCoordinateSystemFactory();</span>
<span style="color: #40ffff;">$cs1</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateFromCode</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"LL84"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$cs2</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateFromCode</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"WGS84.PseudoMercator"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$xform</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetTransform</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$cs1</span><span style="color: #d0d0d0;">,</span> <span style="color: #40ffff;">$cs2</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$wktRw</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgWktReaderWriter();</span>
<span style="color: #40ffff;">$pt</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$wktRw</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Read</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"POINT (1 2)"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$coord</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$pt</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetCoordinate</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Point ("</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$coord</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetX</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">", "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$coord</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetY</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">")\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$pt</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$pt</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Transform</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$xform</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$coord</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$pt</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetCoordinate</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"XPoint ("</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$coord</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetX</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">", "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$coord</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetY</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">")\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">connectionServiceTest</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> Expected release book-keeping:</span>
<span style="color: #999999; font-style: italic;"> MgUserInformation - 1</span>
<span style="color: #999999; font-style: italic;"> MgSiteConnection - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyResourceService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyFeatureService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyRenderingService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyMappingService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyKmlService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyDrawingService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyTileService - 1</span>
<span style="color: #999999; font-style: italic;"> MgProxyProfilingService - 1</span>
<span style="color: #999999; font-style: italic;"> */</span>
<span style="color: #40ffff;">$userInfo</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgUserInformation(</span><span style="color: #ed9d13;">"Anonymous"</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$site</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgSiteConnection();</span>
<span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Open</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$userInfo</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service1</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">ResourceService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service2</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">FeatureService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service3</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">RenderingService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service4</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">MappingService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service5</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">KmlService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service6</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">DrawingService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service7</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">TileService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$service8</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">ProfilingService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">functionWithParam</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$userInfo</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #40ffff;">$userInfo</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">SetLocale</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"en"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">function</span> <span style="color: #447fcf;">parameterPassingTest</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #999999; font-style: italic;">// We want to check parameters of Mg* objects passed do not encounter</span>
<span style="color: #999999; font-style: italic;">// refcounting shenanigans, but if they do, we want to make sure that</span>
<span style="color: #999999; font-style: italic;">// proper increment/decrement is happening so that the MgUserInformation</span>
<span style="color: #999999; font-style: italic;">// is released to 0 refcount (and thus deleted) when this function returns</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> Expected release book-keeping:</span>
<span style="color: #999999; font-style: italic;"> MgUserInformation - 1</span>
<span style="color: #999999; font-style: italic;"> */</span>
<span style="color: #40ffff;">$userInfo</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgUserInformation();</span>
<span style="color: #d0d0d0;">functionWithParam(</span><span style="color: #40ffff;">$userInfo</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Locale: "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #40ffff;">$userInfo</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetLocale</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">MgInitializeWebTier(</span><span style="color: #ed9d13;">"C:\\mg-4.0-install\\Web\\www\\webconfig_dev.ini"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== BEGIN - exceptionTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">exceptionTest();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== END - exceptionTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== BEGIN - exceptionTest2() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">exceptionTest2();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== END - exceptionTest2() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== BEGIN - exceptionTest3() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">exceptionTest3();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== END - exceptionTest3() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== BEGIN - connectionServiceTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">connectionServiceTest();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== END - connectionServiceTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== BEGIN - parameterPassingTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">parameterPassingTest();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== END - parameterPassingTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== BEGIN - geometryXformTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">geometryXformTest();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"=========== END - geometryXformTest() ===========\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #cd2828; font-weight: bold;">?></span><span style="color: #d0d0d0;"></span>
</pre></td></tr></tbody></table></div><div><br /></div>
The basic tenets behind this test script are:<div><ul style="text-align: left;"><li>If we new any Mg* class, we expect it to be released (reference count dropped by 1) once the respective variable goes out of scope. We consider the script to not be leaking if every "new" statement has a corresponding release as reported by our refcounting diagnostics.</li><li>Any non-primitive value returned by any class in the MapGuide API is also released once its respective captured variable goes out of scope</li><li>If an MgException is thrown and we catch it, it is released once we exit the respective catch block</li><li>If we have multiple try/catch blocks on MgException and we use the same variable name for the caught exception, we're not leaking on subsequent catch blocks (this used to happen when we were generating the PHP bindings on the older SWIG/PHP version)</li><li>Finally any MapGuide API object passed as parameters to other functions does not get touched by reference counting. But if it does, we expect that the reference count for that object is the same before and after the function call.</li></ul><div>Running this script produces the following output</div></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhQVxM6A653hw0iFWMFwNlN_cOXJrIJGEo8pi7qEGfjlrdz1lF5NzfLPS2h4jNggid-32QdQjH81jgomtFCCmPBtQG_dexf8TalQt6fCHpq6QkmtlXvj_8rc1CgH_hqRBdClDki-S0s9Xr3IgvZwUje5T6GeS9ra8jJ3UezviD27mlF91FdmRyEVoT/s950/2022-04-22%2000_55_43-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="950" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhQVxM6A653hw0iFWMFwNlN_cOXJrIJGEo8pi7qEGfjlrdz1lF5NzfLPS2h4jNggid-32QdQjH81jgomtFCCmPBtQG_dexf8TalQt6fCHpq6QkmtlXvj_8rc1CgH_hqRBdClDki-S0s9Xr3IgvZwUje5T6GeS9ra8jJ3UezviD27mlF91FdmRyEVoT/w640-h280/2022-04-22%2000_55_43-Window.png" width="640" /></a></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZCDTUlbiWlfGA6xGnL44J0zzXyHMcyTt0XF2SyB3JUQc8sogOZ2koPEQWqYUSR7szQxYj8cA28qM5T4sporSn2i4gDI3FQqEjhMHh7ZD8owKNvMgckig5ipHEnOAxjifFf5PlNT64vb96Sgh1K56Xw7pgBPDMDXWP56MA7FLXEx3grWVXw7jYyBZc/s953/2022-04-22%2000_53_06-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="931" data-original-width="953" height="626" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZCDTUlbiWlfGA6xGnL44J0zzXyHMcyTt0XF2SyB3JUQc8sogOZ2koPEQWqYUSR7szQxYj8cA28qM5T4sporSn2i4gDI3FQqEjhMHh7ZD8owKNvMgckig5ipHEnOAxjifFf5PlNT64vb96Sgh1K56Xw7pgBPDMDXWP56MA7FLXEx3grWVXw7jYyBZc/w640-h626/2022-04-22%2000_53_06-Window.png" width="640" /></a></div><br /><div>The key things to notice in the script output is that every variable assignment is being properly released upon exiting the function and anything that we new'd explicitly was released with a 1 -> 0 reference count transition. When an object's reference count drops to 0, it will be de-allocated on the C++ side. The script output is proof that we aren't leaking objects we explicitly new'd up from the PHP script, they are being properly de-allocated. Some objects (like the MgCoordinateSystem) release and do not drop to 0 reference count, but that is okay because I know that the MapGuide API caches MgCoordinateSystem instances for performances reasons, so they aren't leaking instances. They can live beyond the scope of the function call where I initially requested for such objects.</div><div><br /></div><div>So now knowing that we aren't leaking for the general cases, we can move onto the main PHP test suite.</div><div><br /></div><div>Running the main PHP test suite it for the first time (in a long time) showed some PHP errors around ambiguous overloaded methods. All of these errors are because PHP 7/8 must've tightened up some of the type checking and passing null as a parameter to a method that has many overloaded signatures may cause confusion. Either that or our heavily modified version of SWIG that we previously used to generate the PHP binding had custom codegen to specifically handle overloaded method resolution.</div><div><br /></div><div>Regardless, the fix was simple enough. Where passing null would cause ambiguity, we just needed to add the necessary cast (in our case, it was casting to string) to make sure the correct method signature is invoked. Once that fix was applied, the test suite ran to completion ...</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT-rRzM4oS0QFSeV51fMhBINO-4vznFLcKpD4uQ3v47u9wS1totB3tZ3YpRDPlD7H-TM99Zc662xM2NgFSQvJI5jXB3NVVc5697bQtZQ63fwO88h1pQwJagW8GgRQpbmASkOPkUKq4Ik2KZ_M7d1Cia0ASVdLlTbZGiZpMOQmOyiHoIqRR_0y4p7cu/s596/2022-04-22%2001_34_46-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="52" data-original-width="596" height="56" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT-rRzM4oS0QFSeV51fMhBINO-4vznFLcKpD4uQ3v47u9wS1totB3tZ3YpRDPlD7H-TM99Zc662xM2NgFSQvJI5jXB3NVVc5697bQtZQ63fwO88h1pQwJagW8GgRQpbmASkOPkUKq4Ik2KZ_M7d1Cia0ASVdLlTbZGiZpMOQmOyiHoIqRR_0y4p7cu/w640-h56/2022-04-22%2001_34_46-Window.png" width="640" /></a></div><br /><div>... with a metric crapton of test failures :(</div><div><br /></div><div>Now to figure out why these test cases are failing, which is where we come to the subject of this post.</div><div><br /></div><div>Anytime in the past, when I need to debug a PHP script, it was a case of sprinkling <a href="https://www.php.net/manual/en/function.var-dump.php" rel="nofollow">var_dump</a> and <a href="https://www.php.net/manual/en/function.print-r.php" rel="nofollow">print_r</a> statements everywhere, running it and try to comprehend the now extra verbose output, rinsing and repeating until I found the problem. Basically, <a href="https://stackoverflow.com/a/189570" rel="nofollow">printf debugging</a>.</div><div><br /></div><div>I had heard about a thing called <a href="https://xdebug.org/" rel="nofollow">xdebug</a>, but I had no idea how to pair it with an IDE (and what IDE to even use?) to get the nice integrated debugging experience I take for granted with .net, Java or C++. Debugging PHP script felt so primitive because I simply didn't know better and getting proper debugging set up just sounded too hard.</div><div><br /></div><div>Now, times have changed. We have <a href="https://code.visualstudio.com/" rel="nofollow">Visual Studio Code</a>. It has a nice ecosystem of extensions for working with PHP that supports the version of PHP that we are now targeting. If <a href="https://themapguyde.blogspot.com/2020/10/in-awe-of-what-vscode-can-do.html" rel="nofollow">debugging C++ code inside docker containers</a> turned out to be such a piece of cake, then surely the same can be said for using VSCode to debug PHP scripts with breakpoints, variable inspection and the whole works!</div><div><br /></div><div>So I searched for a VSCode extension that could help me debug PHP, and the first result was this <a href="https://marketplace.visualstudio.com/items?itemName=xdebug.php-debug" rel="nofollow">PHP debug adapter</a>. I followed its instructions to the letter.</div><div><br /></div><div>I went to the <a href="https://xdebug.org/wizard" rel="nofollow">xdebug install wizard</a> and pasted by dumped phpinfo details</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJJfETSBcZW0uSm_sp4z9HD5e0U7B52Q_l5RYi36RHCFd1rhBYNc4arKt_nXUqjb45EVLesOA8hGPFI_x6BBPMrGBz9V-u1z37Ouq1ZB2rDmDYAIhotHFtkCtApJi8gywJIFdq3_yMi0LZUHEcJfbi52kvt-IU3vyb_WLRmUTTTW3uqHL_h0nXjFby/s711/2022-04-22%2001_56_20-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="711" data-original-width="636" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJJfETSBcZW0uSm_sp4z9HD5e0U7B52Q_l5RYi36RHCFd1rhBYNc4arKt_nXUqjb45EVLesOA8hGPFI_x6BBPMrGBz9V-u1z37Ouq1ZB2rDmDYAIhotHFtkCtApJi8gywJIFdq3_yMi0LZUHEcJfbi52kvt-IU3vyb_WLRmUTTTW3uqHL_h0nXjFby/w572-h640/2022-04-22%2001_56_20-Window.png" width="572" /></a></div><br /><div>Once submitted, the wizard figured out what version of PHP I had and gave me the download link for the xdebug extension to download and further instructions on what php.ini changes I needed to make</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTsoU3j1QGqHyAf_-m1oP0cd584ekYS798kt5D2yEc1QnxaPNaZepgAVAI2FitxpzASS0fnLPWaY8ppLUfzvxpEgC9564C0afkR7LmysJ-PHWj_qOE-7ppWsZ6-4gVVyxTAvuhRxipZEy3n_svmiHxH90SCUBFwX_qW4wxG0VsJNiwiA09n5Yggu3Q/s641/2022-04-22%2001_57_12-Window.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="546" data-original-width="641" height="546" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTsoU3j1QGqHyAf_-m1oP0cd584ekYS798kt5D2yEc1QnxaPNaZepgAVAI2FitxpzASS0fnLPWaY8ppLUfzvxpEgC9564C0afkR7LmysJ-PHWj_qOE-7ppWsZ6-4gVVyxTAvuhRxipZEy3n_svmiHxH90SCUBFwX_qW4wxG0VsJNiwiA09n5Yggu3Q/w640-h546/2022-04-22%2001_57_12-Window.png" width="640" /></a></div><br /><div>Then back to the VSCode extension instructions, I also updated php.ini to activate extra xdebug settings</div><div><br /></div>
<!--HTML generated using hilite.me--><div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #bbbbbb;">xdebug.mode</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">debug</span>
<span style="color: #bbbbbb;">xdebug.start_with_request</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">yes</span>
</pre></td></tr></tbody></table></div><div><br /></div>
Then in VSCode, I opened the PHP script I intend to run and debug, and created a new launch.json file for my active workspace.<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg6uUUv-sT9ZIwXBs72G5YjoJWlhk9Dm9g3kA6FoKnIR15amMS3-XjyIwhAMRs1kuZCLzptLEZHi4QYdAiS-NW9FtP92Uxg5MHHzUVSesZRLSXov9NC-k-aJT33AhvDAZFcrXxzlDOqB4QsKcakjiiMsXBPnDReLF3HDSBSwYNucMxD9AO7IsJeVg7/s854/2022-04-22%2002_02_22-Window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="491" data-original-width="854" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg6uUUv-sT9ZIwXBs72G5YjoJWlhk9Dm9g3kA6FoKnIR15amMS3-XjyIwhAMRs1kuZCLzptLEZHi4QYdAiS-NW9FtP92Uxg5MHHzUVSesZRLSXov9NC-k-aJT33AhvDAZFcrXxzlDOqB4QsKcakjiiMsXBPnDReLF3HDSBSwYNucMxD9AO7IsJeVg7/w640-h368/2022-04-22%2002_02_22-Window.png" width="640" /></a></div><br /><div>The newly installed VSCode PHP debug extension must've kicked in at this point because it created a launch.json with 3 xdebug launch presets ready to go. I modify the "Launch currently open script" preset to add in the extra command-line arguments needed by my PHP script.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1wKgTY3EyXbOzTrdukeJUmm1mO2hiwzaj66F9zWWZ-dG5VInHInaWhF45exGGMsoOI4D11DUfBVrwGkmvxMDmGkaOtFEXNNRlta6egyDjpPT6HR7NMqQWhEpn6KsCyViUyxThGUFJGPrDy3kfapTN6dugGGZmRVQvY92VrPSmM8Usj4IHyyjXzuDw/s646/2022-04-22%2002_05_39-Window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="367" data-original-width="646" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1wKgTY3EyXbOzTrdukeJUmm1mO2hiwzaj66F9zWWZ-dG5VInHInaWhF45exGGMsoOI4D11DUfBVrwGkmvxMDmGkaOtFEXNNRlta6egyDjpPT6HR7NMqQWhEpn6KsCyViUyxThGUFJGPrDy3kfapTN6dugGGZmRVQvY92VrPSmM8Usj4IHyyjXzuDw/w640-h364/2022-04-22%2002_05_39-Window.png" width="640" /></a></div><br /><div>Once I saved the launch.json, I open the PHP script again, stuck some breakpoints, switched to the debug tab, making sure to use the "Launch currently open script" preset.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6kvxR1FC6u-0hTl-9xvFaFgATQq1FGc9GLPeigyFzzhpQUjaGMA9vMcdftluO9bBUVAMkNvy-iCyd4lpGRP26zvQIT_KmotuKfH0chK9IeZgiWL7QAis4ZrqbxzD_8nQitVgyrWWH7Ub6_CfF2OI8zOhXc5AuqBqW-fInDJNDYN3d28nCSqqOflSL/s1128/2022-04-22%2002_08_00-Window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="441" data-original-width="1128" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6kvxR1FC6u-0hTl-9xvFaFgATQq1FGc9GLPeigyFzzhpQUjaGMA9vMcdftluO9bBUVAMkNvy-iCyd4lpGRP26zvQIT_KmotuKfH0chK9IeZgiWL7QAis4ZrqbxzD_8nQitVgyrWWH7Ub6_CfF2OI8zOhXc5AuqBqW-fInDJNDYN3d28nCSqqOflSL/w640-h250/2022-04-22%2002_08_00-Window.png" width="640" /></a></div><br /><div>I press the play button to start debugging and lo and behold! We're now breaking and stepping through PHP code and inspecting variables!</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnvHrwh-5U8m35yQQce6PqLlKr0d9zXhITp3cWENFBggmYDkqsJwMODOUyp-YaTAGYa97JOjq2pNxoAnaEIZmhhYaBwz_iOq2uYGRMs4THvA9f3jBHXFzEr7OijcRvwoRl5suVN_Jef18SLghY_DF_Gwqv50-5-XX8yeLqScR83kImOeQf9_EuEGPq/s1775/2022-04-22%2002_09_13-Window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="741" data-original-width="1775" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnvHrwh-5U8m35yQQce6PqLlKr0d9zXhITp3cWENFBggmYDkqsJwMODOUyp-YaTAGYa97JOjq2pNxoAnaEIZmhhYaBwz_iOq2uYGRMs4THvA9f3jBHXFzEr7OijcRvwoRl5suVN_Jef18SLghY_DF_Gwqv50-5-XX8yeLqScR83kImOeQf9_EuEGPq/w640-h268/2022-04-22%2002_09_13-Window.png" width="640" /></a></div><br /><div>Now I can focus on figuring out why there are so many test failures, at a much faster pace than what I would've normally done in the past!</div><div><br /></div><div>No doubt when MapGuide Open Source 4.0 is finally out the door, I'll have to write up a variation of this post on how to set up VSCode with PHP debugging for your PHP-based MapGuide applications. Because nobody should be sprinking var_dumps and print_r statements to debug PHP code like I have done in the past when this is many orders of magnitude faster and more productive!</div>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-65479782684404079332022-04-20T02:30:00.002+10:002022-04-20T02:30:40.354+10:00MapGuide dev diary: An important breakthrough!<p>Recently I have gotten back into the grind of MapGuide development pushing to <a href="https://themapguyde.blogspot.com/2020/11/mapguide-dev-diary-beginnings-of.html" rel="nofollow">clear the final hurdle</a> of having functional PHP bindings for the MapGuide API.</p><p>Since I last touched this code, several things have changed.</p><p></p><ul style="text-align: left;"><li>We originally wanted to target PHP 7.x, but this is no longer the latest. PHP 8.1.x is the latest. This release of PHP 8.1 for Windows is also built with the same MSVC compiler we use for MapGuide and FDO (MSVC 2019), which means the stars have aligned again where we can source official windows PHP binaries for bundling.</li><li>Our last attempt used <a href="https://swig.org/" rel="nofollow">SWIG</a> 4.0.2 (the most recent stable release). This release unfortunately cannot generate functional bindings for PHP 8, so our hand has been forced and we are now using and assuming current git master of SWIG for generating PHP bindings. The latest git master also no longer generates a [PHP extension .dll + .php proxy script] combination and goes back to generating just a PHP extension .dll, which is great because that how our (now) legacy PHP binding was generated.</li></ul><div>Given these environmental changes, we've re-activated the PHP binding work with a semi-clean slate. A lot of hacks and workarounds that were in place because the previous SWIG generated a [PHP extension .dll + .php proxy script] combination have been removed.</div><div><br /></div><div>The PHP binding work has now advanced to the stage where we can run this basic sanity test script against a binary PHP 8.1.4 distribution on Windows with no errors or crashes.</div><p></p>
<!--HTML generated using hilite.me--><div style="background: rgb(32, 32, 32); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #cd2828; font-weight: bold;"><?php</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Initializing web tier"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">MgInitializeWebTier(</span><span style="color: #ed9d13;">"C:\\mg-4.0-install\\Web\\www\\webconfig_dev.ini"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$initEx</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Init failure!"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">die</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(Exception</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Exception: "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">getMessage</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">die</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Initialized\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #999999; font-style: italic;">// We haven't and shouldn't need to require/include constants.php</span>
<span style="color: #999999; font-style: italic;">// they are now baked into the PHP extension along with the other</span>
<span style="color: #999999; font-style: italic;">// MapGuide API proxy classes</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Testing some constants\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgMimeType::</span><span style="color: #bbbbbb;">Agf</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgMimeType::</span><span style="color: #bbbbbb;">Kml</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgMimeType::</span><span style="color: #bbbbbb;">Mvt</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgImageFormats::</span><span style="color: #bbbbbb;">Png</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgImageFormats::</span><span style="color: #bbbbbb;">Gif</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgLogFileType::</span><span style="color: #bbbbbb;">Authentication</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">" - "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">MgServerInformationProperties::</span><span style="color: #bbbbbb;">ClientOperationsQueueCount</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$user</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgUserInformation(</span><span style="color: #ed9d13;">"Anonymous"</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">);</span>
<span style="color: #999999; font-style: italic;">// Basic set/get</span>
<span style="color: #40ffff;">$user</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">SetLocale</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"en"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Locale is: "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #40ffff;">$user</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetLocale</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$conn</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgSiteConnection();</span>
<span style="color: #40ffff;">$conn</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Open</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$user</span><span style="color: #d0d0d0;">);</span>
<span style="color: #999999; font-style: italic;">// Create a session repository</span>
<span style="color: #40ffff;">$site</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$conn</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetSite</span><span style="color: #d0d0d0;">();</span>
<span style="color: #40ffff;">$sessionID</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateSession</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Created session: $sessionID\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$user</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">SetMgSessionId</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$sessionID</span><span style="color: #d0d0d0;">);</span>
<span style="color: #999999; font-style: italic;">// Get an instance of the required services.</span>
<span style="color: #40ffff;">$resourceService</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$conn</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">ResourceService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Created Resource Service\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$mappingService</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$conn</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateService</span><span style="color: #d0d0d0;">(MgServiceType::</span><span style="color: #bbbbbb;">MappingService</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Created Mapping Service\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$resId</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgResourceIdentifier(</span><span style="color: #ed9d13;">"Library://"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Enumeratin'\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$resources</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$resourceService</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">EnumerateResources</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$resId</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">-</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">,</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #40ffff;">$resources</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">ToString</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Coordinate System\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$csFactory</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgCoordinateSystemFactory();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: CS Catalog\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$catalog</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetCatalog</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Category Dictionary\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$catDict</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$catalog</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetCategoryDictionary</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: CS Dictionary\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$csDict</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$catalog</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetCoordinateSystemDictionary</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Datum Dictionary\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$datumDict</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$catalog</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetDatumDictionary</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Coordinate System - LL84\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$cs1</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateFromCode</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"LL84"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Coordinate System - WGS84.PseudoMercator\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$cs2</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">CreateFromCode</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"WGS84.PseudoMercator"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Make xform\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$xform</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$csFactory</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetTransform</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$cs1</span><span style="color: #d0d0d0;">,</span> <span style="color: #40ffff;">$cs2</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: WKT Reader\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$wktRw</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgWktReaderWriter();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: WKT Point\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$pt</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$wktRw</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Read</span><span style="color: #d0d0d0;">(</span><span style="color: #ed9d13;">"POINT (1 2)"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$coord</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$pt</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetCoordinate</span><span style="color: #d0d0d0;">();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: X: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$coord</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetX</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">", Y: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$coord</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetY</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$site</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">DestroySession</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$sessionID</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Destroyed session $sessionID\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Test byte reader\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$bs</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgByteSource(</span><span style="color: #ed9d13;">"abcd1234"</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">8</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$content</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$br</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$bs</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetReader</span><span style="color: #d0d0d0;">();</span>
<span style="color: #40ffff;">$buf</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">while</span> <span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$br</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Read</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$buf</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">2</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">></span> <span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Buffer: '$buf'\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$content</span> <span style="color: #d0d0d0;">.=</span> <span style="color: #40ffff;">$buf</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Test byte reader2\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$bs2</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgByteSource(</span><span style="color: #ed9d13;">"abcd1234"</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">8</span><span style="color: #d0d0d0;">);</span>
<span style="color: #40ffff;">$content</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$br2</span> <span style="color: #d0d0d0;">=</span> <span style="color: #40ffff;">$bs2</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetReader</span><span style="color: #d0d0d0;">();</span>
<span style="color: #40ffff;">$buf</span> <span style="color: #d0d0d0;">=</span> <span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">while</span> <span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$br2</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Read</span><span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$buf</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">3</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">></span> <span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Buffer: '$buf'\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #40ffff;">$content</span> <span style="color: #d0d0d0;">.=</span> <span style="color: #40ffff;">$buf</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #40ffff;">$agfRw</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgAgfReaderWriter();</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Trigger an exception\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #40ffff;">$agfRw</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">Read</span><span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">NULL</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException caught\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Code: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetExceptionCode</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Message: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetExceptionMessage</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Details: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetDetails</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Stack: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetStackTrace</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Is standard PHP exception too? "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$ex</span> <span style="color: #d0d0d0;">instanceof</span> <span style="color: #d0d0d0;">Exception)</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(Exception</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Exception: "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">getMessage</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Trigger another exception\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">try</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #40ffff;">$r2</span> <span style="color: #d0d0d0;">=</span> <span style="color: #6ab825; font-weight: bold;">new</span> <span style="color: #d0d0d0;">MgResourceIdentifier(</span><span style="color: #ed9d13;">""</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(MgException</span> <span style="color: #40ffff;">$ex2</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException caught\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Code: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex2</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetExceptionCode</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Message: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex2</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetExceptionMessage</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Details: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex2</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetDetails</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: MgException - Stack: "</span><span style="color: #d0d0d0;">.</span><span style="color: #40ffff;">$ex2</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">GetStackTrace</span><span style="color: #d0d0d0;">().</span><span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Is standard PHP exception too? "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #d0d0d0;">(</span><span style="color: #40ffff;">$ex2</span> <span style="color: #d0d0d0;">instanceof</span> <span style="color: #d0d0d0;">Exception)</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span> <span style="color: #6ab825; font-weight: bold;">catch</span> <span style="color: #d0d0d0;">(Exception</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"[php]: Exception: "</span> <span style="color: #d0d0d0;">.</span> <span style="color: #40ffff;">$ex</span><span style="color: #d0d0d0;">-></span><span style="color: #bbbbbb;">getMessage</span><span style="color: #d0d0d0;">()</span> <span style="color: #d0d0d0;">.</span> <span style="color: #ed9d13;">"\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">echo</span> <span style="color: #ed9d13;">"Press any key to exit\n"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #24909d;">readline</span><span style="color: #d0d0d0;">();</span>
<span style="color: #cd2828; font-weight: bold;">?></span><span style="color: #d0d0d0;"></span>
</pre></td></tr></tbody></table></div><div><br /></div>
This script is a "sanity check" in that it is testing the key aspects of the MapGuide API that *must* function properly.<div><ul style="text-align: left;"><li>We can init the web tier</li><li>We can create a site connection</li><li>We can request instances of MgService-derived subclasses with proper downcasting (eg. if we ask for a resource service, we get a MgResourceService and not its parent MgService)</li><li>We can catch MgExceptions and inspect all relevant properties from it.</li><li>We can access constants. Notice we aren't require/include-ing constants.php? That's because we've found a way to get SWIG to bake all MapGuide constants into the PHP extension itself so this file is no longer necessary!</li><li>We can interact with MgByteReader contents properly</li></ul><div>Currently the sanity check script is failing on the last point and I strongly suspect it is another case of SWIG typemaps that were relevant for PHP7 but no longer valid for PHP8. We also need to make sure that this script doesn't leak memory. Also I've yet to get this binding building on Linux nor have I ran this sanity check script on Linux.</div></div><div><br /></div><div>Once this is taken care of, the long journey begins to make sure everything else is working in order of importance:</div><div><ol style="text-align: left;"><li>Our PHP test suite passes</li><li>Our PHP web tier applications (site administrator, schema report, AJAX viewer) are functional</li><li>Fusion is functional</li><li>We can build updated Apache and PHP end-to-end on Linux</li><li>All of the above is functional in both IIS and Apache web server configurations on both Windows and Linux</li></ol><div>Then, and only then we can start thinking about a new MapGuide Open Source 4.0 preview/beta release.</div></div>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-14077192413942397152022-03-04T00:56:00.002+11:002022-03-04T00:56:38.813+11:00Announcing: mapguide-react-layout 0.14.7<p>This release updates <a href="https://openlayers.org/" rel="nofollow">OpenLayers</a> to the latest version 6.13 and includes the following changes/fixes:</p><p></p><ul style="text-align: left;"><li>Un-break support for Web Layout resources</li><li>Use <a href="https://github.com/cure53/DOMPurify" rel="nofollow">DOMPurify</a> to sanitize all possible manually constructed HTML content. DOMPurify is now also the default HTML cleaning function for the selection panel if no custom HTML cleaning function is specified.</li></ul><div>The last release was 0.14.5. What happened to 0.14.6?</div><div><br /></div><div>The 0.14.6 release was pushed shortly before this announcement and was found to carry a vulnerable version of a package (shortid) that we no longer use. This release (0.14.7) was made shortly after to remove this dependency.</div><div><br /></div><div><a href="https://github.com/jumpinjackie/mapguide-react-layout/releases/tag/v0.14.7" rel="nofollow">Download</a></div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-81394029137716894612022-03-03T22:04:00.002+11:002022-03-03T22:04:38.830+11:00Announcing: vscode-map-preview 0.5.9<p><a href="https://marketplace.visualstudio.com/items?itemName=jumpinjackie.vscode-map-preview" rel="nofollow">This update</a> tidies up the feature popup display so that overly long name and values are now ellipsized</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj9qDcRAt9fgxmH9asZ9Nfi0LD7VfwYbrjIbh1ZAtP5VH7rwcni6blc_ngNN_eXiWzRrcgY1PKcOLb_B1R6wBW-4qK1yyoeLL4gYVy_hqC3CgoanRmi8g9h_ziD8bN_DmDUdLZ-vhinrUlrDFR5sJ208xY2I_boLtwfcm27X6bC7fOEjB4SLIq2D3qE=s1384" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="236" data-original-width="1384" height="110" src="https://blogger.googleusercontent.com/img/a/AVvXsEj9qDcRAt9fgxmH9asZ9Nfi0LD7VfwYbrjIbh1ZAtP5VH7rwcni6blc_ngNN_eXiWzRrcgY1PKcOLb_B1R6wBW-4qK1yyoeLL4gYVy_hqC3CgoanRmi8g9h_ziD8bN_DmDUdLZ-vhinrUlrDFR5sJ208xY2I_boLtwfcm27X6bC7fOEjB4SLIq2D3qE=w640-h110" width="640" /></a></div><br /><p>The original un-ellipsized content is available as a mouseover tooltip</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg1FYoP90eMAwnDYl7LCA0n61szHKdPtWydIeple1sxy6Wce52g7ix6-j57ZHS9LDdutx9BGKo09EI-h0HA-eW-WQOBF9PR6KlHAqLhKBwPCxu9-3U4Xq0MtLrxOJ4oBgCb_e5yoaJRINDeYnhuop75H9i58l0EH1HNV45L67tVBdHadLisgIv-pabE=s754" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="167" data-original-width="754" height="142" src="https://blogger.googleusercontent.com/img/a/AVvXsEg1FYoP90eMAwnDYl7LCA0n61szHKdPtWydIeple1sxy6Wce52g7ix6-j57ZHS9LDdutx9BGKo09EI-h0HA-eW-WQOBF9PR6KlHAqLhKBwPCxu9-3U4Xq0MtLrxOJ4oBgCb_e5yoaJRINDeYnhuop75H9i58l0EH1HNV45L67tVBdHadLisgIv-pabE=w640-h142" width="640" /></a></div><br /><p>Although I couldn't verify it, the name and content values are now also sanitized with DOMPurify to guard against any potential XSS shenanigans.</p><p>This update also includes an updated <a href="https://openlayers.org/" rel="nofollow">OpenLayers</a> (6.13.0)</p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-48026497116029363472021-12-29T20:26:00.000+11:002021-12-29T20:26:08.020+11:00Announcing: mapguide-react-layout 0.14.5<p> To cap off this year, here's one last release of mapguide-react-layout that includes the following changes:</p><p></p><ul style="text-align: left;"><li><a href="https://openlayers.org/" rel="nofollow">OpenLayers</a> updated to 6.10.0</li><li><a href="https://github.com/jumpinjackie/mapguide-react-layout/issues/1368" rel="nofollow">Fix instability on Firefox due to excessive usage of history APIs for URL state updates</a></li><li><a href="https://github.com/jumpinjackie/mapguide-react-layout/issues/1370" rel="nofollow">Allow appdef vector layers to opt-out of automatic hover highlighting</a></li></ul><div><a href="https://github.com/jumpinjackie/mapguide-react-layout/releases/tag/v0.14.5" rel="nofollow">Download</a></div><div><br /></div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-7992485403651600892021-12-15T23:53:00.002+11:002021-12-15T23:53:44.555+11:00MapGuide and log4shell<p>The <a href="https://en.wikipedia.org/wiki/Log4Shell" rel="nofollow">log4shell</a> vulnerability has been making the rounds across the tech space and since MapGuide has Java support, I did a check of our MGOS 3.1.2 and current 4.0 preview installation layouts to see if MapGuide is affected.</p><p>MapGuide's Java support comes in the form of:</p><p></p><ul style="text-align: left;"><li>Bundling the Apache Tomcat web server</li><li>Providing a Java language binding to the MapGuide API in the form of a consumable jar archive.</li></ul><div>None of these components carry log4j as a dependency. No log4j jar archives are present in any MGOS installation.</div><div><br /></div><div>Therefore, you are not affected by log4shell. Everything is good!</div><div><br /></div><div>Naturally, if your Java-based MapGuide application running on top carries the log4j dependency, you should check if the version you're consuming is affected by log4shell and upgrade that dependency to a non-vulnerable version.</div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-85347870408133764042021-12-14T00:53:00.002+11:002021-12-14T00:54:25.423+11:00All API code samples should be written as interactive notebooks!<p>Consider this hypothetical if you will.</p><p>What if instead of our <a href="https://jumpinjackie.github.io/mapguide-maestro/devguide/introduction.html" rel="nofollow">current static API documentation</a> for <a href="https://jumpinjackie.github.io/mapguide-maestro/" rel="nofollow">MapGuide Maestro</a>, we delivered API documentation as a series of <a href="https://devblogs.microsoft.com/dotnet/net-interactive-is-here-net-notebooks-preview-2/" rel="nofollow">.net interactive notebook</a> documents? Code examples that are not only editable, but also interactive!</p><p>Behold! A .net interactive notebook explaining how how to use the Maestro API to render an image of a map.</p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzeqYnXV4_dsvzj5tlMm026G5ow07SV41iAxJMco0Q07hA__iQDH9lf2G01ukm2dfMeienO5VSXkLUy9mYUYA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div><br /><p>Want to try this code sample yourself? In addition to having <a href="https://mapguide.osgeo.org/" rel="nofollow">MapGuide Open Source</a> installed locally, you will need Visual Studio Code and the <a href="https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode" rel="nofollow">.NET Interactive Notebooks</a> extension installed. Once both are installed, you can download <a href="https://gist.github.com/jumpinjackie/f8b5ac6372bbc70e8d06a6163df56cc5" rel="nofollow">this interactive notebook</a> and save it with a .dib extension. Once downloaded, open the .dib file in VSCode and you can run and play around with the code just like the video above.</p><p>I believe this is a game-changer for writing API documentation. I have had the same revelation with interactive notebooks for API documentation as I did with the discovery of <a href="https://storybook.js.org/" rel="nofollow">storybook</a> for designing, developing and showcasing <a href="https://reactjs.org/" rel="nofollow">React</a> components. With tools like this, you are actively incentivized to maintain your API docs and its a win-win for your (developer) userbase who get better quality API docs in the process.</p><p>The "killer app" for me is if there was a way to either:</p><p></p><ul style="text-align: left;"><li>Self-host these interactive notebooks on a asp.net core application</li><li>Export these interactive notebooks to blazor WASM so it can be hosted as static web content on something like GitHub pages</li></ul><div>Because right now you need specific tools to consume these interactive notebooks. The tipping point for me will be if you can consume these interactive notebooks straight from your web browser!</div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0tag:blogger.com,1999:blog-1951542926024108564.post-73977112643324995172021-11-12T23:20:00.001+11:002021-11-12T23:20:54.878+11:00Announcing: mapguide-react-layout 0.14.4<p>This release improves upon the <a href="https://themapguyde.blogspot.com/2021/10/announcing-mapguide-react-layout-0143.html" rel="nofollow">0.14.3 release</a> with the following fixes and changes:</p><p></p><ul style="text-align: left;"><li>The hover highlighting of vector layer features will now only happen if the active map tool is the <b>select</b> tool.</li><li>Fix viewer init of an appdef with static image layers</li><li>Fix support for Map Definitions using arbitrary coordinate systems whose units are not in meters.</li><li>Fix ability to add GeoJSON layers for some WFS services</li><li>A GeoJSON appdef layer can now source data from a browser global variable</li><li>WFS is now supported as an appdef external layer</li></ul><div><a href="https://github.com/jumpinjackie/mapguide-react-layout/releases/tag/v0.14.4" rel="nofollow">Download</a></div><p></p>Jackie Nghttp://www.blogger.com/profile/14319639645667992869noreply@blogger.com0