<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[RSS Feed]]></title><description><![CDATA[My experiences as a software developer]]></description><link>https://www.wimpyprogrammer.com</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 16 Apr 2026 02:56:55 GMT</lastBuildDate><item><title><![CDATA[Understanding Jest Mocks]]></title><description><![CDATA[Decipher Jest's complex rules for mocking modules.]]></description><link>https://www.wimpyprogrammer.com/understanding-jest-mocks</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/understanding-jest-mocks</guid><pubDate>Sun, 25 Jul 2021 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@flowforfrank?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Ferenc Almasi&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://jestjs.io/&quot;&gt;Jest&lt;/a&gt; is a powerful toolkit for testing JavaScript and TypeScript code.  It&apos;s an all-in-one test runner, mocking framework, and assertion library.  Without Jest, you might need to stitch together a separate library for each of these testing needs.&lt;/p&gt;
&lt;p&gt;But I&apos;ve always struggled to navigate Jest&apos;s complex mocking functionality.  A long list of factors determine whether Jest replaces a module with fake logic (mocked) or executes the actual module (unmocked).  To figure it out, I created &lt;a href=&quot;https://github.com/wimpyprogrammer/jest-mock-examples&quot;&gt;a test project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the following questions, imagine you want to test a file which imports &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; — which could be a local file, an npm package, or a built-in Node.js module.&lt;/p&gt;
&lt;h3 id=&quot;1-explicit-unmock&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-explicit-unmock&quot; aria-label=&quot;1 explicit unmock permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. Explicit unmock&lt;/h3&gt;
&lt;p&gt;Does the test call &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestunmockmodulename&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.unmock(&apos;some-dependency&apos;)&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestdontmockmodulename&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.dontMock(&apos;some-dependency&apos;)&lt;/code&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, continue to the next section.&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;yes&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will not be mocked.&lt;/p&gt;
&lt;h3 id=&quot;2-explicit-mock&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-explicit-mock&quot; aria-label=&quot;2 explicit mock permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Explicit mock&lt;/h3&gt;
&lt;p&gt;Does the test call &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestmockmodulename-factory-options&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.mock(&apos;some-dependency&apos;)&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestdomockmodulename-factory-options&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.doMock(&apos;some-dependency&apos;)&lt;/code&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, continue to the next section.&lt;/p&gt;
&lt;p&gt;If the test uses &lt;a href=&quot;https://jestjs.io/docs/mock-function-api#methods&quot;&gt;the mock functions API&lt;/a&gt; like &lt;a href=&quot;https://jestjs.io/docs/mock-function-api#mockfnmockimplementationfn&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mockImplementation()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://jestjs.io/docs/mock-function-api#mockfnmockreturnvaluevalue&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mockReturnValue()&lt;/code&gt;&lt;/a&gt;, or &lt;a href=&quot;https://jestjs.io/docs/mock-function-api#mockfnmockresolvedvaluevalue&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;mockResolvedValue()&lt;/code&gt;&lt;/a&gt; to specify the mock&apos;s behavior, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will use that behavior.&lt;/p&gt;
&lt;p&gt;Or if the &lt;code class=&quot;language-text&quot;&gt;jest.mock(&apos;some-dependency&apos;)&lt;/code&gt; / &lt;code class=&quot;language-text&quot;&gt;jest.doMock(&apos;some-dependency&apos;)&lt;/code&gt; call includes the &lt;code class=&quot;language-text&quot;&gt;factory&lt;/code&gt; parameter, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will use the behavior specified by &lt;code class=&quot;language-text&quot;&gt;factory&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Or if &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; has a &lt;a href=&quot;https://jestjs.io/docs/manual-mocks#mocking-node-modules&quot;&gt;manual mock&lt;/a&gt; (a file in the appropriate &lt;code class=&quot;language-text&quot;&gt;/__mocks__/&lt;/code&gt; directory), &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will use the behavior specified by that manual mock.&lt;/p&gt;
&lt;p&gt;Otherwise Jest will autogenerate a default mock of &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; using the substitution approach described in the docs for &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestcreatemockfrommodulemodulename&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.createMockFromModule()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;3-core-module&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-core-module&quot; aria-label=&quot;3 core module permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Core module&lt;/h3&gt;
&lt;p&gt;Is &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; a &lt;a href=&quot;https://nodejs.org/api/&quot;&gt;core Node.js module&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, continue to the next section.&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;yes&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will not be mocked.&lt;/p&gt;
&lt;h3 id=&quot;4-automocking&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-automocking&quot; aria-label=&quot;4 automocking permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. Automocking&lt;/h3&gt;
&lt;p&gt;Is Jest automocking enabled?  Automocking may be enabled with &lt;a href=&quot;https://jestjs.io/docs/configuration#automock-boolean&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;automock: true&lt;/code&gt;&lt;/a&gt; in the Jest configuration, or by calling &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestenableautomock&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.enableAutomock()&lt;/code&gt;&lt;/a&gt; in the test.&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, continue to the next section.&lt;/p&gt;
&lt;p&gt;If &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; has a &lt;a href=&quot;https://jestjs.io/docs/manual-mocks#mocking-node-modules&quot;&gt;manual mock&lt;/a&gt; (a file in the appropriate &lt;code class=&quot;language-text&quot;&gt;/__mocks__/&lt;/code&gt; directory), &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will use the behavior specified by that manual mock.&lt;/p&gt;
&lt;p&gt;Otherwise Jest will autogenerate a default mock of &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; using the substitution approach described in the docs for &lt;a href=&quot;https://jestjs.io/docs/jest-object#jestcreatemockfrommodulemodulename&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;jest.createMockFromModule()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;5-local-module&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-local-module&quot; aria-label=&quot;5 local module permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;5. Local module&lt;/h3&gt;
&lt;p&gt;Is &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; a local file?&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, continue to the next question.&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;yes&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will not be mocked.&lt;/p&gt;
&lt;h3 id=&quot;6-manual-mock&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#6-manual-mock&quot; aria-label=&quot;6 manual mock permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;6. Manual mock&lt;/h3&gt;
&lt;p&gt;Does &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; have a &lt;a href=&quot;https://jestjs.io/docs/manual-mocks#mocking-node-modules&quot;&gt;manual mock&lt;/a&gt; (a file in the appropriate &lt;code class=&quot;language-text&quot;&gt;/__mocks__/&lt;/code&gt; directory)?&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;no&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will not be mocked.&lt;/p&gt;
&lt;p&gt;If &lt;strong&gt;yes&lt;/strong&gt;, &lt;code class=&quot;language-text&quot;&gt;some-dependency&lt;/code&gt; will use the behavior specified in the manual mock.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Faster Google Classroom Assignments with a Bookmarklet]]></title><description><![CDATA[A free tool for teachers to automate the repetitive task of assigning work to a group.]]></description><link>https://www.wimpyprogrammer.com/faster-google-classroom-assignments-with-a-bookmarklet</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/faster-google-classroom-assignments-with-a-bookmarklet</guid><pubDate>Mon, 01 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@christinhumephoto?utm_content=creditCopyText&amp;#x26;utm_medium=referral&amp;#x26;utm_source=unsplash&quot;&gt;Christin Hume&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/person-using-macbook-hBuwVLcYTnA?utm_content=creditCopyText&amp;#x26;utm_medium=referral&amp;#x26;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you&apos;re a teacher and manage a Google Classroom, you probably have daily or weekly routines for adding assignments. If you frequently assign work to a subset of your students, like &quot;Advanced Readers&quot; or &quot;Group Two&quot;, here&apos;s a free tool that can streamline your work and avoid repetitive tasks.&lt;/p&gt;
&lt;p&gt;I wrote this tool for my wife to use during Distance Learning, and hope it will benefit other teachers too.&lt;/p&gt;
&lt;h2 id=&quot;browser-bookmarklets&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#browser-bookmarklets&quot; aria-label=&quot;browser bookmarklets permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Browser Bookmarklets&lt;/h2&gt;
&lt;p&gt;Most browsers support &quot;bookmarklets&quot; as a lightweight way to script interactions with a webpage. You&apos;re probably familiar with &quot;bookmarks&quot; as a means to save a webpage address so you can find it later. Bookmarklets live alongside your bookmarks, but instead of navigating you to a saved address, a bookmarklet can perform actions on the current page.&lt;/p&gt;
&lt;p&gt;A bookmarklet is like a simple kind of browser extension.&lt;/p&gt;
&lt;h2 id=&quot;automating-assignees&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#automating-assignees&quot; aria-label=&quot;automating assignees permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Automating Assignees&lt;/h2&gt;
&lt;p&gt;I&apos;ve created a free bookmarklet to streamline two scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Assigning work to &lt;strong&gt;only&lt;/strong&gt; a specified list of students.&lt;/li&gt;
&lt;li&gt;Assigning work to all students &lt;strong&gt;except&lt;/strong&gt; a specified list.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, assigning an advanced math homework or a differentiated language assignment.&lt;/p&gt;
&lt;p&gt;Let&apos;s say you have a group of five students – Scooby, Shaggy, Fred, Velma, and Daphne – that you sometimes assign work to. Your current workflow is something like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Look up which students are in the group.&lt;/li&gt;
&lt;li&gt;Open the drop-down list of assignees.&lt;/li&gt;
&lt;li&gt;Uncheck &quot;All students&quot;.&lt;/li&gt;
&lt;li&gt;Check each of the five students.&lt;/li&gt;
&lt;li&gt;Close the assignees list.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Use &lt;a href=&quot;./google-classroom-bookmarklets&quot;&gt;the bookmarklet generator&lt;/a&gt; to create a bookmarklet that automates these repetitive clicks. Your new workflow is as simple as:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click the &quot;Mystery Incorporated&quot; bookmarklet.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you have multiple groups, you can easily create a bookmarklet for each one.&lt;/p&gt;
&lt;button type=&quot;button&quot; class=&quot;cta&quot; onclick=&quot;location.href=&apos;./google-classroom-bookmarklets&apos;;&quot;&gt;
	Get Started
&lt;/button&gt;
&lt;p&gt;&lt;span id=&quot;help&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;troubleshooting&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#troubleshooting&quot; aria-label=&quot;troubleshooting permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;If you see an error message when you run the bookmarklet, follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Read the error message and look for troubleshooting tips. If you need to edit student names, open &lt;a href=&quot;./google-classroom-bookmarklets&quot;&gt;the bookmarklet generator&lt;/a&gt; and run your bookmarklet.&lt;/p&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 474px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fd9673bc23db97c3bf977ab2af802908/5595f/name-not-found.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 33.97683397683397%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABNUlEQVQoz3VQ7W6CQBC892iTAoIKglIP7hOpxiLamKb+6HtWqzb25aa5Q7RN7I/Nzu5mZ2aXuF4A1/PR5ACO68PxfHjn2ut04Qd9dPzev2HmjhtgOp2DjFIKXUwhZAEuNXTxBK1L5ExBqgmGo0cE3RD9MEYYJTcjTlLc3T/gdPoGoZlAXb/gebFCvVqjXq5RLZaYzStU9Qq6KJFlAskwvUlqeoN4ZAkPxy+QQZyCcQluHIoCWS5Bcw4uFLJc2JoxZZfMad1eaB03OLKEcUt4OIIYu0xoMK6Qs2aZ86Y2QkJoCDmxL5mUM4ulKlEazJV12Tr83B9AzOL6dYO3zTuqRQ1K+dmZsAJWhCvQjNvc9o0ApewP4Xa3B4miIdJxjjFlSJLUnmNO+R1t7zoLL/j6Qwcf2x1+AJan465/1TQmAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/fd9673bc23db97c3bf977ab2af802908/e90ce/name-not-found.avif 259w,
/static/fd9673bc23db97c3bf977ab2af802908/d7af0/name-not-found.avif 474w&quot;
              sizes=&quot;(max-width: 474px) 100vw, 474px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/fd9673bc23db97c3bf977ab2af802908/652f5/name-not-found.webp 259w,
/static/fd9673bc23db97c3bf977ab2af802908/01944/name-not-found.webp 474w&quot;
              sizes=&quot;(max-width: 474px) 100vw, 474px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/fd9673bc23db97c3bf977ab2af802908/a2ead/name-not-found.png 259w,
/static/fd9673bc23db97c3bf977ab2af802908/5595f/name-not-found.png 474w&quot;
            sizes=&quot;(max-width: 474px) 100vw, 474px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/fd9673bc23db97c3bf977ab2af802908/5595f/name-not-found.png&quot;
            alt=&quot;Bookmarklet error, name not found&quot;
            title=&quot;Bookmarklet error, name not found&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Changes to the Google Classroom interface may inadvertently break the bookmarklet. Open &lt;a href=&quot;./google-classroom-bookmarklets&quot;&gt;the bookmarklet generator&lt;/a&gt; and run your bookmarklet(s) to check for updates.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If all else fails, leave a comment below describing the issue and the error message you receive. I will assist as time allows.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Segment S3 uploads by Cognito user]]></title><description><![CDATA[Use S3 policies to isolate Cognito users into subdirectories of a bucket.]]></description><link>https://www.wimpyprogrammer.com/segment-s3-uploads-by-cognito-user</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/segment-s3-uploads-by-cognito-user</guid><pubDate>Tue, 14 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@tjevans?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Tim Evans&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/deposit?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Continuing my last post about &lt;a href=&quot;https://www.wimpyprogrammer.com/calculate-aws-v4-signature-client-side-javascript/&quot;&gt;combining AWS Cognito with EvaporateJS to upload to S3&lt;/a&gt;, we&apos;ll use S3 policies to isolate Cognito users into subdirectories of the S3 bucket.&lt;/p&gt;
&lt;h2 id=&quot;aws-policies-to-isolate-users&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#aws-policies-to-isolate-users&quot; aria-label=&quot;aws policies to isolate users permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;AWS Policies to Isolate Users&lt;/h2&gt;
&lt;p&gt;Imagine you want User 1 to have exclusive access to a &lt;code class=&quot;language-text&quot;&gt;/Users/1/&lt;/code&gt; subdirectory of your S3 bucket. You could update the S3 bucket&apos;s policy to specify that only User 1 has access to &lt;code class=&quot;language-text&quot;&gt;/Users/1/&lt;/code&gt;. Then what if you want User 2 to have exclusive access to &lt;code class=&quot;language-text&quot;&gt;/Users/2/&lt;/code&gt;? You could amend the bucket&apos;s policy to add rules for User 2. What about users 3, 4, and 5? Or the next 1,000 users of your site? Obviously this approach doesn&apos;t scale well.&lt;/p&gt;
&lt;p&gt;Luckily &lt;a href=&quot;http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html&quot;&gt;AWS supports variables in policies&lt;/a&gt;. Instead of explicitly listing users, you could write a generic policy allowing User X to access &lt;code class=&quot;language-text&quot;&gt;/Users/X/&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;policy-to-isolate-cognito-users&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#policy-to-isolate-cognito-users&quot; aria-label=&quot;policy to isolate cognito users permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Policy to Isolate Cognito Users&lt;/h2&gt;
&lt;p&gt;To use this approach with Cognito, I chose the &lt;code class=&quot;language-text&quot;&gt;cognito-identity.amazonaws.com:sub&lt;/code&gt; policy variable. This evaluates to the Cognito user&apos;s Identity ID, which follows the format &lt;code class=&quot;language-text&quot;&gt;region:guid&lt;/code&gt;. Here&apos;s an example policy.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre style=&quot;counter-reset: linenumber 0&quot; class=&quot;language-json line-numbers&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;&quot;Version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2012-10-17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token property&quot;&gt;&quot;Statement&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token property&quot;&gt;&quot;Sid&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AllowAccessToPrivateCognitoUserFolder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token property&quot;&gt;&quot;Effect&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Allow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token property&quot;&gt;&quot;Principal&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token property&quot;&gt;&quot;AWS&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::12345:role/Cognito_Auth_Role&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token property&quot;&gt;&quot;Action&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;s3:GetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;s3:PutObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;s3:DeleteObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;s3:AbortMultipartUpload&quot;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token property&quot;&gt;&quot;Resource&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::bucket-name/Users/${cognito-identity.amazonaws.com:sub}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::bucket-name/Users/${cognito-identity.amazonaws.com:sub}/*&quot;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;line-numbers-rows&quot; style=&quot;white-space: normal; width: auto; left: 0;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The highlighted lines require additional attention:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;On line 8, enter the role used by your authenticated Cognito users. This is listed in the Cognito area of the AWS Console, under &lt;a href=&quot;https://console.aws.amazon.com/cognito/federated/&quot;&gt;Federated Identities&lt;/a&gt;. In the identity pool settings, click &quot;Edit identity pool&quot; in the top-right corner. The role&apos;s name is displayed in the &quot;Authenticated role&quot; menu. However, the bucket policy needs the role&apos;s full ARN, so you can hop over to the &lt;a href=&quot;https://console.aws.amazon.com/iam/home#/roles&quot;&gt;Roles list in IAM&lt;/a&gt;, find the role named in the identity pool&apos;s settings, and click it to find the Role ARN. Update line 8 with this value, wrapped in double quotes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you use Cognito&apos;s group feature to assign a custom IAM role to some users, your policy must include the ARN of every role that needs access to S3. Wrap each role ARN in double quotes and separate entries with commas. For example, if your &quot;Moderators&quot; group has a custom IAM role, you would list both roles like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;Principal&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;AWS&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::12345:role/Cognito_Auth_Role&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:iam::12345:role/Cognito_Moderator_Role&quot;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On lines 17 and 18, replace &lt;code class=&quot;language-text&quot;&gt;bucket-name&lt;/code&gt; with the name of your S3 bucket.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;code-to-isolate-cognito-users&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code-to-isolate-cognito-users&quot; aria-label=&quot;code to isolate cognito users permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Code to Isolate Cognito Users&lt;/h2&gt;
&lt;p&gt;Thanks to the AWS policy above, User 2 will be unable to access &lt;code class=&quot;language-text&quot;&gt;/Users/1/&lt;/code&gt;. But how do we send a user&apos;s uploads to the correct subdirectory? Building on the S3Manager code in &lt;a href=&quot;https://www.wimpyprogrammer.com/calculate-aws-v4-signature-client-side-javascript/&quot;&gt;the previous article&lt;/a&gt;, I chose to pass the uploader&apos;s ID during instantiation.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getS3Manager&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// skipping unchanged code...&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		accessKeyId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;		identityId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;		secretAccessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		sessionToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s3Manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Manager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		accessKeyId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		secretAccessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		sessionToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;		identityId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// skipping unchanged code...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Manager&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;accessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; secretKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sessionToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// skipping unchanged code...&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;		&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token function&quot;&gt;upload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; transferHeaders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// skipping unchanged code...&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Users/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/encoded/upload/path.extension&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// TODO: Specify this&lt;/span&gt;&lt;/span&gt;		&lt;span class=&quot;token comment&quot;&gt;// skipping unchanged code..&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now every Cognito user automatically has a private subdirectory in the S3 bucket that only they can access.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Calculate AWS v4 Signature with client-side JavaScript]]></title><description><![CDATA[Use AWS Cognito credentials to authenticate requests directly in the browser.]]></description><link>https://www.wimpyprogrammer.com/calculate-aws-v4-signature-client-side-javascript</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/calculate-aws-v4-signature-client-side-javascript</guid><pubDate>Fri, 10 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rareyesphoto?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Ray Reyes&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/calculator?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;My team recently completed a challenging 5-month product build that integrates with many Amazon Web Services (AWS) features. We had the opportunity to use some new services, namely &lt;a href=&quot;https://aws.amazon.com/cognito/&quot;&gt;AWS Cognito&lt;/a&gt;, which forced us to pioneer new solutions more than a typical project. First up: calculating AWS v4 signatures client-side to integrate &lt;a href=&quot;https://github.com/TTLabs/EvaporateJS&quot;&gt;EvaporateJS&lt;/a&gt; with AWS Cognito.&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-aws-cognito&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#benefits-of-aws-cognito&quot; aria-label=&quot;benefits of aws cognito permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Benefits of AWS Cognito&lt;/h2&gt;
&lt;p&gt;Although some parts of AWS Cognito feel incomplete (multi-factor authentication and documentation come to mind), it offers great potential by allowing users to authenticate directly to the AWS ecosystem. When Member Matt logs in, he can run client-side JavaScript to authenticate and talk directly with the AWS API. And when Admin Amber logs in, Cognito&apos;s group feature allows her to run elevated commands that Matt cannot. This lets us securely interact with AWS without intermediary servers to proxy commands.&lt;/p&gt;
&lt;p&gt;Case in point: uploading private files to &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;AWS S3&lt;/a&gt;. We want users of our product to store sensitive files in S3 without the ability to read or overwrite another user&apos;s files. We &lt;em&gt;could&lt;/em&gt; upload files to a custom API that identifies the user and saves their files to S3, but this adds a lot of overhead. Instead, Cognito gives each user their own AWS credentials so they can read and write directly to S3, and we can write AWS policies to isolate users (see &lt;a href=&quot;https://www.wimpyprogrammer.com/segment-s3-uploads-by-cognito-user/&quot;&gt;&quot;Segment S3 uploads by Cognito user&quot;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 593px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3225c78c0e17369c1baff9899ef5dd57/0b5b1/s3-uploads-without-cognito.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 30.888030888030887%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZ0lEQVQY002QvUsCcRyHj/6AxpYQWmoIoSGIcJOgppwbgqCt0U0CW1oDcRCxaAmiIXIIM9AuODULX85O7U5Tzzg9z/c7vEPRu9/vG5dLz/DZHvjwEBhjAOh1pUI+F4/HGIZ5SyQoispm6Bpb+86x9VKVJMlMJkPTdDKZpGKxXr8PABhjAgAmk9lrosFV2rI8whiPx2N9pg+0boD2HYZcd1wUEMx0HSGkadpU1xvvcSWdBABT5gVt64C2H3Nppq0MO6IkjYbqdf5y+XyDcK6ueBycwEtNUWw2eqoqRsPk7vatzfoTChKGoT+FX+z7ru09b5Xv8HylyLLqQDkKnRLOtYWzzSX3TpxJldnSV7FQabYKVz7Ktn5jteT9HkJV1Ww2fR98iERCAAgAEDb3WfiweByLbvvJ4wX8Ma+DNI0LeGt+z1SRzduGYUjtNvwDA8YGLtbKKe6zK5t5EEJzuS8rdUEQW1JfUX4Bu7ghW6NOGWYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/3225c78c0e17369c1baff9899ef5dd57/e90ce/s3-uploads-without-cognito.avif 259w,
/static/3225c78c0e17369c1baff9899ef5dd57/0d37b/s3-uploads-without-cognito.avif 518w,
/static/3225c78c0e17369c1baff9899ef5dd57/5a5bb/s3-uploads-without-cognito.avif 593w&quot;
              sizes=&quot;(max-width: 593px) 100vw, 593px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/3225c78c0e17369c1baff9899ef5dd57/652f5/s3-uploads-without-cognito.webp 259w,
/static/3225c78c0e17369c1baff9899ef5dd57/c29d2/s3-uploads-without-cognito.webp 518w,
/static/3225c78c0e17369c1baff9899ef5dd57/ee627/s3-uploads-without-cognito.webp 593w&quot;
              sizes=&quot;(max-width: 593px) 100vw, 593px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/3225c78c0e17369c1baff9899ef5dd57/a2ead/s3-uploads-without-cognito.png 259w,
/static/3225c78c0e17369c1baff9899ef5dd57/6b9fd/s3-uploads-without-cognito.png 518w,
/static/3225c78c0e17369c1baff9899ef5dd57/0b5b1/s3-uploads-without-cognito.png 593w&quot;
            sizes=&quot;(max-width: 593px) 100vw, 593px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/3225c78c0e17369c1baff9899ef5dd57/0b5b1/s3-uploads-without-cognito.png&quot;
            alt=&quot;Without Cognito, user uploads to custom API which proxies the file to S3&quot;
            title=&quot;Without Cognito, user uploads to custom API which proxies the file to S3&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 462px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/810daee8b12a7b8352eb7c5133736fce/e389b/s3-uploads-with-cognito.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.62934362934363%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAABqElEQVQoz4WQv0vccBjG79/o0qVTpxbp1B92qlaogwg6u7SLUHAuLkIrpXtpB0Vol6AojXIc2JJTj9xxl7szCTGXS2LyTc7Gs4KYxuS+P/JKcou0g5/h4X3hfXjf5y14nmfb9lARQtaNOggCwzB833ccxzAMhFCv13Mdx+x2B4MBABQsy2o2pVr1oFwWWq1WsVgUBKFUKtXrdVmWRVFsSJIgCJVKRdf1HZ7fFcp7Yu387E9mBoCLS+z6V2kKt5BPXJod4jnDNjNv//Qezx68/aCsbBgAmFCGMSaEUEpZDiEkTdM4ioIt7sfUWHF6vMN9A0Iy81eue/dF+c5z+f1n5KMjWdEURWlnHLbbbTnnSNebUkOaeflr9MHayL318SeAcUHTtHeLS5NTb+4/muc2qwAQxwml9LTf75qmZVlRFBGCKWMnvl+fmai9esaNPlyfeJqZVVXlef7L6vePn5b7gZ9nSYfKGEtvfAIPkrBR3Z+fUxZe/xb3gbHs7CRJgqDP2C0fo5SGLD2xrXP3OAbAOM8chiFy3X/2/E8cx5qq2q5rHjsdXf8bRdcOAs8/5EcVHQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/810daee8b12a7b8352eb7c5133736fce/e90ce/s3-uploads-with-cognito.avif 259w,
/static/810daee8b12a7b8352eb7c5133736fce/28233/s3-uploads-with-cognito.avif 462w&quot;
              sizes=&quot;(max-width: 462px) 100vw, 462px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/810daee8b12a7b8352eb7c5133736fce/652f5/s3-uploads-with-cognito.webp 259w,
/static/810daee8b12a7b8352eb7c5133736fce/c589b/s3-uploads-with-cognito.webp 462w&quot;
              sizes=&quot;(max-width: 462px) 100vw, 462px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/810daee8b12a7b8352eb7c5133736fce/a2ead/s3-uploads-with-cognito.png 259w,
/static/810daee8b12a7b8352eb7c5133736fce/e389b/s3-uploads-with-cognito.png 462w&quot;
            sizes=&quot;(max-width: 462px) 100vw, 462px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/810daee8b12a7b8352eb7c5133736fce/e389b/s3-uploads-with-cognito.png&quot;
            alt=&quot;With Cognito, user authenticates and uploads directly to S3&quot;
            title=&quot;With Cognito, user authenticates and uploads directly to S3&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;uploading-to-s3-with-evaporatejs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#uploading-to-s3-with-evaporatejs&quot; aria-label=&quot;uploading to s3 with evaporatejs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Uploading to S3 with EvaporateJS&lt;/h2&gt;
&lt;p&gt;To upload files to S3 we chose &lt;a href=&quot;https://github.com/TTLabs/EvaporateJS&quot;&gt;EvaporateJS&lt;/a&gt;, which immediately added value like multi-part uploads, pausing, resuming, and progress callbacks.&lt;/p&gt;
&lt;div class=&quot;callout&quot;&gt;
&lt;p&gt;The following code uses EvaporateJS 1.x. The current version of EvaporateJS, 2.x, adds &lt;code class=&quot;language-text&quot;&gt;customAuthMethod&lt;/code&gt; so the implementation is slightly different. See &lt;a href=&quot;https://github.com/TTLabs/EvaporateJS/issues/380#issuecomment-324184217&quot;&gt;this EvaporateJS 2.x example&lt;/a&gt; by &lt;a href=&quot;https://github.com/paolavness&quot;&gt;paolavness&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; assign&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; curry&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mapKeys&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; map &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lodash&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Evaporate &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;evaporate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// These cryptography functions are defined later in the article&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; hashSha256ToHex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hmacSha256 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./crypto&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; * Generate the signature for AWS to authenticate the request.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; * @param {String} secretKey - The IAM secret key of the AWS user making the request&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; * @param {Object} response - The response from the signerUrl or awsLambda requests&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; * @param {String} stringToSign - The &quot;string to sign&quot; generated in the previous step&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; *   of the AWS Signature v4 process.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; * @returns {String} - The signature included in the Authorization header for AWS&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; *   to authenticate the request.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;signRequest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;secretKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; stringToSign&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// stringToSign is URL-encoded by EvaporateJS, but the signature must use the decoded string.&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stringToSignDecoded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;decodeURIComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stringToSign&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	&lt;span class=&quot;token comment&quot;&gt;// Signing is defined later in the article&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Manager&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * Create an instance of S3Manager.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @constructor&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @param {String} accessKey - Uploader&apos;s AWS access key&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @param {String} secretKey - Uploader&apos;s AWS secret key&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @param {String} sessionToken - Uploader&apos;s AWS session token&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 */&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;accessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; secretKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sessionToken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Evaporate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;aws_key&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; accessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;awsRegion&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my-aws-region-identifier&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// TODO: Specify this&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;awsSignatureVersion&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;4&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// this is default in EvaporateJS 2.x&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;bucket&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my-s3-bucket-name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// TODO: Specify this&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;// Required for AWS Signature Version 4&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;cryptoHexEncodedHash256&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; hashSha256ToHex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;signResponseHandler&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;signRequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;secretKey&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sessionToken &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sessionToken&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;/**&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * Upload a file to AWS S3.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @param {File} file - The File object uploaded to the browser&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @param {Object} transferHeaders - Key-value pairs of headers to add to the AWS request, like&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 *   x-amz-server-side-encryption or x-amz-meta-* headers&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 * @param {Object} options - EvaporateJS properties to set/override for this upload&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;	 */&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;upload&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; transferHeaders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; authHeaders &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&apos;x-amz-security-token&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sessionToken &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				file&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;encoded/upload/path.extension&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// TODO: Specify this&lt;/span&gt;
				&lt;span class=&quot;token literal-property property&quot;&gt;xAmzHeadersAtInitiate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; authHeaders&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; transferHeaders&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token literal-property property&quot;&gt;xAmzHeadersCommon&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; authHeaders&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			options&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To create an instance of &lt;code class=&quot;language-text&quot;&gt;S3Manager&lt;/code&gt; using our logged-in cognitoUser:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getS3Manager&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
		cognitoUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;sessionErr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tokens&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sessionErr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sessionErr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// getSession() will populate AWS.config.credentials&lt;/span&gt;
			&lt;span class=&quot;token constant&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;credentialsErr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;credentialsErr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;credentialsErr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

				&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					accessKeyId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
					secretAccessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
					sessionToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;AWS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s3Manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Manager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
					accessKeyId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
					secretAccessKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
					sessionToken&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s3Manager&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;signing-the-aws-request&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#signing-the-aws-request&quot; aria-label=&quot;signing the aws request permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Signing the AWS Request&lt;/h2&gt;
&lt;p&gt;Using third-party libraries to interact with AWS requires us to cryptographically sign our own requests. The AWS SDK takes care of this but other libraries do not.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html&quot;&gt;Signature Version 4&lt;/a&gt; is the latest method for signing AWS requests. Of the four steps, EvaporateJS handles all except the third.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;3. You use your AWS secret access key to derive a signing key, and then use that signing key and the string to sign to create a signature.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The EvaporateJS docs explain &lt;a href=&quot;https://github.com/TTLabs/EvaporateJS#using-aws-lambda-to-sign-requests&quot;&gt;how to use AWS Lambda to sign requests&lt;/a&gt;. This is comparable to the Custom API proxy described earlier, in that we need to use our AWS Secret Key when calling AWS but we can&apos;t reveal it to the user. But with Cognito, that&apos;s no longer an issue! How can we use the Cognito user&apos;s credentials to sign the EvaporateJS request?&lt;/p&gt;
&lt;p&gt;There are many popular client-side cryptography libraries, and I played with the v4 signature in several. Here are examples of the &lt;code class=&quot;language-text&quot;&gt;signRequest&lt;/code&gt; function from the code above:&lt;/p&gt;
&lt;div class=&quot;callout&quot;&gt;
&lt;p&gt;These examples calculate the v4 signature of the &lt;code class=&quot;language-text&quot;&gt;stringToSign&lt;/code&gt; variable. To integrate with EvaporateJS, be sure to instead sign the &lt;code class=&quot;language-text&quot;&gt;stringToSignDecoded&lt;/code&gt; variable in the &lt;code class=&quot;language-text&quot;&gt;signRequest&lt;/code&gt; function.&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://runkit.com/wimpyprogrammer/aws-v4-signature-with-cryptojs&quot;&gt;CryptoJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://runkit.com/wimpyprogrammer/aws-v4-signature-with-crypto-browserify&quot;&gt;Crypto Browserify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://runkit.com/wimpyprogrammer/aws-v4-signature-with-aws-sdk&quot;&gt;AWS SDK (which includes an old version of Crypto Browserify)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;still-more-cryptography&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#still-more-cryptography&quot; aria-label=&quot;still more cryptography permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Still More Cryptography&lt;/h2&gt;
&lt;p&gt;Finally, EvaporateJS uses other cryptographic operations, some required (like &lt;code class=&quot;language-text&quot;&gt;cryptoHexEncodedHash256&lt;/code&gt;) and some just encouraged (like &lt;code class=&quot;language-text&quot;&gt;cryptoMd5Method&lt;/code&gt;). Here are implementations of those functions, compared side-by-side for accuracy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://runkit.com/wimpyprogrammer/aws-sdk-vs-cryptojs&quot;&gt;AWS SDK and CryptoJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://runkit.com/wimpyprogrammer/aws-sdk-vs-crypto-browserify&quot;&gt;AWS SDK and Crypto Browserify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope these examples help you dive into exciting libraries like AWS Cognito and EvaporateJS!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Code Style: Accessing JavaScript Variables]]></title><description><![CDATA[JavaScript's syntax allows for a lot of shortcuts when accessing variables. But shorter code can also be confusing. Which techniques are the shortest? Which are the easiest to read?]]></description><link>https://www.wimpyprogrammer.com/code-style-accessing-javascript-variables</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/code-style-accessing-javascript-variables</guid><pubDate>Sun, 25 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Kelly Sikkema&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/calligraphy?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;JavaScript&apos;s syntax allows for a lot of shortcuts when accessing variables. But shorter code can also be confusing. Which techniques are the shortest? Which are the easiest to read? A recent discussion with my co-workers led me to dive deeper.&lt;/p&gt;
&lt;p&gt;A wise adage says, &quot;code is read more than it is written.&quot; So my priorities are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Readability&lt;/li&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We want a pattern that is easily recognizable and predictable so our brains don&apos;t need to process it. When code is erratic I have to actually study it to find the purpose, or conversely I make quick assumptions that could be wrong.&lt;/p&gt;
&lt;p&gt;Our task is to access a deeply nested property -- &lt;code class=&quot;language-text&quot;&gt;settings.server.port&lt;/code&gt; -- in a safe way lest any property is undefined, then assign it to the property of another object. If &lt;code class=&quot;language-text&quot;&gt;settings.server.port&lt;/code&gt; is falsy (&lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;, etc.), we&apos;ll default to &lt;code class=&quot;language-text&quot;&gt;80&lt;/code&gt;. Let&apos;s see how various methods stack up.&lt;/p&gt;
&lt;h2 id=&quot;1-if-statements&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-if-statements&quot; aria-label=&quot;1 if statements permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; Statements&lt;/h2&gt;
&lt;p&gt;As a baseline, let&apos;s consider how verbose we could be.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settings &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	foo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	foo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This approach is recognizable by programmers from any language. But, by the same token, we don&apos;t leverage any of JavaScript&apos;s convenience syntax.&lt;/p&gt;
&lt;p&gt;Plus, if we are quickly skimming this code it&apos;s not obvious that &lt;code class=&quot;language-text&quot;&gt;foo.bar&lt;/code&gt; gets set on both code paths; the &lt;code class=&quot;language-text&quot;&gt;else&lt;/code&gt; statement might just as easily set &lt;code class=&quot;language-text&quot;&gt;hasPort = false&lt;/code&gt; or run &lt;code class=&quot;language-text&quot;&gt;handleMissingPort()&lt;/code&gt;. Nor is it obvious that the &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; criteria merely check the property tree for undefined values, instead of including a property like &lt;code class=&quot;language-text&quot;&gt;!useDefaultPort&lt;/code&gt;. This pattern opens the door for unexpected logic to hide inside.&lt;/p&gt;
&lt;h2 id=&quot;2-self-executing-anonymous-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-self-executing-anonymous-function&quot; aria-label=&quot;2 self executing anonymous function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. Self-executing Anonymous Function&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settings &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By wrapping our logic in a self-executing function, it now runs as a single statement. This allows us to use it in a large object initialization block, like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;baz&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We see this all the time in JavaScript, so all methods moving forward should accommodate that syntax.&lt;/p&gt;
&lt;p&gt;We can be sure that the result of the anonymous function is assigned to the &lt;code class=&quot;language-text&quot;&gt;bar&lt;/code&gt; property, but like example #1 we would need to inspect the contents of the function to find side effects like &lt;code class=&quot;language-text&quot;&gt;hasPort = false&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;handleMissingPort()&lt;/code&gt;, and extra conditions like &lt;code class=&quot;language-text&quot;&gt;!useDefaultPort&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;3-ternary-operator&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-ternary-operator&quot; aria-label=&quot;3 ternary operator permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Ternary Operator&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settings &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;
    settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Another improvement. The ternary operator&apos;s tighter syntax helps minimize the logic since only one statement can run per code path. It&apos;s possible that someone could execute an anonymous function in one of the paths, but that giant block of code would hopefully catch our eye.&lt;/p&gt;
&lt;p&gt;Nevertheless, this format still leaves lots of room for unexpected logic. The conditional statement might still contain weird conditions and either code path might call a function with side-effects (e.g. &lt;code class=&quot;language-text&quot;&gt;getDefaultPortAndEmailAdmins()&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&quot;4-conditional-shorthand&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-conditional-shorthand&quot; aria-label=&quot;4 conditional shorthand permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. Conditional Shorthand&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settings &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This technique is much shorter because it uses JavaScript syntax that you won&apos;t find in every language.&lt;/p&gt;
&lt;p&gt;By comparison, PHP is also a loosely-typed language. But its conditional operators always return a Boolean.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Conditionals in PHP&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$and&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Cat&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Dog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$and&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gettype&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$or&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Cat&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Dog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$or&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gettype&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$or&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 1: boolean&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 1: boolean&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I was new to JavaScript, the results of the same code surprised me.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Conditionals in JavaScript&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; and &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cat&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Dog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;and &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; and&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; or &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cat&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Dog&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;or &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;: &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; or&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Dog: string&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Cat: string&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This behavior allows for succinct code because we can test &lt;em&gt;and&lt;/em&gt; access the property at once. But beware that anyone new to JavaScript might misinterpret your code and think &lt;code class=&quot;language-text&quot;&gt;bar&lt;/code&gt; will be &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;80&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Technically there&apos;s still room for unexpected logic, same as the techniques above. But at least there is overall less code, leaving fewer opportunities for surprises.&lt;/p&gt;
&lt;h2 id=&quot;5-try-catch-block&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-try-catch-block&quot; aria-label=&quot;5 try catch block permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;5. &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; Block&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This solution came from my co-worker and is smart because it&apos;s straightforward. All programmers should recognize the purpose of a &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; block, and we&apos;ve eliminated all conditional statements that could hide unexpected logic. It can also grow easily to access a property nested 5 or 10 levels deep.&lt;/p&gt;
&lt;p&gt;On the downside, the anonymous block &lt;em&gt;plus&lt;/em&gt; the &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; block add a lot of boilerplate code. Because this method is uncommon in JavaScript (in my experience) it could backfire and trigger a lot of cognition to deduce what errors are being caught. And lastly &lt;code class=&quot;language-text&quot;&gt;try-catch&lt;/code&gt; adds some performance overhead in JavaScript, so avoid this technique in core parts of your app.&lt;/p&gt;
&lt;h2 id=&quot;6-utility-function&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#6-utility-function&quot; aria-label=&quot;6 utility function permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;6. Utility Function&lt;/h2&gt;
&lt;p&gt;The last approach we&apos;ll consider is hiding all the object traversal code inside a utility function. You can write your own or import a third-party option like &lt;a href=&quot;https://github.com/wilmoore/selectn.js&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;selectn&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;selectn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;server.port&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; settings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This option is the most succinct, and leaves zero room for side-effects or unexpected logic. It requires a slight learning curve to figure out what is happening, so you might think twice if your project is open source with many transient readers. But anyone who frequently reads the code can get used to it quickly.&lt;/p&gt;
&lt;p&gt;Personally I would prefer a wrapper function to reverse the order of parameters and improve readability, like &lt;code class=&quot;language-text&quot;&gt;getProp(settings, &apos;server.port&apos;) || 80&lt;/code&gt;. &lt;code class=&quot;language-text&quot;&gt;selectn&lt;/code&gt; makes the second parameter optional with a fallback to the global scope.&lt;/p&gt;
&lt;div class=&quot;callout&quot;&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I finally realized that my favorite library, &lt;a href=&quot;https://lodash.com/&quot;&gt;Lodash&lt;/a&gt;, includes this functionality and it&apos;s everything I could ask for. See &lt;a href=&quot;https://lodash.com/docs/latest#get&quot;&gt;the &lt;code class=&quot;language-text&quot;&gt;_.get()&lt;/code&gt; method&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;settings&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;server.port&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Code style is inherently subjective. But if you value readability you should use a consistent technique that the reader can skim and move on without much thought. For a light library or app I like &lt;a href=&quot;#4-conditional-shorthand&quot;&gt;the Conditional Shorthand technique&lt;/a&gt;. If you&apos;re working with many nested properties, especially on an internal project, then &lt;a href=&quot;#6-utility-function&quot;&gt;the Utility Function technique&lt;/a&gt; may add a lot of value to your codebase.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A Parser for Conditional Expressions]]></title><description><![CDATA[I've created a tool for analyzing conditional expressions.]]></description><link>https://www.wimpyprogrammer.com/a-parser-for-conditional-expressions</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/a-parser-for-conditional-expressions</guid><pubDate>Tue, 07 Jul 2015 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@yungnoma?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Yung Chang&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/switches?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I&apos;ve created a tool at &lt;a href=&quot;https://www.wimpyprogrammer.com/conditional-parser/&quot;&gt;https://www.wimpyprogrammer.com/conditional-parser/&lt;/a&gt; for analyzing conditional expressions.&lt;/p&gt;
&lt;p&gt;A while back my co-worker and I encountered a tricky conditional statement on a legacy C# project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;HasDeadlinePassed
&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; Active
&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IsVerified&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HasValue
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IsVerified&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Value
    &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;IsVerified&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Value
      &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AccountType &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CannotValidate&quot;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;String&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AccountType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; importID&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HasValue
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While troubleshooting that portion of the code, we needed to understand all of the circumstances in which the expression would evaluate to true. &quot;Surely there&apos;s a tool that can break this down for us!&quot; I thought, but couldn&apos;t find one and decided to build my own.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.wimpyprogrammer.com/conditional-parser/&quot;&gt;Conditional Expression Parser&lt;/a&gt; will divide a conditional statement into its operators and conditions, then list the combinations that would cause the entire expression to evaluate to &lt;code class=&quot;language-text&quot;&gt;true&lt;/code&gt;. It recognizes &lt;code class=&quot;language-text&quot;&gt;AND&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;), &lt;code class=&quot;language-text&quot;&gt;OR&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;||&lt;/code&gt;), and &lt;code class=&quot;language-text&quot;&gt;XOR&lt;/code&gt; (&lt;code class=&quot;language-text&quot;&gt;^&lt;/code&gt;) operators and is smart enough to ignore strings (&lt;code class=&quot;language-text&quot;&gt;&quot;a &amp;amp;&amp;amp; b&quot;&lt;/code&gt;) and function calls (&lt;code class=&quot;language-text&quot;&gt;foo(a &amp;amp;&amp;amp; b)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The source code is &lt;a href=&quot;https://github.com/wimpyprogrammer/conditional-expression-parser&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Managing Puppet modules on Vagrant with Librarian-Puppet]]></title><description><![CDATA[Load Puppet's third-party dependencies on-demand and keep them out of source control.]]></description><link>https://www.wimpyprogrammer.com/managing-puppet-modules-on-vagrant-with-librarian-puppet</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/managing-puppet-modules-on-vagrant-with-librarian-puppet</guid><pubDate>Wed, 29 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@inakihxz?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Iñaki del Olmo&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/library?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When it comes to source code control I&apos;m a purist: I avoid storing any derived files (ex. generated CSS) or third-party code. So when I started &lt;a href=&quot;http://www.wimpyprogrammer.com/using-the-mean-stack-on-windows-with-puphpet/&quot;&gt;using PuPHPet to generate Vagrant and Puppet configurations&lt;/a&gt;, I was dismayed by the gigantic &lt;code class=&quot;language-text&quot;&gt;/puphpet/puppet/modules&lt;/code&gt; directory. 3,000 files totaling 5 MB?! There must be a better way.&lt;/p&gt;
&lt;p&gt;Instead of keeping the Puppet dependencies in our repository, &lt;a href=&quot;https://github.com/rodjek/librarian-puppet&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;librarian-puppet&lt;/code&gt;&lt;/a&gt; lets us automatically load these modules during setup of the Vagrant box. In our &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt; we add a new setup script:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-ruby.sh&apos;&lt;/span&gt;&lt;/span&gt;
config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-puppet.sh&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;always&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-puppet-modules.sh&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/vagrant/puphpet/puppet&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;always&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
    s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/windows-path-limit-fix.sh&apos;&lt;/span&gt;&lt;/span&gt;
    s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/vagrant/node_modules&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The setup script is based on the bootstrap script from &lt;a href=&quot;https://github.com/mindreframer/vagrant-puppet-librarian/blob/master/shell/bootstrap.sh&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;vagrant-puppet-librarian&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Temporary directory in which to install puppet modules.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Avoids issues with writing to a VirtualBox shared folder.&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;TMP_FOLDER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/var/tmp/install-puppet-modules/&quot;&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Skip install if the temp folder already exists&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$TMP_FOLDER&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;

        &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Skipping puppet dependencies because the temporary installation folder already exists&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Create the temp folder and populate it with the Puppetfile, Puppetfile.lock, etc.&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_FOLDER&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_FOLDER&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;/* ./

        &lt;span class=&quot;token comment&quot;&gt;# NB: librarian-puppet might need git installed. If it is not already installed&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# in your basebox, this will manually install it at this point using apt or yum&lt;/span&gt;
        &lt;span class=&quot;token assign-left variable&quot;&gt;GIT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/usr/bin/git
        &lt;span class=&quot;token assign-left variable&quot;&gt;APT_GET&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/usr/bin/apt-get
        &lt;span class=&quot;token assign-left variable&quot;&gt;YUM&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/usr/sbin/yum
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$GIT&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$YUM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing git via yum&quot;&lt;/span&gt;
                yum &lt;span class=&quot;token parameter variable&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; git-core
            &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$APT_GET&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing git via apt-get&quot;&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; git-core
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;No package installer available. You may need to install git manually.&quot;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;gem query &lt;span class=&quot;token parameter variable&quot;&gt;--local&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; librarian-puppet &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-l&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
          &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing the librarian-puppet gem&quot;&lt;/span&gt;
          gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; librarian-puppet
        &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

        &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Installing puppet dependencies&quot;&lt;/span&gt;
        librarian-puppet &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Copy the installed modules back to the project&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;rsync&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Lr&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--inplace&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_FOLDER&lt;/span&gt;/.librarian &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;/
        &lt;span class=&quot;token function&quot;&gt;rsync&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Lr&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--inplace&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_FOLDER&lt;/span&gt;/modules &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;/
        &lt;span class=&quot;token function&quot;&gt;rsync&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Lr&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--inplace&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_FOLDER&lt;/span&gt;/Puppetfile.lock &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;/
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You must specify a destination for the Puppet module installation (recommend an absolute path)&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Puppet module installation destination &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; must already exist&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;librarian-puppet&lt;/code&gt; reads from our &lt;code class=&quot;language-text&quot;&gt;Puppetfile&lt;/code&gt; -- also provided by PuPHPet -- for a list of all the Puppet dependencies to download. It behaves similar to &lt;a href=&quot;http://www.wimpyprogrammer.com/updated-vagrant-on-windows-path-limit-fix/&quot;&gt;the Windows path limit fix&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The modules install to a temporary directory because I had issues running &lt;code class=&quot;language-text&quot;&gt;librarian-puppet install&lt;/code&gt; inside the &lt;code class=&quot;language-text&quot;&gt;/vagrant&lt;/code&gt; directory, presumably because it&apos;s shared with Windows. After installation, the modules are copied to &lt;code class=&quot;language-text&quot;&gt;/vagrant/puphpet/puppet/modules&lt;/code&gt; so Vagrant&apos;s setup can continue as usual.&lt;/li&gt;
&lt;li&gt;If the temp directory already exists during setup, the script assumes that the Puppet dependencies are ready and aborts.&lt;/li&gt;
&lt;li&gt;Temporary files are stored in &lt;code class=&quot;language-text&quot;&gt;/var/tmp&lt;/code&gt; to persist during restarts, and the &lt;code class=&quot;language-text&quot;&gt;run: &apos;always&apos;&lt;/code&gt; parameter in the Vagrantfile ensures that the script will fire during both &lt;code class=&quot;language-text&quot;&gt;vagrant reload&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;vagrant up&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally we add two entries to our &lt;code class=&quot;language-text&quot;&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;git&quot;&gt;&lt;pre class=&quot;language-git&quot;&gt;&lt;code class=&quot;language-git&quot;&gt;puphpet/puppet/.tmp/
puphpet/puppet/modules/&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can keep our repository lean while leveraging the power of third-party Puppet modules!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Updated - Vagrant on Windows path limit fix]]></title><description><![CDATA[Improved Vagrant and Puppet scripts for hosting Linux VMs on Windows.]]></description><link>https://www.wimpyprogrammer.com/updated-vagrant-on-windows-path-limit-fix</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/updated-vagrant-on-windows-path-limit-fix</guid><pubDate>Fri, 24 Apr 2015 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@xjono?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Jono&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/puppet?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I &lt;a href=&quot;http://www.wimpyprogrammer.com/using-the-mean-stack-on-windows-with-puphpet/&quot; title=&quot;Using the MEAN stack on Windows with PuPHPet&quot;&gt;previously shared my experience&lt;/a&gt; using PuPHPet to host a Linux VM on my Windows computer for MEAN stack development. Since then I&apos;ve made some improvements to the startup script I use to overcome Windows&apos;s 260 character path limit, which &lt;code class=&quot;language-text&quot;&gt;npm&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;bower&lt;/code&gt; easily exceed.&lt;/p&gt;
&lt;p&gt;Here&apos;s the latest script (and another nod to &lt;a href=&quot;https://github.com/fideloper/Vaprobash/issues/183&quot;&gt;the GitHub discussion&lt;/a&gt; that started it):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;BASE_FOLDER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/var/tmp/windows-path-limit-fix/&quot;&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Generate a unique but predictable directory by hashing the folder mount point&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# From http://stackoverflow.com/a/1602389&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; $1 &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; md5sum &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f1&lt;/span&gt; -d&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;destination&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$BASE_FOLDER&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Skip setup if the folder already exists&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;

        &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Creating mount destination: &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mkdir -p &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;chown -R www-data:www-data &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;chmod 775 &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;

        &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Transferring files from &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; to &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;rsync&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Lr&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--inplace&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;/ &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt;/

    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;

        &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Creating mount target: &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mkdir -p &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mounting &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt; at &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mount -o bind &lt;span class=&quot;token variable&quot;&gt;$destination&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You must specify a folder mount point (recommend an absolute path)&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    create &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the updated method for calling it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-ruby.sh&apos;&lt;/span&gt;&lt;/span&gt;
config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-puppet.sh&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;always&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/windows-path-limit-fix.sh&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/vagrant/node_modules&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;always&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/windows-path-limit-fix.sh&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  s&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;args &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/vagrant/.bower-tmp&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:puppet&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;puppet&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
  puppet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;facter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ssh_username&apos;&lt;/span&gt;&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;ssh_username&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;provisioner_type&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;VAGRANT_DEFAULT_PROVIDER&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vm_target_key&apos;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vagrantfile-local&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While the old script got the job done, it had many inconveniences. The new version makes several improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Temporary files are stored in &lt;code class=&quot;language-text&quot;&gt;/var/tmp&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;/tmp&lt;/code&gt;, meaning they persist after the VM is restarted.&lt;/li&gt;
&lt;li&gt;Building on that, the temporary directory name is now a hash of the mount point instead of choosing a new name every time. This allows us to detect when the directory is already present then remount it.&lt;/li&gt;
&lt;li&gt;The updated provisioner syntax in the &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt; causes the script to run during &lt;code class=&quot;language-text&quot;&gt;vagrant reload&lt;/code&gt; in addition to the usual &lt;code class=&quot;language-text&quot;&gt;vagrant up&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These updates avoid repeated setup of the mounted directories. No more &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt; after every reload!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Statistics of War (the card game)]]></title><description><![CDATA[How does shuffling affect the duration of a game of War?]]></description><link>https://www.wimpyprogrammer.com/the-statistics-of-war-the-card-game</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/the-statistics-of-war-the-card-game</guid><pubDate>Wed, 24 Dec 2014 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@jacc?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Jack Hamilton&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/cards?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;During Thanksgiving Break I played &lt;a href=&quot;http://en.wikipedia.org/wiki/War_%28card_game%29&quot;&gt;the card game War&lt;/a&gt; with my girlfriend and remembered how wonderfully mindless it is. Because there&apos;s no strategy or decision-making, it was feasible to write a program to play the game. Once I could simulate one game, I could simulate several and collect some statistics.&lt;/p&gt;
&lt;p&gt;Evidently the rules of War have some gaps, including what to do with the cards you win. Do you place them on the bottom of your deck, in order, or do you shuffle and reuse them once your deck is empty? Why not program both methods and compare? Here is a plot of both approaches after 100,000 trials of each. The x-axis is the number of turns required to complete the game, and the y-axis is the frequency of that outcome across 100,000 trials.&lt;/p&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 906px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/6029f/chart-of-num-turns-to-win.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 98.06949806949807%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAABmUlEQVQ4y52TXUvCUBjHz2frM3TXB+gzBIF33UVBVHTRRRAUBUVgJZllzhbuxU23OXfmmTVT0ppo1kLdOU9MvSxw+18cOAd+z/M/zwvq9fqe543HY8YYzKevwWfrrcPjNqpWTUFWfN+fE/Z9v93uuA62c8fIIeShoHzPDbOJABjAMITTj/JwOJrf9iwKAMIYC6oeXiiFiEKOQ1S9MjUUGa7ZWCrpQSwa2dhWtLiZHUIUzaDTOkaFMbbE2LbrDpFK+k+s1KFtrWKyOK4BYctSNK0/Bhqjz/WX19z5/vt7J5iNTSTbbpM73njhDiefphHhGs5Khs1f0DcjfKBBFNtus5w6UJO7H8kE/HSnVQdGgQWTk8Fsh9hf41l3zes9P7te2VqEk0VGLgFG/63RpClAGQQ0DIkajYbAZbp+sHmUXFtZziUWqjtLzbPVTmb7Qzj1tLRXffJqcvdZd02J6CLRJWIUzXKx3++hwWCgKoosCYZp3YjWfRFzeV7gMmL2Ss2n9MKd+nhriDmVvzdkvlTgDJnXJF4u5Fut5i+N+nZTzSEV4wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/e90ce/chart-of-num-turns-to-win.avif 259w,
/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/0d37b/chart-of-num-turns-to-win.avif 518w,
/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/f5e2f/chart-of-num-turns-to-win.avif 906w&quot;
              sizes=&quot;(max-width: 906px) 100vw, 906px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/652f5/chart-of-num-turns-to-win.webp 259w,
/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/c29d2/chart-of-num-turns-to-win.webp 518w,
/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/45005/chart-of-num-turns-to-win.webp 906w&quot;
              sizes=&quot;(max-width: 906px) 100vw, 906px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/a2ead/chart-of-num-turns-to-win.png 259w,
/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/6b9fd/chart-of-num-turns-to-win.png 518w,
/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/6029f/chart-of-num-turns-to-win.png 906w&quot;
            sizes=&quot;(max-width: 906px) 100vw, 906px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/de1accbefd2c8a2c5d3dd2a2b2d4026e/6029f/chart-of-num-turns-to-win.png&quot;
            alt=&quot;Scatter plot of number of turns to win game when shuffling vs. not shuffling winnings&quot;
            title=&quot;Scatter plot of number of turns to win game when shuffling vs. not shuffling winnings&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The data proved more interesting than I expected.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shuffling the winnings led to much faster games — a mean of 262, a mode of 84, and a max of 2,702 turns.&lt;/li&gt;
&lt;li&gt;When the winnings aren&apos;t shuffled, the numbers are less clear. Many games were seemingly infinite so I added a cap of 5,000 turns per game. 11,837 (11.8%) of the games hit this limit (and do not appear on the graph). But plenty of games ended after 4,000+ turns, so we could expect many of these long games to be finite as well. If we ignore the capped games, the mode is 104 turns.&lt;/li&gt;
&lt;li&gt;Both plots show a binary distribution of the results, as you can see in the higher and lower groupings of dots. It turns out that games are more likely to finish after an even number of turns. Each player starts with 26 cards, so if there are no wars and one player wins every hand, the game will last 26 turns. For every turn that player loses, they must win an additional hand to cancel the loss, so the game still requires an even number of turns. Only a war will break this trend because 4 cards change possession instead of 1. A game with an odd number of wars will take an odd number of turns to complete (ignoring wars with fewer than 3 cards, when one player&apos;s deck is low).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As for the program, here it is in JavaScript. The highlighted lines show the changes made between the Shuffle and No-Shuffle versions.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NUM_TRIALS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// # games to simulate&lt;/span&gt;
		&lt;span class=&quot;token constant&quot;&gt;MAX_TURNS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// maximum # of turns to avoid infinite loops&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// From http://stackoverflow.com/a/2450976&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; currentIndex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			temporaryValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			randomIndex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// While there remain elements to shuffle...&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; currentIndex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;// Pick a remaining element...&lt;/span&gt;
			randomIndex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; currentIndex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			currentIndex &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;// And swap it with the current element.&lt;/span&gt;
			temporaryValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;currentIndex&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;currentIndex&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;randomIndex&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			array&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;randomIndex&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; temporaryValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; array&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; self &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;suit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; o&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;suit&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; o&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Generate a string representation of the card&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; displayValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
					displayValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;J&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
					displayValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Q&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
					displayValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;K&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
					displayValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;suit &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; displayValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Return a negative number if compare is higher than this card.&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Return a positive number if this card is higher than compare.&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Return zero if the cards are equal.&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/*Card*/&lt;/span&gt; compare&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; compare&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; self &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			hand &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			discard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; o&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Player&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Draw one card from the player&apos;s hand&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;				&lt;span class=&quot;token comment&quot;&gt;// Version 1: The discard pile is shuffled before using&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;				&lt;span class=&quot;token comment&quot;&gt;//hand = shuffle(discard).concat(hand);&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;				&lt;span class=&quot;token comment&quot;&gt;// Version 2: The discard pile is used in the order that it was created&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;				hand &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; discard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hand&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;				discard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Add one or more cards to the player&apos;s discard pile&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;discard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cards&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				discard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cards&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;discard&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				discard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cards&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Count the total number of cards in this player&apos;s possession&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;numCards&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; discard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Does the user have any cards remaining?&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;hasCards&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;numCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Generate a string representation of the player&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; (&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;numCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos; cards)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Game&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; self &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			deck &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;o&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;deck&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// The number of turns that have elapsed in this game&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;numTurns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Simulate a single game&lt;/span&gt;
		self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; player1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;John&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				player2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Player&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jane&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// Split the deck between the two players&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; iDeck&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;iDeck &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iDeck &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; deck&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iDeck&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;iDeck &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deck&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;iDeck&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;deck&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;iDeck&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; player1Card&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				player2Card&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				cardCompare&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				winnings&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				isWar&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				numWarCards&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				iWarCards&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;numTurns&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

				&lt;span class=&quot;token comment&quot;&gt;// End this game if it&apos;s taking too long, to avoid potentially infinite loops&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;numTurns &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;MAX_TURNS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

				player1Card &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				player2Card &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				winnings &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;player1Card&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; player2Card&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

				cardCompare &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player1Card&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player2Card&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

				&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cardCompare &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token comment&quot;&gt;// Player 1 wins this turn&lt;/span&gt;
					player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;winnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cardCompare &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token comment&quot;&gt;// Player 2 wins this turn&lt;/span&gt;
					player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;winnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token comment&quot;&gt;// War!&lt;/span&gt;
					&lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
						&lt;span class=&quot;token comment&quot;&gt;// If a player is completely out of cards now, they lose the game&lt;/span&gt;
						&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
							&lt;span class=&quot;token comment&quot;&gt;// Player 2 wins this game&lt;/span&gt;
							isWar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;winnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
							&lt;span class=&quot;token comment&quot;&gt;// Player 1 wins this game&lt;/span&gt;
							isWar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;winnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
							isWar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

							&lt;span class=&quot;token comment&quot;&gt;// If either player doesn&apos;t have enough cards for war, bet what they have&lt;/span&gt;
							numWarCards &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
								player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;numCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
								player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;numCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
								&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
							&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

							&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;iWarCards &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iWarCards &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; numWarCards&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iWarCards&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
								winnings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
								winnings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

							player1Card &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							player2Card &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							winnings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player1Card&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							winnings&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player2Card&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

							cardCompare &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player1Card&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;player2Card&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

							&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cardCompare &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
								&lt;span class=&quot;token comment&quot;&gt;// Player 1 wins the war and this turn&lt;/span&gt;
								isWar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
								player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;winnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cardCompare &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
								&lt;span class=&quot;token comment&quot;&gt;// Player 2 wins the war and this turn&lt;/span&gt;
								isWar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
								player2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;winnings&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
							&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
								&lt;span class=&quot;token comment&quot;&gt;// The card values are equal again, continue the war&lt;/span&gt;
							&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
						&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
					&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isWar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// Note: this is erroneous if MAX_TURNS was reached&lt;/span&gt;
			self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;winner &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; player1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; player1 &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; player2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// Generate the master deck of all 52 cards.&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// It will be reused and shuffled in each Game instance.&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; suits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&amp;amp;spadesuit;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;amp;clubsuit;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;amp;heartsuit;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;amp;diamondsuit;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		deck &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; iSuit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; iValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;iSuit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iSuit &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; suits&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iSuit&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// J = 11, Q = 12, K = 13, A = 14&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;iValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iValue &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iValue&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			deck&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;suit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; suits&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;iSuit&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; iValue &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// Run the desired number of trials.&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Populate wins with the number of turns and frequency of that outcome.&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; iTrials&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		thisGame&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		wins &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;iTrials &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iTrials &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NUM_TRIALS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; iTrials&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		thisGame &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Game&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;deck&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; deck &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		thisGame&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;wins&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;thisGame&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;numTurns&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			wins&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;thisGame&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;numTurns&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			wins&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;thisGame&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;numTurns&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To close, enjoy &lt;a href=&quot;http://qi.com/infocloud/playing-cards&quot;&gt;the amazing uniqueness of a well-shuffled deck&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Using the MEAN stack on Windows with PuPHPet]]></title><description><![CDATA[Lately I've been playing with Vagrant and Puppet to create virtual machines for local MEAN stack development.]]></description><link>https://www.wimpyprogrammer.com/using-the-mean-stack-on-windows-with-puphpet</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/using-the-mean-stack-on-windows-with-puphpet</guid><pubDate>Tue, 14 Oct 2014 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@liliane?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Liliane Limpens&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/puppet?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Lately I&apos;ve been playing with Vagrant and Puppet to create virtual machines for local MEAN stack development. I quickly learned that hosting a Linux VM on a Windows host is tricky. Let&apos;s look at the challenges and workarounds for them.&lt;/p&gt;
&lt;h2 id=&quot;virtual-machines-with-puppet-and-vagrant&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#virtual-machines-with-puppet-and-vagrant&quot; aria-label=&quot;virtual machines with puppet and vagrant permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Virtual Machines with Puppet and Vagrant&lt;/h2&gt;
&lt;p&gt;But before we dive in, let&apos;s define some terms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;virtual machine (VM)&lt;/strong&gt; is an operating system (OS) that you host within your primary OS. For example, you might run a Linux VM within your Windows OS. To work with VMs I like &lt;a href=&quot;https://www.virtualbox.org/wiki/VirtualBox&quot;&gt;VirtualBox&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.vagrantup.com/about.html&quot;&gt;&lt;strong&gt;Vagrant&lt;/strong&gt;&lt;/a&gt; is a tool that automates the setup of virtual machines to the specifications you define in your &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt;. Just like you version your application code, you can version the code for creating the application environment.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://puppetlabs.com/puppet/what-is-puppet&quot;&gt;&lt;strong&gt;Puppet&lt;/strong&gt;&lt;/a&gt; adds Ruby script support to Vagrant, allowing for much more powerful setup routines.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the past couple years I&apos;ve worked with PHP, C#.NET, and Node.js, and gradually my computer grew messy with all of the runtimes and dependencies. Using the tools above I can create clean, controlled development VMs and throw them away when I&apos;m done. Or if my project takes off, I can deploy my Vagrant configuration to providers like &lt;a href=&quot;https://github.com/mitchellh/vagrant-aws&quot;&gt;Amazon&lt;/a&gt;, &lt;a href=&quot;https://github.com/smdahlen/vagrant-digitalocean&quot;&gt;Digital Ocean&lt;/a&gt;, &lt;a href=&quot;https://github.com/mitchellh/vagrant-rackspace&quot;&gt;Rackspace&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;puphpet-to-the-rescue&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#puphpet-to-the-rescue&quot; aria-label=&quot;puphpet to the rescue permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;PuPHPet to the Rescue&lt;/h2&gt;
&lt;p&gt;This all sounds great, but as a Linux-novice and a Ruby-nothing I was soon overwhelmed by the demands of creating and managing these environments. I eventually found &lt;a href=&quot;https://puphpet.com/&quot;&gt;PuPHPet&lt;/a&gt; (think Puppet + PHP) which handles most of the hard work. PuPHPet is a web GUI for generating the Puppet scripts to meet your needs. It&apos;s described nicely in &lt;a href=&quot;https://jtreminio.com/2013/05/introduction_to_vagrant_puppet_and_introducing_puphpet_a_simple_to_use_vagrant_puppet_gui_configurator/&quot;&gt;this article by its creator&lt;/a&gt; and &lt;a href=&quot;http://www.sitepoint.com/build-virtual-machines-easily-puphpet/&quot;&gt;this Sitepoint article&lt;/a&gt;. PuPHPet is named for its original PHP focus, but is evolving to support more stacks like &lt;a href=&quot;http://en.wikipedia.org/wiki/MEAN&quot;&gt;MEAN&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;hosting-linux-vms-on-windows&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#hosting-linux-vms-on-windows&quot; aria-label=&quot;hosting linux vms on windows permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hosting Linux VMs on Windows&lt;/h2&gt;
&lt;p&gt;Now that PuPHPet has created our Linux VM, there will be some problems running it within Windows. Vagrant will map our Windows project directory (containing the &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt;) to &lt;code class=&quot;language-text&quot;&gt;/vagrant&lt;/code&gt; on the Linux VM, so the two OSes need to play nicely together.&lt;/p&gt;
&lt;h3 id=&quot;symbolic-links&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#symbolic-links&quot; aria-label=&quot;symbolic links permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Symbolic Links&lt;/h3&gt;
&lt;p&gt;In order for VirtualBox to support Linux symbolic links in the shared folder, we need to enable the &lt;code class=&quot;language-text&quot;&gt;VBoxInternal2/SharedFoldersEnableSymlinksCreate&lt;/code&gt; property. Conveniently this can be done through our PuPHPet configuration file.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;virtualbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;modifyvm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;natdnshostresolver1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; on
    &lt;span class=&quot;token key atrule&quot;&gt;setextradata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;VBoxInternal2/SharedFoldersEnableSymlinksCreate/vagranthome&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;vmware&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;numvcpus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;parallels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;cpus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;vagranthome&lt;/code&gt; part of this setting is the name of the Vagrant shared folder. It seems to vary depending on which version of Vagrant you use. To verify the name, open the &lt;strong&gt;Shared Folders&lt;/strong&gt; list in the VirtualBox VM properties and find the name of the Machine Folder that maps to the folder containing your &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 657px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4e055bcfd64ab2119967eff56764bf90/a1253/VirtualBox-shared-folders.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 61.77606177606177%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1klEQVQoz4WO6Y7TMBSF89Y8AP/4AbS/GDEPwKMwKKVpOtk3N3aSxrGdZrGTZjPKBMQiBJ+uju6VztG5Sqi+KfxHHDxm7oN72Nvq3jnsHXVnfXnvft0bn98aT+8cdeccdu5hZ6u73PsY2x+On16rD68Uy9UAJITQYZwgTIIgtGynKOg4zvf7OAzTME6rDuP95wyTlJ2IlbN98uOiqW7zsnieDwAglJZlyf4FJawiV1sxPT2ERcnoImUUgfgSE0IpZZyLtm0554QQjLEQ38+25V0nUsy88Ekx3BNAtKlv0zS3bZul6UnTLdOqq2p1t1wIAeMYQYQgii8XCBGMYwBgBk+K42koo6TA/cq9qWvLNF3bAWGEVh+qqso0DNO0TMN81s+WaRn62fNAWTiKHZwBKqpbKbqOc8EoA1GU57mUUi6LlHKeZyFE94JY/xCdEFXN17Dpn0NEswQlKOFcvESWTTfk3+j6kWFHYdje7mEYuBBb1R/W5XekXEQ3rGH6a3hrlv+n68f17eJq3u9z3/dCdNccJ0maJCmEKI5hkqQIJXmOm5aXt6Zu2mqlrus6zynDtnJFGqOMFjklmNGCkPzH4G2hFAcg0p+fgyjU9aNh6L5va9opg8dvVyaTUyF70acAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/4e055bcfd64ab2119967eff56764bf90/e90ce/VirtualBox-shared-folders.avif 259w,
/static/4e055bcfd64ab2119967eff56764bf90/0d37b/VirtualBox-shared-folders.avif 518w,
/static/4e055bcfd64ab2119967eff56764bf90/b5dc5/VirtualBox-shared-folders.avif 657w&quot;
              sizes=&quot;(max-width: 657px) 100vw, 657px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/4e055bcfd64ab2119967eff56764bf90/652f5/VirtualBox-shared-folders.webp 259w,
/static/4e055bcfd64ab2119967eff56764bf90/c29d2/VirtualBox-shared-folders.webp 518w,
/static/4e055bcfd64ab2119967eff56764bf90/b9f96/VirtualBox-shared-folders.webp 657w&quot;
              sizes=&quot;(max-width: 657px) 100vw, 657px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/4e055bcfd64ab2119967eff56764bf90/a2ead/VirtualBox-shared-folders.png 259w,
/static/4e055bcfd64ab2119967eff56764bf90/6b9fd/VirtualBox-shared-folders.png 518w,
/static/4e055bcfd64ab2119967eff56764bf90/a1253/VirtualBox-shared-folders.png 657w&quot;
            sizes=&quot;(max-width: 657px) 100vw, 657px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/4e055bcfd64ab2119967eff56764bf90/a1253/VirtualBox-shared-folders.png&quot;
            alt=&quot;VirtualBox shared folders&quot;
            title=&quot;VirtualBox shared folders&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;windows-pathname-length-limit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#windows-pathname-length-limit&quot; aria-label=&quot;windows pathname length limit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Windows pathname length limit&lt;/h3&gt;
&lt;p&gt;Windows file paths are limited to 260 characters, but tools like &lt;code class=&quot;language-text&quot;&gt;npm&lt;/code&gt; may easily create paths longer than this. The workaround I use is a mix of ideas from &lt;a href=&quot;https://github.com/fideloper/Vaprobash/issues/183&quot;&gt;this GitHub issue&lt;/a&gt; because no single suggestion worked for me.&lt;/p&gt;
&lt;div class=&quot;callout&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;http://www.wimpyprogrammer.com/updated-vagrant-on-windows-path-limit-fix/&quot;&gt;Updated – Vagrant on Windows path limit fix&lt;/a&gt; for an updated version of these scripts.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;BASE_FOLDER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/tmp/windows-path-limit-fix/&quot;&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Generate a unique, random directory&lt;/span&gt;
    &lt;span class=&quot;token assign-left variable&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$BASE_FOLDER&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$$&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;token assign-left variable&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$BASE_FOLDER&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$$&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;

    &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mkdir -p &lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;chown -R www-data:www-data &lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;chmod 775 &lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mkdir -p &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;token builtin class-name&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mount -o bind &lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You must specify a folder mount point (recommend an absolute path)&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    create &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This script will create a temporary directory inside the VM and mount it at the specified path. Because the temporary directory is solely within Linux, it can fully support long paths. When either OS tries to access the mounted path, the operation will be transparently rerouted to the temporary directory.&lt;/p&gt;
&lt;p&gt;Update your &lt;code class=&quot;language-text&quot;&gt;Vagrantfile&lt;/code&gt; to call this script for each directory you want to remap.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-ruby.sh&apos;&lt;/span&gt;&lt;/span&gt;
config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-puppet.sh&apos;&lt;/span&gt;&lt;/span&gt;
config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/install-puppet-modules.sh&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/windows-path-limit-fix.sh&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:args&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/vagrant/node_modules&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:shell&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;puphpet/shell/windows-path-limit-fix.sh&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token symbol&quot;&gt;:args&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/vagrant/.bower-tmp&apos;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;vm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;provision &lt;span class=&quot;token symbol&quot;&gt;:puppet&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;puppet&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
    puppet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;facter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ssh_username&apos;&lt;/span&gt;&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;ssh_username&lt;/span&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;provisioner_type&apos;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;VAGRANT_DEFAULT_PROVIDER&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vm_target_key&apos;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;vagrantfile-local&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With these problems wrapped up, we should have a fully-functioning Linux VM running within Windows.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Get bound property name in a KnockoutJS custom binding]]></title><description><![CDATA[Retrieve the name of a variable passed to a Knockout binding.]]></description><link>https://www.wimpyprogrammer.com/get-bound-property-name-in-a-knockoutjs-custom-binding</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/get-bound-property-name-in-a-knockoutjs-custom-binding</guid><pubDate>Mon, 06 May 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@_imkiran?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Sai Kiran Anagani&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/html?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In a &lt;a href=&quot;http://knockoutjs.com/&quot;&gt;KnockoutJS&lt;/a&gt; custom binding, you may want to retrieve the name of the bound property. This usually isn&apos;t necessary; you can reference the &lt;code class=&quot;language-text&quot;&gt;valueAccessor&lt;/code&gt; parameter to get the bound data without knowing the property&apos;s name. But a recent project raised the need.&lt;/p&gt;
&lt;p&gt;The custom binding that I wrote mirrors the syntax of the &lt;a href=&quot;http://knockoutjs.com/documentation/foreach-binding.html&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;foreach&lt;/code&gt;&lt;/a&gt; binding, which accepts a few different formats. These are all valid:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foreach: property&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foreach: { data: property }&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foreach: { data: property, option: value }&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;style: property2, foreach: property&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&apos;s look at a sample custom binding.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;myBinding &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The bound data is passed as the &lt;code class=&quot;language-text&quot;&gt;valueAccessor&lt;/code&gt; parameter, but I couldn&apos;t find a reliable way to retrieve the name. So instead I parsed the properties of the bound DOM node, the &lt;code class=&quot;language-text&quot;&gt;element&lt;/code&gt; parameter.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; dataBind &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attributes&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;data-bind&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nodeValue&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; propertyName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dataBind&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;	&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;myBinding\s*:\s*(?:{.*,?\s*data\s*:\s*)?([^{},\s]+)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; propertyName &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; propertyName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length
	&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; propertyName&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Value if the property name was not found&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the &lt;code class=&quot;language-text&quot;&gt;dataBind.match&lt;/code&gt;, be sure to replace &lt;code class=&quot;language-text&quot;&gt;myBinding&lt;/code&gt;. This approach would return &lt;code class=&quot;language-text&quot;&gt;&quot;property&quot;&lt;/code&gt; in the examples above.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[KnockoutJS custom binding for Quicksand]]></title><description><![CDATA[Animate KnockoutJS observable changes with the Quicksand plugin for jQuery.]]></description><link>https://www.wimpyprogrammer.com/knockoutjs-custom-binding-for-quicksand</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/knockoutjs-custom-binding-for-quicksand</guid><pubDate>Sun, 28 Apr 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@alistairmacrobert?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Alistair MacRobert&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/sand?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;callout&quot;&gt;
&lt;p&gt;This plugin has been &lt;a href=&quot;https://github.com/wimpyprogrammer/knockout-quicksand&quot;&gt;moved into GitHub&lt;/a&gt;. And thanks to some updates to Quicksand, it now works with &lt;a href=&quot;http://jsfiddle.net/wimpyprogrammer/r3hkwp3b/&quot;&gt;the latest versions of jQuery, Quicksand, and KnockoutJS&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Lately I&apos;ve been experimenting with &lt;a href=&quot;http://knockoutjs.com/&quot;&gt;KnockoutJS&lt;/a&gt;, a JavaScript framework for streamlining client-side data and UI updates. I&apos;ve found it wonderfully easy to implement Knockout&apos;s out-of-box functionality and obsolete tons of my custom code. This conversion was helped by &lt;a href=&quot;http://knockoutjs.com/documentation/introduction.html&quot;&gt;Knockout&apos;s thorough documentation&lt;/a&gt; and &lt;a href=&quot;http://www.knockmeout.net/2011/08/all-of-knockoutjscom-live-samples-in.html&quot;&gt;numerous working examples&lt;/a&gt;. But I soon had the desire to integrate Knockout with &lt;a href=&quot;http://razorjack.net/quicksand/&quot;&gt;Quicksand&lt;/a&gt;, a jQuery plugin for animating list sorts and filters. This quickly proved difficult, probably because I&apos;m still new to Knockout, but with help from &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/knockoutjs&quot;&gt;the Knockout forums&lt;/a&gt; I eventually created a custom binding to apply Quicksand animations to a Knockout &lt;code class=&quot;language-text&quot;&gt;observableArray&lt;/code&gt;. No one else has published such a binding so I&apos;m sharing mine for others&apos; benefit. But beware that it may not handle every circumstance you throw at it.&lt;/p&gt;
&lt;h2 id=&quot;overview&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overview&quot; aria-label=&quot;overview permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overview&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;quicksand&lt;/code&gt; custom binding mirrors Knockout&apos;s &lt;code class=&quot;language-text&quot;&gt;foreach&lt;/code&gt; (&lt;a href=&quot;http://knockoutjs.com/documentation/foreach-binding.html&quot;&gt;docs&lt;/a&gt;), which displays and tracks changes to an &lt;code class=&quot;language-text&quot;&gt;observableArray&lt;/code&gt; (&lt;a href=&quot;http://knockoutjs.com/documentation/observableArrays.html&quot;&gt;docs&lt;/a&gt;). Simply put, the &lt;code class=&quot;language-text&quot;&gt;quicksand&lt;/code&gt; binding aims for the same functionality but with fancier animations. The &lt;code class=&quot;language-text&quot;&gt;foreach&lt;/code&gt; binding can also be added to a &lt;code class=&quot;language-text&quot;&gt;template&lt;/code&gt; (&lt;a href=&quot;http://knockoutjs.com/documentation/template-binding.html&quot;&gt;docs&lt;/a&gt;) binding for greater flexibility. So I&apos;ve created a &lt;code class=&quot;language-text&quot;&gt;quicksandTemplate&lt;/code&gt; to mirror that functionality as well. The &lt;code class=&quot;language-text&quot;&gt;quicksandTemplate&lt;/code&gt; binding depends on functions in the &lt;code class=&quot;language-text&quot;&gt;quicksand&lt;/code&gt; binding.&lt;/p&gt;
&lt;h2 id=&quot;code&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#code&quot; aria-label=&quot;code permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Code&lt;/h2&gt;
&lt;p&gt;Here is the JavaScript code for the custom bindings, written against KnockoutJS 2.2.1.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/**
	 * Create the hidden working space to facilitate the Quicksand animation.
	 *
	 * @param Element element  The DOM element with the KnockoutJS data bind.
	 * @param jQuery $repeatingElements  The HTML used to render each array element.
	 * @return jQuery  The Quicksand working space.
	 */&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;createWorkspace&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; $repeatingElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Generate a unique ID for the DOM element that will facilitate the Quicksand animation.&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; quicksandWorkspaceId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ko-quicksand-&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Store the unique ID for reference during the &quot;update&quot; event.&lt;/span&gt;
		ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&apos;ko-quicksand-workspace-id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			quicksandWorkspaceId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Look up the outermost element type in the rendering template and store it for reference during the &quot;update&quot; event.&lt;/span&gt;
		ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&apos;ko-quicksand-container-tag&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			$repeatingElements&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tagName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Create the hidden DOM element that will facilitate the Quicksand animation.&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $quicksandWorkspace &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;div/&gt;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; quicksandWorkspaceId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token literal-property property&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;display: none&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Append it to the DOM for use during the &quot;update&quot; event.&lt;/span&gt;
		$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;body&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; $quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/**
	 * Get the hidden working space used to facilitate the Quicksand animation.
	 *
	 * @param Element element  The DOM element with the KnockoutJS data bind.
	 * @return jQuery  The Quicksand working space.
	 */&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;getWorkspace&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&apos;#&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ko-quicksand-workspace-id&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/**
	 * Get the name of the HTML tag that encompasses each array element.
	 *
	 * @param Element element  The DOM element with the KnockoutJS data bind.
	 * @return string  The container tag name.
	 */&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;getContainerTag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;domData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ko-quicksand-container-tag&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Look up the provided template for rendering each element of the array.&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $repeatingElements &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $quicksandWorkspace &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createWorkspace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			$repeatingElements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Populate the workspace with the rendering template so it mirrors the contents of element.&lt;/span&gt;
		$repeatingElements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Register the hidden DOM element for updates by Knockout.&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;foreach&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;init&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Unwrap the observable to subscribe to updates.  Check if the data property is implicit or explicit.&lt;/span&gt;
		ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrapObservable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data
				&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $quicksandWorkspace &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWorkspace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Update the hidden DOM element using Knockout.&lt;/span&gt;
		ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;foreach&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;update&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; quicksandOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;options&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;options
			&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Run Quicksand to copy the contents of the hidden DOM element to the visible element using the Quicksand animation.&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;quicksand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
				ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getContainerTag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			quicksandOptions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksandTemplate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Look up the provided template for rendering each element of the array.&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;allBindingsAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksandTemplate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;// The repeating template is defined in a named &amp;lt;script&gt; block.&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $repeatingElements &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
				jQuery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
					jQuery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
						&lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;#&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;allBindingsAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksandTemplate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
					&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $quicksandWorkspace &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createWorkspace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
				element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				$repeatingElements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token comment&quot;&gt;// The repeating template is the children of element.&lt;/span&gt;
			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $repeatingElements &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $quicksandWorkspace &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createWorkspace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
				element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
				$repeatingElements&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

			&lt;span class=&quot;token comment&quot;&gt;// Populate the workspace with the rendering template so it mirrors the contents of element.&lt;/span&gt;
			$repeatingElements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Register the hidden DOM element for updates by Knockout.&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;template&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;init&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token function-variable function&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token parameter&quot;&gt;element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// Unwrap the observable to subscribe to updates.&lt;/span&gt;
		ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unwrapObservable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;foreach&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; $quicksandWorkspace &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWorkspace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			element&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Update the hidden DOM element using Knockout.&lt;/span&gt;
		ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;template&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;update&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			valueAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			allBindingsAccessor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			viewModel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			bindingContext&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; quicksandOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;options&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;options
			&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// Run Quicksand to copy the contents of the hidden DOM element to the visible element using the Quicksand animation.&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;quicksand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			$quicksandWorkspace&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
				ko&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindingHandlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quicksand&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getContainerTag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			quicksandOptions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The logic above is actually pretty simple.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a hidden container that mirrors the content of the data-bound element.&lt;/li&gt;
&lt;li&gt;Wire the hidden container, rather than the data-bound one, to be updated by Knockout.&lt;/li&gt;
&lt;li&gt;Whenever the hidden container changes, synchronize its contents with the data-bound element using Quicksand.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;usage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#usage&quot; aria-label=&quot;usage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Usage&lt;/h2&gt;
&lt;p&gt;The Quicksand custom bindings aim to support the same syntax as their built-in counterparts.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quicksand: arrayName&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text: elementPropertyName&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quicksand: { data: arrayName }&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text: elementPropertyName&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The optional &lt;code class=&quot;language-text&quot;&gt;options&lt;/code&gt; attribute can specify &lt;a href=&quot;http://razorjack.net/quicksand/docs-and-demos.html&quot;&gt;Quicksand parameters&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quicksand: { data: arrayName, options: { quicksandOption: value } }&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text: elementPropertyName&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quicksandTemplate: { foreach: arrayName, options: { quicksandOption: value } }&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text: elementPropertyName&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;
	&lt;span class=&quot;token attr-name&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quicksandTemplate: { foreach: arrayName, name: &apos;template-id&apos;, options: { quicksandOption: value } }&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;template-id&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;
	&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;li data&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;bind&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text: elementPropertyName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;li&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And to see the bindings in action, check out &lt;a href=&quot;http://jsfiddle.net/wimpyprogrammer/LrVr3/&quot;&gt;this jsFiddle&lt;/a&gt; based on Knockout&apos;s &quot;animated transitions&quot; example.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Microsoft Access is confused]]></title><description><![CDATA[Solving Microsoft Access's "ambiguous outer joins" error.]]></description><link>https://www.wimpyprogrammer.com/microsoft-access-is-confused</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/microsoft-access-is-confused</guid><pubDate>Sun, 28 Apr 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@baboudi?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Bill Aboudi&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/microsoft-office?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The other day while working on a legacy Microsoft Access database I was reminded of how bizarre Access can be. When I ran the following query:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Authors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Publications&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Authors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Str&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Publications&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;authors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;VALUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Publications&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;BETWEEN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;Begin&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I received a peculiar error:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Access&lt;/strong&gt; The SQL statement could not be executed because it contains ambiguous outer joins. To force one of the joins to be performed first, create a separate query that performs the first join and then include that query in your SQL statement.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For a query with no outer joins, this was terribly unhelpful.&lt;/p&gt;
&lt;p&gt;Researching the error, I found solutions like, &quot;change all of the joins to INNER&quot; which obviously didn&apos;t help me. So I began trying solutions that didn&apos;t make sense. Ultimately I found a version that worked:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sql&quot;&gt;&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Publications&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;LEFT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Authors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Authors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Str&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Publications&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;authors&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;VALUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Publications&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;BETWEEN&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;Begin&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By reversing the order of the tables and changing the INNER join to a LEFT join, the query works. Neither change solved the problem alone.&lt;/p&gt;
&lt;p&gt;So next time you&apos;re faced with a confusing Microsoft Access error message, try doing the opposite!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Relative paths in PHP INI]]></title><description><![CDATA[Improve the portability of your code from server-to-server with environment variables in your PHP INI.]]></description><link>https://www.wimpyprogrammer.com/relative-paths-in-php-ini</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/relative-paths-in-php-ini</guid><pubDate>Thu, 11 Apr 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@wilsonjim?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Jim Wilson&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/sign?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I&apos;ve always preferred to use relative file paths in my PHP INI, but ran into problems when running PHP from different directories. For example, a directive like &lt;code class=&quot;language-text&quot;&gt;error_log = &quot;../logs/php_errors.log&quot;&lt;/code&gt; will resolve to different paths when invoked by &lt;code class=&quot;language-text&quot;&gt;/public/index.php&lt;/code&gt; (e.g. Zend Framework) and &lt;code class=&quot;language-text&quot;&gt;/cli-config.php&lt;/code&gt; (e.g. Doctrine CLI). Some INI directives can be set at runtime by our application (&lt;a href=&quot;http://www.php.net/manual/en/ini.list.php&quot;&gt;see &lt;code class=&quot;language-text&quot;&gt;PHP_INI_ALL&lt;/code&gt;&lt;/a&gt;), but many cannot. I finally found the solution with environment variables.&lt;/p&gt;
&lt;p&gt;In a past post, &lt;a href=&quot;http://www.wimpyprogrammer.com/hosting-php-on-iis7/&quot;&gt;&quot;Hosting PHP on IIS7&quot;&lt;/a&gt;, I detailed my typical server configuration for PHP sites. For maximum flexibility, every site has its own PHP INI. To point PHP to its INI file, I create a FastCGI environment variable named &lt;a href=&quot;http://www.php.net/manual/en/configuration.file.php&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;PHPRC&lt;/code&gt;&lt;/a&gt;. The &lt;code class=&quot;language-text&quot;&gt;PHPRC&lt;/code&gt; variable stores the absolute path of the directory containing &lt;code class=&quot;language-text&quot;&gt;php.ini&lt;/code&gt;. So the &lt;code class=&quot;language-text&quot;&gt;PHPRC&lt;/code&gt; variable contains a path like &lt;code class=&quot;language-text&quot;&gt;C:\inetpub\wwwroot\Blog\public&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now I can simply use the PHPRC environment variable in my PHP INI. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ini&quot;&gt;&lt;pre class=&quot;language-ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token key attr-name&quot;&gt;error_log&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;${PHPRC}/../logs/php_errors.log&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;upload_tmp_dir&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;${PHPRC}/../temp/uploads&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;session.save_path&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;${PHPRC}/../temp/sessions&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These paths will automatically update depending on which server runs my code. Granted, these paths are not truly relative. But as long as every server contains an absolute path to the PHP INI, I may as well reuse it.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Microsoft Office Link Pre-fetching and Single Sign-On]]></title><description><![CDATA[I updated a site to use Single Sign-On (SSO) capability, specifically with Shibboleth, and was shocked to discover that links to the site in Microsoft Office files stopped working. After thorough troubleshooting I found a workaround.]]></description><link>https://www.wimpyprogrammer.com/microsoft-office-link-pre-fetching-and-single-sign-on</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/microsoft-office-link-pre-fetching-and-single-sign-on</guid><pubDate>Sun, 31 Mar 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@gaspanik?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Masaaki Komori&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/gate?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I updated a site to use &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_sign-on&quot;&gt;Single Sign-On (SSO)&lt;/a&gt; capability, specifically with &lt;a href=&quot;http://shibboleth.net/&quot;&gt;Shibboleth&lt;/a&gt;, and was shocked to discover that links to the site in Microsoft Office files stopped working. This turns out to be &lt;a href=&quot;http://shibboleth.1660669.n2.nabble.com/Dealing-with-links-embedded-in-Excel-td6841047.html&quot;&gt;a known issue&lt;/a&gt; with no definitive solution. So after thorough troubleshooting I created my own workaround, and as usual I hope sharing it will benefit others.&lt;/p&gt;
&lt;h2 id=&quot;a-normal-shibboleth-sign-on&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-normal-shibboleth-sign-on&quot; aria-label=&quot;a normal shibboleth sign on permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A Normal Shibboleth Sign-On&lt;/h2&gt;
&lt;p&gt;To understand the problem, let&apos;s first look at a successful Shibboleth sign-on. When a user visits a resource protected by Shibboleth, the &lt;span style=&quot;color: orange&quot;&gt;Service Provider (SP)&lt;/span&gt; examines the request. For example, on IIS &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt; is installed as an ISAPI filter in the protected website. &lt;span style=&quot;color: orange&quot;&gt;The SP&lt;/span&gt; checks the user&apos;s cookies to verify that they have a valid session. If the session is valid, the request continues to the resource. If the user has an invalid or no session, they are redirected to &lt;span style=&quot;color: blue&quot;&gt;the Identity Provider (IdP)&lt;/span&gt;, the central authentication server. The original request details (&lt;span style=&quot;color: orange&quot;&gt;the SP&apos;s&lt;/span&gt; address, the requested URL, etc.) are stored in a cookie by &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt;. If the user successfully authenticates to &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt;, they are transferred back to &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt;, which is sent the request URL and the tokens of a valid session. Finally &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt; redirects the user to the resource they requested. Phew!&lt;/p&gt;
&lt;h2 id=&quot;microsoft-office-and-link-pre-fetching&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#microsoft-office-and-link-pre-fetching&quot; aria-label=&quot;microsoft office and link pre fetching permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Microsoft Office and Link Pre-fetching&lt;/h2&gt;
&lt;p&gt;Now we&apos;ll look at Microsoft Office and its peculiar handling of links. When you click a hyperlink in an Office file (Word document, Excel spreadsheet, PowerPoint presentation, etc.), the URL is not immediately passed to your browser. First, Office will internally fetch the address. If the link returns a 3xx Redirection code, Office will request the new address and repeat. If the link returns a 4xx Client Error code, Office will abort the request and tell the user that the link is unavailable, having never opened a browser (I&apos;m guessing that&apos;s the whole point of this &quot;feature&quot;). And if the link returns a 2xx Success code, the URL is finally opened in a browser. Only the final URL is passed to the browser; any redirects are masked by Office.&lt;/p&gt;
&lt;h2 id=&quot;microsoft-office-and-sso&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#microsoft-office-and-sso&quot; aria-label=&quot;microsoft office and sso permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Microsoft Office and SSO&lt;/h2&gt;
&lt;p&gt;Microsoft Office conflicts with Shibboleth (and other SSO systems, I expect) because of cookies. When Office requests the protected resource, &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt; redirects to &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt; login page. Office follows the redirect and &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt; login page returns a 200 response, waiting for the user&apos;s credentials. Office opens &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt; login page address in the user&apos;s browser, &lt;strong&gt;but the cookies describing the request are lost&lt;/strong&gt;. After the user authenticates, &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt; doesn&apos;t know how to return the user to &lt;span style=&quot;color: orange&quot;&gt;their SP&lt;/span&gt; and displays an error. Thus hyperlinks in Office files never load.&lt;/p&gt;
&lt;h2 id=&quot;client-side-solutions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#client-side-solutions&quot; aria-label=&quot;client side solutions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Client-side Solutions?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://support.microsoft.com/kb/899927&quot;&gt;Microsoft KB #899927&lt;/a&gt; (see &quot;&lt;em&gt;Hyperlinks from Office to Internet Explorer or to another Web browser&lt;/em&gt;&quot;) describes some client-side workarounds for this problem that will alter Office&apos;s behavior. But the registry changes could have unexpected side effects. Depending on your audience, a registry change may be inconvenient or impossible.&lt;/p&gt;
&lt;h2 id=&quot;a-server-side-solution&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-server-side-solution&quot; aria-label=&quot;a server side solution permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A Server-side Solution&lt;/h2&gt;
&lt;p&gt;Ultimately we want a server-side solution that will transparently fix the problem for the user.&lt;/p&gt;
&lt;p&gt;To start, we need finer control over Shibboleth&apos;s redirects. By default, &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt; will automatically detect invalid sessions and redirect to &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt;. We need to disable this behavior and enable &quot;lazy sessions&quot; instead. In the &lt;code class=&quot;language-text&quot;&gt;&amp;lt;RequestMap&gt;&lt;/code&gt; section of &lt;span style=&quot;color: orange&quot;&gt;your SP&lt;/span&gt; configuration you&apos;ll find a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;Host&gt;&lt;/code&gt; section like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Host&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;example.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;authType&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shibboleth&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;requireSession&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;applicationId&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;xxx&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;favicon.ico&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;requireSession&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Make note of any unprotected paths, like &lt;code class=&quot;language-text&quot;&gt;favicon.ico&lt;/code&gt; in the example above.&lt;/p&gt;
&lt;p&gt;Update &lt;span style=&quot;color: orange&quot;&gt;your SP&apos;s&lt;/span&gt; configuration to set &lt;code class=&quot;language-text&quot;&gt;requireSession=&quot;false&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Host&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;example.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;authType&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;shibboleth&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;requireSession&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;applicationId&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;xxx&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the site is unprotected, with nothing to require authentication. We will shift this responsibility to a URL rewriter. On IIS I use &lt;a href=&quot;http://iirf.codeplex.com/&quot;&gt;Ionic&apos;s ISAPI Rewrite&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;apacheconf&quot;&gt;&lt;pre class=&quot;language-apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt;  &lt;span class=&quot;token variable&quot;&gt;%{HTTP_SHIB_IDENTITY_PROVIDER}&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt; ^\s*$&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt;  &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_URI}&lt;/span&gt;  !/Shibboleth\.sso/ &lt;span class=&quot;token directive-flags keyword&quot;&gt;[I]&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt;  &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_URI}&lt;/span&gt;  !/favicon\.ico &lt;span class=&quot;token directive-flags keyword&quot;&gt;[I]&lt;/span&gt;
RedirectRule  .*  /Shibboleth.sso/Login?target=&lt;span class=&quot;token comment&quot;&gt;#X%{URL}#E&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This rule will detect any unauthenticated requests and force them to log in. The &lt;code class=&quot;language-text&quot;&gt;/Shibboleth.sso/Login&lt;/code&gt; path will redirect the user from &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt; to &lt;span style=&quot;color: blue&quot;&gt;the IdP&lt;/span&gt;, and the target parameter will contain the URL-encoded address to which the user should return after authentication. Any unprotected paths like &lt;code class=&quot;language-text&quot;&gt;favicon.ico&lt;/code&gt; should be added as exceptions to this rule.&lt;/p&gt;
&lt;p&gt;Now that Shibboleth&apos;s protection is restored, we can add a workaround for Microsoft Office. &lt;strong&gt;Before&lt;/strong&gt; the rule above, add another one.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;apacheconf&quot;&gt;&lt;pre class=&quot;language-apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{HTTP_USER_AGENT}&lt;/span&gt; ;\sms-office(\)|;) &lt;span class=&quot;token directive-flags keyword&quot;&gt;[I]&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteRule&lt;/span&gt; .* /Shibboleth-MSOffice.html &lt;span class=&quot;token directive-flags keyword&quot;&gt;[L]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This rule will check the user agent for &lt;code class=&quot;language-text&quot;&gt;ms-office&lt;/code&gt; (along with some syntax to minimize false positives). When Microsoft Office fetches a link, its user agent contains this unique &lt;code class=&quot;language-text&quot;&gt;ms-office&lt;/code&gt; string. The request from Office will be rewritten to a simple HTML file, causing the link to return a 200 response code and avoid the Shibboleth redirects.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Shibboleth-MSOffice.html&lt;/code&gt; file must exist, but its contents are not critical. In theory, no person will see it. Still, I recommend some additional measures in case of false positives.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Microsoft Office application detected&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/html;charset=utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;refresh&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			The web server has detected that your visit originated from a Microsoft
			Office application.
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			To make MS Office compatible with Single Sign-On (SSO) authentication, the
			visit has been halted.
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;strong&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
				Please press F5 to refresh the browser and continue to your page.
			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;strong&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This message will help users who are mistakenly caught by the rule, and the redirect will help in case the response is somehow cached.&lt;/p&gt;
&lt;p&gt;With everything in place, the Office links will work again. When Office fetches a protected resource, the server&apos;s URL rewriter will detect the request and return an immediate 200 response. Office will pass the URL, unaltered, to the user&apos;s browser. When the user visits the address again, the request is validated by &lt;span style=&quot;color: orange&quot;&gt;the SP&lt;/span&gt; and finally taken to the resource.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Multiple forms on the same page in Zend Framework]]></title><description><![CDATA[Processing two forms on the same page is not the simplest task in the Zend Framework. After a few attempts, I think I found an elegant solution.]]></description><link>https://www.wimpyprogrammer.com/multiple-forms-on-the-same-page-in-zend-framework</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/multiple-forms-on-the-same-page-in-zend-framework</guid><pubDate>Thu, 21 Mar 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@krystagrusseck?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Christa Dodoo&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/paperwork?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Processing two forms on the same page is not the simplest task in the Zend Framework. About a year ago I encountered this problem and studied others&apos; approaches. Eventually I hacked together a solution with multiple actions and lots of redundant code. But I was recently making updates to this page and found a more elegant method for handling multiple forms.&lt;/p&gt;
&lt;p&gt;Most solutions to this problem involve submitting each form to a different action. And many times that is appropriate. Imagine a login page with a search box in the corner. The login form can self-post and the search form can submit to its own action. If the search form fails validation, it can reappear with errors on its own page and the user won&apos;t miss the login form.&lt;/p&gt;
&lt;p&gt;But sometimes your forms are similar enough that they should be processed by the same action. It&apos;s hard to describe such a scenario, but frankly it doesn&apos;t matter. If you&apos;re reading this post, you probably have such a need in your project and my example doesn&apos;t matter. So we&apos;ll imagine a user profile page with two forms for the user to update different parts of their account.&lt;/p&gt;
&lt;p&gt;I&apos;ve written previously about how I use forms across the MVC layers. If something in the code below doesn&apos;t make sense, please check my &lt;a href=&quot;http://www.wimpyprogrammer.com/mvc-form-layer/&quot; title=&quot;MVC Form Layer&quot;&gt;&quot;MVC Form Layer&quot;&lt;/a&gt; post.&lt;/p&gt;
&lt;p&gt;First let&apos;s look at the view for the user profile edit page.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;post&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$submitForm1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Submit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;submitForm1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$submitForm1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLabel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Save Form 1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$submitForm1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;post&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$submitForm2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Submit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;submitForm2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$submitForm2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLabel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Save Form 2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$submitForm2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that each form has a separate submit button, and each submit button has a different name in the form.&lt;/p&gt;
&lt;p&gt;And now the edit profile action in the User module&apos;s Index controller.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;editProfileAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// TODO: Get user&apos;s ID from their session.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//$userId = ???&lt;/span&gt;

    &lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Application_Model_Mapper_Users&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// TODO: Handle failed profile lookup.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getForm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;form1Name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getForm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;form2Name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$request&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$postData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$postData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;submitForm1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// The user submitted editForm1.&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveForm1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$postData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Redisplay editForm1 with validation errors.&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Repopulate the editForm2 from saved data.&lt;/span&gt;
                &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;populateFromUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// TODO: Handle successful editForm1 submission.&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// OR elseif(isset($postData[&apos;submitForm2&apos;]))&lt;/span&gt;&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;// The user submitted editForm2.&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveForm2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$postData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Redisplay editForm2 with validation errors.&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Repopulate editForm1 from saved data.&lt;/span&gt;
                &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;populateFromUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// TODO: Handle successful editForm2 submission.&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Populate both forms from saved data.&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;populateFromUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;editForm2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;populateFromUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that we&apos;re checking the POST data for the names of the submit button that we created in the view. I&apos;ve replaced some sections with &lt;code class=&quot;language-text&quot;&gt;// TODO&lt;/code&gt; comments to focus on the multi-form handling.&lt;/p&gt;
&lt;p&gt;This is a bare bones example, but once you add more logic the advantages of a single action will stand out. If you submit each form to a different action, each action and view will share much of the same code. The approach above is much &lt;a href=&quot;http://en.wikipedia.org/wiki/Don%27t_Repeat_Yourself&quot;&gt;DRY-er&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Autoloading Symfony using Doctrine with Zend Framework]]></title><description><![CDATA[Fix Symphony autoloading in the Doctrine CLI.]]></description><link>https://www.wimpyprogrammer.com/autoloading-symfony-using-doctrine-with-zend-framework</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/autoloading-symfony-using-doctrine-with-zend-framework</guid><pubDate>Sat, 16 Mar 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@dtopkin1?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Dayne Topkin&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/orchestra?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;On some projects I use the &lt;a href=&quot;http://www.doctrine-project.org/projects/orm.html&quot;&gt;Doctrine Object Relational Mapper&lt;/a&gt;, a fantastic library for modeling database objects. To combine it with Zend Framework 1, I use &lt;a href=&quot;https://github.com/guilhermeblanco/zendframework1-doctrine2&quot;&gt;Guilherme Blanco&apos;s Bisna application resource&lt;/a&gt;. I recently upgraded a project to the latest version of Doctrine and suddenly couldn&apos;t autoload the Symphony classes. It took far too long for me to figure out the problem, so I hope I can spare someone else the same trouble.&lt;/p&gt;
&lt;p&gt;Doctrine borrows some classes from &lt;a href=&quot;http://symfony.com/&quot;&gt;the Symfony framework&lt;/a&gt;, namely for the Doctrine console and YAML parser. These classes retain the Symfony namespace, but reside in &lt;code class=&quot;language-text&quot;&gt;/Doctrine/Symfony&lt;/code&gt;. This adds a wrinkle to the autoloading process. If you use the Bisna application resource, you may have something like this in your application INI:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ini&quot;&gt;&lt;pre class=&quot;language-ini&quot;&gt;&lt;code class=&quot;language-ini&quot;&gt;&lt;span class=&quot;token key attr-name&quot;&gt;resources.doctrine.classLoader.loaderClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;Doctrine\Common\ClassLoader&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;resources.doctrine.classLoader.loaderFile&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;Doctrine/Common/ClassLoader.php&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token key attr-name&quot;&gt;resources.doctrine.classLoader.loaders.symfony_console.namespace&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;Symfony&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token key attr-name&quot;&gt;resources.doctrine.classLoader.loaders.symfony_console.includePath&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token value attr-value&quot;&gt;&quot;&lt;span class=&quot;token inner-value&quot;&gt;Doctrine&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However you choose to autoload, you need to specify that the root of the Symfony library is in the &lt;code class=&quot;language-text&quot;&gt;/Doctrine&lt;/code&gt; directory. Once the Bisna resource initializes during your application&apos;s bootstrap phase, any references to Symfony will autoload correctly.&lt;/p&gt;
&lt;p&gt;The problem occurs when you use the Doctrine command line tool. This tool resides in Doctrine&apos;s &lt;code class=&quot;language-text&quot;&gt;/bin&lt;/code&gt; directory and includes the &lt;code class=&quot;language-text&quot;&gt;doctrine.php&lt;/code&gt; script. Depending on how you obtained Doctrine (PEAR, Composer, or a downloadable archive), a &lt;code class=&quot;language-text&quot;&gt;doctrine.php&lt;/code&gt; script may already be in the &lt;code class=&quot;language-text&quot;&gt;/bin&lt;/code&gt; directory. This &lt;code class=&quot;language-text&quot;&gt;doctrine.php&lt;/code&gt; script used to properly autoload Symfony, until &lt;a href=&quot;https://github.com/doctrine/doctrine2/commit/be6fb617dfc494acec144ba058fc708f02a54f61#diff-2&quot;&gt;a recent update&lt;/a&gt;. As you can see in the commit changelog, the call to &lt;code class=&quot;language-text&quot;&gt;\Doctrine\Common\ClassLoader&lt;/code&gt; was updated and no longer specifies &lt;code class=&quot;language-text&quot;&gt;/Doctrine&lt;/code&gt; as the base directory of the Symfony library. This code runs before your &lt;code class=&quot;language-text&quot;&gt;cli-config.php&lt;/code&gt;, and once Symfony&apos;s path is defined in the autoloading stack it&apos;s difficult to change. We need our own version of the &lt;code class=&quot;language-text&quot;&gt;doctrine.php&lt;/code&gt; script.&lt;/p&gt;
&lt;p&gt;Luckily the Doctrine command line loads the script with a simple &lt;code class=&quot;language-text&quot;&gt;include(&apos;doctrine.php&apos;);&lt;/code&gt;. Because this path is relative, we can override the default with our own &lt;code class=&quot;language-text&quot;&gt;doctrine.php&lt;/code&gt; if we place it higher in the &lt;code class=&quot;language-text&quot;&gt;include_path&lt;/code&gt;. Our &lt;code class=&quot;language-text&quot;&gt;doctrine.php&lt;/code&gt; can mirror the default one, minus the autoloader settings.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// doctrine.php&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$configFile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getcwd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;DIRECTORY_SEPARATOR&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;cli-config.php&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$helperSet&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;file_exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$configFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_readable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$configFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;trigger_error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Configuration file [&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$configFile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;] does not have read permission.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;E_ERROR&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$configFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$GLOBALS&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$helperSetCandidate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$helperSetCandidate&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name class-name-fully-qualified&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Symfony&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Component&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Helper&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;HelperSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$helperSet&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$helperSetCandidate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$helperSet&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$helperSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name class-name-fully-qualified&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Symfony&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Component&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Helper&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;HelperSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token class-name class-name-fully-qualified static-context&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Doctrine&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;ORM&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Tools&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Console&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;ConsoleRunner&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$helperSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This version will still kick off the &lt;code class=&quot;language-text&quot;&gt;cli-config.php&lt;/code&gt; script, which will bootstrap the application and configure the autoloader.&lt;/p&gt;
&lt;p&gt;So in the end, the problem was complex but the solution is simple. Copy the &lt;code class=&quot;language-text&quot;&gt;/bin/doctrine.php&lt;/code&gt; file from the Doctrine library into your project and remove the &lt;code class=&quot;language-text&quot;&gt;\Doctrine\Common\ClassLoader&lt;/code&gt; setup code.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Don't host on a .255 IP address]]></title><description><![CDATA[Not all IP addresses are created equal.]]></description><link>https://www.wimpyprogrammer.com/dont-host-on-a-255-ip-address</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/dont-host-on-a-255-ip-address</guid><pubDate>Sun, 06 Jan 2013 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@mathyaskurmann?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Mathyas Kurmann&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/po-box?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Most of the websites that I build at work are for internal use, but last year I created a site with a public audience. Everything was going well post-launch until I received a handful of reports from users who couldn&apos;t access the site. They tried clearing cookies, switching browsers, switching computers, and resetting modems, but nothing worked. Visiting any page on the site would result in an error like&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Internet Explorer cannot display the webpage&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unable to connect&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They could view other sites hosted on my network, but nothing hosted on the same server as this public site. The PHP and server logs recorded nothing unusual. What was happening?&lt;/p&gt;
&lt;p&gt;Lucky for me, this public site hosts content that our users really want to access. Otherwise countless people would have failed to reach the site but moved on without reporting it. For every user who contacted me, I would collect some basic information, ask them to attempt some tests, then apologize for the problems and suggest they use the Internet at somewhere like Starbucks.&lt;/p&gt;
&lt;p&gt;After much frustration, I remembered that when the server was deployed months before, it was assigned an odd IP address. Its public IP address ended in .255. If you&apos;re familiar with networking, you recognize that an IP address ending in .255 is traditionally the broadcast address of a \24 network (#.#.#.0 - #.#.#.255). The broadcast address has special meaning within the network and is never assigned to any clients. But evidently this server is not on a \24 network because the .255 address worked fine, so I let it go.&lt;/p&gt;
&lt;p&gt;I researched online and found &lt;a href=&quot;https://forums.aws.amazon.com/thread.jspa?threadID=43792&quot;&gt;some reports&lt;/a&gt; (but not many) to corroborate this problem with .255 IP addresses. Continuing with this hunch, the server farm administrators assigned an additional IP address to the server which didn&apos;t end in .0 or .255. I moved the website to the new IP address and, after the DNS change propagated, the problem was fixed. To date, no more users have reported problems accessing the site.&lt;/p&gt;
&lt;p&gt;My testing suggests that the problem lies with the user&apos;s Internet Service Provider (ISP). Because a .255 IP address is normally significant, some ISPs may block outbound traffic to those addresses to prevent &lt;a href=&quot;http://en.wikipedia.org/wiki/Smurf_attack&quot;&gt;smurf attacks&lt;/a&gt;. While everyone agrees that this is a crude method, some ISPs clearly still use it.&lt;/p&gt;
&lt;p&gt;If you don&apos;t want to ban a percentage of users from accessing your site, be sure you don&apos;t have public content hosted on a .255 IP address.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Preserve encoded slashes in URL]]></title><description><![CDATA[Configure your IIS URL rewrite tool to preserve encoded characters in the original URL.]]></description><link>https://www.wimpyprogrammer.com/preserve-encoded-slashes-in-url</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/preserve-encoded-slashes-in-url</guid><pubDate>Fri, 14 Dec 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@konkarampelas?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Kon Karampelas&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/website?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To use a reserved character in a URL without invoking its special meaning, the character must be URL encoded. For example, a &lt;code class=&quot;language-text&quot;&gt;?&lt;/code&gt; separates the page name from the query string, a &lt;code class=&quot;language-text&quot;&gt;&amp;amp;&lt;/code&gt; separates query string parameters, and a &lt;code class=&quot;language-text&quot;&gt;=&lt;/code&gt; separates parameter names from their values. These characters must be converted to &lt;code class=&quot;language-text&quot;&gt;%3F&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;%26&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;%3D&lt;/code&gt; respectively if we want them interpreted literally.&lt;/p&gt;
&lt;p&gt;In MVC applications, these special characters are less common because URLs follow a pattern like &lt;code class=&quot;language-text&quot;&gt;/Module/Controller/Action/Parameter1/Parameter2&lt;/code&gt;. In this case, the most important reserved character is the forward slash. Let&apos;s see how to handle slashes in Zend Framework 1 URLs.&lt;/p&gt;
&lt;h2 id=&quot;encoding-in-a-basic-php-application&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#encoding-in-a-basic-php-application&quot; aria-label=&quot;encoding in a basic php application permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Encoding in a basic PHP application&lt;/h2&gt;
&lt;p&gt;A basic PHP-on-IIS application handles encoded characters well. Let&apos;s review the output of &lt;code class=&quot;language-text&quot;&gt;phpinfo()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;scrollable-table-wrapper&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Literal URL:&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost/index.php?param=value&amp;amp;%2F%3F%26%3D=%3D%2F%26%3F&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_GET[&quot;param&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_GET[&quot;/?&amp;amp;=&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;=/&amp;amp;?&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_SERVER[&quot;REQUEST_URI&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;/index.php?param=value&amp;amp;%2F%3F%26%3D=%3D%2F%26%3F&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_SERVER[&quot;QUERY_STRING&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;param=value&amp;amp;%2F%3F%26%3D=%3D%2F%26%3F&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Note that the characters have been decoded in the &lt;code class=&quot;language-text&quot;&gt;$_GET&lt;/code&gt; superglobal, but the encoded version remains intact in the &lt;code class=&quot;language-text&quot;&gt;$_SERVER&lt;/code&gt; superglobal.&lt;/p&gt;
&lt;h2 id=&quot;encoding-in-an-mvc-php-application&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#encoding-in-an-mvc-php-application&quot; aria-label=&quot;encoding in an mvc php application permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Encoding in an MVC PHP application&lt;/h2&gt;
&lt;p&gt;Compare this behavior to an MVC PHP application hosted on IIS.&lt;/p&gt;
&lt;div class=&quot;scrollable-table-wrapper&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Literal URL:&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost/param/value/%2F%3F%26%3D/%3D%2F%26%3F&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_GET[&quot;?&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;no value&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_SERVER[&quot;REQUEST_URI&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;/param/value/?&amp;amp;=/=/&amp;amp;?&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_SERVER[&quot;QUERY_STRING&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;amp;=/=/&amp;amp;?&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;This time the URL interpretation is all wrong. The encoded characters were decoded before IIS parsed the URL, so they were treated as query string delimiters. None of the PHP superglobals contain the encoded URL that appears in the browser bar. How can we pass encoded characters to the PHP MVC application?&lt;/p&gt;
&lt;h2 id=&quot;rewriting-to-the-rescue&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#rewriting-to-the-rescue&quot; aria-label=&quot;rewriting to the rescue permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Rewriting to the Rescue&lt;/h2&gt;
&lt;p&gt;The solution lies in our URL rewriter. On IIS, my tool of choice is &lt;a href=&quot;http://iirf.codeplex.com/&quot;&gt;Ionic&apos;s ISAPI Rewrite&lt;/a&gt;. To funnel MVC requests to the Zend Framework I use the following rule.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;apacheconf&quot;&gt;&lt;pre class=&quot;language-apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# IIRF.ini&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_FILENAME}&lt;/span&gt; !-f
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_FILENAME}&lt;/span&gt; !-d
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_URI}&lt;/span&gt; !\. &lt;span class=&quot;token directive-flags keyword&quot;&gt;[I]&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteRule&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt; ^[^?]*(\?.*|$&lt;/span&gt;) /index.php&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;token directive-flags keyword&quot;&gt;[L]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These rules include some enhancements beyond the ones you might find online. Namely the &lt;code class=&quot;language-text&quot;&gt;RewriteRule&lt;/code&gt; will persist any query string parameters, which helps me use &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; forms in my MVC application. But these customizations don&apos;t solve the encoding problem.&lt;/p&gt;
&lt;p&gt;To preserve the encoded characters we need only add a modifier to the &lt;code class=&quot;language-text&quot;&gt;RewriteRule&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;apacheconf&quot;&gt;&lt;pre class=&quot;language-apacheconf&quot;&gt;&lt;code class=&quot;language-apacheconf&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# IIRF.ini&lt;/span&gt;
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_FILENAME}&lt;/span&gt; !-f
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_FILENAME}&lt;/span&gt; !-d
&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteCond&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;%{REQUEST_URI}&lt;/span&gt; !\. &lt;span class=&quot;token directive-flags keyword&quot;&gt;[I]&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token directive-inline property&quot;&gt;RewriteRule&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt; ^[^?]*(\?.*|$&lt;/span&gt;) /index.php&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;token directive-flags keyword&quot;&gt;[L,U]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;U&lt;/code&gt; modifier will save the original URL, before IIS decodes it, to the &lt;code class=&quot;language-text&quot;&gt;HTTP_X_REWRITE_URL&lt;/code&gt; server variable.&lt;/p&gt;
&lt;div class=&quot;scrollable-table-wrapper&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Literal URL:&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost/param/value/%2F%3F%26%3D/%3D%2F%26%3F&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;_SERVER[&quot;HTTP_X_REWRITE_URL&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;/param/value/%2F%3F%26%3D/%3D%2F%26%3F&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;When the Zend Framework (&lt;code class=&quot;language-text&quot;&gt;Zend_Controller_Request_Http::setRequestUri()&lt;/code&gt;) parses the URL to determine the route and parameters, it will first look for the &lt;code class=&quot;language-text&quot;&gt;HTTP_X_REWRITE_URL&lt;/code&gt; variable containing the preserved URL. Voilà! Our MVC application sees our encoded characters.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[MVC Form Layer]]></title><description><![CDATA[Forms are a tricky part of any Model-View-Controller (MVC) application. They incorporate validation, presentation, and security logic that spans all tiers of the application. Separating these concerns is difficult but important. I'll walk through how I use Zend_Form in Zend Framework 1, but the same principles should apply to any MVC application.]]></description><link>https://www.wimpyprogrammer.com/mvc-form-layer</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/mvc-form-layer</guid><pubDate>Sat, 01 Dec 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@hero92?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;amin khorsand&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/assembly-line?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Forms are a tricky part of any &lt;a href=&quot;http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;&gt;Model-View-Controller (MVC)&lt;/a&gt; application. They incorporate validation, presentation, and security logic that spans all tiers of the application. Separating these concerns is difficult but important. I&apos;ll walk through how I use &lt;code class=&quot;language-text&quot;&gt;Zend_Form&lt;/code&gt; in Zend Framework 1, but the same principles should apply to any MVC application.&lt;/p&gt;
&lt;h2 id=&quot;a-user-account-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-user-account-form&quot; aria-label=&quot;a user account form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A User account form&lt;/h2&gt;
&lt;p&gt;For this article, imagine a basic form for users to create or update their account. To keep things simple, I&apos;ve replaced some of the logic with &lt;code class=&quot;language-text&quot;&gt;// TODO:&lt;/code&gt; comments. Let&apos;s start with the form itself.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;Application_Form_Account&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;FIELD_USERNAME&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;account&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword static-context&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FIELD_USERNAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLabel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// TODO: Add filters and validators&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;populateFromUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name type-declaration&quot;&gt;Application_Model_User&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword static-context&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FIELD_USERNAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because the form field names are referenced outside of this class, I assign them to class constants. The &lt;code class=&quot;language-text&quot;&gt;populateFromUser()&lt;/code&gt; function will receive a User object and copy its attributes to the appropriate form fields. Other &lt;code class=&quot;language-text&quot;&gt;populateFrom*()&lt;/code&gt; functions could be added to accommodate other objects.&lt;/p&gt;
&lt;h2 id=&quot;the-user-model&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-user-model&quot; aria-label=&quot;the user model permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The User model&lt;/h2&gt;
&lt;p&gt;Next we look at the User model. As a foundation I used the approach suggested by Matthew Weier O&apos;Phinney, Zend Framework Project Lead, in &lt;a href=&quot;http://mwop.net/blog/200-Using-Zend_Form-in-Your-Models.html&quot;&gt;&quot;Using Zend_Form in Your Models&quot;&lt;/a&gt;. Here&apos;s the User model and its base class.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;Application_Model_User&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;My_Model_Abstract&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_formDefault&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Account&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;saveFormAccount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name type-declaration&quot;&gt;Application_Form_Account&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword type-hint&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FIELD_USERNAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Store the object; not discussed in this article&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;My_Model_Abstract&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// The base class name or an array of class names to use when loading forms for this object.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_formBase&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Application_Form_&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// The name of the default form to load for this object.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$_formDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * Retrieve an instance of Zend_Form that can be used to interact with this object.
     *
     * @param  string $type  The type of form to retrieve, if many are applicable.
     * @param  array|Zend_Config $options  The options to pass to the form.
     * @return Zend_Form
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;getForm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$options&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Determine the name of the form to return.  This may be passed as a parameter&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// or set as a property of the model.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_formDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogicException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Default form not specified in %s::%s&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__CLASS__&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;::&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__FUNCTION__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ucfirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_formDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ucfirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// Determine the full name of the form class.&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$class&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_formBase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogicException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Form base path(s) not specified in &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__CLASS__&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;::&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__FUNCTION__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_formBase&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$formBase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;class_exists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$formBase&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token variable&quot;&gt;$class&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$formBase&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogicException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Unable to locate form &quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$type&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;&quot; in &apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__CLASS__&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;::&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;__FUNCTION__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Compared to Matthew&apos;s example, I removed the &lt;code class=&quot;language-text&quot;&gt;$_forms&lt;/code&gt; property and added support for form options and multiple form bases.&lt;/p&gt;
&lt;h2 id=&quot;the-controller&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-controller&quot; aria-label=&quot;the controller permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The controller&lt;/h2&gt;
&lt;p&gt;Finally, we&apos;ll tie everything together in the controller.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;Application_IndexController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Controller_Action&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;indexAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$userId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_getParam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;userId&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;isNewUser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$userId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Application_Model_Mapper_User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// The User data mapper; not discussed in this article&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;isNewUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Custom mapper function to return a new Application_Model_User&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$userId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getForm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;account&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Parameter is redundant&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$postData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;saveFormAccount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$postData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Redisplay the form with validation errors.&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// TODO: Display success message, 302-redirect user&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;isNewUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Display a blank form.&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Display the saved form values.&lt;/span&gt;
                &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;populateFromUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The controller retrieves an instance of &lt;code class=&quot;language-text&quot;&gt;Application_Model_User&lt;/code&gt; and gets an &lt;code class=&quot;language-text&quot;&gt;Application_Form_Account&lt;/code&gt; from it. If loading the form for the first time, it is populated with the user&apos;s attributes. If the user submits the form, the form and its contents are passed to the User model to validate and save.&lt;/p&gt;
&lt;h2 id=&quot;displaying-the-form&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#displaying-the-form&quot; aria-label=&quot;displaying the form permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Displaying the form&lt;/h2&gt;
&lt;p&gt;To cap off this example, let&apos;s see the view that renders this action.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;post&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$submit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Submit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;submit&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;isNewUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$submit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLabel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Register&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token variable&quot;&gt;$submit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLabel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Update&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$submit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// TODO: Set form and form element decorators&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Presentation concerns like the submit button and form decorators are handled here because they aren&apos;t pertinent to the form-model interaction.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;With this approach, all form operations are done in the appropriate tier. The form populates itself from models, the model digests all of the form data, and the view handles all of the rendering. This keeps the form flexible and reusable.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Using sprintf with multiple iterations]]></title><description><![CDATA[PHP's built-in sprintf() function is great for formatting complicated output and improving code readability. I recently had the need to output a string multiple times with some changes each time.]]></description><link>https://www.wimpyprogrammer.com/using-sprintf-with-multiple-iterations</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/using-sprintf-with-multiple-iterations</guid><pubDate>Sun, 25 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@jon_chng?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Jonathan Chng&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/sprint?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;PHP&apos;s built-in &lt;a href=&quot;http://php.net/manual/en/function.sprintf.php&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt;&lt;/a&gt; function is great for formatting complicated output and improving code readability. I recently had the need to output a string multiple times with some changes each time.&lt;/p&gt;
&lt;h2 id=&quot;basic-output&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#basic-output&quot; aria-label=&quot;basic output permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Basic output&lt;/h2&gt;
&lt;p&gt;To start, here&apos;s a basic usage of &lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt;. It prints a &quot;Clear Date&quot; hyperlink that uses jQuery to blank the field with an ID of &lt;code class=&quot;language-text&quot;&gt;&quot;date&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string nowdoc-string&quot;&gt;&lt;span class=&quot;token delimiter symbol&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&apos;&lt;/span&gt;NOWDOC&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&amp;lt;a onclick=&quot;%1$s(&apos;%2$s&apos;).val(&apos;&apos;)&quot;&gt;%3$s&amp;lt;/a&gt;
&lt;span class=&quot;token delimiter symbol&quot;&gt;NOWDOC&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;$j&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//1&lt;/span&gt;
                         &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;#date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//2&lt;/span&gt;
                         &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Clear Date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I highly recommend using the &lt;a href=&quot;http://www.php.net/manual/en/function.sprintf.php#example-4560&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;n$&lt;/code&gt; position specifier&lt;/a&gt; syntax along with comments to number your &lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt; arguments. This makes it easier to change your format string, reuse arguments, and trace arguments to their placeholders.&lt;/p&gt;
&lt;p&gt;This example is overly-simplified and the &lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt; is excessive, but it demonstrates the concept.&lt;/p&gt;
&lt;h2 id=&quot;advanced-output-with-iterations&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#advanced-output-with-iterations&quot; aria-label=&quot;advanced output with iterations permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Advanced output with iterations&lt;/h2&gt;
&lt;p&gt;Now imagine that we need to print several clear links for various form inputs. Some of the &lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt; arguments will change but some will not. We can organize our output with multiple passes through &lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string nowdoc-string&quot;&gt;&lt;span class=&quot;token delimiter symbol&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&apos;&lt;/span&gt;NOWDOC&lt;span class=&quot;token punctuation&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&amp;lt;a onclick=&quot;%3$s(&apos;%1$s&apos;).val(&apos;&apos;)&quot;&gt;%2$s&amp;lt;/a&gt;
&lt;span class=&quot;token delimiter symbol&quot;&gt;NOWDOC&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Fill placeholders that will not vary; preserve the rest&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;%1$s&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;%2$s&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                     &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;$j&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//3&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Fill the remaining placeholders&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;#date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//1&lt;/span&gt;
                         &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Clear Date&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;#time&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//1&lt;/span&gt;
                         &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Clear Time&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$clearLink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;#name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//1&lt;/span&gt;
                         &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Clear Name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that I&apos;ve renumbered the placeholders in the original string. The placeholders that will vary on each iteration are numbered first. This avoids any renumbering on the first call to &lt;code class=&quot;language-text&quot;&gt;sprintf()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course this technique is not guaranteed to produce cleaner code. The added complexity may just obfuscate your logic. But keep it in your toolbox as an option for reusing complex templates.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Zend_Form_Decorator_Fieldset for individual elements]]></title><description><![CDATA[Here's a custom decorator to render your Zend_Form_Element with a &lt;fieldset&gt;.]]></description><link>https://www.wimpyprogrammer.com/zend_form_decorator_fieldset-for-individual-elements</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/zend_form_decorator_fieldset-for-individual-elements</guid><pubDate>Fri, 23 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@no_one_cares?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;no one cares&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/field?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you want to include a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;fieldset&gt;&lt;/code&gt; in your &lt;code class=&quot;language-text&quot;&gt;Zend_Form&lt;/code&gt;, you might try the &lt;code class=&quot;language-text&quot;&gt;Zend_Form_Decorator_Fieldset&lt;/code&gt; decorator. But it&apos;s not apparent that this decorator is meant for the form and not the individual elements in it. Instead, here&apos;s a custom decorator to render your &lt;code class=&quot;language-text&quot;&gt;Zend_Form_Element&lt;/code&gt; with a &lt;code class=&quot;language-text&quot;&gt;&amp;lt;fieldset&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;My_Form_Decorator_Fieldset_Element&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Decorator_Fieldset&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/**
     * Attribs that should be removed prior to rendering
     * @var array
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$stripAttribs&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;maxlength&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;jqueryparams&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;size&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;readonly&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;checked&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;helper&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;renderpassword&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;onclick&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Uncomment for Zend Framework versions &amp;lt; 1.12.0.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/* public function getOptions()
    {
        $options = parent::getOptions();

        // Do not inherit the id of the element.  Ids must be unique.
        // See http://framework.zend.com/issues/browse/ZF-10803.
        if(array_key_exists(&apos;id&apos;, $options) &amp;amp;&amp;amp;
           $options[&apos;id&apos;] == $this-&gt;getElement()-&gt;getId()) {
            unset($options[&apos;id&apos;]);
        }

        return $options;
    } */&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I use this decorator to implement the form design at &lt;a href=&quot;http://pea.rs/forms/top-labels&quot;&gt;http://pea.rs/forms/top-labels&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Zend_Validate_Callback Success on False]]></title><description><![CDATA[What if you need to validate input using a callback function that will return False when the input is valid? Here's a custom validator to do the job.]]></description><link>https://www.wimpyprogrammer.com/zend_validate_callback-success-on-false</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/zend_validate_callback-success-on-false</guid><pubDate>Fri, 23 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@thenewmalcolm?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Obi Onyeador&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;What if you need to validate input using a callback function that will return &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt; when the input is valid? Here&apos;s a custom validator to do the job.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;My_Validate_Callback_False&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Validate_Callback&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$context&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// Run the validator normally and collect the result.&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword static-context&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// The callback returned TRUE, so we should return FALSE.&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword static-context&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;INVALID_VALUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;elseif&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;in_array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword static-context&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;INVALID_CALLBACK&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_errors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// The callback errored.  We should persist the FALSE result.&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// The callback returned FALSE and did not error.  Clear the errors and return TRUE.&lt;/span&gt;
            &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_errors&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;when-would-you-use-this&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#when-would-you-use-this&quot; aria-label=&quot;when would you use this permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;When would you use this?&lt;/h2&gt;
&lt;p&gt;If you wrote the callback function, you control the result. But if your callback function is built into PHP or a library, it may not be so easy. You could wrap the function with a version that reverses the result, or you can use &lt;code class=&quot;language-text&quot;&gt;My_Validate_Callback_False&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, I have a user registration form with a &lt;a href=&quot;http://en.wikipedia.org/wiki/CAPTCHA&quot;&gt;CAPTCHA&lt;/a&gt;. New usernames are checked in the database for uniqueness. But I don&apos;t want to query the database unless the user has passed the CAPTCHA — this combats automated queries that probe for usernames. So the username validation chain includes a callback to &lt;code class=&quot;language-text&quot;&gt;Zend_Form_Element_Captcha-&gt;hasErrors()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addPrefixPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;My_Validate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;My/Validate/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;validate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addValidator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Callback_False&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
               &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;callback&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$captcha&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;hasErrors&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because &lt;code class=&quot;language-text&quot;&gt;hasErrors()&lt;/code&gt; will return &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt; when the input is valid, I need &lt;code class=&quot;language-text&quot;&gt;My_Validate_Callback_False&lt;/code&gt; to reverse the normal behavior.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Zend_Validate_Callback with no context]]></title><description><![CDATA[This class is super simple, so we'll begin with the code.]]></description><link>https://www.wimpyprogrammer.com/zend_validate_callback-with-no-context</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/zend_validate_callback-with-no-context</guid><pubDate>Wed, 21 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Kelly Sikkema&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/paper-form?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This class is super simple, so we&apos;ll begin with the code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name-definition class-name&quot;&gt;My_Validate_Callback_NoContext&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Validate_Callback&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword static-context&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;how-does-it-work&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-does-it-work&quot; aria-label=&quot;how does it work permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How does it work?&lt;/h2&gt;
&lt;p&gt;During &lt;code class=&quot;language-text&quot;&gt;Zend_Form-&gt;isValid()&lt;/code&gt;, every validator on the form is passed an extra parameter called the &quot;context&quot;. The context contains all of the data submitted with the form. This lets you validate one form field based on the value of another, like a Password Confirm field that must match a Password field.&lt;/p&gt;
&lt;p&gt;One of the Zend Framework standard validators is &lt;a href=&quot;http://framework.zend.com/manual/en/zend.validate.set.html#zend.validate.set.callback&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Zend_Validate_Callback&lt;/code&gt;&lt;/a&gt;, which lets you validate the field using any function. For example, a Username field could validate with the following function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;isUsernameAvailable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$excludeId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;$excludeId&lt;/code&gt; parameter is supplied when the user has an existing account, and omitted for new user registrations. For example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Application_Model_Mapper_Users&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addValidator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Callback&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;callback&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;isUsernameAvailable&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;options&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Application_Model_Mapper_Users&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addValidator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Callback&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;callback&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;isUsernameAvailable&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;options&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;_applicantId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(In this case, you might also use &lt;a href=&quot;http://framework.zend.com/manual/en/zend.validate.set.html#zend.validate.Db&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Zend_Validate_Db_NoRecordExists&lt;/code&gt;&lt;/a&gt;, but I prefer not to leak so much model information into the form validation.)&lt;/p&gt;
&lt;h2 id=&quot;whats-the-problem&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#whats-the-problem&quot; aria-label=&quot;whats the problem permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What&apos;s the problem?&lt;/h2&gt;
&lt;p&gt;As it stands, the &lt;code class=&quot;language-text&quot;&gt;Register.php&lt;/code&gt; form above will trigger a &lt;code class=&quot;language-text&quot;&gt;Zend_Validate_Callback::INVALID_CALLBACK&lt;/code&gt; error:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An exception has been raised within the callback&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&apos;s because the form context will be appended as a parameter to the callback and interpreted as the &lt;code class=&quot;language-text&quot;&gt;$excludeId&lt;/code&gt;, fouling the database lookup.&lt;/p&gt;
&lt;p&gt;Cue the custom validator. By overriding the &lt;code class=&quot;language-text&quot;&gt;Zend_Validate_Callback-&gt;isValid()&lt;/code&gt; function, we&apos;ll drop the form context before invoking the callback function. The registration form would be updated as follows:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;php&quot;&gt;&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Application_Model_Mapper_Users&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Zend_Form_Element_Text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;username&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token variable&quot;&gt;$username&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addPrefixPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;My_Validate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;My/Validate/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;validate&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addValidator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;Callback_NoContext&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;callback&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$userMapper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;isUsernameAvailable&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&apos;options&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can setup callback validators without worrying about the default parameters of the callback function.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hosting PHP on IIS7]]></title><description><![CDATA[Running PHP sites on Internet Information Services (IIS) is easy! And with a few extra steps, you can achieve a versatile and extensible setup to avoid management headaches down the line. Follow this guide to add PHP functionality to your IIS server and avoid common mistakes.]]></description><link>https://www.wimpyprogrammer.com/hosting-php-on-iis7</link><guid isPermaLink="false">https://www.wimpyprogrammer.com/hosting-php-on-iis7</guid><pubDate>Tue, 20 Nov 2012 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;photo-credit&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@maselkowski?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Peter Masełkowski&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/php?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Running PHP sites on Internet Information Services (IIS) is easy! And with a few extra steps, you can achieve a versatile and extensible setup to avoid management headaches down the line. Follow this guide to add PHP functionality to your IIS server and avoid common mistakes.&lt;/p&gt;
&lt;h2 id=&quot;install-the-php-binaries&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#install-the-php-binaries&quot; aria-label=&quot;install the php binaries permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Install the PHP Binaries&lt;/h2&gt;
&lt;p&gt;Head over to &lt;a href=&quot;http://windows.php.net/download/&quot;&gt;http://windows.php.net/download/&lt;/a&gt; and download the Zip of your desired PHP version. For IIS, get the &quot;Non Thread Safe&quot; version. If your desired version has an Installer download, ignore it and get the Zip instead. For this guide we&apos;ll get the latest version, &lt;a href=&quot;http://windows.php.net/downloads/releases/php-5.4.8-nts-Win32-VC9-x86.zip&quot;&gt;5.4.8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Extract the Zip to a central location with a descriptive folder name, such as &lt;code class=&quot;language-text&quot;&gt;C:\Program Files (x86)\PHP\PHP_5_4_8_NTS_x86\&lt;/code&gt;. The folder name will distinguish these binaries from other versions you install later. For reasons discussed later, you should minimize spaces in the folder path.&lt;/p&gt;
&lt;h2 id=&quot;configure-php-in-iis&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#configure-php-in-iis&quot; aria-label=&quot;configure php in iis permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Configure PHP in IIS&lt;/h2&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 374px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0065f02c9272386455e04a3563231769/52dba/CGI-feature.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 25.482625482625483%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAr0lEQVQY03WPSQ7CMBAE/f/fEWWRl7EnNhEEcwMCcTweFODCVseWqlstdJBLTscYq6qSUgIAIiqllFa7/cjvlJx73zdtsx8PzCzmOa0pkTFms6lijMy8LJmISin8aRMAWOe6pkYfRErpmQffO+uMAaUkWMffJjMTWeuw911TO/Tilq6PyqK1Pp0vr4EHv+QMFhxi29bovbA7lZZ5XQ5hmqanyX8olLfD0HbdeFjf3QGBMhtzBYZJ+AAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/0065f02c9272386455e04a3563231769/e90ce/CGI-feature.avif 259w,
/static/0065f02c9272386455e04a3563231769/7002f/CGI-feature.avif 374w&quot;
              sizes=&quot;(max-width: 374px) 100vw, 374px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/0065f02c9272386455e04a3563231769/652f5/CGI-feature.webp 259w,
/static/0065f02c9272386455e04a3563231769/ad40e/CGI-feature.webp 374w&quot;
              sizes=&quot;(max-width: 374px) 100vw, 374px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/0065f02c9272386455e04a3563231769/a2ead/CGI-feature.png 259w,
/static/0065f02c9272386455e04a3563231769/52dba/CGI-feature.png 374w&quot;
            sizes=&quot;(max-width: 374px) 100vw, 374px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/0065f02c9272386455e04a3563231769/52dba/CGI-feature.png&quot;
            alt=&quot;CGI feature&quot;
            title=&quot;CGI feature&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Verify that the CGI feature is enabled in IIS. In &lt;strong&gt;Administrative Tools &gt; Server Manager&lt;/strong&gt; enable &lt;strong&gt;Roles &gt; Web Server &gt; Application Development &gt; CGI&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 223px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6a66e01ed21db46576fee838b353701f/e92b6/IIS-Feature-Delegation.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41.25560538116592%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABlUlEQVQY00WOWWvbQBSF/Yv7R/rQ19KQktdAm7SFQEs2ihPbgViWtXkk2dbm0WJto82y5Jm5xU6ghwvnvHznnsG+O0hGIpmp4RB1nSErXzgkIR0AcA4c3o8xTik/UNZTdjgFSvmAUo6j2g1qwy2QneNtY3pkExUpKeOEVFWbl01WNP2Bnuo454wxDicN3iwIfM9z27YFgDApV9FuIhofz7+O7dhNO+QV26wCABuHyspzXNz3/RHmnFPK5mg5U1CW5QCA49IlMJXRpx/XHy6u7CBwcx6dYORFQ7QJsd/sdv8/+ynBUfzW5yfVIuicrBNX+cOfMyTf6TGESQEAMam8MCGEMMaOsGNbhrnUNNVeW7KspMk2yHZzt3mWnJsn9X6ivaBA8WmY1gBUVWVdNxZIL8rjkAEhxLLW48no8f5RN5d1VeKkfhD9m2f0a6h9vxV+v1ivdmvjuCrJTBBmM1GS5A3232eXJBeE6fR1GqcpAHhRefFz/OXb37PL28+Xd+dXw+unlWnhhaaqmjYZjURxLitKu9//A5mtrn8uhUtdAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/6a66e01ed21db46576fee838b353701f/96883/IIS-Feature-Delegation.avif 223w&quot;
              sizes=&quot;(max-width: 223px) 100vw, 223px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/6a66e01ed21db46576fee838b353701f/ca0a1/IIS-Feature-Delegation.webp 223w&quot;
              sizes=&quot;(max-width: 223px) 100vw, 223px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/6a66e01ed21db46576fee838b353701f/e92b6/IIS-Feature-Delegation.png 223w&quot;
            sizes=&quot;(max-width: 223px) 100vw, 223px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/6a66e01ed21db46576fee838b353701f/e92b6/IIS-Feature-Delegation.png&quot;
            alt=&quot;IIS Feature Delegation&quot;
            title=&quot;IIS Feature Delegation&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To help bridge the gap between development and server configuration, I recommend enabling Feature Delegation. In the IIS server properties, open Feature Delegation and change all of the properties to Read/Write. Or to enable Feature Delegation for a single site, choose &quot;Custom Site Delegation&quot; from the Actions menu. With read/write Feature Delegation, most changes made through the IIS Manager will be saved in the &lt;code class=&quot;language-text&quot;&gt;&amp;lt;system.webServer&gt;&lt;/code&gt; section of the site&apos;s &lt;code class=&quot;language-text&quot;&gt;web.config&lt;/code&gt;, and changes made to the &lt;code class=&quot;language-text&quot;&gt;web.config&lt;/code&gt; will be enacted by IIS. This lets you track configuration changes in your source control and deploy them just like code updates.&lt;/p&gt;
&lt;div class=&quot;callout&quot;&gt;
&lt;p&gt;Before continuing, let&apos;s discuss IIS&apos;s FastCGI settings. Every FastCGI module used in IIS — the executable and parameters — must be added to a whitelist. If you run a module not in the whitelist, you&apos;ll get an error like:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Error Summary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;error-message&quot;&gt;HTTP Error 500.0 - Internal Server Error &amp;#x3C;handler&gt; scriptProcessor could not be found in &amp;#x3C;fastCGI&gt; application configuration&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detailed Error Information&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Module: FastCgiModule&lt;br/&gt;
Notification: ExecuteRequestHandler&lt;br/&gt;
Handler: PHP 5.4.8 NTS x86 via FastCGI&lt;br/&gt;
Error Code: 0x80070585&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;This whitelist improves security but complicates Feature Delegation. If you modify a handler in your &lt;code class=&quot;language-text&quot;&gt;web.config&lt;/code&gt; (like changing the PHP version), you must also update the IIS whitelist before the new handler will work. Every FastCGI module in the whitelist has its own configuration, including a distinct set of environment variables. To allow every site to have its own configuration, we&apos;ll create a separate entry for each one. This is more tedious than having one entry per PHP version, but is necessary to keep independent settings.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 151px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fd8c81c7f95bd2d9c8c401b6e9581346/29fe9/IIS-Handler-Mappings.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 109.27152317880795%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAACXBIWXMAAAsTAAALEwEAmpwYAAADSUlEQVQ4y41U204bVxT156RP/ALfkTw0zWPzwmuJKpVGAgmwFKpITUoVVaCgEF8DJrYglIJtIHHsgD2ewfexxzae+/1+LpWxY0iUVmydmZHW2WvWPmevcwIY43pH2U7TlgsgRK4HAES3HIEhmVETaVozPYwxQvibeb4PPg/4BXkShmX3Bxy+dQSu1BCAAGPcLOz/OvO9JCsjcPLmeH4xuLIUXHk8v7ixGZ7gY2WE0IAhTuJPVx/dtV1/Mg0hxBhXqtUfHjyYm5v78eHD2Z9mb5CvPq6jlQ+XI69/D67vhbItjMDopyMyQZTv3Pluenp6amrq7r17E3xM9l0tH72f2Hz86lR8dUD6njepCGMsCOJyMLi0tLywsBCNxa6VEYKGYSKIuUHf8ywMfd+xEARf7Q1CCEIAARiJjTdMEdi3ybfx2FbiTSS5fxCNbcVDm6WLmq4bEF2LM+3m+9PjjbU1VjGulQGAmq4PLgemaQiCIMuKqsiSJKmahm4oA99TVEUUBB/AL1v13538vymExn1GCN5MhhAhhG5lknFhw4DDB8LPCKx1uGqbq3W4BsMxfaHd45s9sc7wlTbX6vKBkYKuG+dEvUicfyqWSmR9VIJh2mc1jjdwTwY1zg/nmPhHJpUhLzqK7OD8xeWYbBiG62G+OiPQq6oOfd+9srpTaoqSjXsyepm/vB9q/ZJkQqkC2ZY0H5/V2DHZtGyGaafCs9n9Z70+CwAYkT81BNbEVUFZIGYWP/x8VCXSBbrcUXgH56vseM2u69J0+6xYpyp0t9cbgabl5GtCV8W0DA47xZNGpdzhy7Tc5EFXw7kKGwCeq6gKuOqebZuyLE+sa1pOrio2RUx0TJoHjIrJrkn13YYAaRm/p9iAyrN7u8mDo8w/7/aKFBmPbe+8iUUj4ePcme14p1WJGrh/hXd/exFZDyefv07MP1nbTldoDR+XBwEIgCxLmm5IQ/f4tm1TRKnRbJmmZVrOMSUWaCtNsFlKzNWULCVkSKHQdio8zpJc4GtHoWuv6KadLgsvt9Lzz8NP/oz8sZFYjWefre+uvIjslaQMyU8chiZXBxweoOGaXc8/IXqZYvfvfCuSOgntHKU+1HcOz9ej79LE4CPV/xeiUahOsNkebwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/fd8c81c7f95bd2d9c8c401b6e9581346/188ec/IIS-Handler-Mappings.avif 151w&quot;
              sizes=&quot;(max-width: 151px) 100vw, 151px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/fd8c81c7f95bd2d9c8c401b6e9581346/8d139/IIS-Handler-Mappings.webp 151w&quot;
              sizes=&quot;(max-width: 151px) 100vw, 151px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/fd8c81c7f95bd2d9c8c401b6e9581346/29fe9/IIS-Handler-Mappings.png 151w&quot;
            sizes=&quot;(max-width: 151px) 100vw, 151px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/fd8c81c7f95bd2d9c8c401b6e9581346/29fe9/IIS-Handler-Mappings.png&quot;
            alt=&quot;IIS Handler Mappings&quot;
            title=&quot;IIS Handler Mappings&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In the properties of the IIS site/application/folder/virtual directory for which you want to enable PHP scripts, open Handler Mappings. In the Actions menu, choose &quot;Add Module Mapping&quot;. Enter the following settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Request path:&lt;/strong&gt; *.php&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Module:&lt;/strong&gt; FastCgiModule&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Executable:&lt;/strong&gt; &lt;em&gt;(Path to php-cgi.exe)&lt;/em&gt;|my.app=&lt;em&gt;(Name for application)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;em&gt;(Descriptive name of PHP version)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The executable is the most complex part, so let&apos;s break it down.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First specify the absolute path to php-cgi.exe that you extracted earlier from the Zip. If the path contains spaces, enclose it in quotes. But these quotes are lost when writing to the web.config and must be constantly replaced. To avoid headaches later, I recommend using the &lt;a href=&quot;http://en.wikipedia.org/wiki/8.3_filename#How_to_convert_a_long_filename_to_a_short_filename&quot;&gt;8.3 filename&lt;/a&gt; for any folders with spaces.&lt;/li&gt;
&lt;li&gt;Next add a vertical bar (&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;) to separate the executable from its arguments.&lt;/li&gt;
&lt;li&gt;Finally supply a custom parameter that will distinguish this handler in the list of FastCGI modules. The name you assign is for your reference only.&lt;/li&gt;
&lt;li&gt;Altogether, the executable looks like &lt;code class=&quot;language-text&quot;&gt;C:\PROGRA~2\PHP\PHP_5_4_8_NTS_x86\php-cgi.exe|my.app=Blog&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Open &quot;Request Restrictions&quot; and set the following options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Invoke handler only if request is mapped to: File or folder&lt;/li&gt;
&lt;li&gt;Specify the verbs to be handled: GET,POST&lt;/li&gt;
&lt;li&gt;Specify the access required by the handler: Script&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 484px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/ff42b/IIS-Add-Module-Mapping.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.83783783783784%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABjUlEQVQY002PS2+bQBSF+f/qor+gu6hNm0WqprLdOE0NJuJh88rDbuMAJrWBYTzDPGAYR4UIp4ry6dNZXN3FOcrZxDnT3NMf+peBdqoGwxv8PUDffHxiZ0fT5KP+99jYntj5V6cYBPDiBqorpqqe+v7d9NOx0kjZ7PeI1EXJARGA7gGRgMqcyAyLrGzSQ+aH447vcfWEuMRUPBZMuV2VQzXiFDNKCcYUoxLtCN5hWBR5VuQZhgBBACEoEUw3G5ClaAe7rmVVo1wajx8+B0kc+r4/m819z3NdN7i+njmOYRi2bbueF0VxvF5HUbxYLsMwZKzqug6SWum6rm1bzjnuKdkLfQmMMSpLXFX961vats+C1IoUDaVcNE0/XsrmABWSCFkKSYWsa8E5Y5y/Shmv6yrJkPLvqREV763/W1X8bgO8Pytneb/YgizP4ujh9+Iu3W5Anq7j0HXmSfxwn6SKbgeq6WuWr5oHLX9iuCPNHk7MwcQ81+eXV/OfU2usWWPNvNDtc9Uc/TLGmjWaus+81KijNV5MQQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/e90ce/IIS-Add-Module-Mapping.avif 259w,
/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/135f4/IIS-Add-Module-Mapping.avif 484w&quot;
              sizes=&quot;(max-width: 484px) 100vw, 484px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/652f5/IIS-Add-Module-Mapping.webp 259w,
/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/bdae1/IIS-Add-Module-Mapping.webp 484w&quot;
              sizes=&quot;(max-width: 484px) 100vw, 484px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/a2ead/IIS-Add-Module-Mapping.png 259w,
/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/ff42b/IIS-Add-Module-Mapping.png 484w&quot;
            sizes=&quot;(max-width: 484px) 100vw, 484px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/1d0f4f3f45b12fa77f4f9fa371e99dbb/ff42b/IIS-Add-Module-Mapping.png&quot;
            alt=&quot;IIS Add Module Mapping&quot;
            title=&quot;IIS Add Module Mapping&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Choose Yes when prompted to add the module to the FastCGI whitelist.&lt;/p&gt;
&lt;h2 id=&quot;customize-your-php-ini&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#customize-your-php-ini&quot; aria-label=&quot;customize your php ini permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Customize your PHP INI&lt;/h2&gt;
&lt;p&gt;Your site&apos;s PHP configuration needs updating to work on IIS. If you&apos;re starting a new application, you&apos;ll find sample php.ini files in the Zip you downloaded earlier. Copy the sample INI to your application files and rename it to &lt;code class=&quot;language-text&quot;&gt;php.ini&lt;/code&gt;. Verify the following settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;cgi.fix_pathinfo = 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;cgi.force_redirect = 0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;extension_dir = &quot;ext&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fastcgi.impersonate = 0&lt;/code&gt; - This is contrary to the Microsoft guides — I&apos;ll explain in &lt;a href=&quot;#permissions&quot;&gt;the Permissions section&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;configure-fastcgi-module&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#configure-fastcgi-module&quot; aria-label=&quot;configure fastcgi module permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Configure FastCGI Module&lt;/h2&gt;
&lt;div class=&quot;image-group screenshot&quot;&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 149px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5f2e68377db1b9e33536521289470d6e/d371d/IIS-FastCGI-Settings.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 112.08053691275168%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAACXBIWXMAAAsTAAALEwEAmpwYAAADZUlEQVQ4y31T647bRBT2axSJPgB9gD4EL0B/tYXCAyBUQCJC/KMSlGvLn6Vd2t2VSguilM1qN5tus5dmE2fjJJuk8SWJN44d3+1kbccez3hQMiHNriqOjmbsT/OdM/rONxTGuFCTl/8WxgABEAfjCMToXEYAjqOYZBjBOU5hjEdeqJoBRAmeRvKmXIw5SM3+k8mBZrX85PHvpApByOoHQYsTWL7dfMXJA3WOU+QLIQQi7/DRrTupG3ChHEIIY8wwlesffPTxJzevvf/hjz/dnePUrPbIaJae/nH/m1/vfGeHhDvBIZyU2tvbv3LlvVTqi+vXrqZSqUXyZBsZrd0H7648un/rmbS0fjRlT/rD6aGX+fzbFy++c+nShQtvffrZ56/JRI4Eel36rsjTLSUcWKM5mQQAwLYdx3WHrnt66s1xyjINlm2KPYmmG6ZpSL1Os9k69bw5mdzfMg2B5/LFo3Ewfi2YKku5nczWzu52Op3NbuZeHqbTGY7nLMtaJKtK/7hazeb2At8/r3aCzswySWaCLSBT8c6CFJnTbCWZnDPFojvOBIX/N0AMIxBHAEQAgDgBMYohmiIxQglF2vhBcCLJiuqK0sC0bMJ0vZBu9Opds96xmpxSqR6UKuXSFKm19Sonz0yi6rqiDVvHD0Wx3hEHBNRtn+87bohVD9XkUrnwbZVe6suy4WE7wPWORq6d2M4IRU5l47LdW3OGMYQAY2w4fl20TB+XB+JN5uo99vuywgxsr2dDeZjUBJ10TkzTqh/XVleWtzY3+rJCXDkhdx1lhEULNgZKnlWelGTmxJJsJDm4KujzV4XCMPKCaByCGAAiq+74lY5zMsTSKe67UDDChnzKa0FviLs2ZnidMg29Ua9rumYYpii0uLZoGla/3/d9z3CDI8EVdLj+gtlvaNkCm6W76b3KVrHbsXGJ1Shd03Z3soVC/nluv91qHOQPHjxcW1tda7GsNYpo3mUHcOug+dvT3XuPtzfy/J/bh3/lWN7EdEubjIo8nXmMhsMwAuTaRcFtqDBT6maK7c2i8JwZ7B+rdMd/ZeAiOxVsaiyyE7Nh9N+oMoyab4c/r25+dXv5h5X128uZL7/+Zekf5rALXlT61BtNSASLYsj3DF6yeMlqy05bdjqywzTanGRxPUvS3H8B3r+qFTowX6YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source srcset=&quot;/static/5f2e68377db1b9e33536521289470d6e/183f7/IIS-FastCGI-Settings.avif 149w&quot; sizes=&quot;(max-width: 149px) 100vw, 149px&quot; type=&quot;image/avif&quot;&gt;&lt;source srcset=&quot;/static/5f2e68377db1b9e33536521289470d6e/1e205/IIS-FastCGI-Settings.webp 149w&quot; sizes=&quot;(max-width: 149px) 100vw, 149px&quot; type=&quot;image/webp&quot;&gt;
          &lt;source srcset=&quot;/static/5f2e68377db1b9e33536521289470d6e/d371d/IIS-FastCGI-Settings.png 149w&quot; sizes=&quot;(max-width: 149px) 100vw, 149px&quot; type=&quot;image/png&quot;&gt;
          &lt;img class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5f2e68377db1b9e33536521289470d6e/d371d/IIS-FastCGI-Settings.png&quot; alt=&quot;IIS FastCGI Settings&quot; title=&quot;IIS FastCGI Settings&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 151px; &quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/95389487e31b90b4de38f7a6d447d91b/29fe9/IIS-Configuration-Editor.png&quot; style=&quot;display: block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom: 60.9271523178808%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACUUlEQVQoz1XQSW/TUBQF4PxFfkk3XbJnEAsQAimrSBQELYW2ahKXppnazJA6aeM4qR3Ps5/nuHh6fihNkeDoLs93FreQJClC+UpwJwsgg1Cz7nXrXgWhpAeaFQraWtDXCCEIIcxzmP+XQrrBaE7ZWJu/nGojEuyfs4d1drowOzd6pSP9JEyEUJLBHKEU5nEK0+zxCn4QrkRDNlzZcHjFEhQwozVGthTT4VXLDyP0kCRNXM+L4wT9kwIrgymt8yChlGCIkwN8MZyQS9HlzJgU3TlrbHs0J7x4/bbdvUQI5RA+Yl6xV6rvxEi2o/lyxYnKkuY4PbAjJDsxJVrb3oykXr5/s1s/fVrBw9/2ZiLPN5gUPG2NOD2akhTJsAR5RymBFiDWiJc82OIRPqlfNV9h4ye7z1Ru9IBhgVNsUvKlAPEWvKaV7pybzllajyUfUXq8+IvzPCMppr80b893xic7j5hXnD6hMjZiLEhIIe8hwUecm9NGttCSLU7iyA+CKIk9d52EUhQI28ECJ5ufjponzfG7vWqxdPCh0il9bZU+fi8eVIufGze0hhByTa1+UcMq1fIZ1mgPWo22dx8/PEx1mrg4WNq9hd0ar76cDbEB2yO0LmnWcZngLJjGjuuufZdnWdOyJVFUFTlOsw2mRWvIhiPG38f6e+Ve8Vvt+fuj0mGry0a4EhO8CxT+6LR6fHxSv6hdVCvVH5V6u39WLluuV9BM73Iidmdq49eqNrrDevPq1RzrzHqkcXUrM7IDs8QEwDAMjmXw62vTAoZhAgDSLPsDaJF42jjguw4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source srcset=&quot;/static/95389487e31b90b4de38f7a6d447d91b/188ec/IIS-Configuration-Editor.avif 151w&quot; sizes=&quot;(max-width: 151px) 100vw, 151px&quot; type=&quot;image/avif&quot;&gt;&lt;source srcset=&quot;/static/95389487e31b90b4de38f7a6d447d91b/8d139/IIS-Configuration-Editor.webp 151w&quot; sizes=&quot;(max-width: 151px) 100vw, 151px&quot; type=&quot;image/webp&quot;&gt;
          &lt;source srcset=&quot;/static/95389487e31b90b4de38f7a6d447d91b/29fe9/IIS-Configuration-Editor.png 151w&quot; sizes=&quot;(max-width: 151px) 100vw, 151px&quot; type=&quot;image/png&quot;&gt;
          &lt;img class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/95389487e31b90b4de38f7a6d447d91b/29fe9/IIS-Configuration-Editor.png&quot; alt=&quot;IIS Configuration Editor&quot; title=&quot;IIS Configuration Editor&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Next we need to configure the newly-created FastCGI module. There are two ways to change these settings in the IIS Manager, both in the server properties. The first method is FastCGI Settings, but this doesn&apos;t let you edit the executable path if you upgrade PHP. So I recommend using the Configuration Editor. Choose a section of &lt;code class=&quot;language-text&quot;&gt;system.webServer/fastCgi&lt;/code&gt; and edit the collection. Use the &lt;code class=&quot;language-text&quot;&gt;my.app&lt;/code&gt; argument to find the new FastCGI entry.&lt;/p&gt;
&lt;div class=&quot;image-group screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 149px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5f2e68377db1b9e33536521289470d6e/d371d/IIS-FastCGI-Settings.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 112.08053691275168%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAIAAABPIytRAAAACXBIWXMAAAsTAAALEwEAmpwYAAADZUlEQVQ4y31T647bRBT2axSJPgB9gD4EL0B/tYXCAyBUQCJC/KMSlGvLn6Vd2t2VSguilM1qN5tus5dmE2fjJJuk8SWJN44d3+1kbccez3hQMiHNriqOjmbsT/OdM/rONxTGuFCTl/8WxgABEAfjCMToXEYAjqOYZBjBOU5hjEdeqJoBRAmeRvKmXIw5SM3+k8mBZrX85PHvpApByOoHQYsTWL7dfMXJA3WOU+QLIQQi7/DRrTupG3ChHEIIY8wwlesffPTxJzevvf/hjz/dnePUrPbIaJae/nH/m1/vfGeHhDvBIZyU2tvbv3LlvVTqi+vXrqZSqUXyZBsZrd0H7648un/rmbS0fjRlT/rD6aGX+fzbFy++c+nShQtvffrZ56/JRI4Eel36rsjTLSUcWKM5mQQAwLYdx3WHrnt66s1xyjINlm2KPYmmG6ZpSL1Os9k69bw5mdzfMg2B5/LFo3Ewfi2YKku5nczWzu52Op3NbuZeHqbTGY7nLMtaJKtK/7hazeb2At8/r3aCzswySWaCLSBT8c6CFJnTbCWZnDPFojvOBIX/N0AMIxBHAEQAgDgBMYohmiIxQglF2vhBcCLJiuqK0sC0bMJ0vZBu9Opds96xmpxSqR6UKuXSFKm19Sonz0yi6rqiDVvHD0Wx3hEHBNRtn+87bohVD9XkUrnwbZVe6suy4WE7wPWORq6d2M4IRU5l47LdW3OGMYQAY2w4fl20TB+XB+JN5uo99vuywgxsr2dDeZjUBJ10TkzTqh/XVleWtzY3+rJCXDkhdx1lhEULNgZKnlWelGTmxJJsJDm4KujzV4XCMPKCaByCGAAiq+74lY5zMsTSKe67UDDChnzKa0FviLs2ZnidMg29Ua9rumYYpii0uLZoGla/3/d9z3CDI8EVdLj+gtlvaNkCm6W76b3KVrHbsXGJ1Shd03Z3soVC/nluv91qHOQPHjxcW1tda7GsNYpo3mUHcOug+dvT3XuPtzfy/J/bh3/lWN7EdEubjIo8nXmMhsMwAuTaRcFtqDBT6maK7c2i8JwZ7B+rdMd/ZeAiOxVsaiyyE7Nh9N+oMoyab4c/r25+dXv5h5X128uZL7/+Zekf5rALXlT61BtNSASLYsj3DF6yeMlqy05bdjqywzTanGRxPUvS3H8B3r+qFTowX6YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/5f2e68377db1b9e33536521289470d6e/183f7/IIS-FastCGI-Settings.avif 149w&quot;
              sizes=&quot;(max-width: 149px) 100vw, 149px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/5f2e68377db1b9e33536521289470d6e/1e205/IIS-FastCGI-Settings.webp 149w&quot;
              sizes=&quot;(max-width: 149px) 100vw, 149px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/5f2e68377db1b9e33536521289470d6e/d371d/IIS-FastCGI-Settings.png 149w&quot;
            sizes=&quot;(max-width: 149px) 100vw, 149px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/5f2e68377db1b9e33536521289470d6e/d371d/IIS-FastCGI-Settings.png&quot;
            alt=&quot;IIS FastCGI Settings&quot;
            title=&quot;IIS FastCGI Settings&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 151px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/95389487e31b90b4de38f7a6d447d91b/29fe9/IIS-Configuration-Editor.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.9271523178808%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACUUlEQVQoz1XQSW/TUBQF4PxFfkk3XbJnEAsQAimrSBQELYW2ahKXppnazJA6aeM4qR3Ps5/nuHh6fihNkeDoLs93FreQJClC+UpwJwsgg1Cz7nXrXgWhpAeaFQraWtDXCCEIIcxzmP+XQrrBaE7ZWJu/nGojEuyfs4d1drowOzd6pSP9JEyEUJLBHKEU5nEK0+zxCn4QrkRDNlzZcHjFEhQwozVGthTT4VXLDyP0kCRNXM+L4wT9kwIrgymt8yChlGCIkwN8MZyQS9HlzJgU3TlrbHs0J7x4/bbdvUQI5RA+Yl6xV6rvxEi2o/lyxYnKkuY4PbAjJDsxJVrb3oykXr5/s1s/fVrBw9/2ZiLPN5gUPG2NOD2akhTJsAR5RymBFiDWiJc82OIRPqlfNV9h4ye7z1Ru9IBhgVNsUvKlAPEWvKaV7pybzllajyUfUXq8+IvzPCMppr80b893xic7j5hXnD6hMjZiLEhIIe8hwUecm9NGttCSLU7iyA+CKIk9d52EUhQI28ECJ5ufjponzfG7vWqxdPCh0il9bZU+fi8eVIufGze0hhByTa1+UcMq1fIZ1mgPWo22dx8/PEx1mrg4WNq9hd0ar76cDbEB2yO0LmnWcZngLJjGjuuufZdnWdOyJVFUFTlOsw2mRWvIhiPG38f6e+Ve8Vvt+fuj0mGry0a4EhO8CxT+6LR6fHxSv6hdVCvVH5V6u39WLluuV9BM73Iidmdq49eqNrrDevPq1RzrzHqkcXUrM7IDs8QEwDAMjmXw62vTAoZhAgDSLPsDaJF42jjguw4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/95389487e31b90b4de38f7a6d447d91b/188ec/IIS-Configuration-Editor.avif 151w&quot;
              sizes=&quot;(max-width: 151px) 100vw, 151px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/95389487e31b90b4de38f7a6d447d91b/8d139/IIS-Configuration-Editor.webp 151w&quot;
              sizes=&quot;(max-width: 151px) 100vw, 151px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/95389487e31b90b4de38f7a6d447d91b/29fe9/IIS-Configuration-Editor.png 151w&quot;
            sizes=&quot;(max-width: 151px) 100vw, 151px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/95389487e31b90b4de38f7a6d447d91b/29fe9/IIS-Configuration-Editor.png&quot;
            alt=&quot;IIS Configuration Editor&quot;
            title=&quot;IIS Configuration Editor&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Next we need to configure the newly-created FastCGI module. There are two ways to change these settings in the IIS Manager, both in the server properties. The first method is FastCGI Settings, but this doesn&apos;t let you edit the executable path if you upgrade PHP. So I recommend using the Configuration Editor. Choose a section of &lt;code class=&quot;language-text&quot;&gt;system.webServer/fastCgi&lt;/code&gt; and edit the collection. Use the &lt;code class=&quot;language-text&quot;&gt;my.app&lt;/code&gt; argument to find the new FastCGI entry.&lt;/p&gt;
&lt;div class=&quot;screenshot&quot;&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 655px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/11161c140e9d5da2e08e04407354925d/ae6b7/IIS-FastCGI-Configuration.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 44.78764478764479%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAABm0lEQVQoz2WQbW+bMBSF+f9/ZVqzTd1SLVPXJLzYZqSlIWwZ4GBjg50EWEoEmLRhSlJVmnb06OpI957z4Wp3zvLO/jW9j8Zu/Nn0B2Pv6vbhix0P5+WnmXxn0feQD36IM3LgyGs3H87L4by48QrtZjQZj3UIHMNEEM4gnAHgQOgg+wGiewBnhmnrOrKAYwFHN9BkCiZTYJi2YdpaFCeb9ZoQ8ui6Qgie8izNpJScMc65XEuWJI+uyxir63otJSUxpZQxtvA8zV+GGK9iQiOMl8vfYRgFQRgEASUJY5xxfiriaZZl27woy/LPSbs8L4QQ2tfR949XH76Nbk3dsgwLmOACAsiG9mU6toMAghaEFrxsoQURQJof0p++H+FVtd+3SjVt+0rTKtVttzmJCaG0qvZN29TNmfrVaCu+kVIkjGdCKqX6f6VUG8ekKMvj8dj/J2254gvPYzyt67rv++Mb5+unqlos/Oz0yDRhTAiRpimhCWNss9lqIRVhGGKM87xQXfeWfzmHd0+7COPD83OrVKuU6jrVdRffHQ5/AY/p2ru2tLxgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/11161c140e9d5da2e08e04407354925d/e90ce/IIS-FastCGI-Configuration.avif 259w,
/static/11161c140e9d5da2e08e04407354925d/0d37b/IIS-FastCGI-Configuration.avif 518w,
/static/11161c140e9d5da2e08e04407354925d/3ab81/IIS-FastCGI-Configuration.avif 655w&quot;
              sizes=&quot;(max-width: 655px) 100vw, 655px&quot;
              type=&quot;image/avif&quot;
            /&gt;&lt;source
              srcset=&quot;/static/11161c140e9d5da2e08e04407354925d/652f5/IIS-FastCGI-Configuration.webp 259w,
/static/11161c140e9d5da2e08e04407354925d/c29d2/IIS-FastCGI-Configuration.webp 518w,
/static/11161c140e9d5da2e08e04407354925d/09ab1/IIS-FastCGI-Configuration.webp 655w&quot;
              sizes=&quot;(max-width: 655px) 100vw, 655px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/11161c140e9d5da2e08e04407354925d/a2ead/IIS-FastCGI-Configuration.png 259w,
/static/11161c140e9d5da2e08e04407354925d/6b9fd/IIS-FastCGI-Configuration.png 518w,
/static/11161c140e9d5da2e08e04407354925d/ae6b7/IIS-FastCGI-Configuration.png 655w&quot;
            sizes=&quot;(max-width: 655px) 100vw, 655px&quot;
            type=&quot;image/png&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/11161c140e9d5da2e08e04407354925d/ae6b7/IIS-FastCGI-Configuration.png&quot;
            alt=&quot;IIS FastCGI Configuration&quot;
            title=&quot;IIS FastCGI Configuration&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Set &lt;code class=&quot;language-text&quot;&gt;instanceMaxRequests&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;10000&lt;/code&gt; &lt;a href=&quot;http://www.iis.net/learn/application-frameworks/install-and-configure-php-applications-on-iis/using-fastcgi-to-host-php-applications-on-iis#BestPractices&quot;&gt;(Per Microsoft)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;code class=&quot;language-text&quot;&gt;PHP_FCGI_MAX_REQUESTS&lt;/code&gt; environment variable with a value of &lt;code class=&quot;language-text&quot;&gt;10000&lt;/code&gt; &lt;a href=&quot;http://www.iis.net/learn/application-frameworks/install-and-configure-php-applications-on-iis/using-fastcgi-to-host-php-applications-on-iis#BestPractices&quot;&gt;(Also per Microsoft)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;code class=&quot;language-text&quot;&gt;PHPRC&lt;/code&gt; environment variable with the absolute path of the directory containing &lt;code class=&quot;language-text&quot;&gt;php.ini&lt;/code&gt;. Ex. &lt;code class=&quot;language-text&quot;&gt;C:\inetpub\wwwroot\Blog\public&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Any other site-specific variables should be added here, such as the &lt;code class=&quot;language-text&quot;&gt;APPLICATION_ENV&lt;/code&gt; environment variable used by the &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;installing-pear&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#installing-pear&quot; aria-label=&quot;installing pear permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Installing PEAR&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://pear.php.net/&quot;&gt;PEAR&lt;/a&gt; is a library of PHP extensions. If you&apos;re not using it now... don&apos;t start! Explore better options like &lt;a href=&quot;http://getcomposer.org/&quot;&gt;Composer&lt;/a&gt; or &lt;a href=&quot;http://pear2.php.net/&quot;&gt;Pyrus (PEAR2)&lt;/a&gt;, and &lt;a href=&quot;#permissions&quot;&gt;skip to the next section&lt;/a&gt;. But if you&apos;re supporting some legacy code that relies on PEAR, we&apos;ll install it now.&lt;/p&gt;
&lt;p&gt;Download &lt;a href=&quot;http://pear.php.net/go-pear.phar&quot;&gt;http://pear.php.net/go-pear.phar&lt;/a&gt; to your PHP installation directory, ex. &lt;code class=&quot;language-text&quot;&gt;C:\Program Files (x86)\PHP\PHP_5_4_8_NTS_x86\go-pear.phar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We intentionally haven&apos;t added or changed any environment variables on the server, namely the &lt;code class=&quot;language-text&quot;&gt;PATH&lt;/code&gt; variable. This would tie our server to a single version of PHP and we want the flexibility to run several. Instead we&apos;ll use Windows batch scripts: any changes to the environment variable only occur in the scope of the script. Create the following batch script in your PHP installation directory.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;batch&quot;&gt;&lt;pre class=&quot;language-batch&quot;&gt;&lt;code class=&quot;language-batch&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt; OFF&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;PHPFramework&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;%CD%&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;REM Append our PHP version to the PATH variable.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;%PATH%&lt;/span&gt;;&lt;span class=&quot;token variable&quot;&gt;%PHPFramework%&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;REM When using PEAR from outside of its home directory, we need to specify PHP_PEAR_PHP_BIN as an absolute path to php.exe.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;REM Use the same PHP installation that is specified in the PATH variable.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;PHP_PEAR_PHP_BIN&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;%PHPFramework%&lt;/span&gt;\php.exe&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;REM Output the versions that will be used by this script.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;REM After each &quot;CALL&quot; command we need to reset ECHO. The other batch files may reenable it.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; php &lt;span class=&quot;token parameter attr-name&quot;&gt;-v&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt; OFF&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt;;&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; pear version&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt; OFF&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt;;&lt;/span&gt;

&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt; Some PEAR package installers will verify that the prerequisite components are enabled in the PHP INI file. Because the PHP INI files on this server are per-site, not per-PHP version, these checks will fail. Verify that the prerequisites are enabled in the PHP INI of the site that will use the component, and then force the installation with &lt;span class=&quot;token string&quot;&gt;&quot;pear install -f ...&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;ECHO&lt;/span&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;REM Launch a shell so the user can issue commands.&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CMD&lt;/span&gt; &lt;span class=&quot;token parameter attr-name&quot;&gt;/T&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;token parameter attr-name&quot;&gt;/Q&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Launch this batch script and run &lt;code class=&quot;language-text&quot;&gt;php go-pear.phar&lt;/code&gt;. When prompted to install PEAR system-wide or locally, enter &lt;code class=&quot;language-text&quot;&gt;local&lt;/code&gt; and confirm. All of the installation paths should auto-detect correctly, so press Enter to continue. When the installation completes, you can use the &lt;code class=&quot;language-text&quot;&gt;pear&lt;/code&gt; command to install the libraries you need. In your application&apos;s PHP INI, update the &lt;code class=&quot;language-text&quot;&gt;include_path&lt;/code&gt; to add the absolute path to the PEAR directory, ex. &lt;code class=&quot;language-text&quot;&gt;C:\Program Files (x86)\PHP\PHP_5_4_8_NTS_x86\PEAR&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;permissions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#permissions&quot; aria-label=&quot;permissions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Permissions&lt;/h2&gt;
&lt;p&gt;Lastly, let&apos;s configure the file permissions for your application. Your application may have special requirements, but these settings should get you started.&lt;/p&gt;
&lt;p&gt;For some reason, PHP and Microsoft prescribe &lt;code class=&quot;language-text&quot;&gt;fastcgi.impersonate&lt;/code&gt;. I&apos;ve asked around (&lt;a href=&quot;http://forums.iis.net/post/1986868.aspx&quot;&gt;1&lt;/a&gt;|&lt;a href=&quot;http://serverfault.com/q/282806&quot;&gt;2&lt;/a&gt;) for the rationale but can&apos;t get any answers. This seems to be a recommendation for IIS6, but thanks to improved security in IIS7 I advise disabling impersonation.&lt;/p&gt;
&lt;p&gt;Here are the settings that I recommend:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a dedicated IIS application pool for your site. In the Advanced Settings, choose an Identity of &lt;strong&gt;Built-in account: ApplicationPoolIdentity&lt;/strong&gt;. This option, introduced in IIS7, will create a new user account named &lt;strong&gt;IIS APPPOOL\&lt;em&gt;[Application pool name]&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the IIS Authentication settings for your site, choose an Anonymous user identity of &lt;strong&gt;IUSR&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Update the NTFS permissions on your site&apos;s web directory to Grant read access and Deny write access to &lt;strong&gt;IUSR&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Update the NTFS permissions on your application directory and anything in your &lt;code class=&quot;language-text&quot;&gt;include_path&lt;/code&gt; to Grant read &amp;#x26; list access to &lt;strong&gt;IIS APPPOOL\&lt;em&gt;[Application pool name]&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Update the NTFS permissions for any path where your application will write (such as &lt;code class=&quot;language-text&quot;&gt;upload_tmp_dir&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;session.save_path&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;error_log&lt;/code&gt;) to Grant modify access to &lt;strong&gt;IIS APPPOOL\&lt;em&gt;[Application pool name]&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations, you&apos;ve added PHP support to IIS! With this setup, you can host multiple PHP versions on the same server, customize environment variables and PHP settings per site, manage multiple copies of PEAR, and sandbox your sites with separate user accounts. Happy coding!&lt;/p&gt;</content:encoded></item></channel></rss>