<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Montmere</title>
	<atom:link href="http://blog.montmere.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.montmere.com</link>
	<description>The goings-on of Montmere Limited</description>
	<lastBuildDate>Wed, 07 Dec 2011 18:40:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Convert an 8 character string to a 64-bit integer</title>
		<link>http://blog.montmere.com/2011/12/06/convert-an-8-character-string-to-a-64-bit-integer/</link>
		<comments>http://blog.montmere.com/2011/12/06/convert-an-8-character-string-to-a-64-bit-integer/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 20:27:08 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[MSSQL]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=49</guid>
		<description><![CDATA[You can store an 8 character (10 byte) string as an integer in SQL Server. Note that any more than 8 characters will get truncated. I mean, you probably shouldn&#8217;t ever do it, but it works. Here&#8217;s how: Convert String to Int SELECT CONVERT(BIGINT, CONVERT(VARBINARY, 'ABC123DE')) yields: 4702394839502898245 Convert Int back to string SELECT CONVERT(VARCHAR(8), [...]]]></description>
			<content:encoded><![CDATA[<p>You can store an 8 character (10 byte) string as an integer in SQL Server. Note that any more than 8 characters will get truncated.</p>
<p>I mean, you probably shouldn&#8217;t ever do it, but it works. Here&#8217;s how:</p>
<p><strong>Convert String to Int</strong></p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>SELECT</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>BIGINT</span><span style='color:#808030; '>,</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span>VARBINARY<span style='color:#808030; '>,</span> <span style='color:#0000e6; '>'ABC123DE'</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span>
</pre>
<p>yields:</p>
<pre>4702394839502898245</pre>
<p><strong>Convert Int back to string</strong></p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>SELECT</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>VARCHAR</span><span style='color:#808030; '>(</span><span style='color:#008c00; '>8</span><span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span>VARBINARY<span style='color:#808030; '>,</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>BIGINT</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>4702394839502898245</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span>
</pre>
<p>Yields:</p>
<pre>ABC123DE</pre>
<p><strong>Convert String to Int &#8211; then back to a String again:</strong></p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>SELECT</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>VARCHAR</span><span style='color:#808030; '>(</span><span style='color:#008c00; '>8</span><span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span>VARBINARY<span style='color:#808030; '>,</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>BIGINT</span><span style='color:#808030; '>,</span> <span style='color:#bb7977; font-weight:bold; '>CONVERT</span><span style='color:#808030; '>(</span>VARBINARY<span style='color:#808030; '>,</span> <span style='color:#0000e6; '>'ABC123DE'</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/12/06/convert-an-8-character-string-to-a-64-bit-integer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PSR-0 Final Proposal</title>
		<link>http://blog.montmere.com/2011/09/21/psr-0-final-proposal/</link>
		<comments>http://blog.montmere.com/2011/09/21/psr-0-final-proposal/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 05:02:20 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=48</guid>
		<description><![CDATA[Somehow the PSR-0 Final Proposal disappeared from groups.google.com. I&#8217;m putting it here since no one seems to have been responsible enough to post it elsewhere. The following describes the mandatory requirements that must be adhered to for autoloader interoperability. Mandatory: A fully-qualified namespace and class must have the following structure \\(\)* Each namespace must have [...]]]></description>
			<content:encoded><![CDATA[<p>Somehow the PSR-0 Final Proposal disappeared from groups.google.com. I&#8217;m putting it here since no one seems to have been responsible enough to post it elsewhere.<br />
The following describes the mandatory requirements that must be adhered to for autoloader interoperability.</p>
<h1>Mandatory:</h1>
<ul>
<li>A fully-qualified namespace and class must have the following structure \<Vendor Name>\(<Namespace>\)*<Class Name></li>
<li>Each namespace must have a top-level namespace (&#8220;Vendor Name&#8221;).</li>
<li>Each namespace can have as many sub-namespaces as it wishes.</li>
<li>Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.</li>
<li>Each &#8220;_&#8221; character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR. The &#8220;_&#8221; character has no special meaning in the namespace.</li>
<li>The fully-qualified namespace and class is suffixed with &#8220;.php&#8221; when loading from the file system.</li>
<li>Alphabetic characters in vendor names, namespaces, and class names may be of any combination of lower case and upper case.</li>
</ul>
<h1>Examples:</h1>
<p><code>\Doctrine\Common\IsolatedClassLoader =&gt; /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php</p>
<p>\Symfony\Core\Request =&gt; /path/to/project/lib/vendor/Symfony/Core/Request.php</p>
<p>\Zend\Acl =&gt; /path/to/project/lib/vendor/Zend/Acl.php</p>
<p>\Zend\Mail\Message =&gt; /path/to/project/lib/vendor/Zend/Mail/Message.php</code></p>
<h1>Underscores in namespaces and class names:</h1>
<p><code>\namespace\package\Class_Name =&gt; /path/to/project/lib/vendor/namespace/package/Class/Name.php</p>
<p>\namespace\package_name\Class_Name =&gt; /path/to/project/lib/vendor/namespace/package_name/Class/Name.php</code><br />
The standards we set here should be the lowest common denominator for painless autoloader interoperability. You can test that you are following these standards by utilizing this sample SplClassLoader implementation which is able to load PHP 5.3 classes.</p>
<h1>Example Implementation</h1>
<p>Below is an example function to simply demonstrate how the above proposed standards are autoloaded.<br />
<code>&lt;?php</p>
<p>function autoload($className)<br />
{<br />
    $className = ltrim($className, '\\');<br />
    $fileName  = '';<br />
    $namespace = '';<br />
    if ($lastNsPos = strripos($className, '\\')) {<br />
        $namespace = substr($className, 0, $lastNsPos);<br />
        $className = substr($className, $lastNsPos + 1);<br />
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;<br />
    }<br />
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';</p>
<p>    require $fileName;<br />
}</code></p>
<h1>SplClassLoader Implementation</h1>
<p>The following gist is a sample SplClassLoader implementation that can load your classes if you follow the autoloader interoperability standards proposed above. It is the current recommended way to load PHP 5.3 classes that follow these standards.</p>
<p><a href="http://gist.github.com/221634">http://gist.github.com/221634</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/09/21/psr-0-final-proposal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Determining Month to Date Sales in Dynamics GP 10 with Project Accounting</title>
		<link>http://blog.montmere.com/2011/05/17/determining-month-to-date-sales-in-dynamics-gp-10-with-project-accounting/</link>
		<comments>http://blog.montmere.com/2011/05/17/determining-month-to-date-sales-in-dynamics-gp-10-with-project-accounting/#comments</comments>
		<pubDate>Tue, 17 May 2011 20:06:52 +0000</pubDate>
		<dc:creator>Eric Sukalac</dc:creator>
				<category><![CDATA[Dynamics GP]]></category>
		<category><![CDATA[Dynamics]]></category>
		<category><![CDATA[GP]]></category>
		<category><![CDATA[Month to Date Sales]]></category>
		<category><![CDATA[MTD]]></category>
		<category><![CDATA[Project Accounting]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SSRS]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=40</guid>
		<description><![CDATA[This was a tough one. I needed to find month to date sales in GP compiling Sales Orders and entries in Project Accounting. To complicated things a little more, I needed to use the Invoicing amount in Sales Orders if they&#8217;ve been fully invoiced and the Invoiced amount from Project Accounting when it is more [...]]]></description>
			<content:encoded><![CDATA[<p>This was a tough one. I needed to find month to date sales in GP compiling Sales Orders and entries in Project Accounting.  To complicated things a little more, I needed to use the Invoicing amount in Sales Orders if they&#8217;ve been fully invoiced and the Invoiced amount from Project Accounting when it is more than the total Fee Schedule.</p>
<p>The SQL gets a little messy so I&#8217;ve tried to add some comments to clarify exactly what I&#8217;m trying to do.  The basic idea is that I&#8217;m getting the total sales order numbers and performing a UNION with the total Project Accounting numbers then summing them with an outer query. You can modify this to include previous months by changing any references to a date field from &#8220;DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)&#8221; (meaning, the first day of the current month) to &#8220;DATEADD(mm, DATEDIFF(mm,0,getdate()) -1, 0)&#8221; (the first day of the previous month) or can change that -1 to a -2 to look 2 months back.</p>
<p>There are likely many better ways to get this done, but this has seemed to work well so far.</p>
<p>Let me know if you have any questions or comments.</p>
<pre>
SELECT SUM("total") as "MTD Sales" 

FROM (

	SELECT myMonth, myMonthNUm, SUM("Totals") as total
	FROM 

	-- Sales Orders Entered this month
	(
		SELECT 

		-- Name of Month
		DateName(month,CASE WHEN Sales."CREATED DATE" < Sales."Order Date"
			THEN Sales."Created Date"
			ELSE Sales."Order Date"
		END) as myMonth,

		-- Number of Month
		month(CASE WHEN Sales."CREATED DATE" < Sales."Order Date"
			THEN Sales."Created Date"
			ELSE Sales."Order Date"
		END
	) as myMonthNum,

	-- Here, we look to see if the SO has been invoiced. If it has, we use the invoice amount
	-- otherwise, we use the subtotal.
	CASE WHEN Sales."Sales Document Status" != 'Complete'
	THEN (Sales."Subtotal" - Sales."Trade Discount Amount")
	ELSE (SUM(ISNULL(INV1."Subtotal",0)) + SUM(ISNULL(WORK."Subtotal",0)) - SUM(ISNULL(INV1."TRDISAMT",0)) )
	END
	AS Totals

	FROM dbo.SalesTransactions Sales
	LEFT JOIN dbo.SOP30200 SO
		ON SALES."SOP Number" = SO."SOPNUMBE"
	LEFT JOIN dbo.SOP10100 WORK
		ON SALES."SOP Number" = WORK."ORIGNUMB"
	LEFT JOIN dbo.SOP30200 INV1
		ON SO."SOPNUMBE" = INV1."ORIGNUMB"

	-- Look at orders made this month using the earlier date between created and order date
	WHERE
	CASE WHEN Sales."CREATED DATE" < Sales."Order Date"
		THEN Sales."Created Date"
		ELSE Sales."Order Date"
	END <  DATEADD(mm, DATEDIFF(mm,0,getdate()) + 1, 0)
	AND CASE WHEN Sales."Created Date" < Sales."Order Date"
		THEN Sales."Created Date"
		ELSE Sales."Order Date"
	END
	>=  DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
	AND Sales."SOP Type" = 'Order'
	AND (INV1."BCHSOURC" IS NULL OR INV1."BCHSOURC" = 'Sales Entry')
	GROUP BY Sales."SOP Number", Sales."Subtotal", Sales."Customer Name", Sales."Sales Document Status", Sales."Trade Discount Amount",

	CASE WHEN Sales."CREATED DATE" < Sales."Order Date"
		THEN Sales."Created Date"
		ELSE Sales."Order Date"
	END

	) as T
	GROUP BY myMonth,mymonthnum

	-- Now we'll include contracts entered in project accounting
	UNION
	(
		SELECT  Datename(month,(T."SuperDate")) as myMonth, month(T."SuperDate") as myMonthNum,

		-- Just as in Sales Orders, we'll use the billed amount if it is higher than the original contract amount
		SUM(CASE
		WHEN T."Total" > ISNULL(B.Billing,0)
		THEN "Total"
		ELSE ISNULL(B.Billing,0)
		END
		)
		as Totals
		FROM
		(	-- Here, we're grabbing the "as sold" amounts from the contract fee schedule for each contract line item
			SELECT
			Glue."Contract ID",
			MIN(SuperGlue."PA Forecast Begin Date") as SuperDate,
			SUM(Fee."PAFeeAmount") as Total
			FROM dbo.PA02101 Fee
			LEFT JOIN dbo.PAProjects Glue
			ON Fee."PAPROJNUMBER" = Glue."Project Number"
			LEFT JOIN dbo.PAContracts SuperGlue
			ON Glue."Contract ID" = SuperGlue."Contract ID"
			WHERE "PA Forecast Begin Date" >=  DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
			AND "PA Forecast Begin Date" <  DATEADD(mm, DATEDIFF(mm,0,getdate()) + 1, 0)
			GROUP BY Glue."Contract ID"
		) as T
		LEFT JOIN
		(   -- Here, we're looking at our total billed amount
			SELECT  "PACONTNUMBER", SUM("PABillingAmount") as Billing
			FROM dbo.PA11500
			GROUP BY "PACONTNUMBER"
		) as B
		ON T."Contract ID" = B."PACONTNUMBER"
		GROUP BY  Datename(month,(T."SuperDate")), month(T."SuperDate")
	)
) as P
GROUP BY myMonth, myMonthNum
ORDER BY myMonthNum
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/05/17/determining-month-to-date-sales-in-dynamics-gp-10-with-project-accounting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bill of Materials and Quantities in Dynamics GP 10</title>
		<link>http://blog.montmere.com/2011/05/16/bill-of-materials-and-quantities-in-dynamics-gp-10/</link>
		<comments>http://blog.montmere.com/2011/05/16/bill-of-materials-and-quantities-in-dynamics-gp-10/#comments</comments>
		<pubDate>Mon, 16 May 2011 20:45:11 +0000</pubDate>
		<dc:creator>Eric Sukalac</dc:creator>
				<category><![CDATA[Dynamics GP]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=39</guid>
		<description><![CDATA[Here&#8217;s a SQL query that will allow you to see what components go into a given finished part number along with the available, on hand, allocated, and back ordered quantities. This is useful if you have a rush job with not enough quantity available in GP and want to see what&#8217;s actually in house. Just [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a SQL query that will allow you to see what components go into a given finished part number along with the available, on hand, allocated, and back ordered quantities.</p>
<p>This is useful if you have a rush job with not enough quantity available in GP and want to see what&#8217;s actually in house.</p>
<p>Just define @needed as how many items you&#8217;re trying to manufacture and set @item to the finished part number.  You&#8217;ll also need to enter in your own location code in the left join for ItemQuantities.  The &#8220;Assembly&#8221; column will let you know if the component is itself an assembly. When I make a report out of this in Business Intelligence Development Studio, I use this column to show or hide a symbol to navigate to this report with the part number of the component (pretty much &#8220;scoping in&#8221; to that part) to see if the material is available to make that.<br />
<code>DECLARE @needed as INT<br />
DECLARE @item as char(20)</p>
<p>SET @needed = 1<br />
SET @item = '115-0001'</p>
<p>SELECT<br />
Item."Item Description",<br />
Bill."FINISHED GOOD ITEM NUMBER",<br />
Bill."Component",<br />
(Bill."QTY" * @needed) as "QTY",<br />
Item."QTY Available",<br />
Item."QTY On Order",<br />
Item."QTY On Hand",<br />
Item."QTY Allocated",<br />
CASE<br />
WHEN Sub.SubParts IS NOT NULL<br />
THEN 1<br />
ELSE 0<br />
END as "Assembly"<br />
FROM dbo.BillofMaterials as Bill<br />
LEFT JOIN dbo.ItemQuantities as Item ON Bill."Component" = Item."Item Number" AND Item."Location Code" = 'YOUR LOCATION CODE'<br />
LEFT JOIN<br />
(<br />
SELECT "Finished Good Item Number", COUNT(*) as SubParts FROM dbo.BillofMaterials<br />
GROUP BY "Finished Good Item Number") as Sub<br />
ON<br />
Sub."Finished Good Item Number" = Bill."Component"</p>
<p>WHERE Bill."FINISHED GOOD ITEM NUMBER" = @item</code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/05/16/bill-of-materials-and-quantities-in-dynamics-gp-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Looking at Manufacturing Orders Associated with Sales Order Lines in Dynamics GP 10</title>
		<link>http://blog.montmere.com/2011/05/06/looking-at-manufacturing-orders-associated-with-sales-order-lines-in-dynamics-gp-10/</link>
		<comments>http://blog.montmere.com/2011/05/06/looking-at-manufacturing-orders-associated-with-sales-order-lines-in-dynamics-gp-10/#comments</comments>
		<pubDate>Fri, 06 May 2011 16:02:56 +0000</pubDate>
		<dc:creator>Eric Sukalac</dc:creator>
				<category><![CDATA[Dynamics GP]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=36</guid>
		<description><![CDATA[Here&#8217;s a query that will allow you to see which Open SO Lines have MOs associated with them and which MO exactly it is. This is helpful when you&#8217;re looking to find &#8220;lost orders&#8221; that haven&#8217;t yet been processed in Manufacturing. SELECT  MO."MANUFACTUREORDER_I", Sales."SOP Number", Sales."Item Number", Sales."Order Date", Sales."QTY", Sales."QTY Remaining", Sales."Customer Name", Sales."Item [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a query that will allow you to see which Open SO Lines have MOs associated with them and which MO exactly it is.</p>
<p>This is helpful when you&#8217;re looking to find &#8220;lost orders&#8221; that haven&#8217;t yet been processed in Manufacturing.</p>
<pre>SELECT 
MO."MANUFACTUREORDER_I",
Sales."SOP Number",
Sales."Item Number",
Sales."Order Date",
Sales."QTY",
Sales."QTY Remaining",
Sales."Customer Name",
Sales."Item Description",
Sales."Due Date"
FROM dbo.SalesLineItems Sales
LEFT JOIN dbo.SOP10202ON Sales."SOP Number" = dbo.SOP10202.SOPNUMBEAND Sales."Line Item Sequence" = dbo.SOP10202.LNITMSEQ
LEFT JOIN dbo.IS010001 As MOON Sales."SOP Number" = MO.SOPNUMBEAND Sales."Line Item Sequence" = MO.LNITMSEQAND Sales."Item Number" = MO.ITEMNMBR
WHERE Sales."SOP Type" = 'Order' AND Sales."Sales Document Status" != 'Complete'AND Sales."QTY Remaining" &gt; 0
ORDER BY "SOP Number" ASC</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/05/06/looking-at-manufacturing-orders-associated-with-sales-order-lines-in-dynamics-gp-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend_Form_Element_Daterange with jQuery UI datepicker</title>
		<link>http://blog.montmere.com/2011/04/10/zend_form_element_daterange-with-jquery-ui-datepicker/</link>
		<comments>http://blog.montmere.com/2011/04/10/zend_form_element_daterange-with-jquery-ui-datepicker/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 17:30:23 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=35</guid>
		<description><![CDATA[It&#8217;s pretty easy to create a wrapper around Zend_Form_Element_Text to make a datepicker, but creating a good, smart daterange picker is a little more tricky. The only two requirements are jQuery UI and that you have some way of injecting JavaScript into your site layout (I use a $this-&#62;layout()-&#62;headJavascript). Other than that, this should be [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s pretty easy to create a wrapper around Zend_Form_Element_Text to make a datepicker, but creating a good, smart daterange picker is a little more tricky.</p>
<p>The only two requirements are jQuery UI and that you have some way of injecting JavaScript into your site layout (I use a $this-&gt;layout()-&gt;headJavascript).</p>
<p>Other than that, this should be pretty plug-and-play.</p>
<p>Here are the 3x files you&#8217;ll need:<br />
1. Your view script for the actual element (check in here for how I&#8217;m dealing with the JavaScript):<br />
<code>/application/views/scripts/misc/form/element/daterange.phtml</code></p>
<p>2. The actual element<br />
<code>/library/M/Form/Element/Daterange.php</code></p>
<p>3. And a filter to parse out the actual daterange when you do $form->getValues():<br />
<code>/library/M/Filter/Daterange.php</code></p>
<p>Have fun!</p>
<p><code>/library/M/Form/Element/Daterange.php</code><br />
<code>&lt;?php</p>
<p>class M_Form_Element_Daterange extends Zend_Form_Element_Select {<br />
	public function init() {</p>
<p>		$this-&gt;setDecorators(array(array('ViewScript', array(<br />
		    'viewScript' =&gt; 'misc/form/element/daterange.phtml',<br />
			'viewModule' =&gt; 'default',<br />
		    'class'      =&gt; 'form element'<br />
		))));</p>
<p>		return parent::init();<br />
	}<br />
}</code></p>
<p><code>/library/M/Filter/Daterange.php</code></p>
<p><code>&lt;?php</p>
<p>class M_Filter_Daterange implements Zend_Filter_Interface {</p>
<p>	private $_param = null;</p>
<p>	public function __construct($param, $options = array()) {<br />
		if (!is_string($param) || strlen($param) &lt; 1) {<br />
			throw new Zend_Filter_Exception("param must be a string, and must have a length");<br />
		}<br />
		$this-&gt;_param = $param;<br />
	}</p>
<p>	/**<br />
	 * (non-PHPdoc)<br />
	 * @see Zend_Filter_Interface::filter()<br />
	 */<br />
	public function filter($val) {<br />
		if ($val != 'custom') {<br />
			$rangestring = self::stringToRange($val);<br />
			if ($rangestring) {<br />
				return $rangestring;<br />
			}<br />
		}<br />
		if ($this-&gt;_param === null) {<br />
			throw new Zend_Filter_Exception("Must instantiate this class and pass a valid parameter");<br />
		}<br />
		$range = Zend_Controller_Front::getInstance()-&gt;getRequest()-&gt;getParam($this-&gt;_param, false);<br />
		$start = strtotime(Zend_Controller_Front::getInstance()-&gt;getRequest()-&gt;getParam($this-&gt;_param . '_start', false));<br />
		$end = strtotime(Zend_Controller_Front::getInstance()-&gt;getRequest()-&gt;getParam($this-&gt;_param . '_end', false));</p>
<p>		if (!$start || !$end) {<br />
			return false;<br />
		}<br />
		return array(<br />
			'start' =&gt; date('Y-m-d', $start),<br />
			'end' =&gt; date('Y-m-d', $end),<br />
		);</p>
<p>	}</p>
<p>	/**<br />
	 * Converts a known relative date range string to an array of dates, returns false on failure<br />
	 *<br />
	 * @param string $datestring<br />
	 * @return array|bool<br />
	 */<br />
	static public function stringToRange($datestring) {<br />
		switch ($datestring) {<br />
			case 'yesterday':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('yesterday')),<br />
					'end'	=&gt; date('Y-m-d'),<br />
				);<br />
				break;<br />
			case 'weektodate':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('sunday this week')),<br />
					'end'	=&gt; date('Y-m-d'),<br />
				);<br />
				break;<br />
			case 'lastweek':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('sunday last week')),<br />
					'end'	=&gt; date('Y-m-d', strtotime('saturday -2 weeks')),<br />
				);<br />
				break;<br />
			case 'monthtodate':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('first day of this month')),<br />
					'end'	=&gt; date('Y-m-d'),<br />
				);<br />
				break;<br />
			case 'lastmonth':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('first day of last month')),<br />
					'end'	=&gt; date('Y-m-d', strtotime('last day of last month')),<br />
				);<br />
				break;<br />
			case 'yeartodate':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('first day of this year')),<br />
					'end'	=&gt; date('Y-m-d'),<br />
				);<br />
				break;<br />
			case 'lastyear':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('first day of last year')),<br />
					'end'	=&gt; date('Y-m-d', strtotime('last day of last year')),<br />
				);<br />
				break;<br />
			case 'all':<br />
				$daterange = array(<br />
					'start'	=&gt; date('Y-m-d', strtotime('1970-01-01')),<br />
					'end'	=&gt; date('Y-m-d'),<br />
				);<br />
				break;<br />
			default:<br />
				return false;</p>
<p>		}<br />
		return $daterange;<br />
	}</p>
<p>}</code></p>
<p><code>/application/views/scripts/misc/form/element/daterange.phtml</code></p>
<p><code>&lt;?php<br />
/**<br />
 * Output a daterange element<br />
 *<br />
 */</p>
<p>/**<br />
 * @var Zend_Form_Element<br />
 */<br />
$element = $this-&gt;element;<br />
$opts = $element-&gt;getDecorator('ViewScript')-&gt;getOptions();</p>
<p>ob_start();<br />
?&gt;<br />
&lt;script&gt;<br />
$(document).ready(function() {<br />
	var dates = $(&lt;?=json_encode('#' . $element-&gt;getName() . '_start, #' . $element-&gt;getName() . '_end')?&gt;).datepicker({<br />
		changeMonth : true<br />
		, onSelect : function( selectedDate ) {<br />
			// don't let end date be after start date<br />
			var option = this.id == &lt;?=json_encode($element-&gt;getName() . '_start')?&gt; ? "minDate" : "maxDate",<br />
				instance = $(this).data("datepicker"),<br />
				date = $.datepicker.parseDate(<br />
					instance.settings.dateFormat || $.datepicker._defaults.dateFormat<br />
					, selectedDate<br />
					, instance.settings<br />
				);<br />
			dates.not(this).datepicker("option", option, date);<br />
		}</p>
<p>	});</p>
<p>	$(&lt;?=json_encode('#' . $element-&gt;getName())?&gt;).change(function() {<br />
		if ($(this).val() == 'custom') {<br />
			$(&lt;?=json_encode('#_custom_daterange_' . $element-&gt;getName() . '_start')?&gt;).show();<br />
			$(&lt;?=json_encode('#_custom_daterange_' . $element-&gt;getName() . '_end')?&gt;).show();<br />
		} else {<br />
			$(&lt;?=json_encode('#_custom_daterange_' . $element-&gt;getName() . '_start')?&gt;).hide();<br />
			$(&lt;?=json_encode('#_custom_daterange_' . $element-&gt;getName() . '_end')?&gt;).hide();<br />
		}<br />
	});<br />
});<br />
&lt;/script&gt;<br />
&lt;?php<br />
$this-&gt;layout()-&gt;headJavascript .= ob_get_clean();</p>
<p>?&gt;<br />
&lt;table id="_custom_daterange_&lt;?=htmlentities($element-&gt;getName())?&gt;"&gt;<br />
	&lt;tr&gt;<br />
		&lt;td&gt;&lt;?=$element-&gt;getLabel()?&gt;&lt;/td&gt;<br />
		&lt;td&gt;&lt;?php<br />
			echo $this-&gt;{$element-&gt;helper}(<br />
				$element-&gt;getName(),<br />
				$element-&gt;getValue(),<br />
				$element-&gt;getAttribs(),<br />
				$element-&gt;getMultiOptions()<br />
			);?&gt;<br />
		&lt;/td&gt;<br />
	&lt;/tr&gt;<br />
	&lt;tr style="display:none" id="_custom_daterange_&lt;?=htmlentities($element-&gt;getName())?&gt;_start"&gt;<br />
		&lt;td&gt;&lt;label for="&lt;?=htmlentities($element-&gt;getName())?&gt;_start"&gt;Start: &lt;/label&gt;&lt;/td&gt;<br />
		&lt;td&gt;&lt;input id="&lt;?=htmlentities($element-&gt;getName())?&gt;_start" name="&lt;?=htmlentities($element-&gt;getName())?&gt;_start" type="text"&gt;&lt;/td&gt;<br />
	&lt;/tr&gt;<br />
	&lt;tr style="display:none" id="_custom_daterange_&lt;?=htmlentities($element-&gt;getName())?&gt;_end"&gt;<br />
		&lt;td&gt;&lt;label for="&lt;?=htmlentities($element-&gt;getName())?&gt;_end"&gt;End: &lt;/label&gt;&lt;/td&gt;<br />
		&lt;td&gt;&lt;input id="&lt;?=htmlentities($element-&gt;getName())?&gt;_end" name="&lt;?=htmlentities($element-&gt;getName())?&gt;_end" type="text"&gt;&lt;/td&gt;<br />
	&lt;/tr&gt;<br />
&lt;/table&gt;<br />
&lt;div class="error bold"&gt;&lt;?=$this-&gt;formErrors($element-&gt;getMessages())?&gt;&lt;/div&gt;<br />
&lt;div class="hint"&gt;&lt;?=$element-&gt;getDescription()?&gt;&lt;/div&gt;</code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/04/10/zend_form_element_daterange-with-jquery-ui-datepicker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unfollow everyone on formspring</title>
		<link>http://blog.montmere.com/2011/01/09/unfollow-everyone-on-formspring/</link>
		<comments>http://blog.montmere.com/2011/01/09/unfollow-everyone-on-formspring/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 17:45:38 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=31</guid>
		<description><![CDATA[Unfollow everyone on formspring using jash and jquerify!]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been creating accounts on various social networking sites lately for a project we&#8217;re working on, and I somehow managed to bulk-follow over a thousand people on <a href="http://formspring.me">formspring.me</a> with their &#8220;find friends&#8221; tool. Like seriously, I was following hundreds of Asian teenagers &#8212; no idea how that happened.</p>
<p>No worries though, I just fired up <a href="http://billyreisinger.com/jash/">jash</a> and <a href="http://www.learningjquery.com/2009/04/better-stronger-safer-jquerify-bookmarklet">jquerify</a> (a no-conflict version, since <a href="http://formspring.me">formspring.me</a> uses prototype, which jquery doesn&#8217;t always play nice with) to bulk unfollow all of them.</p>
<p>Once you get jquerify and jash up, just put this bad boy in jash, and you&#8217;re good to go:</p>
<pre><code >$jq.each($jq(".unfollow"), function() {
	var str = this.id.split('-');
	fspring.unfollow(str[1],this,'People-View');
});</code></pre>
<div id="attachment_33" class="wp-caption alignnone" style="width: 377px"><a href="http://blog.montmere.com/wp-content/uploads/2011/01/formspring.unfollow.all_.png"><img class="size-full wp-image-33 " title="formspring.unfollow.all" src="http://blog.montmere.com/wp-content/uploads/2011/01/formspring.unfollow.all_.png" alt="Unfollow all on Formspring - screenshot" width="367" height="312" /></a><p class="wp-caption-text">Unfollow all on Formspring</p></div>
<p>Be prepared to wait!!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/01/09/unfollow-everyone-on-formspring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend_Form_Element_Hidden not really hidden</title>
		<link>http://blog.montmere.com/2011/01/08/zend_form_element_hidden-not-really-hidden/</link>
		<comments>http://blog.montmere.com/2011/01/08/zend_form_element_hidden-not-really-hidden/#comments</comments>
		<pubDate>Sat, 08 Jan 2011 17:56:47 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=29</guid>
		<description><![CDATA[The point of having a hidden field is that it is truly hidden, and doesn&#8217;t require labels / etc. Unfortunately, Zend_Form_Element_Hidden doesn&#8217;t really recognise this. Here&#8217;s how to subclass it and get rid of that stuff so you can create an input that is hidden for real: class M_Form_Element_Hidden extends Zend_Form_Element_Hidden { public function init() [...]]]></description>
			<content:encoded><![CDATA[<p>The point of having a hidden field is that it is truly hidden, and doesn&#8217;t require labels / etc. Unfortunately, Zend_Form_Element_Hidden doesn&#8217;t really recognise this. Here&#8217;s how to subclass it and get rid of that stuff so you can create an input that is hidden for real:</p>
<pre><code >class M_Form_Element_Hidden extends Zend_Form_Element_Hidden {
   public function init() {
      $this-&gt;setDisableLoadDefaultDecorators(true);
      $this-&gt;addDecorator('ViewHelper');
      $this-&gt;removeDecorator('DtDdWrapper');
      $this-&gt;removeDecorator('HtmlTag');
      $this-&gt;removeDecorator('Label');
      return parent::init();
   }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2011/01/08/zend_form_element_hidden-not-really-hidden/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autoload PhpThumb with Zend Framework</title>
		<link>http://blog.montmere.com/2010/12/26/autoload-phpthumb-with-zend-framework/</link>
		<comments>http://blog.montmere.com/2010/12/26/autoload-phpthumb-with-zend-framework/#comments</comments>
		<pubDate>Sun, 26 Dec 2010 23:02:11 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[image resize]]></category>
		<category><![CDATA[image rotate]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[PhpThumb]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=25</guid>
		<description><![CDATA[Here&#8217;s an easy way to autoload PhpThumb (an excellent &#38; fast image resizing / manipulating PHP library) using Zend Framework without having to modify the PhpThumb source at all. First we need to make our own custom autoloader: class M_Loader_Autoloader_PhpThumb implements Zend_Loader_Autoloader_Interface { static protected $php_thumb_classes = array( 'PhpThumb' =&#62; 'PhpThumb.inc.php', 'ThumbBase' =&#62; 'ThumbBase.inc.php', 'PhpThumbFactory' [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s an easy way to autoload <a title="PhpThumb" href="http://phpthumb.gxdlabs.com/" target="_blank">PhpThumb</a> (an excellent &amp; fast image resizing / manipulating PHP library) using Zend Framework without having to modify the PhpThumb source at all. First we need to make our own custom autoloader:</p>
<pre>class M_Loader_Autoloader_PhpThumb implements Zend_Loader_Autoloader_Interface {

   static protected $php_thumb_classes = array(
      'PhpThumb'        =&gt; 'PhpThumb.inc.php',
      'ThumbBase'       =&gt; 'ThumbBase.inc.php',
      'PhpThumbFactory' =&gt; 'ThumbLib.inc.php',
      'GdThumb'         =&gt; 'GdThumb.inc.php',
      'GdReflectionLib' =&gt; 'thumb_plugins/gd_reflection.inc.php',
   );

  /**
   * Autoload a class
   *
   * @param   string $class
   * @return  mixed
   *          False [if unable to load $class]
   *          get_class($class) [if $class is successfully loaded]
   */
   public function autoload($class) {
      $file = APPLICATION_PATH . '/../library/PhpThumb/' . self::$php_thumb_classes[$class];
      if (is_file($file)) {
         require_once($file);
         return $class;
      }
      return false;
   }
}</pre>
<p>Then simply put this in your Bootstrap:</p>
<pre><code ></code>Zend_Loader_Autoloader::getInstance()-&gt;pushAutoloader(new M_Loader_Autoloader_PhpThumb());
</pre>
<p>Done. Now you can use PhpThumb in your controllers like this:</p>
<pre>class PhotoController extends Zend_Controller_Action {
   public function indexAction() {
      $this-&gt;_helper-&gt;layout()-&gt;disableLayout();
      $this-&gt;_helper-&gt;viewRenderer-&gt;setNoRender(true);
      $thumb = PhpThumbFactory::create("/path/to/image.jpg");
      $thumb-&gt;adaptiveResize(250, 250);
      $thumb-&gt;show();
   }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2010/12/26/autoload-phpthumb-with-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Script to generate command to push MySQL database changes between enviornments</title>
		<link>http://blog.montmere.com/2010/12/18/script-to-generate-command-to-push-mysql-database-changes-between-enviornments/</link>
		<comments>http://blog.montmere.com/2010/12/18/script-to-generate-command-to-push-mysql-database-changes-between-enviornments/#comments</comments>
		<pubDate>Sat, 18 Dec 2010 20:45:26 +0000</pubDate>
		<dc:creator>Stephen J. Fuhry</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.montmere.com/?p=22</guid>
		<description><![CDATA[Got sick of manually doing database dumps between our production, test, and development environments, so I just wrote a very handy script using Zend Framework to generate a command to push changes between environments as you make them. You will have to tweak ssh_to to suit your needs (our test and production dbs are not [...]]]></description>
			<content:encoded><![CDATA[<p>Got sick of manually doing database dumps between our production, test, and development environments, so I just wrote a very handy script using Zend Framework to generate a command to push changes between environments as you make them.</p>
<p>You will have to tweak ssh_to to suit your needs (our test and production dbs are not separated at the moment, so that removes a layer of complexity for us), but if you have everything setup in application.ini like most people do, this should work almost out of box. You&#8217;ll need to setup the autoloader on your own.</p>
<p>usage: <code >php push_db.php --to=dev --from=prod</code></p>
<p>Enjoy!</p>
<pre>
<code >#!/usr/bin/env php5
&lt;?php
require_once(getcwd() . '/autoload.php');</code>

$opts = new Zend_Console_Getopt(
   array(
      'from=s'    =&gt; 'From environment, with required string parameter',
      'to=s'        =&gt; 'To environment, with required string parameter',
   )
);

$from = $opts-&gt;getOption('from');
$to = $opts-&gt;getOption('to');

foreach (array('from','to') as $env) {
      if (!in_array($$env, array('production','prod','testing','test','development','dev'))) {
         die('Error: invalid parameter ' . $env . " = '{$$env}'" . PHP_EOL);
      }
}

$prod_env = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'production');
$test_env = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'testing');
$dev_env = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'development');

$to_server = array();
$from_server = array();
foreach (array('from','to') as $serv) {
   $server = $serv . '_server';
   switch ($$serv) {
      case 'production':
      case 'prod':
         ${$server}['host'] =                   $prod_env-&gt;database-&gt;params-&gt;host;
         ${$server}['username'] =                   $prod_env-&gt;database-&gt;params-&gt;username;
         ${$server}['password'] =                   $prod_env-&gt;database-&gt;params-&gt;password;
         ${$server}['dbname'] =                   $prod_env-&gt;database-&gt;params-&gt;dbname;
         ${$server}['ssh_to'] = 'me@foobar';
         break;
      case 'testing':
      case 'test':
         ${$server}['host'] = $test_env-&gt;database-&gt;params-&gt;host;
         ${$server}['username'] =                   $test_env-&gt;database-&gt;params-&gt;username;
         ${$server}['password'] =                   $test_env-&gt;database-&gt;params-&gt;password;
         ${$server}['dbname'] =                   $test_env-&gt;database-&gt;params-&gt;dbname;
         ${$server}['ssh_to'] = 'me@foobar';
         break;
      case 'development':
      case 'dev':
         ${$server}['host'] = $dev_env-&gt;database-&gt;params-&gt;host;
         ${$server}['username'] =                   $dev_env-&gt;database-&gt;params-&gt;username;
         ${$server}['password'] =                   $dev_env-&gt;database-&gt;params-&gt;password;
         ${$server}['dbname'] =                   $dev_env-&gt;database-&gt;params-&gt;dbname;
         ${$server}['ssh_to'] = 'me@foobar';
         break;
      }
}

print "Run this command on " . $from . ':' . PHP_EOL;
echo 'mysqldump -u ' . $from_server['username'] . ' -p' . $from_server['password'] . ' ' . $from_server['dbname']
. ' | ssh ' . $from_server['ssh_to'] . ' "mysql -u ' . $to_server['username'] . ' -p' . $to_server['password'] . ' ' . $to_server['dbname'] . '"' . PHP_EOL;
﻿</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.montmere.com/2010/12/18/script-to-generate-command-to-push-mysql-database-changes-between-enviornments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

