File indexing completed on 2024-12-22 05:36:56
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Pdf 0017 * @subpackage Actions 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** Internally used classes */ 0025 // require_once 'Zend/Pdf/Element.php'; 0026 // require_once 'Zend/Pdf/Element/Array.php'; 0027 0028 0029 /** Zend_Pdf_Target */ 0030 // require_once 'Zend/Pdf/Target.php'; 0031 0032 0033 /** 0034 * Abstract PDF action representation class 0035 * 0036 * @package Zend_Pdf 0037 * @subpackage Actions 0038 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0039 * @license http://framework.zend.com/license/new-bsd New BSD License 0040 */ 0041 abstract class Zend_Pdf_Action extends Zend_Pdf_Target implements RecursiveIterator, Countable 0042 { 0043 /** 0044 * Action dictionary 0045 * 0046 * @var Zend_Pdf_Element_Dictionary|Zend_Pdf_Element_Object|Zend_Pdf_Element_Reference 0047 */ 0048 protected $_actionDictionary; 0049 0050 0051 /** 0052 * An original list of chained actions 0053 * 0054 * @var array Array of Zend_Pdf_Action objects 0055 */ 0056 protected $_originalNextList; 0057 0058 /** 0059 * A list of next actions in actions tree (used for actions chaining) 0060 * 0061 * @var array Array of Zend_Pdf_Action objects 0062 */ 0063 public $next = array(); 0064 0065 /** 0066 * Object constructor 0067 * 0068 * @param Zend_Pdf_Element_Dictionary $dictionary 0069 * @param SplObjectStorage $processedActions list of already processed action dictionaries, used to avoid cyclic references 0070 * @throws Zend_Pdf_Exception 0071 */ 0072 public function __construct(Zend_Pdf_Element $dictionary, SplObjectStorage $processedActions) 0073 { 0074 // require_once 'Zend/Pdf/Element.php'; 0075 if ($dictionary->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) { 0076 // require_once 'Zend/Pdf/Exception.php'; 0077 throw new Zend_Pdf_Exception('$dictionary mast be a direct or an indirect dictionary object.'); 0078 } 0079 0080 $this->_actionDictionary = $dictionary; 0081 0082 if ($dictionary->Next !== null) { 0083 if ($dictionary->Next instanceof Zend_Pdf_Element_Dictionary) { 0084 // Check if dictionary object is not already processed 0085 if (!$processedActions->contains($dictionary->Next)) { 0086 $processedActions->attach($dictionary->Next); 0087 $this->next[] = Zend_Pdf_Action::load($dictionary->Next, $processedActions); 0088 } 0089 } else if ($dictionary->Next instanceof Zend_Pdf_Element_Array) { 0090 foreach ($dictionary->Next->items as $chainedActionDictionary) { 0091 // Check if dictionary object is not already processed 0092 if (!$processedActions->contains($chainedActionDictionary)) { 0093 $processedActions->attach($chainedActionDictionary); 0094 $this->next[] = Zend_Pdf_Action::load($chainedActionDictionary, $processedActions); 0095 } 0096 } 0097 } else { 0098 // require_once 'Zend/Pdf/Exception.php'; 0099 throw new Zend_Pdf_Exception('PDF Action dictionary Next entry must be a dictionary or an array.'); 0100 } 0101 } 0102 0103 $this->_originalNextList = $this->next; 0104 } 0105 0106 /** 0107 * Load PDF action object using specified dictionary 0108 * 0109 * @internal 0110 * @param Zend_Pdf_Element $dictionary (It's actually Dictionary or Dictionary Object or Reference to a Dictionary Object) 0111 * @param SplObjectStorage $processedActions list of already processed action dictionaries, used to avoid cyclic references 0112 * @return Zend_Pdf_Action 0113 * @throws Zend_Pdf_Exception 0114 */ 0115 public static function load(Zend_Pdf_Element $dictionary, SplObjectStorage $processedActions = null) 0116 { 0117 if ($processedActions === null) { 0118 $processedActions = new SplObjectStorage(); 0119 } 0120 0121 // require_once 'Zend/Pdf/Element.php'; 0122 if ($dictionary->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) { 0123 // require_once 'Zend/Pdf/Exception.php'; 0124 throw new Zend_Pdf_Exception('$dictionary mast be a direct or an indirect dictionary object.'); 0125 } 0126 if (isset($dictionary->Type) && $dictionary->Type->value != 'Action') { 0127 // require_once 'Zend/Pdf/Exception.php'; 0128 throw new Zend_Pdf_Exception('Action dictionary Type entry must be set to \'Action\'.'); 0129 } 0130 0131 if ($dictionary->S === null) { 0132 // require_once 'Zend/Pdf/Exception.php'; 0133 throw new Zend_Pdf_Exception('Action dictionary must contain S entry'); 0134 } 0135 0136 switch ($dictionary->S->value) { 0137 case 'GoTo': 0138 // require_once 'Zend/Pdf/Action/GoTo.php'; 0139 return new Zend_Pdf_Action_GoTo($dictionary, $processedActions); 0140 break; 0141 0142 case 'GoToR': 0143 // require_once 'Zend/Pdf/Action/GoToR.php'; 0144 return new Zend_Pdf_Action_GoToR($dictionary, $processedActions); 0145 break; 0146 0147 case 'GoToE': 0148 // require_once 'Zend/Pdf/Action/GoToE.php'; 0149 return new Zend_Pdf_Action_GoToE($dictionary, $processedActions); 0150 break; 0151 0152 case 'Launch': 0153 // require_once 'Zend/Pdf/Action/Launch.php'; 0154 return new Zend_Pdf_Action_Launch($dictionary, $processedActions); 0155 break; 0156 0157 case 'Thread': 0158 // require_once 'Zend/Pdf/Action/Thread.php'; 0159 return new Zend_Pdf_Action_Thread($dictionary, $processedActions); 0160 break; 0161 0162 case 'URI': 0163 // require_once 'Zend/Pdf/Action/URI.php'; 0164 return new Zend_Pdf_Action_URI($dictionary, $processedActions); 0165 break; 0166 0167 case 'Sound': 0168 // require_once 'Zend/Pdf/Action/Sound.php'; 0169 return new Zend_Pdf_Action_Sound($dictionary, $processedActions); 0170 break; 0171 0172 case 'Movie': 0173 // require_once 'Zend/Pdf/Action/Movie.php'; 0174 return new Zend_Pdf_Action_Movie($dictionary, $processedActions); 0175 break; 0176 0177 case 'Hide': 0178 // require_once 'Zend/Pdf/Action/Hide.php'; 0179 return new Zend_Pdf_Action_Hide($dictionary, $processedActions); 0180 break; 0181 0182 case 'Named': 0183 // require_once 'Zend/Pdf/Action/Named.php'; 0184 return new Zend_Pdf_Action_Named($dictionary, $processedActions); 0185 break; 0186 0187 case 'SubmitForm': 0188 // require_once 'Zend/Pdf/Action/SubmitForm.php'; 0189 return new Zend_Pdf_Action_SubmitForm($dictionary, $processedActions); 0190 break; 0191 0192 case 'ResetForm': 0193 // require_once 'Zend/Pdf/Action/ResetForm.php'; 0194 return new Zend_Pdf_Action_ResetForm($dictionary, $processedActions); 0195 break; 0196 0197 case 'ImportData': 0198 // require_once 'Zend/Pdf/Action/ImportData.php'; 0199 return new Zend_Pdf_Action_ImportData($dictionary, $processedActions); 0200 break; 0201 0202 case 'JavaScript': 0203 // require_once 'Zend/Pdf/Action/JavaScript.php'; 0204 return new Zend_Pdf_Action_JavaScript($dictionary, $processedActions); 0205 break; 0206 0207 case 'SetOCGState': 0208 // require_once 'Zend/Pdf/Action/SetOCGState.php'; 0209 return new Zend_Pdf_Action_SetOCGState($dictionary, $processedActions); 0210 break; 0211 0212 case 'Rendition': 0213 // require_once 'Zend/Pdf/Action/Rendition.php'; 0214 return new Zend_Pdf_Action_Rendition($dictionary, $processedActions); 0215 break; 0216 0217 case 'Trans': 0218 // require_once 'Zend/Pdf/Action/Trans.php'; 0219 return new Zend_Pdf_Action_Trans($dictionary, $processedActions); 0220 break; 0221 0222 case 'GoTo3DView': 0223 // require_once 'Zend/Pdf/Action/GoTo3DView.php'; 0224 return new Zend_Pdf_Action_GoTo3DView($dictionary, $processedActions); 0225 break; 0226 0227 default: 0228 // require_once 'Zend/Pdf/Action/Unknown.php'; 0229 return new Zend_Pdf_Action_Unknown($dictionary, $processedActions); 0230 break; 0231 } 0232 } 0233 0234 /** 0235 * Get resource 0236 * 0237 * @internal 0238 * @return Zend_Pdf_Element 0239 */ 0240 public function getResource() 0241 { 0242 return $this->_actionDictionary; 0243 } 0244 0245 /** 0246 * Dump Action and its child actions into PDF structures 0247 * 0248 * Returns dictionary indirect object or reference 0249 * 0250 * @internal 0251 * @param Zend_Pdf_ElementFactory $factory Object factory for newly created indirect objects 0252 * @param SplObjectStorage $processedActions list of already processed actions (used to prevent infinity loop caused by cyclic references) 0253 * @return Zend_Pdf_Element_Object|Zend_Pdf_Element_Reference Dictionary indirect object 0254 */ 0255 public function dumpAction(Zend_Pdf_ElementFactory_Interface $factory, SplObjectStorage $processedActions = null) 0256 { 0257 if ($processedActions === null) { 0258 $processedActions = new SplObjectStorage(); 0259 } 0260 if ($processedActions->contains($this)) { 0261 // require_once 'Zend/Pdf/Exception.php'; 0262 throw new Zend_Pdf_Exception('Action chain cyclyc reference is detected.'); 0263 } 0264 $processedActions->attach($this); 0265 0266 $childListUpdated = false; 0267 if (count($this->_originalNextList) != count($this->next)) { 0268 // If original and current children arrays have different size then children list was updated 0269 $childListUpdated = true; 0270 } else if ( !(array_keys($this->_originalNextList) === array_keys($this->next)) ) { 0271 // If original and current children arrays have different keys (with a glance to an order) then children list was updated 0272 $childListUpdated = true; 0273 } else { 0274 foreach ($this->next as $key => $childAction) { 0275 if ($this->_originalNextList[$key] !== $childAction) { 0276 $childListUpdated = true; 0277 break; 0278 } 0279 } 0280 } 0281 0282 if ($childListUpdated) { 0283 $this->_actionDictionary->touch(); 0284 switch (count($this->next)) { 0285 case 0: 0286 $this->_actionDictionary->Next = null; 0287 break; 0288 0289 case 1: 0290 $child = reset($this->next); 0291 $this->_actionDictionary->Next = $child->dumpAction($factory, $processedActions); 0292 break; 0293 0294 default: 0295 // require_once 'Zend/Pdf/Element/Array.php'; 0296 $pdfChildArray = new Zend_Pdf_Element_Array(); 0297 foreach ($this->next as $child) { 0298 0299 $pdfChildArray->items[] = $child->dumpAction($factory, $processedActions); 0300 } 0301 $this->_actionDictionary->Next = $pdfChildArray; 0302 break; 0303 } 0304 } else { 0305 foreach ($this->next as $child) { 0306 $child->dumpAction($factory, $processedActions); 0307 } 0308 } 0309 0310 if ($this->_actionDictionary instanceof Zend_Pdf_Element_Dictionary) { 0311 // It's a newly created action. Register it within object factory and return indirect object 0312 return $factory->newObject($this->_actionDictionary); 0313 } else { 0314 // It's a loaded object 0315 return $this->_actionDictionary; 0316 } 0317 } 0318 0319 0320 //////////////////////////////////////////////////////////////////////// 0321 // RecursiveIterator interface methods 0322 ////////////// 0323 0324 /** 0325 * Returns current child action. 0326 * 0327 * @return Zend_Pdf_Action 0328 */ 0329 public function current() 0330 { 0331 return current($this->next); 0332 } 0333 0334 /** 0335 * Returns current iterator key 0336 * 0337 * @return integer 0338 */ 0339 public function key() 0340 { 0341 return key($this->next); 0342 } 0343 0344 /** 0345 * Go to next child 0346 */ 0347 public function next() 0348 { 0349 return next($this->next); 0350 } 0351 0352 /** 0353 * Rewind children 0354 */ 0355 public function rewind() 0356 { 0357 return reset($this->next); 0358 } 0359 0360 /** 0361 * Check if current position is valid 0362 * 0363 * @return boolean 0364 */ 0365 public function valid() 0366 { 0367 return current($this->next) !== false; 0368 } 0369 0370 /** 0371 * Returns the child action. 0372 * 0373 * @return Zend_Pdf_Action|null 0374 */ 0375 public function getChildren() 0376 { 0377 return current($this->next); 0378 } 0379 0380 /** 0381 * Implements RecursiveIterator interface. 0382 * 0383 * @return bool whether container has any pages 0384 */ 0385 public function hasChildren() 0386 { 0387 return count($this->next) > 0; 0388 } 0389 0390 0391 //////////////////////////////////////////////////////////////////////// 0392 // Countable interface methods 0393 ////////////// 0394 0395 /** 0396 * count() 0397 * 0398 * @return int 0399 */ 0400 public function count() 0401 { 0402 return count($this->childOutlines); 0403 } 0404 }