web/lib/Zend/Pdf/Action.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Pdf
       
    17  * @subpackage Actions
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Action.php 22437 2010-06-15 16:13:46Z alexander $
       
    21  */
       
    22 
       
    23 
       
    24 /** Internally used classes */
       
    25 require_once 'Zend/Pdf/Element.php';
       
    26 require_once 'Zend/Pdf/Element/Array.php';
       
    27 
       
    28 
       
    29 /** Zend_Pdf_Target */
       
    30 require_once 'Zend/Pdf/Target.php';
       
    31 
       
    32 
       
    33 /**
       
    34  * Abstract PDF action representation class
       
    35  *
       
    36  * @package    Zend_Pdf
       
    37  * @subpackage Actions
       
    38  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    39  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    40  */
       
    41 abstract class Zend_Pdf_Action extends Zend_Pdf_Target implements RecursiveIterator, Countable
       
    42 {
       
    43     /**
       
    44      * Action dictionary
       
    45      *
       
    46      * @var Zend_Pdf_Element_Dictionary|Zend_Pdf_Element_Object|Zend_Pdf_Element_Reference
       
    47      */
       
    48     protected $_actionDictionary;
       
    49 
       
    50 
       
    51     /**
       
    52      * An original list of chained actions
       
    53      *
       
    54      * @var array  Array of Zend_Pdf_Action objects
       
    55      */
       
    56     protected $_originalNextList;
       
    57 
       
    58     /**
       
    59      * A list of next actions in actions tree (used for actions chaining)
       
    60      *
       
    61      * @var array  Array of Zend_Pdf_Action objects
       
    62      */
       
    63     public $next = array();
       
    64 
       
    65     /**
       
    66      * Object constructor
       
    67      *
       
    68      * @param Zend_Pdf_Element_Dictionary $dictionary
       
    69      * @param SplObjectStorage            $processedActions  list of already processed action dictionaries, used to avoid cyclic references
       
    70      * @throws Zend_Pdf_Exception
       
    71      */
       
    72     public function __construct(Zend_Pdf_Element $dictionary, SplObjectStorage $processedActions)
       
    73     {
       
    74         require_once 'Zend/Pdf/Element.php';
       
    75         if ($dictionary->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
       
    76             require_once 'Zend/Pdf/Exception.php';
       
    77             throw new Zend_Pdf_Exception('$dictionary mast be a direct or an indirect dictionary object.');
       
    78         }
       
    79 
       
    80         $this->_actionDictionary = $dictionary;
       
    81 
       
    82         if ($dictionary->Next !== null) {
       
    83             if ($dictionary->Next instanceof Zend_Pdf_Element_Dictionary) {
       
    84                 // Check if dictionary object is not already processed
       
    85                 if (!$processedActions->contains($dictionary->Next)) {
       
    86                     $processedActions->attach($dictionary->Next);
       
    87                     $this->next[] = Zend_Pdf_Action::load($dictionary->Next, $processedActions);
       
    88                 }
       
    89             } else if ($dictionary->Next instanceof Zend_Pdf_Element_Array) {
       
    90                 foreach ($dictionary->Next->items as $chainedActionDictionary) {
       
    91                     // Check if dictionary object is not already processed
       
    92                     if (!$processedActions->contains($chainedActionDictionary)) {
       
    93                         $processedActions->attach($chainedActionDictionary);
       
    94                         $this->next[] = Zend_Pdf_Action::load($chainedActionDictionary, $processedActions);
       
    95                     }
       
    96                 }
       
    97             } else {
       
    98                 require_once 'Zend/Pdf/Exception.php';
       
    99                 throw new Zend_Pdf_Exception('PDF Action dictionary Next entry must be a dictionary or an array.');
       
   100             }
       
   101         }
       
   102 
       
   103         $this->_originalNextList = $this->next;
       
   104     }
       
   105 
       
   106     /**
       
   107      * Load PDF action object using specified dictionary
       
   108      *
       
   109      * @internal
       
   110      * @param Zend_Pdf_Element $dictionary (It's actually Dictionary or Dictionary Object or Reference to a Dictionary Object)
       
   111      * @param SplObjectStorage $processedActions  list of already processed action dictionaries, used to avoid cyclic references
       
   112      * @return Zend_Pdf_Action
       
   113      * @throws Zend_Pdf_Exception
       
   114      */
       
   115     public static function load(Zend_Pdf_Element $dictionary, SplObjectStorage $processedActions = null)
       
   116     {
       
   117         if ($processedActions === null) {
       
   118             $processedActions = new SplObjectStorage();
       
   119         }
       
   120 
       
   121         require_once 'Zend/Pdf/Element.php';
       
   122         if ($dictionary->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
       
   123             require_once 'Zend/Pdf/Exception.php';
       
   124             throw new Zend_Pdf_Exception('$dictionary mast be a direct or an indirect dictionary object.');
       
   125         }
       
   126         if (isset($dictionary->Type)  &&  $dictionary->Type->value != 'Action') {
       
   127             require_once 'Zend/Pdf/Exception.php';
       
   128             throw new Zend_Pdf_Exception('Action dictionary Type entry must be set to \'Action\'.');
       
   129         }
       
   130 
       
   131         if ($dictionary->S === null) {
       
   132             require_once 'Zend/Pdf/Exception.php';
       
   133             throw new Zend_Pdf_Exception('Action dictionary must contain S entry');
       
   134         }
       
   135 
       
   136         switch ($dictionary->S->value) {
       
   137             case 'GoTo':
       
   138                 require_once 'Zend/Pdf/Action/GoTo.php';
       
   139                 return new Zend_Pdf_Action_GoTo($dictionary, $processedActions);
       
   140                 break;
       
   141 
       
   142             case 'GoToR':
       
   143                 require_once 'Zend/Pdf/Action/GoToR.php';
       
   144                 return new Zend_Pdf_Action_GoToR($dictionary, $processedActions);
       
   145                 break;
       
   146 
       
   147             case 'GoToE':
       
   148                 require_once 'Zend/Pdf/Action/GoToE.php';
       
   149                 return new Zend_Pdf_Action_GoToE($dictionary, $processedActions);
       
   150                 break;
       
   151 
       
   152             case 'Launch':
       
   153                 require_once 'Zend/Pdf/Action/Launch.php';
       
   154                 return new Zend_Pdf_Action_Launch($dictionary, $processedActions);
       
   155                 break;
       
   156 
       
   157             case 'Thread':
       
   158                 require_once 'Zend/Pdf/Action/Thread.php';
       
   159                 return new Zend_Pdf_Action_Thread($dictionary, $processedActions);
       
   160                 break;
       
   161 
       
   162             case 'URI':
       
   163                 require_once 'Zend/Pdf/Action/URI.php';
       
   164                 return new Zend_Pdf_Action_URI($dictionary, $processedActions);
       
   165                 break;
       
   166 
       
   167             case 'Sound':
       
   168                 require_once 'Zend/Pdf/Action/Sound.php';
       
   169                 return new Zend_Pdf_Action_Sound($dictionary, $processedActions);
       
   170                 break;
       
   171 
       
   172             case 'Movie':
       
   173                 require_once 'Zend/Pdf/Action/Movie.php';
       
   174                 return new Zend_Pdf_Action_Movie($dictionary, $processedActions);
       
   175                 break;
       
   176 
       
   177             case 'Hide':
       
   178                 require_once 'Zend/Pdf/Action/Hide.php';
       
   179                 return new Zend_Pdf_Action_Hide($dictionary, $processedActions);
       
   180                 break;
       
   181 
       
   182             case 'Named':
       
   183                 require_once 'Zend/Pdf/Action/Named.php';
       
   184                 return new Zend_Pdf_Action_Named($dictionary, $processedActions);
       
   185                 break;
       
   186 
       
   187             case 'SubmitForm':
       
   188                 require_once 'Zend/Pdf/Action/SubmitForm.php';
       
   189                 return new Zend_Pdf_Action_SubmitForm($dictionary, $processedActions);
       
   190                 break;
       
   191 
       
   192             case 'ResetForm':
       
   193                 require_once 'Zend/Pdf/Action/ResetForm.php';
       
   194                 return new Zend_Pdf_Action_ResetForm($dictionary, $processedActions);
       
   195                 break;
       
   196 
       
   197             case 'ImportData':
       
   198                 require_once 'Zend/Pdf/Action/ImportData.php';
       
   199                 return new Zend_Pdf_Action_ImportData($dictionary, $processedActions);
       
   200                 break;
       
   201 
       
   202             case 'JavaScript':
       
   203                 require_once 'Zend/Pdf/Action/JavaScript.php';
       
   204                 return new Zend_Pdf_Action_JavaScript($dictionary, $processedActions);
       
   205                 break;
       
   206 
       
   207             case 'SetOCGState':
       
   208                 require_once 'Zend/Pdf/Action/SetOCGState.php';
       
   209                 return new Zend_Pdf_Action_SetOCGState($dictionary, $processedActions);
       
   210                 break;
       
   211 
       
   212             case 'Rendition':
       
   213                 require_once 'Zend/Pdf/Action/Rendition.php';
       
   214                 return new Zend_Pdf_Action_Rendition($dictionary, $processedActions);
       
   215                 break;
       
   216 
       
   217             case 'Trans':
       
   218                 require_once 'Zend/Pdf/Action/Trans.php';
       
   219                 return new Zend_Pdf_Action_Trans($dictionary, $processedActions);
       
   220                 break;
       
   221 
       
   222             case 'GoTo3DView':
       
   223                 require_once 'Zend/Pdf/Action/GoTo3DView.php';
       
   224                 return new Zend_Pdf_Action_GoTo3DView($dictionary, $processedActions);
       
   225                 break;
       
   226 
       
   227             default:
       
   228                 require_once 'Zend/Pdf/Action/Unknown.php';
       
   229                 return new Zend_Pdf_Action_Unknown($dictionary, $processedActions);
       
   230                 break;
       
   231         }
       
   232     }
       
   233 
       
   234     /**
       
   235      * Get resource
       
   236      *
       
   237      * @internal
       
   238      * @return Zend_Pdf_Element
       
   239      */
       
   240     public function getResource()
       
   241     {
       
   242         return $this->_actionDictionary;
       
   243     }
       
   244 
       
   245     /**
       
   246      * Dump Action and its child actions into PDF structures
       
   247      *
       
   248      * Returns dictionary indirect object or reference
       
   249      *
       
   250      * @internal
       
   251      * @param Zend_Pdf_ElementFactory $factory   Object factory for newly created indirect objects
       
   252      * @param SplObjectStorage $processedActions  list of already processed actions (used to prevent infinity loop caused by cyclic references)
       
   253      * @return Zend_Pdf_Element_Object|Zend_Pdf_Element_Reference   Dictionary indirect object
       
   254      */
       
   255     public function dumpAction(Zend_Pdf_ElementFactory_Interface $factory, SplObjectStorage $processedActions = null)
       
   256     {
       
   257         if ($processedActions === null) {
       
   258             $processedActions = new SplObjectStorage();
       
   259         }
       
   260         if ($processedActions->contains($this)) {
       
   261             require_once 'Zend/Pdf/Exception.php';
       
   262             throw new Zend_Pdf_Exception('Action chain cyclyc reference is detected.');
       
   263         }
       
   264         $processedActions->attach($this);
       
   265 
       
   266         $childListUpdated = false;
       
   267         if (count($this->_originalNextList) != count($this->next)) {
       
   268             // If original and current children arrays have different size then children list was updated
       
   269             $childListUpdated = true;
       
   270         } else if ( !(array_keys($this->_originalNextList) === array_keys($this->next)) ) {
       
   271             // If original and current children arrays have different keys (with a glance to an order) then children list was updated
       
   272             $childListUpdated = true;
       
   273         } else {
       
   274             foreach ($this->next as $key => $childAction) {
       
   275                 if ($this->_originalNextList[$key] !== $childAction) {
       
   276                     $childListUpdated = true;
       
   277                     break;
       
   278                 }
       
   279             }
       
   280         }
       
   281 
       
   282         if ($childListUpdated) {
       
   283             $this->_actionDictionary->touch();
       
   284             switch (count($this->next)) {
       
   285                 case 0:
       
   286                     $this->_actionDictionary->Next = null;
       
   287                     break;
       
   288 
       
   289                 case 1:
       
   290                     $child = reset($this->next);
       
   291                     $this->_actionDictionary->Next = $child->dumpAction($factory, $processedActions);
       
   292                     break;
       
   293 
       
   294                 default:
       
   295                     require_once 'Zend/Pdf/Element/Array.php';
       
   296                     $pdfChildArray = new Zend_Pdf_Element_Array();
       
   297                     foreach ($this->next as $child) {
       
   298 
       
   299                         $pdfChildArray->items[] = $child->dumpAction($factory, $processedActions);
       
   300                     }
       
   301                     $this->_actionDictionary->Next = $pdfChildArray;
       
   302                     break;
       
   303             }
       
   304         } else {
       
   305             foreach ($this->next as $child) {
       
   306                 $child->dumpAction($factory, $processedActions);
       
   307             }
       
   308         }
       
   309 
       
   310         if ($this->_actionDictionary instanceof Zend_Pdf_Element_Dictionary) {
       
   311             // It's a newly created action. Register it within object factory and return indirect object
       
   312             return $factory->newObject($this->_actionDictionary);
       
   313         } else {
       
   314             // It's a loaded object
       
   315             return $this->_actionDictionary;
       
   316         }
       
   317     }
       
   318 
       
   319 
       
   320     ////////////////////////////////////////////////////////////////////////
       
   321     //  RecursiveIterator interface methods
       
   322     //////////////
       
   323 
       
   324     /**
       
   325      * Returns current child action.
       
   326      *
       
   327      * @return Zend_Pdf_Action
       
   328      */
       
   329     public function current()
       
   330     {
       
   331         return current($this->next);
       
   332     }
       
   333 
       
   334     /**
       
   335      * Returns current iterator key
       
   336      *
       
   337      * @return integer
       
   338      */
       
   339     public function key()
       
   340     {
       
   341         return key($this->next);
       
   342     }
       
   343 
       
   344     /**
       
   345      * Go to next child
       
   346      */
       
   347     public function next()
       
   348     {
       
   349         return next($this->next);
       
   350     }
       
   351 
       
   352     /**
       
   353      * Rewind children
       
   354      */
       
   355     public function rewind()
       
   356     {
       
   357         return reset($this->next);
       
   358     }
       
   359 
       
   360     /**
       
   361      * Check if current position is valid
       
   362      *
       
   363      * @return boolean
       
   364      */
       
   365     public function valid()
       
   366     {
       
   367         return current($this->next) !== false;
       
   368     }
       
   369 
       
   370     /**
       
   371      * Returns the child action.
       
   372      *
       
   373      * @return Zend_Pdf_Action|null
       
   374      */
       
   375     public function getChildren()
       
   376     {
       
   377         return current($this->next);
       
   378     }
       
   379 
       
   380     /**
       
   381      * Implements RecursiveIterator interface.
       
   382      *
       
   383      * @return bool  whether container has any pages
       
   384      */
       
   385     public function hasChildren()
       
   386     {
       
   387         return count($this->next) > 0;
       
   388     }
       
   389 
       
   390 
       
   391     ////////////////////////////////////////////////////////////////////////
       
   392     //  Countable interface methods
       
   393     //////////////
       
   394 
       
   395     /**
       
   396      * count()
       
   397      *
       
   398      * @return int
       
   399      */
       
   400     public function count()
       
   401     {
       
   402         return count($this->childOutlines);
       
   403     }
       
   404 }