Permalink
Browse files

Merge branch 'master' of git://github.com/zendframework/zf2

  • Loading branch information...
sgehrig committed Aug 23, 2010
2 parents cd3deb5 + dc86be6 commit c7c402a3a89db4883d43001dc8eadc49c1c058fd
Showing with 995 additions and 913 deletions.
  1. +78 −35 documentation/manual/en/module_specs/Zend_Pdf-Pages.xml
  2. +3 −2 library/Zend/Pdf/Action/AbstractAction.php
  3. +20 −0 library/Zend/Pdf/InternalType/AbstractTypeObject.php
  4. +33 −0 library/Zend/Pdf/InternalType/ArrayObject.php
  5. +47 −1 library/Zend/Pdf/InternalType/DictionaryObject.php
  6. +39 −2 library/Zend/Pdf/InternalType/IndirectObject.php
  7. +26 −0 library/Zend/Pdf/InternalType/IndirectObjectReference.php
  8. +12 −5 library/Zend/Pdf/InternalType/StreamContent.php
  9. +76 −45 library/Zend/Pdf/InternalType/StreamObject.php
  10. +298 −24 library/Zend/Pdf/ObjectFactory.php
  11. +0 −443 library/Zend/Pdf/ObjectFactory/ElementFactory.php
  12. +0 −233 library/Zend/Pdf/ObjectFactory/Proxy.php
  13. +4 −4 library/Zend/Pdf/Outline/AbstractOutline.php
  14. +4 −4 library/Zend/Pdf/Outline/Created.php
  15. +4 −4 library/Zend/Pdf/Outline/Loaded.php
  16. +82 −30 library/Zend/Pdf/Page.php
  17. +1 −1 library/Zend/Pdf/PdfDocument.php
  18. +6 −6 library/Zend/Pdf/PdfParser/DataParser.php
  19. +56 −1 library/Zend/Pdf/Resource/AbstractResource.php
  20. +83 −0 library/Zend/Pdf/Resource/Extractor.php
  21. +2 −2 library/Zend/Pdf/Resource/Image/Png.php
  22. +1 −1 library/Zend/Session/Configuration/StandardConfiguration.php
  23. +1 −53 tests/Bootstrap.php
  24. +3 −3 tests/Zend/Pdf/ActionTest.php
  25. +11 −11 tests/Zend/Pdf/InternalType/ObjectTest.php
  26. +3 −3 tests/Zend/Pdf/InternalType/StreamObjectTest.php
  27. +22 −0 tests/Zend/Session/ContainerTest.php
  28. +22 −0 tests/Zend/Session/SessionManagerTest.php
  29. +58 −0 tests/_autoload.php
@@ -8,49 +8,42 @@
<para>
The pages in a <acronym>PDF</acronym> document are represented as
- <classname>Zend_Pdf_Page</classname> instances in <classname>Zend_Pdf</classname>.
+ <classname>\Zend\Pdf\Page</classname> instances in <code>Zend\Pdf</code>.
</para>
<para>
<acronym>PDF</acronym> pages either are loaded from an existing <acronym>PDF</acronym>
- or created using the <classname>Zend_Pdf</classname> <acronym>API</acronym>.
+ or created using the <code>Zend\Pdf</code> <acronym>API</acronym>.
</para>
<para>
- New pages can be created by instantiating new <classname>Zend_Pdf_Page</classname>
- objects directly or by calling the <methodname>Zend_Pdf::newPage()</methodname> method,
- which returns a <classname>Zend_Pdf_Page</classname> object.
- <methodname>Zend_Pdf::newPage()</methodname> creates a page that is already attached to
- a document. Unattached pages can't be used with multiple <acronym>PDF</acronym>
- documents, but they are somewhat more performant.
-
- <footnote>
- <para>
- It's a limitation of current Zend Framework version. It will be eliminated in
- future versions. But unattached pages will always give better (more optimal)
- result for sharing pages between documents.
- </para>
- </footnote>
+ New pages can be created by instantiating new <classname>\Zend\Pdf\Page</classname>
+ objects directly or by calling the <methodname>\Zend\Pdf\PdfDocument::newPage()</methodname> method,
+ which returns a <classname>\Zend\Pdf\Page</classname> object.
+ <methodname>\Zend\Pdf\PdfDocument::newPage()</methodname> creates a page that is already attached to
+ a document. Attached pages can't be used with another <acronym>PDF</acronym>
+ documents until it's not cloned. See <link linkend="zend.pdf.pages.cloning">Page
+ cloning</link> section for the details.
</para>
<para>
- The <methodname>Zend_Pdf::newPage()</methodname> method and the
- <classname>Zend_Pdf_Page</classname> constructor take the same parameters specifying
+ The <methodname>\Zend\Pdf\PdfDocument::newPage()</methodname> method and the
+ <classname>\Zend\Pdf\Page</classname> constructor take the same parameters specifying
page size. They can take either the size of page ($x, $y) in points (1/72 inch) or a
predefined constant representing a page type:
<itemizedlist>
- <listitem><para>Zend_Pdf_Page::SIZE_A4</para></listitem>
- <listitem><para>Zend_Pdf_Page::SIZE_A4_LANDSCAPE</para></listitem>
- <listitem><para>Zend_Pdf_Page::SIZE_LETTER</para></listitem>
- <listitem><para>Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_A4</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_A4_LANDSCAPE</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_LETTER</para></listitem>
+ <listitem><para>\Zend\Pdf\Page::SIZE_LETTER_LANDSCAPE</para></listitem>
</itemizedlist>
</para>
<para>
Document pages are stored in the <varname>$pages</varname> public attribute of the
- <classname>Zend_Pdf</classname> class. The attribute holds an array of
- <classname>Zend_Pdf_Page</classname> objects and completely defines the instances and
+ <classname>\Zend\Pdf\PdfDocument</classname> class. The attribute holds an array of
+ <classname>\Zend\Pdf\Page</classname> objects and completely defines the instances and
order of pages. This array can be manipulated like any other <acronym>PHP</acronym>
array:
</para>
@@ -64,9 +57,9 @@
$pdf->pages = array_reverse($pdf->pages);
...
// Add new page
-$pdf->pages[] = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);
+$pdf->pages[] = new \Zend\Pdf\Page(\Zend\Pdf\Page::SIZE_A4);
// Add new page
-$pdf->pages[] = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
+$pdf->pages[] = $pdf->newPage(\Zend\Pdf\Page::SIZE_A4);
// Remove specified page.
unset($pdf->pages[$id]);
@@ -80,25 +73,27 @@ unset($pdf->pages[$id]);
<title>Page cloning</title>
<para>
- Existing <acronym>PDF</acronym> page can be cloned by creating new
- <classname>Zend_Pdf_Page</classname> object with existing page as a parameter:
+ Existing <acronym>PDF</acronym> page can be duplicated by creating new
+ <classname>\Zend\Pdf\Page</classname> object with existing page as a parameter:
</para>
<example id="zend.pdf.pages.example-2">
- <title>Cloning existing page</title>
+ <title>Duplicating existing page</title>
<programlisting language="php"><![CDATA[
...
// Store template page in a separate variable
$template = $pdf->pages[$templatePageIndex];
...
// Add new page
-$page1 = new Zend_Pdf_Page($template);
+$page1 = new \Zend\Pdf\Page($template);
+$page1->drawText('Some text...', $x, $y);
$pdf->pages[] = $page1;
...
// Add another page
-$page2 = new Zend_Pdf_Page($template);
+$page2 = new \Zend\Pdf\Page($template);
+$page2->drawText('Another text...', $x, $y);
$pdf->pages[] = $page2;
...
@@ -115,11 +110,59 @@ unset($pdf->pages[$templatePageIndex]);
<caution>
<para>
- Important! Cloned page shares some <acronym>PDF</acronym> resources with a template
- page, so it can be used only within the same document as a template page. Modified
- document can be saved as new one.
+ Important! Duplicated page shares some <acronym>PDF</acronym> resources with
+ a template page, so it can be used only within the same document as a template page.
+ Modified document can be saved as new one.
</para>
- </caution>
+</caution>
+
+ <para>
+ <code>clone</code> operator may be used to create page which is not attached to any document.
+ It takes more time than duplicating page since it needs to copy all dependent objects
+ (used fonts, images and other resources), but it allows to use pages from different source
+ documents to create new one:
+ </para>
+
+ <example id="zend.pdf.pages.example-3">
+ <title>Cloning existing page</title>
+
+ <programlisting language="php"><![CDATA[
+$page1 = clone $pdf1->pages[$templatePageIndex1];
+$page2 = clone $pdf2->pages[$templatePageIndex2];
+$page1->drawText('Some text...', $x, $y);
+$page2->drawText('Another text...', $x, $y);
+...
+$pdf = new \Zend\Pdf\PdfDocument();
+$pdf->pages[] = $page1;
+$pdf->pages[] = $page2;
+]]></programlisting>
+ </example>
+
+ <para>
+ If several template pages are planned to be used as templates then it could be more efficient
+ to utilize <classname>\Zend\Pdf\Resource\Extractor</classname> class which gives an ability
+ to share resources between cloned pages - fonts, images, etc. (otherwise new resource copy
+ will be created for each cloned page):
+ </para>
+
+ <example id="zend.pdf.pages.example-4">
+ <title>
+ Cloning existing page using <classname>\Zend\Pdf\Resource\Extractor</classname> class
+ </title>
+
+ <programlisting language="php"><![CDATA[
+$extractor = new \Zend\Pdf\Resource\Extractor();
+....
+$page1 = $extractor->clonePage($pdf->pages[$templatePageIndex1]);
+$page2 = $extractor->clonePage($pdf->pages[$templatePageIndex2]);
+$page1->drawText('Some text...', $x, $y);
+$page2->drawText('Another text...', $x, $y);
+...
+$pdf = new Zend_Pdf();
+$pdf->pages[] = $page1;
+$pdf->pages[] = $page2;
+]]></programlisting>
+ </example>
</sect2>
</sect1>
<!--
@@ -24,6 +24,7 @@
* @namespace
*/
namespace Zend\Pdf\Action;
+use Zend\Pdf\ObjectFactory;
use Zend\Pdf\InternalType;
use Zend\Pdf;
@@ -249,12 +250,12 @@ public function getResource()
* Returns dictionary indirect object or reference
*
* @internal
- * @param \Zend\Pdf\ObjectFactory $factory Object factory for newly created indirect objects
+ * @param \Zend\Pdf\ObjectFactory $factory Object factory for newly created indirect objects
* @param SplObjectStorage $processedActions list of already processed actions
* (used to prevent infinity loop caused by cyclic references)
* @return \Zend\Pdf\InternalType\IndirectObject|\Zend\Pdf\InternalType\IndirectObjectReference
*/
- public function dumpAction(Pdf\ObjectFactory $factory, \SplObjectStorage $processedActions = null)
+ public function dumpAction(ObjectFactory $factory, \SplObjectStorage $processedActions = null)
{
if ($processedActions === null) {
$processedActions = new \SplObjectStorage();
@@ -24,6 +24,7 @@
* @namespace
*/
namespace Zend\Pdf\InternalType;
+use Zend\Pdf;
/**
* PDF file element implementation
@@ -76,6 +77,25 @@
abstract public function toString($factory = null);
+ const CLONE_MODE_SKIP_PAGES = 1; // Do not follow pages during deep copy process
+ const CLONE_MODE_FORCE_CLONING = 2; // Force top level object cloning even it's already processed
+
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @todo It's necessary to check if SplObjectStorage class works faster
+ * (Needs PHP 5.3.x to attach object _with_ additional data to storage)
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ return clone $this;
+ }
+
/**
* Set top level parent indirect object.
*
@@ -132,6 +132,39 @@ public function toString($factory = null)
return $outStr;
}
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ $newArray = new self();
+
+ foreach ($this->items as $key => $value) {
+ $newArray->items[$key] = $value->makeClone($factory, $processed, $mode);
+ }
+
+ return $newArray;
+ }
+
+ /**
+ * Set top level parent indirect object.
+ *
+ * @param \Zend\Pdf\InternalType\IndirectObject $parent
+ */
+ public function setParentObject(IndirectObject $parent)
+ {
+ parent::setParentObject($parent);
+
+ foreach ($this->items as $item) {
+ $item->setParentObject($parent);
+ }
+ }
+
/**
* Convert PDF element to PHP type.
*
@@ -137,7 +137,6 @@ public function getType()
return AbstractTypeObject::TYPE_DICTIONARY;
}
-
/**
* Return object as string
*
@@ -167,6 +166,53 @@ public function toString($factory = null)
return $outStr;
}
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ * @throws \Zend\Pdf\Exception
+ */
+ public function makeClone(Pdf\ObjectFactory $factory, array &$processed, $mode)
+ {
+ if (isset($this->_items['Type'])) {
+ if ($this->_items['Type']->value == 'Pages') {
+ // It's a page tree node
+ // skip it and its children
+ return new NullObject();
+ }
+
+ if ($this->_items['Type']->value == 'Page' &&
+ $mode == AbstractTypeObject::CLONE_MODE_SKIP_PAGES
+ ) {
+ // It's a page node, skip it
+ return new NullObject();
+ }
+ }
+
+ $newDictionary = new self();
+ foreach ($this->_items as $key => $value) {
+ $newDictionary->_items[$key] = $value->makeClone($factory, $processed, $mode);
+ }
+
+ return $newDictionary;
+ }
+
+ /**
+ * Set top level parent indirect object.
+ *
+ * @param \Zend\Pdf\InternalType\IndirectObject $parent
+ */
+ public function setParentObject(IndirectObject $parent)
+ {
+ parent::setParentObject($parent);
+
+ foreach ($this->_items as $item) {
+ $item->setParentObject($parent);
+ }
+ }
/**
* Convert PDF element to PHP type.
@@ -31,7 +31,7 @@
* PDF file 'indirect object' element implementation
*
* @uses \Zend\Pdf\InternalType\AbstractTypeObject
- * @uses \Zend\Pdf\ObjectFactory\ElementFactory
+ * @uses \Zend\Pdf\ObjectFactory
* @uses \Zend\Pdf\Exception
* @category Zend
* @package Zend_PDF
@@ -78,7 +78,10 @@ class IndirectObject extends AbstractTypeObject
* @param \Zend\Pdf\ObjectFactory $factory
* @throws \Zend\Pdf\Exception
*/
- public function __construct(AbstractTypeObject $val, $objNum, $genNum, ObjectFactory $factory)
+ public function __construct(AbstractTypeObject $val,
+ $objNum,
+ $genNum,
+ ObjectFactory $factory)
{
if ($val instanceof self) {
throw new Pdf\Exception('Object number must not be an instance of \Zend\Pdf\InternalType\IndirectObject.');
@@ -215,6 +218,40 @@ public function __call($method, $args)
return call_user_func_array(array($this->_value, $method), $args);
}
+ /**
+ * Detach PDF object from the factory (if applicable), clone it and attach to new factory.
+ *
+ * @param \Zend\Pdf\ObjectFactory $factory The factory to attach
+ * @param array &$processed List of already processed indirect objects, used to avoid objects duplication
+ * @param integer $mode Cloning mode (defines filter for objects cloning)
+ * @returns \Zend\Pdf\InternalType\AbstractTypeObject
+ */
+ public function makeClone(ObjectFactory $factory, array &$processed, $mode)
+ {
+ $id = spl_object_hash($this);
+ if (isset($processed[$id])) {
+ // Do nothing if object is already processed
+ // return it
+ return $processed[$id];
+ }
+
+ // Create obect with null value and register it in $processed container
+ $processed[$id] = $clonedObject = $factory->newObject(new NullObject());
+
+ // Pecursively process actual data
+ $clonedObject->_value = $this->_value->makeClone($factory, $processed, $mode);
+
+ if ($clonedObject->_value instanceof NullObject) {
+ // Do not store null objects within $processed container since it may be filtered
+ // by $mode parameter but used in some future pass
+ unset($processed[$id]);
+
+ // Return direct null object
+ return $clonedObject->_value;
+ }
+
+ return $clonedObject;
+ }
/**
* Mark object as modified, to include it into new PDF file segment
Oops, something went wrong.

0 comments on commit c7c402a

Please sign in to comment.