Преглед изворни кода

Promoted Zend_Service_LiveDocx to trunk

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@19349 44c647ce-9c0f-0410-b52a-842ac1e357ba
matthew пре 16 година
родитељ
комит
f447092de7

+ 1 - 0
documentation/manual/en/manual.xml.in

@@ -459,6 +459,7 @@
         <xi:include href="module_specs/Zend_Service_Audioscrobbler.xml" />
         <xi:include href="module_specs/Zend_Service_Delicious.xml" />
         <xi:include href="module_specs/Zend_Service_Flickr.xml" />
+        <xi:include href="module_specs/Zend_Service_LiveDocx.xml" />
         <xi:include href="module_specs/Zend_Service_Nirvanix.xml" />
         <xi:include href="module_specs/Zend_Service-ReCaptcha.xml" />
         <xi:include href="module_specs/Zend_Service_Simpy.xml" />

+ 910 - 0
documentation/manual/en/module_specs/Zend_Service_LiveDocx.xml

@@ -0,0 +1,910 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Reviewed: no -->
+<sect1 id="zend.service.livedocx">
+    <title>Zend_Service_LiveDocx</title>
+
+    <sect2 id="zend.service.livedocx.introduction">
+        <title>Introduction to LiveDocx</title>
+
+        <para>
+            LiveDocx is a <acronym>SOAP</acronym> service that allows developers to generate word
+            processing documents by combining structured data from PHP with a template, created in a
+            word processor. The resulting document can be saved as a <acronym>PDF</acronym>,
+            <acronym>DOCX</acronym>, <acronym>DOC</acronym>, <acronym>HTML</acronym> or 
+            <acronym>RTF</acronym> file. LiveDocx implements <ulink
+                    url="http://en.wikipedia.org/wiki/Mail_merge">mail-merge</ulink> in PHP.
+        </para>
+       
+        <para>
+            The family of <classname>Zend_Service_LiveDocx</classname> components provides a clean
+            and simple interface to the <ulink url="http://www.livedocx.com">LiveDocx API</ulink>
+            and additionally offers functionality to improve network performance.            
+        </para>
+
+        <para>The <ulink url="http://www.phplivedocx.org">phpLiveDocx project site</ulink> contains
+            a large number of sample applications, tips and tricks and latest news, specific
+            to the Zend Framework implementation of LiveDocx. These resources are designed to get
+            you up to speed with LiveDocx in PHP as quickly as possible.
+        </para>
+
+        <para>
+            The backend <acronym>SOAP</acronym> API is documented <ulink
+            url="http://www.livedocx.com/pub/documentation/api.aspx">on the LiveDocx
+            documentation pages</ulink>. 
+        </para>
+        
+        <sect3 id="zend.service.livedocx.account">
+            <title>Sign Up for an Account</title>
+    
+            <para>
+                Before you can start using LiveDocx, you must first <ulink
+                    url="https://www.livedocx.com/user/account_registration.aspx">sign up</ulink>
+                for an account. The account is completely free of charge and you only need to
+                specify a <emphasis>username</emphasis>, <emphasis>password</emphasis> and
+                <emphasis>e-mail address</emphasis>. Your login credentials will be dispatched to
+                the e-mail address you supply, so please type carefully.
+            </para>
+        </sect3>
+    
+        <sect3 id="zend.service.livedocx.templates-documents">
+            <title>Templates and Documents</title>
+    
+            <para>
+                LiveDocx differentiates between the following terms: 1)
+                <emphasis>template</emphasis> and 2) <emphasis>document</emphasis>. In order to
+                fully understand the documentation and indeed the actual API, it is important that
+                any programmer deploying LiveDocx understands the difference.
+            </para>
+    
+            <para>
+                The term <emphasis>template</emphasis> is used to refer to the input file, created
+                in a word processor, containing formatting and text fields. You can download an
+                <ulink
+                    url="http://www.phplivedocx.org/wp-content/uploads/2009/01/license-agreement-template.docx">example
+                    template</ulink>, stored as a <acronym>DOCX</acronym> file. The term
+                <emphasis>document</emphasis> is used to refer to the output file that contains the
+                template file, populated with data - i.e. the finished document. You can download an
+                <ulink
+                    url="http://www.phplivedocx.org/wp-content/uploads/2009/01/license-agreement-document.pdf">example
+                    document</ulink>, stored as a <acronym>PDF</acronym> file.
+            </para>
+        </sect3>
+    
+        <sect3 id="zend.service.livedocx.formats">
+            <title>Supported File Formats</title>
+            
+            <para>
+                LiveDocx supports the following file formats:
+            </para>
+            
+            <sect4 id="zend.service.livedocx.formats.template">
+                <title>Template File Formats (input)</title>
+                
+                <para>
+                    Templates can be saved in any of the following file formats:
+                </para>
+        
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Office_Open_XML">DOCX</ulink> -
+                            Office Open <acronym>XML</acronym> format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/DOC_(computing)">DOC</ulink> -
+                            Microsoft Word <acronym>DOC</acronym> format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Rich_Text_Format">RTF</ulink> -
+                            Rich text file format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://www.textcontrol.com/">TXD</ulink> - TX Text Control
+                            format
+                        </para>
+                    </listitem>
+                </itemizedlist>
+            </sect4>
+            
+            <sect4 id="zend.service.livedocx.formats.document">
+                <title>Document File Formats (output):</title>
+                
+                <para>
+                    The resulting document can be saved in any of the following file formats:
+                </para>
+        
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Office_Open_XML">DOCX</ulink> -
+                            Office Open <acronym>XML</acronym> format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/DOC_(computing)">DOC</ulink> -
+                            Microsoft Word <acronym>DOC</acronym> format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Xhtml">HTML</ulink> -
+                            <acronym>XHTML</acronym> 1.0 transitional format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Rich_Text_Format">RTF</ulink> -
+                            Rich text file format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink
+                                url="http://en.wikipedia.org/wiki/Portable_Document_Format">PDF</ulink>
+                            - Acrobat Portable Document Format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://www.textcontrol.com/">TXD</ulink> - TX Text Control
+                            format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Text_file">TXT</ulink> -
+                            <acronym>ANSI</acronym> plain text
+                        </para>
+                    </listitem>
+                </itemizedlist>
+            </sect4>
+            
+            <sect4 id="zend.service.livedocx.formats.image">
+                <title>Image File Formats (output):</title>
+                
+                <para>
+                    The resulting document can be saved in any of the following graphical file
+                    formats:
+                </para>                
+        
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/BMP_file_format">BMP</ulink> -
+                            Bitmap image format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/GIF">GIF</ulink> - Graphics
+                            Interchange Format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Jpg">JPG</ulink> - Joint
+                            Photographic Experts Group format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink
+                                url="http://en.wikipedia.org/wiki/Portable_Network_Graphics">PNG</ulink>
+                            - Portable Network Graphics format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink
+                                url="http://en.wikipedia.org/wiki/Tagged_Image_File_Format">TIFF</ulink>
+                            - Tagged Image File Format
+                        </para>
+                    </listitem>
+        
+                    <listitem>
+                        <para>
+                            <ulink url="http://en.wikipedia.org/wiki/Windows_Metafile">WMF</ulink> -
+                            Windows Meta File format
+                        </para>
+                    </listitem>
+                </itemizedlist>
+            </sect4>
+        </sect3>
+    </sect2>
+
+    <sect2 id="zend.service.livedocx.mailmerge">
+        <title>Zend_Service_LiveDocx_MailMerge</title>
+        
+        <para>
+             <classname>Zend_Service_LiveDocx_MailMerge</classname> is the mail-merge object in the
+             <classname>Zend_Service_LiveDocx</classname> family.
+        </para>
+
+        <sect3 id="zend.service.livedocx.mailmerge.generation">
+            <title>Document Generation Process</title>
+
+            <para>
+                The document generation process can be simplified with the following equation:
+            </para>
+
+            <para>
+                <emphasis>Template + Data = Document</emphasis>
+            </para>
+
+            <para>
+                Or expressed by the following diagram:
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.generation-diabasic.png" format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Data is inserted into template to create a document (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.generation-diabasic_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                A template, created in a word processing application, such as Microsoft Word, is
+                loaded into LiveDocx. Data is then inserted into the template and the resulting
+                document is saved to any supported format.
+            </para>
+        </sect3>
+
+        <sect3 id="zend.service.livedocx.mailmerge.templates">
+            <title>Creating Templates in Microsoft Word 2007</title>
+
+            <para>
+                Start off by launching Microsoft Word and creating a new document. Next, open up the
+                <emphasis>Field</emphasis> dialog box. This looks as follows:
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.templates-msworddialog.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Microsoft Word 2007 Field dialog box (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.templates-msworddialog_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                Using this dialog, you can insert the required merge fields into your document.
+                Below is a screenshot of a license agreement in Microsoft Word 2007. The merge
+                fields are marked as <code>{ MERGEFIELD FieldName }</code>:
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.templates-mswordtemplatefull.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Template in Microsoft Word 2007 (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.templates-mswordtemplatefull_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                Now, save the template as <emphasis>template.docx</emphasis>.
+            </para>
+
+            <para>
+                 In the next step, we are going to populate the merge fields with textual data from
+                 PHP.
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.templates-mswordtemplatecropped.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Cropped template in Microsoft Word 2007 (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.templates-mswordtemplatecropped_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                To populate the merge fields in the above cropped screenshot of the <ulink
+                    url="http://www.phplivedocx.org/wp-content/uploads/2009/01/license-agreement-template.docx">template</ulink>
+                in Microsoft Word, all we have to code is as follows:
+            </para>
+
+            <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+ 
+$phpLiveDocx->setLocalTemplate('template.docx');
+ 
+$phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9')
+            ->assign('licensee', 'Henry Döner-Meyer')
+            ->assign('company',  'Co-Operation');
+ 
+$phpLiveDocx->createDocument();
+ 
+$document = $phpLiveDocx->retrieveDocument('pdf');
+ 
+file_put_contents('document.pdf', $document);
+]]></programlisting>
+
+            <para>
+                The resulting document is written to disk in the file
+                <emphasis>document.pdf</emphasis>. This file can now be post-processed, sent via
+                e-mail or simply displayed, as is illustrated below in <emphasis>Document Viewer
+                    2.26.1</emphasis> on <emphasis>Ubuntu 9.04</emphasis>:
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.templates-msworddocument.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Resulting document as <acronym>PDF</acronym> in Document Viewer 2.26.1
+                        (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.templates-msworddocument_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+        </sect3>
+
+        <example id="zend.service.livedocx.mailmerge.advanced">
+            <title>Advanced Mail-Merge</title>
+
+            <para>
+                <classname>Zend_Service_LiveDocx_MailMerge</classname> allows designers to insert
+                any number of text fields into a template. These text fields are populated with data
+                when <emphasis>createDocument()</emphasis> is called.
+            </para>
+
+            <para>
+                In addition to text fields, it is also possible specify regions of a document, which
+                should be repeated.
+            </para>
+
+            <para>
+                For example, in a telephone bill it is necessary to print out a list of all
+                connections, including the destination number, duration and cost of each call. This
+                repeating row functionality can be achieved with so called blocks.
+            </para>
+
+            <para>
+                <emphasis>Blocks</emphasis> are simply regions of a document, which are repeated
+                when <methodname>createDocument()</methodname> is called. In a block any number of
+                <emphasis>block fields</emphasis> can be specified.
+            </para>
+
+            <para>
+                Blocks consist of two consecutive document targets with a unique name. The following
+                screenshot illustrates these targets and their names in red:
+            </para>
+
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.advanced-mergefieldblockformat.png" format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.advanced-mergefieldblockformat_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                The format of a block is as follows:
+            </para>
+
+            <programlisting language="text"><![CDATA[
+blockStart_ + unique name
+blockEnd_ + unique name
+]]></programlisting>
+
+            <para>For example:</para>
+
+            <programlisting language="text"><![CDATA[
+blockStart_block1
+blockEnd_block1
+]]></programlisting>
+
+            <para>
+                The content of a block is repeated, until all data assigned in the block fields has
+                been injected into the template. The data for block fields is specified in PHP as a
+                multi-assoc array.
+            </para>
+
+            <para>
+                The following screenshot of a template in Microsoft Word 2007 shows how block fields
+                are used:
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.advanced-mswordblockstemplate.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Template, illustrating blocks in Microsoft Word 2007 (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.advanced-mswordblockstemplate_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                The following code populates the above template with data.
+            </para>
+
+            <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+ 
+$phpLiveDocx->setLocalTemplate('template.doc');
+ 
+$billConnections = array(
+    array(
+        'connection_number'   => '+49 421 335 912', 
+        'connection_duration' => '00:00:07', 
+        'fee'                 => '€ 0.03',
+    ),
+    array(
+        'connection_number'   => '+49 421 335 913', 
+        'connection_duration' => '00:00:07', 
+        'fee'                 => '€ 0.03',
+    ),
+    array(
+        'connection_number'   => '+49 421 335 914', 
+        'connection_duration' => '00:00:07', 
+        'fee'                 => '€ 0.03',
+    ),
+    array(
+        'connection_number'   => '+49 421 335 916', 
+        'connection_duration' => '00:00:07', 
+        'fee'                 => '€ 0.03',
+    ),
+);
+ 
+$phpLiveDocx->assign('connection', $billConnections);
+
+// ... assign other data here ...
+
+$phpLiveDocx->createDocument();
+$document = $phpLiveDocx->retrieveDocument('pdf');
+file_put_contents('document.pdf', $document);
+]]></programlisting>
+
+            <para>
+                The data, which is specified in the array <varname>$billConnections</varname> is
+                repeated in the template in the block connection. The keys of the array
+                (<varname>connection_number</varname>, <varname>connection_duration</varname> and
+                <varname>fee</varname>) are the block field names - their data is inserted, one row
+                per iteration.
+            </para>
+
+            <para>
+                The resulting document is written to disk in the file
+                <emphasis>document.pdf</emphasis>. This file can now be post-processed, sent via
+                e-mail or simply displayed, as is illustrated below in <emphasis>Document Viewer
+                    2.26.1</emphasis> on <emphasis>Ubuntu 9.04</emphasis>:
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.advanced-mswordblocksdocument.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        Resulting document as <acronym>PDF</acronym> in Document Viewer 2.26.1
+                        (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.advanced-mswordblocksdocument_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <para>
+                You can download the <acronym>DOC</acronym> <ulink
+                    url="http://www.phplivedocx.org/wp-content/uploads/2009/01/telephone-bill-template.doc">template
+                    file</ulink> and the resulting <ulink
+                    url="http://www.phplivedocx.org/wp-content/uploads/2009/01/telephone-bill-document.pdf">PDF
+                    document</ulink>.
+            </para>
+
+            <para>
+                <emphasis>NOTE:</emphasis> blocks may not be nested.
+            </para>
+        </example>
+            
+        <example id="zend.service.livedocx.mailmerge.bitmaps">
+            <title>Generating bitmaps image files</title>
+
+            <para>
+                In addition to document file formats,
+                <classname>Zend_Service_LiveDocx_MailMerge</classname> also allows documents to be
+                saved to a number of image file formats (<acronym>BMP</acronym>,
+                <acronym>GIF</acronym>, <acronym>JPG</acronym>, <acronym>PNG</acronym> and
+                <acronym>TIFF</acronym>). Each page of the document is saved to one file.
+            </para>
+
+            <para>
+                The following sample illustrates the use of <methodname>getBitmaps($fromPage,
+                    $toPage, $zoomFactor, $format)</methodname> and
+                <methodname>getAllBitmaps($zoomFactor, $format)</methodname>.
+            </para>
+
+            <para>
+                <varname>$fromPage</varname> is the lower-bound page number of the page range that
+                should be returned as an image and <varname>$toPage</varname> the upper-bound page
+                number.  <varname>$zoomFactor</varname> is the size of the images, as a percent,
+                relative to the original page size. The range of this parameter is 10 to 400.
+                <varname>$format</varname> is the format of the images returned by this method. The
+                supported formats can be obtained by calling
+                <methodname>getImageFormats()</methodname>.
+            </para>
+
+            <programlisting language="php"><![CDATA[
+$date = new Zend_Date();
+$date->setLocale('en_US');
+ 
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+ 
+$phpLiveDocx->setLocalTemplate('template.docx');
+ 
+$phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9')
+            ->assign('licensee', 'Daï Lemaitre')
+            ->assign('company',  'Megasoft Co-operation')
+            ->assign('date',     $date->get(Zend_Date::DATE_LONG))
+            ->assign('time',     $date->get(Zend_Date::TIME_LONG))
+            ->assign('city',     'Lyon')
+            ->assign('country',  'France');
+ 
+$phpLiveDocx->createDocument();
+ 
+// Get all bitmaps
+// (zoomFactor, format)
+$bitmaps = $phpLiveDocx->getAllBitmaps(100, 'png');
+ 
+// Get just bitmaps in specified range
+// (fromPage, toPage, zoomFactor, format)
+// $bitmaps = $phpLiveDocx->getBitmaps(2, 2, 100, 'png');
+ 
+foreach ($bitmaps as $pageNumber => $bitmapData) {
+    $filename = sprintf('documentPage%d.png', $pageNumber);
+    file_put_contents($filename, $bitmapData);
+}
+]]></programlisting>
+
+            <para>
+                This produces two files (<filename>documentPage1.png</filename> and
+                <filename>documentPage2.png</filename>) and writes them to disk in the same
+                directory as the executable PHP file.
+            </para>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.bitmaps-documentpage1.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        documentPage1.png (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.bitmaps-documentpage1_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+            
+            <mediaobject>
+                <imageobject>
+                    <imagedata fileref="./figures/zend.service.livedocx.mailmerge.bitmaps-documentpage2.png"
+                        format="png"></imagedata>
+                </imageobject>
+
+                <caption>
+                    <para>
+                        documentPage2.png (<ulink
+                            url="./figures/zend.service.livedocx.mailmerge.bitmaps-documentpage2_zoom.png">view
+                            larger</ulink>).
+                    </para>
+                </caption>
+            </mediaobject>
+        </example>
+
+        <sect3 id="zend.service.livedocx.mailmerge.templates-types">
+            <title>Local vs. Remote Templates</title>
+    
+            <para>
+                Templates can be stored <emphasis>locally</emphasis>, on the client machine, or
+                <emphasis>remotely</emphasis>, on the server. There are advantages and disadvantages
+                to each approach.
+            </para>
+    
+            <para>
+                In the case that a template is stored locally, it must be transfered from the client
+                to the server on every request. If the content of the template rarely changes, this
+                approach is inefficient. Similarly, if the template is several megabytes in size, it
+                may take considerable time to transfer it to the server. Local template are useful
+                in situations in which the content of the template is constantly changing.
+            </para>
+    
+            <para>
+                The following code illustrates how to use a local template.
+            </para>
+    
+            <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+ 
+$phpLiveDocx->setLocalTemplate('./template.docx');
+ 
+// assign data and create document
+]]></programlisting>
+    
+            <para>
+                In the case that a template is stored remotely, it is uploaded once to the server
+                and then simply referenced on all subsequent requests. Obviously, this is much
+                quicker than using a local template, as the template does not have to be transfered
+                on every request. For speed critical applications, it is recommended to use the
+                remote template method.
+            </para>
+    
+            <para>
+                The following code illustrates how to upload a template to the server:
+            </para>
+    
+            <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+ 
+$phpLiveDocx->uploadTemplate('template.docx');
+]]></programlisting>
+    
+            <para>
+                The following code illustrates how to reference the remotely stored template on all
+                subsequent requests:
+            </para>
+    
+            <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+ 
+$phpLiveDocx->setRemoteTemplate('template.docx');
+ 
+// assign data and create document
+]]></programlisting>
+        </sect3>
+
+        <sect3 id="zend.service.livedocx.mailmerge.information">
+            <title>Getting Information</title>
+    
+            <para>
+                <classname>Zend_Service_LiveDocx_MailMerge</classname> provides a number of methods
+                to get information on field names, available fonts and supported formats.
+            </para>
+    
+            <example id="zend.service.livedocx.mailmerge.information.getfieldname">
+                <title>Get Array of Field Names in Template</title>
+    
+                <para>
+                    The following code returns and displays an array of all field names in the
+                    specified template. This functionality is useful, in the case that you create an
+                    application, in which an end-user can update a template.
+                </para>
+    
+                <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+
+$templateName = 'template-1-text-field.docx';
+$phpLiveDocx->setLocalTemplate($templateName);
+
+$fieldNames = $phpLiveDocx->getFieldNames();
+foreach ($fieldNames as $fieldName) {
+    printf('- %s%s', $fieldName, PHP_EOL);   
+}
+]]></programlisting>            
+            </example>
+    
+            <example id="zend.service.livedocx.mailmerge.information.getblockfieldname">
+                <title>Get Array of Block Field Names in Template</title>
+    
+                <para>
+                    The following code returns and displays an array of all block field names in the
+                    specified template. This functionality is useful, in the case that you create an
+                    application, in which an end-user can update a template. Before such templates
+                    can be populated, it is necessary to find out the names of the contained block
+                    fields.
+                </para>
+    
+                <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+
+$templateName = 'template-block-fields.doc';
+$phpLiveDocx->setLocalTemplate($templateName);
+
+$blockNames = $phpLiveDocx->getBlockNames();
+foreach ($blockNames as $blockName) {
+    $blockFieldNames = $phpLiveDocx->getBlockFieldNames($blockName);
+    foreach ($blockFieldNames as $blockFieldName) {
+        printf('- %s::%s%s', $blockName, $blockFieldName, PHP_EOL);          
+    }
+}
+]]></programlisting>            
+            </example>
+    
+            <example id="zend.service.livedocx.mailmerge.information.getfontnames">
+                <title>Get Array of Fonts Installed on Server</title>
+    
+                <para>
+                    The following code returns and displays an array of all fonts installed on the
+                    server. You can use this method to present a list of fonts which may be used in
+                    a template. It is important to inform the end-user about the fonts installed on
+                    the server, as only these fonts may be used in a template. In the case that a
+                    template contains fonts, which are not available on the server,
+                    font-substitution will take place. This may lead to undesirable results.
+                </para>
+    
+            <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+
+Zend_Debug::dump($phpLiveDocx->getFontNames());
+]]></programlisting>            
+    
+                <para>
+                    <emphasis>NOTE:</emphasis> As the return value of this method changes very
+                    infrequently, it is highly recommended to use a cache, such as
+                    <classname>Zend_Cache</classname> - this will considerably speed up your
+                    application.
+                </para>
+            </example>
+    
+            <example id="zend.service.livedocx.mailmerge.information.gettemplateformats">
+                <title>Get Array of Supported Template File Formats</title>
+    
+                <para>
+                    The following code returns and displays an array of all supported template file
+                    formats. This method is particularly useful in the case that a combo list should
+                    be displayed that allows the end-user to select the input format of the
+                    documentation generation process.
+                </para>
+    
+                <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge()
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+
+Zend_Debug::dump($phpLiveDocx->getTemplateFormats());
+]]></programlisting>    
+    
+                <para>
+                    <emphasis>NOTE:</emphasis> As the return value of this method changes very
+                    infrequently, it is highly recommended to use a cache, such as
+                    <classname>Zend_Cache</classname> - this will considerably speed up your
+                    application.
+                </para>        
+            </example>
+    
+            <example id="zend.service.livedocx.mailmerge.information.gettemplateformats">
+                <title>Get Array of Supported Document File Formats</title>
+    
+                <para>
+                    The following code returns and displays an array of all supported document file
+                    formats. This method is particularly useful in the case that a combo list should
+                    be displayed that allows the end-user to select the output format of the
+                    documentation generation process.
+                </para>
+    
+                <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+
+Zend_Debug::dump($phpLiveDocx->getDocumentFormats());
+]]></programlisting>            
+            </example>
+    
+            <example id="zend.service.livedocx.mailmerge.information.getimageformats">
+                <title>Get Array of Supported Image File Formats</title>
+    
+                <para>
+                    The following code returns and displays an array of all supported image file
+                    formats. This method is particularly useful in the case that a combo list should
+                    be displayed that allows the end-user to select the output format of the
+                    documentation generation process.
+                </para>
+    
+                <programlisting language="php"><![CDATA[
+$phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+
+$phpLiveDocx->setUsername('myUsername')
+            ->setPassword('myPassword');
+
+Zend_Debug::dump($phpLiveDocx->getImageFormats());
+]]></programlisting>    
+    
+                <para>
+                    <emphasis>NOTE:</emphasis> As the return value of this method changes very
+                    infrequently, it is highly recommended to use a cache, such as
+                    <classname>Zend_Cache</classname> - this will considerably speed up your
+                    application.
+                </para>        
+            </example>
+        </sect3>
+    </sect2>
+</sect1>
+<!--
+vim:se ts=4 sw=4 tw=100 et:
+-->

+ 370 - 0
library/Zend/LiveDocx.php

@@ -0,0 +1,370 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage LiveDocx
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage LiveDocx
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_LiveDocx
+{
+    /**
+     * LiveDocx service version
+     */
+    const VERSION = '1.2';
+
+    /**
+     * SOAP client used to connect to LiveDocx service
+     * @var Zend_Soap_Client
+     */
+    protected $_soapClient;
+        
+    /**
+     * Endpoint of public LiveDocx service WSDL
+     * @var string
+     */
+    protected $_endpoint;
+        
+    /**
+     * Array of credentials (username and password) to log into backend server
+     * @var array
+     */
+    protected $_credentials;
+    
+    /**
+     * Set to true, when session is logged into backend server
+     * @var boolean
+     */
+    protected $_loggedIn;
+    
+    /**
+     * Constructor
+     *
+     * Optionally, pass an array of options (or Zend_Config object).
+     * 
+     * If an option with the key 'soapClient' is provided, that value will be 
+     * used to set the internal SOAP client used to connect to the LiveDocx
+     * service.
+     * 
+     * Use 'soapClient' in the case that you have a dedicated or (locally
+     * installed) licensed LiveDocx server. For example:
+     *
+     * {code}
+     * $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(
+     *     array (
+     *         'username'   => 'myUsername',
+     *         'password'   => 'myPassword',
+     *         'soapClient' => new Zend_Soap_Client('https://api.example.com/path/mailmerge.asmx?WSDL')
+     *     )
+     * );
+     * {code}
+     * 
+     * Replace the URI of the WSDL in the constructor of Zend_Soap_Client with
+     * that of your dedicated or licensed LiveDocx server.
+     *
+     * If you are using the public LiveDocx server, simply pass 'username' and
+     * 'password'. For example:
+     *
+     * {code}
+     * $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(
+     *     array (
+     *         'username' => 'myUsername',
+     *         'password' => 'myPassword'
+     *     )
+     * );
+     * {code}
+     * 
+     * If you prefer to not pass the username and password through the
+     * constructor, you can also call the following methods:
+     * 
+     * {code}
+     * $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+     * 
+     * $phpLiveDocx->setUsername('myUsername');
+     * $phpLiveDocx->setPassword('myPassword');
+     * {/code}
+     * 
+     * Or, if you want to specify your own SoapClient:
+     * 
+     * {code}
+     * $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+     * 
+     * $phpLiveDocx->setUsername('myUsername');
+     * $phpLiveDocx->setPassword('myPassword');
+     * 
+     * $phpLiveDocx->setSoapClient(
+     *     new Zend_Soap_Client('https://api.example.com/path/mailmerge.asmx?WSDL')
+     * );
+     * {/code} 
+     *
+     * @param  array|Zend_Config $options
+     * @return void
+     * @throws Zend_Service_LiveDocx_Exception
+     */    
+    public function __construct($options = null)
+    {
+        $this->_credentials = array();
+        $this->_loggedIn = false;
+        
+        if ($options instanceof Zend_Config) {
+            $options = $options->toArray();
+        }
+        
+        if (is_array($options)) {
+            $this->setOptions($options);
+        }
+    }
+    
+    /**
+     * Set options
+     * One or more of username, password, soapClient
+     * 
+     * @param $options
+     * @return $this
+     */
+    public function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            $method = 'set' . $key;
+            if (method_exists($this, $method)) {
+                $this->$method($value);
+            }
+        }
+        
+        return $this;
+    }
+        
+    /**
+     * Clean up and log out of LiveDocx service
+     *
+     * @return boolean
+     */
+    public function __destruct()
+    {
+        return $this->logOut();
+    }
+    
+    /**
+     * Init Soap client - connect to SOAP service
+     *
+     * @param string $endpoint
+     * @throws Zend_Service_LiveDocx_Exception
+     * @return void
+     */
+    protected function _initSoapClient($endpoint)
+    {
+        try {
+            require_once 'Zend/Soap/Client.php';
+            $this->_soapClient = new Zend_Soap_Client();
+            $this->_soapClient->setWsdl($endpoint);                
+        } catch (Zend_Soap_Client_Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception('Cannot connect to LiveDocx service at ' . $endpoint, 0, $e);
+        }            
+    }
+    
+    /**
+     * Get SOAP client
+     *
+     * @return Zend_Soap_Client
+     */
+    public function getSoapClient()
+    {
+        return $this->_soapClient;
+    }
+    
+    /**
+     * Set SOAP client
+     *
+     * @param  Zend_Soap_Client $soapClient
+     * @return Zend_Service_LiveDocx
+     */
+    public function setSoapClient(Zend_Soap_Client $soapClient)
+    {
+        $this->_soapClient = $soapClient;
+    }
+
+    /**
+     * Log in to LiveDocx service
+     *
+     * @param string $username
+     * @param string $password
+     *
+     * @throws Zend_Service_LiveDocx_Exception
+     * @return boolean
+     */
+    public function logIn()
+    {
+        if (!$this->isLoggedIn()) {
+            if (null === $this->getUsername()) {
+                require_once 'Zend/Service/LiveDocx/Exception.php';
+                throw new Zend_Service_LiveDocx_Exception(
+                    'Username has not been set. To set username specify the options array in the constructor or call setUsername($username) after instantiation', 0, $e
+                );
+            }
+            
+            if (null === $this->getPassword()) {
+                require_once 'Zend/Service/LiveDocx/Exception.php';
+                throw new Zend_Service_LiveDocx_Exception(
+                    'Password has not been set. To set password specify the options array in the constructor or call setPassword($password) after instantiation', 0, $e
+                );
+            }
+            
+            if (null === ($client = $this->getSoapClient())) {
+                $this->_initSoapClient($this->_endpoint);
+            }            
+            
+            try {
+                $client->LogIn(array(
+                    'username' => $this->getUsername(),
+                    'password' => $this->getPassword(),
+                ));
+                $this->_loggedIn = true;
+            } catch (Exception $e) {
+                require_once 'Zend/Service/LiveDocx/Exception.php';
+                throw new Zend_Service_LiveDocx_Exception(
+                    'Cannot login into LiveDocx service - username and/or password are invalid', 0, $e
+                );
+            }            
+        }
+        
+        return $this->_loggedIn;
+    }
+
+    /**
+     * Log out of the LiveDocx service
+     *
+     * @throws Zend_Service_LiveDocx_Exception
+     * @return boolean
+     */
+    public function logOut()
+    {
+        if ($this->isLoggedIn()) {
+            try {
+                $this->getSoapClient()->LogOut();
+                $this->_loggedIn = false;
+            } catch (Exception $e) {
+                require_once 'Zend/Service/LiveDocx/Exception.php';
+                throw new Zend_Service_LiveDocx_Exception(
+                    'Cannot log out of LiveDocx service', 0, $e
+                );
+            }            
+        }
+        
+        return $this->_loggedIn;
+    }
+    
+    /**
+     * Return true, if session is currently logged into the backend server
+     * 
+     * @return boolean
+     */
+    public function isLoggedIn()
+    {
+        return $this->_loggedIn;
+    }
+
+    /**
+     * Set username
+     * 
+     * @return Zend_Service_LiveDocx
+     */
+    public function setUsername($username)
+    {
+        $this->_credentials['username'] = $username;
+        return $this;
+    }
+    
+    /**
+     * Set password
+     * 
+     * @return Zend_Service_LiveDocx
+     */    
+    public function setPassword($password)
+    {
+        $this->_credentials['password'] = $password;
+        return $this;
+    }
+      
+    /**
+     * Return current username
+     * 
+     * @return string|null
+     */
+    public function getUsername()
+    {
+        if (isset($this->_credentials['username'])) {
+            return $this->_credentials['username'];
+        }
+        
+        return null;
+    }
+    
+    /**
+     * Return current password
+     * 
+     * @return string|null
+     */    
+    public function getPassword()
+    {
+        if (isset($this->_credentials['password'])) {
+            return $this->_credentials['password'];
+        }
+        
+        return null; 
+    }
+
+    /**
+     * Return the document format (extension) of a filename
+     *
+     * @param string $filename
+     *
+     * @return string
+     */
+    public function getFormat($filename)
+    {
+        return strtolower(substr(strrchr($filename, '.'), 1));
+    }
+    
+    /**
+     * Return the current API version
+     *
+     * @return string
+     */
+    public function getVersion()
+    {
+        return self::VERSION;
+    }
+    
+    /**
+     * Compare the current API version with another version
+     *
+     * @param  string $version (STRING NOT FLOAT)
+     * @return int -1 (version is less than API version), 0 (versions are equal), or 1 (version is greater than API version)
+     */
+    public function compareVersion($version)
+    {
+        return version_compare($version, $this->getVersion());
+    }
+}

+ 38 - 0
library/Zend/LiveDocx/Exception.php

@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage LiveDocx
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_Exception
+ */
+require_once 'Zend/Service/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage LiveDocx
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_LiveDocx_Exception extends Zend_Service_Exception
+{
+}

+ 934 - 0
library/Zend/LiveDocx/MailMerge.php

@@ -0,0 +1,934 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage LiveDocx
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Date **/
+require_once 'Zend/Date.php';
+
+/** Zend_Service_LiveDocx **/
+require_once 'Zend/Service/LiveDocx.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage LiveDocx
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
+{
+    /**
+     * URI of LiveDocx.MailMerge service
+     */
+    const ENDPOINT = 'https://api.livedocx.com/1.2/mailmerge.asmx?WSDL';
+
+    /**
+     * Field values
+     *
+     * @var array
+     */
+    protected $_fieldValues;
+
+    /**
+     * Block field values
+     *
+     * @var array
+     */
+    protected $_blockFieldValues;
+
+    /**
+     * Document properties of PDF file (only)
+     *
+     * @var array
+     */
+    protected $_documentProperties;
+
+    /**
+     * Constructor (LiveDocx.MailMerge SOAP Service)
+     *
+     * @return void
+     * @return throws Zend_Service_LiveDocx_Exception
+     */
+    public function __construct($options = null)
+    {
+        $this->_endpoint         = self::ENDPOINT;
+        $this->_fieldValues      = array();
+        $this->_blockFieldValues = array();
+        
+        $this->_setDefaultDocumentProperties();
+        
+        parent::__construct($options);
+    }
+
+    /**
+     * Set the filename of a LOCAL template
+     * (i.e. a template stored locally on YOUR server)
+     *
+     * @param  string $filename
+     * @return Zend_Service_LiveDocx_MailMerge
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function setLocalTemplate($filename)
+    {
+        $this->logIn();
+        
+        try {
+            $this->getSoapClient()->SetLocalTemplate(array(
+                'template' => base64_encode(file_get_contents($filename)),
+                'format'   => self::getFormat($filename),
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot set local template', 0, $e
+            );
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set the filename of a REMOTE template
+     * (i.e. a template stored remotely on the LIVEDOCX server)
+     *
+     * @param  string $filename
+     * @return Zend_Service_LiveDocx_MailMerge
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function setRemoteTemplate($filename)
+    {
+        $this->logIn();
+        
+        try {
+            $this->getSoapClient()->SetRemoteTemplate(array(
+                'filename' => $filename,
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot set remote template', 0, $e
+            );
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set an associative or multi-associative array of keys and values pairs
+     *
+     * @param  array $values
+     * @return Zend_Service_LiveDocx_MailMerge
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function setFieldValues($values)
+    {
+        $this->logIn();
+        
+        foreach ($values as $value) {
+            if (is_array($value)) {
+                $method = 'multiAssocArrayToArrayOfArrayOfString';
+            } else {
+                $method = 'assocArrayToArrayOfArrayOfString';
+            }
+            break;
+        }
+        
+        try {
+            $this->getSoapClient()->SetFieldValues(array(
+                'fieldValues' => self::$method($values),
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot set field values', 0, $e
+            );
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set an array of key and value or array of values
+     *
+     * @param string $field
+     * @param array|string $value
+     *
+     * @throws Zend_Service_LiveDocx_Exception
+     * @return Zend_Service_LiveDocx_MailMerge
+     */
+    public function setFieldValue($field, $value)
+    {
+        $this->_fieldValues[$field] = $value;
+        return $this;
+    }
+
+    /**
+     * Set block field values
+     *
+     * @param string $blockName
+     * @param array $blockFieldValues
+     *
+     * @return Zend_Service_LiveDocx_MailMerge
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function setBlockFieldValues($blockName, $blockFieldValues)
+    {
+        $this->logIn();
+        
+        try {
+            $this->getSoapClient()->SetBlockFieldValues(array(
+                'blockName'        => $blockName,
+                'blockFieldValues' => self::multiAssocArrayToArrayOfArrayOfString($blockFieldValues)
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot set block field values', 0, $e
+            );
+        }
+
+        return $this;
+    }
+
+    /**
+     * Assign values to template fields
+     *
+     * @param array|string $field
+     * @param array|string $value
+     * @return Zend_Service_LiveDocx_MailMerge
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function assign($field, $value = null)
+    {
+        try {
+            if (is_array($field) && (null === $value)) {
+                foreach ($field as $fieldName => $fieldValue) {
+                    $this->setFieldValue($fieldName, $fieldValue);
+                }
+            } elseif (is_array($value)) {
+                $this->setBlockFieldValues($field, $value);
+            } else {
+                $this->setFieldValue($field, $value);
+            }
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot assign data to template', 0, $e
+            );
+        }
+
+        return $this;
+    }
+
+    /**
+     * Merge assigned data with template to generate document
+     *
+     * @throws Zend_Service_LiveDocx_Excpetion
+     * @return void
+     */
+    public function createDocument()
+    {
+        $this->logIn();
+        
+        if (count($this->_fieldValues) > 0) {
+            $this->setFieldValues($this->_fieldValues);
+        }
+
+        $this->_fieldValues      = array();
+        $this->_blockFieldValues = array();
+
+        try {
+            $this->getSoapClient()->CreateDocument();
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot create document', 0, $e
+            );
+        }
+    }
+
+    /**
+     * Retrieve document in specified format
+     *
+     * @param string $format
+     *
+     * @throws Zend_Service_LiveDocx_Exception
+     * @return binary
+     */
+    public function retrieveDocument($format)
+    {
+        $this->logIn();
+        
+        $ret    = null;
+        $format = strtolower($format);
+        
+        try {
+            $result = $this->getSoapClient()->RetrieveDocument(array(
+                'format' => $format,
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot retrieve document - call setLocalTemplate() or setRemoteTemplate() first', 0, $e
+            );
+        }
+
+        $ret = base64_decode($result->RetrieveDocumentResult);
+
+        if ('pdf' === $format) {
+            require_once 'Zend/Pdf.php';
+            $pdf = Zend_Pdf::parse($ret);
+            $pdf->properties = $this->_getDocumentProperties();
+            $ret = $pdf->render();
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Return WMF (aka Windows metafile) data for specified page range of created document
+     * Return array contains WMF data (binary) - array key is page number
+     *
+     * @param  integer $fromPage
+     * @param  integer $toPage
+     * @return array
+     */
+    public function getMetafiles($fromPage, $toPage)
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetMetafiles(array(
+            'fromPage' => (integer) $fromPage,
+            'toPage'   => (integer) $toPage,
+        ));
+
+        if (isset($result->GetMetafilesResult->string)) {
+            $pageCounter = (integer) $fromPage;
+            if (is_array($result->GetMetafilesResult->string)) {
+                foreach ($result->GetMetafilesResult->string as $string) {
+                    $ret[$pageCounter] = base64_decode($string);
+                    $pageCounter++;
+                }
+            } else {
+               $ret[$pageCounter] = base64_decode($result->GetMetafilesResult->string);
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Return WMF (aka Windows metafile) data for pages of created document
+     * Return array contains WMF data (binary) - array key is page number
+     *
+     * @return array
+     */
+    public function getAllMetafiles()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetAllMetafiles();
+
+        if (isset($result->GetAllMetafilesResult->string)) {
+            $pageCounter = 1;
+            if (is_array($result->GetAllMetafilesResult->string)) {
+                foreach ($result->GetAllMetafilesResult->string as $string) {
+                    $ret[$pageCounter] = base64_decode($string);
+                    $pageCounter++;
+                }
+            } else {
+               $ret[$pageCounter] = base64_decode($result->GetAllMetafilesResult->string);
+            }
+        }
+
+        return $ret;
+    }    
+    
+    /**
+     * Return graphical bitmap data for specified page range of created document
+     * Return array contains bitmap data (binary) - array key is page number
+     *
+     * @param  integer $fromPage
+     * @param  integer $toPage
+     * @param  integer $zoomFactor
+     * @param  string  $format
+     * @return array
+     */    
+    public function getBitmaps($fromPage, $toPage, $zoomFactor, $format)
+    {
+        $this->logIn();
+        
+        $ret = array();
+        
+        $result = $this->getSoapClient()->GetBitmaps(array(
+            'fromPage'   => (integer) $fromPage,
+            'toPage'     => (integer) $toPage,
+            'zoomFactor' => (integer) $zoomFactor,
+            'format'     => (string)  $format,
+        ));
+
+        if (isset($result->GetBitmapsResult->string)) {
+            $pageCounter = (integer) $fromPage;
+            if (is_array($result->GetBitmapsResult->string)) {
+                foreach ($result->GetBitmapsResult->string as $string) {
+                    $ret[$pageCounter] = base64_decode($string);
+                    $pageCounter++;
+                }
+            } else {
+               $ret[$pageCounter] = base64_decode($result->GetBitmapsResult->string);
+            }
+        }
+
+        return $ret;        
+    }
+    
+    /**
+     * Return graphical bitmap data for all pages of created document
+     * Return array contains bitmap data (binary) - array key is page number
+     *
+     * @param  integer $zoomFactor
+     * @param  string  $format
+     * @return array
+     */    
+    public function getAllBitmaps($zoomFactor, $format)
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetAllBitmaps(array(
+            'zoomFactor' => (integer) $zoomFactor,
+            'format'     => (string)  $format,
+        ));
+
+        if (isset($result->GetAllBitmapsResult->string)) {
+            $pageCounter = 1;
+            if (is_array($result->GetAllBitmapsResult->string)) {
+                foreach ($result->GetAllBitmapsResult->string as $string) {
+                    $ret[$pageCounter] = base64_decode($string);
+                    $pageCounter++;
+                }
+            } else {
+               $ret[$pageCounter] = base64_decode($result->GetAllBitmapsResult->string);
+            }
+        }
+
+        return $ret;        
+    }    
+
+    /**
+     * Return all the fields in the template
+     *
+     * @return array
+     */
+    public function getFieldNames()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetFieldNames();
+
+        if (isset($result->GetFieldNamesResult->string)) {
+            if (is_array($result->GetFieldNamesResult->string)) {
+                $ret = $result->GetFieldNamesResult->string;
+            } else {
+                $ret[] = $result->GetFieldNamesResult->string;
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Return all the block fields in the template
+     *
+     * @param  string $blockName
+     * @return array
+     */
+    public function getBlockFieldNames($blockName)
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetBlockFieldNames(array(
+            'blockName' => $blockName
+        ));
+
+        if (isset($result->GetBlockFieldNamesResult->string)) {
+            if (is_array($result->GetBlockFieldNamesResult->string)) {
+                $ret = $result->GetBlockFieldNamesResult->string;
+            } else {
+                $ret[] = $result->GetBlockFieldNamesResult->string;
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Return all the block fields in the template
+     *
+     * @return array
+     */
+    public function getBlockNames()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetBlockNames();
+
+        if (isset($result->GetBlockNamesResult->string)) {
+            if (is_array($result->GetBlockNamesResult->string)) {
+                $ret = $result->GetBlockNamesResult->string;
+            } else {
+                $ret[] = $result->GetBlockNamesResult->string;
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Set the default document properties
+     *
+     * Valid for PDF documents only
+     *
+     * @return null
+     */
+    protected function _setDefaultDocumentProperties()
+    {
+        $date = new Zend_Date();
+
+        $this->_documentProperties = array();
+
+        $projectName  = sprintf('phpLiveDocx %s', self::getVersion());
+        $projectUrl   = 'http://www.phpLiveDocx.org';
+        $creationDate = sprintf('D:%s', $date->toString('YYYYMMddHHmmss'));
+        
+        // Zend_Pdf expects keys with uppercase first letter
+        $this->_documentProperties['Creator']      = $projectName;
+        $this->_documentProperties['Producer']     = $projectUrl;
+        $this->_documentProperties['CreationDate'] = $creationDate;
+        $this->_documentProperties['ModDate']      = $creationDate;
+    }
+
+    /**
+     * Set the document properties
+     *
+     * Valid for PDF documents only
+     *
+     * $properties is an assoc array with the following format:
+     *
+     * {code}
+     * $properties = array (
+     *     'title'        => '', // (string)
+     *     'author'       => '', // (string)
+     *     'subject'      => '', // (string)
+     *     'keywords'     => '', // (string)
+     * );
+     * {code}
+     *
+     * @param  array $properties
+     * @return Zend_Service_LiveDocx_MailMerge
+     */
+    public function setDocumentProperties($properties)
+    {
+        // For consistency, keys in $properties are lowercase.
+        // Zend_Pdf expects keys with uppercase first letter
+        $keys = array('Title', 'Author', 'Subject', 'Keywords');
+        foreach ($keys as $key) {
+            $lowerCaseKey = strtolower($key);
+            if (isset($properties[$lowerCaseKey])) {
+                $this->_documentProperties[$key] = $properties[$lowerCaseKey];
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Return currently set document properties
+     *
+     * @return array
+     */
+    protected function _getDocumentProperties()
+    {
+        return $this->_documentProperties;
+    }
+
+    /**
+     * Upload a template file to LiveDocx service
+     *
+     * @param  string $filename
+     * @return void
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function uploadTemplate($filename)
+    {
+        $this->logIn();
+        
+        try {
+            $this->getSoapClient()->UploadTemplate(array(
+                'template' => base64_encode(file_get_contents($filename)),
+                'filename' => basename($filename),
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot upload template', 0, $e
+            );
+        }
+    }
+
+    /**
+     * Download template file from LiveDocx service
+     *
+     * @param  string $filename
+     * @return binary
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function downloadTemplate($filename)
+    {
+        $this->logIn();
+        
+        try {
+            $result = $this->getSoapClient()->DownloadTemplate(array(
+                'filename' => basename($filename),
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot download template', 0, $e
+            );
+        }
+
+        return base64_decode($result->DownloadTemplateResult);
+    }
+
+    /**
+     * Delete a template file from LiveDocx service
+     *
+     * @param  string $filename
+     * @return void
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function deleteTemplate($filename)
+    {
+        $this->logIn();
+        
+        $this->getSoapClient()->DeleteTemplate(array(
+            'filename' => basename($filename),
+        ));
+    }
+
+    /**
+     * List all templates stored on LiveDocx service
+     *
+     * @return array
+     */
+    public function listTemplates()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->ListTemplates();
+
+        if (isset($result->ListTemplatesResult)) {
+            $ret = $this->_backendListArrayToMultiAssocArray($result->ListTemplatesResult);
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Check whether a template file is available on LiveDocx service
+     *
+     * @param  string $filename
+     * @return boolean
+     */
+    public function templateExists($filename)
+    {
+        $this->logIn();
+        
+        $result = $this->getSoapClient()->TemplateExists(array(
+            'filename' => basename($filename),
+        ));
+
+        return (boolean) $result->TemplateExistsResult;
+    }
+
+    /**
+     * Share a document - i.e. the document is available to all over the Internet
+     *
+     * @return string
+     */
+    public function shareDocument()
+    {
+        $this->logIn();
+        
+        $ret    = null;
+        $result = $this->getSoapClient()->ShareDocument();
+
+        if (isset($result->ShareDocumentResult)) {
+            $ret = (string) $result->ShareDocumentResult;
+        }
+
+        return $ret;
+    }
+
+    /**
+     * List all shared documents stored on LiveDocx service
+     *
+     * @return array
+     */
+    public function listSharedDocuments()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->ListSharedDocuments();
+
+        if (isset($result->ListSharedDocumentsResult)) {
+            $ret = $this->_backendListArrayToMultiAssocArray(
+                $result->ListSharedDocumentsResult
+            );
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Delete a shared document from LiveDocx service
+     *
+     * @param  string $filename
+     * @return void
+     */
+    public function deleteSharedDocument($filename)
+    {
+        $this->logIn();
+        
+        $this->getSoapClient()->DeleteSharedDocument(array(
+            'filename' => basename($filename),
+        ));
+    }
+
+    /*
+     * Download a shared document from LiveDocx service
+     *
+     * @param  string $filename
+     * @return binary
+     * @throws Zend_Service_LiveDocx_Exception
+     */
+    public function downloadSharedDocument($filename)
+    {
+        $this->logIn();
+        
+        try {
+            $result = $this->getSoapClient()->DownloadSharedDocument(array(
+                'filename' => basename($filename),
+            ));
+        } catch (Exception $e) {
+            require_once 'Zend/Service/LiveDocx/Exception.php';
+            throw new Zend_Service_LiveDocx_Exception(
+                'Cannot download shared document', 0, $e
+            );
+        }
+
+        return base64_decode($result->DownloadSharedDocumentResult);
+    }
+
+    /**
+     * Check whether a shared document is available on LiveDocx service
+     *
+     * @param  string $filename
+     * @return boolean
+     */
+    public function sharedDocumentExists($filename)
+    {
+        $this->logIn();
+        
+        $ret             = false;
+        $sharedDocuments = $this->listSharedDocuments();
+        foreach ($sharedDocuments as $shareDocument) {
+            if (isset($shareDocument['filename']) 
+                && (basename($filename) === $shareDocument['filename'])
+            ) {
+                $ret = true;
+                break;
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Return supported template formats (lowercase)
+     *
+     * @return array
+     */
+    public function getTemplateFormats()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetTemplateFormats();
+
+        if (isset($result->GetTemplateFormatsResult->string)) {
+            $ret = $result->GetTemplateFormatsResult->string;
+            $ret = array_map('strtolower', $ret);
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Return supported document formats (lowercase)
+     *
+     * @return array
+     */
+    public function getDocumentFormats()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetDocumentFormats();
+
+        if (isset($result->GetDocumentFormatsResult->string)) {
+            $ret = $result->GetDocumentFormatsResult->string;
+            $ret = array_map('strtolower', $ret);
+        }
+
+        return $ret;
+    }
+    
+    /*
+     * Return supported image formats (lowercase)
+     *
+     * @return array
+     */
+    public function getImageFormats()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetImageFormats();
+
+        if (isset($result->GetImageFormatsResult->string)) {
+            $ret = $result->GetImageFormatsResult->string;
+            $ret = array_map('strtolower', $ret);
+        }
+
+        return $ret;
+    }
+        
+    /**
+     * Return the names of all fonts that are installed on backend server
+     *
+     * @return array
+     */
+    public function getFontNames()
+    {
+        $this->logIn();
+        
+        $ret    = array();
+        $result = $this->getSoapClient()->GetFontNames();
+
+        if (isset($result->GetFontNamesResult->string)) {
+            $ret = $result->GetFontNamesResult->string;
+        }
+
+        return $ret;
+    }    
+
+    /**
+     * Convert LiveDocx service return value from list methods to consistent PHP array
+     *
+     * @param  array $list
+     * @return array
+     */
+    protected function _backendListArrayToMultiAssocArray($list)
+    {
+        $this->logIn();
+        
+        $ret = array();
+        if (isset($list->ArrayOfString)) {
+           foreach ($list->ArrayOfString as $a) {
+               if (is_array($a)) {      // 1 template only
+                   $o = new stdClass();
+                   $o->string = $a;
+               } else {                 // 2 or more templates
+                   $o = $a;
+               }
+               unset($a);
+
+               if (isset($o->string)) {
+                   $date1 = new Zend_Date($o->string[3], Zend_Date::RFC_1123);
+                   $date2 = new Zend_Date($o->string[1], Zend_Date::RFC_1123);
+
+                   $ret[] = array (
+                        'filename'   => $o->string[0],
+                        'fileSize'   => (integer) $o->string[2],
+                        'createTime' => (integer) $date1->get(Zend_Date::TIMESTAMP),
+                        'modifyTime' => (integer) $date2->get(Zend_Date::TIMESTAMP),
+                   );
+               }
+           }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Convert assoc array to required SOAP type
+     *
+     * @param array $assoc
+     *
+     * @return array
+     */
+    public static function assocArrayToArrayOfArrayOfString($assoc)
+    {
+        $arrayKeys   = array_keys($assoc);
+        $arrayValues = array_values($assoc);
+        
+        return array($arrayKeys, $arrayValues);
+    }
+
+    /**
+     * Convert multi assoc array to required SOAP type
+     *
+     * @param  array $multi
+     * @return array
+     */
+    public static function multiAssocArrayToArrayOfArrayOfString($multi)
+    {
+        $arrayKeys   = array_keys($multi[0]);
+        $arrayValues = array();
+
+        foreach ($multi as $v) {
+            $arrayValues[] = array_values($v);
+        }
+
+        $arrayKeys = array($arrayKeys);
+
+        return array_merge($arrayKeys, $arrayValues);
+    }
+}

+ 6 - 0
tests/Zend/Service/AllTests.php

@@ -61,6 +61,11 @@ require_once 'Zend/Service/Delicious/AllTests.php';
 require_once 'Zend/Service/Flickr/AllTests.php';
 
 /**
+ * @see Zend_Service_LiveDocx_AllTests
+ */
+require_once 'Zend/Service/LiveDocx/AllTests.php';
+
+/**
  * @see Zend_Service_Nirvanix_AllTests
  */
 require_once 'Zend/Service/Nirvanix/AllTests.php';
@@ -140,6 +145,7 @@ class Zend_Service_AllTests
         $suite->addTest(Zend_Service_Audioscrobbler_AllTests::suite());
         $suite->addTest(Zend_Service_Delicious_AllTests::suite());
         $suite->addTest(Zend_Service_Flickr_AllTests::suite());
+        $suite->addTest(Zend_Service_LiveDocx_AllTests::suite());
         $suite->addTest(Zend_Service_Nirvanix_AllTests::suite());
         $suite->addTest(Zend_Service_ReCaptcha_AllTests::suite());
         $suite->addTest(Zend_Service_Simpy_AllTests::suite());

+ 65 - 0
tests/Zend/Service/LiveDocx/AllTests.php

@@ -0,0 +1,65 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_LiveDocx
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: $
+ */
+
+if (!defined('PHPUnit_MAIN_METHOD')) {
+    define('PHPUnit_MAIN_METHOD', 'Zend_Service_LiveDocx_AllTests::main');
+}
+
+/**
+ * Test helper
+ */
+require_once dirname(__FILE__) . '/../../../TestHelper.php';
+
+require_once 'Zend/Service/LiveDocx/LiveDocxTest.php';
+require_once 'Zend/Service/LiveDocx/MailMergeTest.php';
+
+/**
+ * Zend_Service_LiveDocx test suite
+ *
+ * @category   Zend
+ * @package    Zend_Service_LiveDocx
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: $
+ */
+class Zend_Service_LiveDocx_AllTests
+{
+    public static function main()
+    {
+        PHPUnit_TextUI_TestRunner::run(self::suite());
+    }
+
+    public static function suite()
+    {
+        $suite = new PHPUnit_Framework_TestSuite('Zend Framework - Zend_Service - LiveDocX');
+
+        $suite->addTestSuite('Zend_Service_LiveDocx_LiveDocxTest');
+        $suite->addTestSuite('Zend_Service_LiveDocx_MailMergeTest');
+
+        return $suite;
+    }
+}
+
+if (PHPUnit_MAIN_METHOD == 'Zend_Service_LiveDocx_AllTests::main') {
+    Zend_Service_LiveDocx_AllTests::main();
+}

+ 99 - 0
tests/Zend/Service/LiveDocx/LiveDocxTest.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_LiveDocx
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: $
+ */
+
+if (!defined('PHPUnit_MAIN_METHOD')) {
+    define('PHPUnit_MAIN_METHOD', 'Zend_Service_LiveDocx_LiveDocxTest::main');
+}
+
+/**
+ * Test helper
+ */
+require_once dirname(__FILE__) . '/../../../TestHelper.php';
+
+/** Zend_Service_LiveDocx_MailMerge */
+require_once 'Zend/Service/LiveDocx/MailMerge.php';
+
+/**
+ * Zend_Service_LiveDocx test case
+ *
+ * @category   Zend
+ * @package    Zend_Service_LiveDocx
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: $
+ */
+class Zend_Service_LiveDocX_LiveDocxTest extends PHPUnit_Framework_TestCase
+{
+    public $phpLiveDocx;
+
+    public static function main()
+    {
+        $suite  = new PHPUnit_Framework_TestSuite(__CLASS__);
+        $result = PHPUnit_TextUI_TestRunner::run($suite);
+    }
+
+    public function setUp()
+    {
+        if (!constant('TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME')
+            || !constant('TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD')
+        ) {
+            $this->markTestSkipped('LiveDocx tests disabled');
+            return;
+        }
+        
+        $this->phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+        $this->phpLiveDocx->setUsername(TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME)
+                          ->setPassword(TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD);
+
+        foreach ($this->phpLiveDocx->listTemplates() as $template) {
+            $this->phpLiveDocx->deleteTemplate($template['filename']);
+        }        
+    }
+    
+    public function tearDown ()
+    {
+        foreach ($this->phpLiveDocx->listTemplates() as $template) {
+            $this->phpLiveDocx->deleteTemplate($template['filename']);
+        }   
+        unset($this->phpLiveDocx);
+    }
+
+    public function testGetFormat ()
+    {
+        $this->assertEquals('',    $this->phpLiveDocx->getFormat('document'));
+        $this->assertEquals('doc', $this->phpLiveDocx->getFormat('document.doc'));
+        $this->assertEquals('doc', $this->phpLiveDocx->getFormat('document-123.doc'));
+        $this->assertEquals('doc', $this->phpLiveDocx->getFormat('document123.doc'));
+        $this->assertEquals('doc', $this->phpLiveDocx->getFormat('document.123.doc'));
+    }
+    
+    public function testGetVersion ()
+    {
+        $expectedResults = '1.2';
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getVersion());
+    }
+}
+
+if (PHPUnit_MAIN_METHOD == 'Zend_Service_LiveDocx_LiveDocxTest::main') {
+    Zend_Service_LiveDocx_LiveDocxTest::main();
+}

BIN
tests/Zend/Service/LiveDocx/MailMerge/phpunit-template-block-fields.doc


BIN
tests/Zend/Service/LiveDocx/MailMerge/phpunit-template.docx


+ 654 - 0
tests/Zend/Service/LiveDocx/MailMergeTest.php

@@ -0,0 +1,654 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_LiveDocx
+ * @subpackage UnitTests
+ * @copyright  Copyright(c) 2005-2009 Zend Technologies USA Inc.(http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: $
+ */
+
+if (!defined('PHPUnit_MAIN_METHOD')) {
+    define('PHPUnit_MAIN_METHOD', 'Zend_Service_LiveDocx_MailMergeTest::main');
+}
+
+/**
+ * Test helper
+ */
+require_once dirname(__FILE__) . '/../../../TestHelper.php';
+
+/** Zend_Service_LiveDocx_MailMerge */
+require_once 'Zend/Service/LiveDocx/MailMerge.php';
+
+/**
+ * Zend_Service_LiveDocx test case
+ *
+ * @category   Zend
+ * @package    Zend_Service_LiveDocx
+ * @subpackage UnitTests
+ * @copyright  Copyright(c) 2005-2009 Zend Technologies USA Inc.(http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: $
+ */
+class Zend_Service_LiveDocx_MailMergeTest extends PHPUnit_Framework_TestCase
+{
+    const TEST_TEMPLATE_1 = 'phpunit-template.docx';
+    const TEST_TEMPLATE_2 = 'phpunit-template-block-fields.doc';
+    const ENDPOINT = 'https://api.livedocx.com/1.2/mailmerge.asmx?wsdl';
+
+    public $path;
+    public $phpLiveDocx;
+
+    // -------------------------------------------------------------------------
+
+    public static function main()
+    {
+        $suite  = new PHPUnit_Framework_TestSuite(__CLASS__);
+        $result = PHPUnit_TextUI_TestRunner::run($suite);
+    }
+
+    public function setUp()
+    {
+        if (!constant('TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME')
+            || !constant('TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD')
+        ) {
+            $this->markTestSkipped('LiveDocx tests disabled');
+            return;
+        }
+        
+        $this->phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+        $this->phpLiveDocx->setUsername(TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME)
+                          ->setPassword(TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD);
+
+        foreach($this->phpLiveDocx->listTemplates() as $template) {
+            $this->phpLiveDocx->deleteTemplate($template['filename']);
+        }
+
+        $this->path = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MailMerge');
+    }
+
+    public function tearDown()
+    {
+        foreach($this->phpLiveDocx->listTemplates() as $template) {
+            $this->phpLiveDocx->deleteTemplate($template['filename']);
+        }
+
+        unset($this->phpLiveDocx);
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testLoginUsernamePassword()
+    {
+        $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+        $phpLiveDocx->setUsername(TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME);
+        $phpLiveDocx->setPassword(TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD);
+        $this->assertTrue($phpLiveDocx->logIn()); 
+    }
+    
+    public function testLoginUsernamePasswordSoapClient()
+    {
+        $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+        $phpLiveDocx->setUsername(TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME);
+        $phpLiveDocx->setPassword(TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD);
+        $phpLiveDocx->setSoapClient(new Zend_Soap_Client(self::ENDPOINT));
+        $this->assertTrue($phpLiveDocx->logIn()); 
+    }    
+        
+    /**
+     * @expectedException Zend_Service_LiveDocx_Exception
+     */
+    public function testLoginUsernamePasswordException()
+    {
+        $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+        $phpLiveDocx->setUsername('phpunitInvalidUsername');
+        $phpLiveDocx->setPassword('phpunitInvalidPassword');
+        $phpLiveDocx->logIn();
+    }
+    
+    /**
+     * @expectedException Zend_Service_LiveDocx_Exception
+     */
+    public function testLoginUsernamePasswordSoapClientException()
+    {
+        $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
+        $phpLiveDocx->setUsername('phpunitInvalidUsername');
+        $phpLiveDocx->setPassword('phpunitInvalidPassword');
+        $phpLiveDocx->setSoapClient(new Zend_Soap_Client(self::ENDPOINT));
+        $phpLiveDocx->logIn();
+    }    
+    
+    public function testConstructorOptionsUsernamePassword()
+    {    
+        $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(
+            array (
+                'username' => TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME,
+                'password' => TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD
+            )
+        );   
+        $this->assertTrue($phpLiveDocx->logIn()); 
+    }
+    
+    public function testConstructorOptionsUsernamePasswordSoapClient()
+    {    
+        $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge(
+            array (
+                'username' => TESTS_ZEND_SERVICE_LIVEDOCX_USERNAME,
+                'password' => TESTS_ZEND_SERVICE_LIVEDOCX_PASSWORD,
+                'soapClient' => new Zend_Soap_Client(self::ENDPOINT)
+            )
+        );   
+        $this->assertTrue($phpLiveDocx->logIn()); 
+    }    
+
+    // -------------------------------------------------------------------------
+
+    public function testSetLocalTemplate()
+    {
+        $this->assertNull($this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1));
+
+        $this->setExpectedException('Zend_Service_LiveDocx_Exception');
+        @$this->phpLiveDocx->setLocalTemplate('phpunit-nonexistent.doc');
+    }
+
+    public function testSetRemoteTemplate()
+    {
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_1));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+    }
+
+    public function testSetFieldValues()
+    {
+        $testValues = array('software' => 'phpunit');
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->setFieldValues($testValues));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->setFieldValues($testValues));
+    }
+
+    public function testSetFieldValue()
+    {
+        $testKey   = 'software';
+        $testValue = 'phpunit';
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->setFieldValue($testKey, $testValue));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->setFieldValue($testKey, $testValue));
+    }
+
+    public function testAssign()
+    {
+        $testKey   = 'software';
+        $testValue = 'phpunit';
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->assign($testKey, $testValue));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->assertNull($this->phpLiveDocx->assign($testKey, $testValue));
+    }
+
+    public function testSetBlockFieldValues()
+    {
+        $testKey    = 'connection';
+        $testValues = array(array('connection_number' => 'unittest', 'connection_duration' => 'unittest', 'fee' => 'unittest'),
+                            array('connection_number' => 'unittest', 'connection_duration' => 'unittest', 'fee' => 'unittest'),
+                            array('connection_number' => 'unittest', 'connection_duration' => 'unittest', 'fee' => 'unittest'),
+                            array('connection_number' => 'unittest', 'connection_duration' => 'unittest', 'fee' => 'unittest') );
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->assertNull($this->phpLiveDocx->setBlockFieldValues($testKey, $testValues));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->assertNull($this->phpLiveDocx->setBlockFieldValues($testKey, $testValues));
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testCreateDocument()
+    {
+        $testValues = array(
+            'software' => 'phpunit',
+            'licensee' => 'phpunit',
+            'company'  => 'phpunit',
+            'date'     => 'phpunit',
+            'time'     => 'phpunit',
+            'city'     => 'phpunit',
+            'country'  => 'phpunit',
+        );
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->assertNull($this->phpLiveDocx->createDocument());
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->assertNull($this->phpLiveDocx->createDocument());
+    }
+
+    public function testRetrieveDocument()
+    {
+        $testValues = array(
+            'software' => 'phpunit',
+            'licensee' => 'phpunit',
+            'company'  => 'phpunit',
+            'date'     => 'phpunit',
+            'time'     => 'phpunit',
+            'city'     => 'phpunit',
+            'country'  => 'phpunit',
+        );
+
+        // PDF and DOCs are always slightly different:
+        // - PDF because of the timestamp in meta data
+        // - DOC because of ???
+
+        $expectedResults = array(
+            'docx' => '50fe2abd9b42e67c3126d355768b6e75',
+            'rtf'  => '24f950ff620ba194fe5900c3a5360570',
+            'txd'  => '22d7a7558b19ba8be9fe03b35068cf20',
+            'txt'  => '3dc103f033ef6efba770c8196059d96d',
+            'html' => '8b91dc8617651b6e3142d0716c0f616a',
+        );
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->phpLiveDocx->createDocument();
+        foreach($expectedResults as $format => $hash) {
+            $document = $this->phpLiveDocx->retrieveDocument($format);
+            $this->assertEquals($hash, md5($document));
+        }
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->phpLiveDocx->createDocument();
+        foreach($expectedResults as $format => $hash) {
+            $document = $this->phpLiveDocx->retrieveDocument($format);
+            $this->assertEquals($hash, md5($document));
+        }
+    }
+
+    public function testRetrieveDocumentAppended()
+    {
+        $testValues = array(
+            array(
+                'software' => 'phpunit - document 1',
+                'licensee' => 'phpunit - document 1',
+                'company'  => 'phpunit - document 1',
+                'date'     => 'phpunit - document 1',
+                'time'     => 'phpunit - document 1',
+                'city'     => 'phpunit - document 1',
+                'country'  => 'phpunit - document 1',
+            ),
+            array(
+                'software' => 'phpunit - document 2',
+                'licensee' => 'phpunit - document 2',
+                'company'  => 'phpunit - document 2',
+                'date'     => 'phpunit - document 2',
+                'time'     => 'phpunit - document 2',
+                'city'     => 'phpunit - document 2',
+                'country'  => 'phpunit - document 2',
+            ),
+        );
+
+        // PDF and DOCs are always slightly different:
+        // - PDF because of the timestamp in meta data
+        // - DOC because of ???
+        $expectedResults = array(
+            'docx' => '0697e57da0c886dee9fa2d5c98335121',
+            'rtf'  => '9a3f448519e2be0da08a13702fd9d48b',
+            'txd'  => 'f76a6575e74db5b15b4c4be76157bc03',
+            'txt'  => 'e997415fd0d5e766b2490fed9386da21',
+            'html' => '2dfafbb8f81281dbbae99e131963cd50',
+        );
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->phpLiveDocx->createDocument();
+        foreach($expectedResults as $format => $hash) {
+            $document = $this->phpLiveDocx->retrieveDocument($format);
+            $this->assertEquals($hash, md5($document));
+        }
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->phpLiveDocx->createDocument();
+        foreach($expectedResults as $format => $hash) {
+            $document = $this->phpLiveDocx->retrieveDocument($format);
+            $this->assertEquals($hash, md5($document));
+        }
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testGetTemplateFormats()
+    {
+        $expectedResults = array('doc', 'docx', 'rtf', 'txd');
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getTemplateFormats());
+    }
+
+    public function testGetDocumentFormats()
+    {
+        $expectedResults = array('doc', 'docx', 'html', 'pdf', 'rtf', 'txd', 'txt');
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getDocumentFormats());
+    }
+
+    public function testGetImageFormats()
+    {
+        $expectedResults = array('bmp', 'gif', 'jpg', 'png', 'tiff');
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getImageFormats());
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testGetMetafiles()
+    {
+        $this->markTestIncomplete();
+    }
+
+    public function testGetAllMetafiles()
+    {
+        $this->markTestIncomplete();
+    }
+
+    public function testGetBitmaps()
+    {
+        $testValues = array(
+            'software' => 'phpunit',
+            'licensee' => 'phpunit',
+            'company'  => 'phpunit',
+            'date'     => 'phpunit',
+            'time'     => 'phpunit',
+            'city'     => 'phpunit',
+            'country'  => 'phpunit',
+        );
+
+        $expectedResults = array(
+            'bmp'  => 'c588ee10d63e0598fe3541a032f509d6',
+            'gif'  => '2edd4066dda5f4c2049717137d76cf58',
+            'jpg'  => '8766618c572f19ceccc39af7ad0c8478',
+            'png'  => '1e12e4937b9ccb0fa6d78dcd342b7f28',
+            'tiff' => '014ae48643e3a50f691b7d9442605426',
+        );
+
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->phpLiveDocx->createDocument();
+        foreach($this->phpLiveDocx->getImageFormats() as $format) {
+            $bitmaps = $this->phpLiveDocx->getBitmaps(1, 1, 20, $format);
+            $this->assertEquals($expectedResults[$format], md5(serialize($bitmaps)));
+        }
+    }
+
+    public function testGetAllBitmaps()
+    {
+        $testValues = array(
+            'software' => 'phpunit',
+            'licensee' => 'phpunit',
+            'company'  => 'phpunit',
+            'date'     => 'phpunit',
+            'time'     => 'phpunit',
+            'city'     => 'phpunit',
+            'country'  => 'phpunit',
+        );
+
+        $expectedResults = array(
+            'bmp'  => '0ae732498dd3798fc51c1ccccd09e3e3',
+            'gif'  => '9a5f7bfa2aafd8b99f6955b8bdbb8bf7',
+            'jpg'  => '38550446bfc84af3ddd1a0f3339a84dd',
+            'png'  => 'a3b5517bb118db67b8a8259652a389c2',
+            'tiff' => 'b49aa783c14bc7f07776d816085894a3',
+        );
+
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->assign($testValues);
+        $this->phpLiveDocx->createDocument();
+        foreach($this->phpLiveDocx->getImageFormats() as $format) {
+            $bitmaps = $this->phpLiveDocx->getAllBitmaps(20, $format);
+            $this->assertEquals($expectedResults[$format], md5(serialize($bitmaps)));
+        }
+    }
+
+    public function testGetFontNames()
+    {
+        $fonts = $this->phpLiveDocx->getFontNames();
+        if (is_array($fonts) && count($fonts) > 5) {
+            foreach (array('Courier New' , 'Verdana' , 'Arial' , 'Times New Roman') as $font) {
+                if (in_array($font, $fonts)) {
+                    $this->assertTrue(true);
+                } else {
+                    $this->assertTrue(false);
+                }
+            }
+        } else {
+            $this->assertTrue(false);
+        }
+    }
+
+    public function testGetFieldNames()
+    {
+        $expectedResults = array('phone', 'date', 'name', 'customer_number', 'invoice_number', 'account_number', 'service_phone', 'service_fax', 'month', 'monthly_fee', 'total_net', 'tax', 'tax_value', 'total');
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getFieldNames());
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getFieldNames());
+    }
+
+    public function testGetBlockFieldNames()
+    {
+        $expectedResults = array('connection_number', 'connection_duration', 'fee');
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getBlockFieldNames('connection'));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getBlockFieldNames('connection'));
+    }
+
+    public function testGetBlockNames()
+    {
+        $expectedResults = array('connection');
+
+        // Remote Template
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->phpLiveDocx->setRemoteTemplate(self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getBlockNames());
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+
+        // Local Template
+        $this->phpLiveDocx->setLocalTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, $this->phpLiveDocx->getBlockNames());
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testSetDocumentProperties()
+    {
+        $testValues = array(
+            'title'    => 'phpunit',
+            'author'   => 'phpunit',
+            'subject'  => 'phpunit',
+            'keywords' => 'phpunit',
+        );
+
+        $this->assertNull($this->phpLiveDocx->setDocumentProperties($testValues));
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testUploadTemplate()
+    {
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+        $this->assertNull($this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+    }
+
+    public function testDownloadTemplate()
+    {
+        $expectedResults = '2f076af778ca5f8afc9661cfb9deb7c6';
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $template = $this->phpLiveDocx->downloadTemplate(self::TEST_TEMPLATE_2);
+        $this->assertEquals($expectedResults, md5($template));
+    }
+
+    public function testDeleteTemplate()
+    {
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+        $templateDeleted = true;
+        foreach($this->phpLiveDocx->listTemplates() as $template) {
+            if($template['filename'] == self::TEST_TEMPLATE_2) {
+                $templateDeleted = false;
+            }
+        }
+        $this->assertTrue($templateDeleted);
+    }
+
+    public function testListTemplates()
+    {
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+
+        // Where templates uploaded and are being listed?
+        $testTemplate1Exists = false;
+        $testTemplate2Exists = false;
+
+        $templates = $this->phpLiveDocx->listTemplates();
+        foreach($templates as $template) {
+            if(self::TEST_TEMPLATE_1 === $template['filename']) {
+                $testTemplate1Exists = true;
+            } elseif(self::TEST_TEMPLATE_2 === $template['filename']) {
+                $testTemplate2Exists = true;
+            }
+        }
+        $this->assertTrue($testTemplate1Exists && $testTemplate2Exists);
+
+        // Is all info about templates available?
+        $expectedResults = array('filename', 'fileSize', 'createTime', 'modifyTime');
+        foreach($templates as $template) {
+            $this->assertEquals($expectedResults, array_keys($template));
+        }
+
+        // Is all info about templates correct?
+        foreach($templates as $template) {
+            $this->assertTrue(strlen($template['filename']) > 0);
+            $this->assertTrue($template['fileSize'] > 1);
+            $this->assertTrue($template['createTime'] > mktime(0, 0, 0, 1, 1, 1980));
+            $this->assertTrue($template['modifyTime'] > mktime(0, 0, 0, 1, 1, 1980));
+        }
+
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_1);
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+    }
+
+    public function testTemplateExists()
+    {
+        $this->phpLiveDocx->uploadTemplate($this->path . DIRECTORY_SEPARATOR . self::TEST_TEMPLATE_2);
+        $this->assertTrue($this->phpLiveDocx->templateExists(self::TEST_TEMPLATE_2));
+        $this->phpLiveDocx->deleteTemplate(self::TEST_TEMPLATE_2);
+    }
+
+    // -------------------------------------------------------------------------
+
+    public function testAssocArrayToArrayOfArrayOfString()
+    {
+        $testValues = array(
+            'a' => '1',
+            'b' => '2',
+            'c' => '3',
+        );
+
+        $expectedResults = array(
+            array('a', 'b', 'c'),
+            array('1', '2', '3'),
+        );
+
+        $actualResults = Zend_Service_LiveDocx_MailMerge::assocArrayToArrayOfArrayOfString($testValues);
+        $this->assertEquals($expectedResults, $actualResults);
+    }
+
+    public function testMultiAssocArrayToArrayOfArrayOfString()
+    {
+        $testValues = array(
+            array(
+                'a' => '1',
+                'b' => '2',
+                'c' => '3',
+            ),
+            array(
+                'a' => '4',
+                'b' => '5',
+                'c' => '6',
+            ),
+            array(
+                'a' => '7',
+                'b' => '8',
+                'c' => '9',
+            ),
+        );
+
+        $expectedResults = array(
+            array('a', 'b', 'c'),
+            array('1', '2', '3'),
+            array('4', '5', '6'),
+            array('7', '8', '9'),
+        );
+        $actualResults = Zend_Service_LiveDocx_MailMerge::multiAssocArrayToArrayOfArrayOfString($testValues);
+        $this->assertEquals($expectedResults, $actualResults);
+    }
+}
+
+if (PHPUnit_MAIN_METHOD == 'Zend_Service_LiveDocx_MailMergeTest::main') {
+    Zend_Service_LiveDocx_MailMergeTest::main();
+}