Action.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /** Zend_Pdf_ElementFactory */
  23. require_once 'Zend/Pdf/ElementFactory.php';
  24. /** Zend_Pdf_Target */
  25. require_once 'Zend/Pdf/Target.php';
  26. /**
  27. * Abstract PDF action representation class
  28. *
  29. * @package Zend_Pdf
  30. * @subpackage Actions
  31. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  32. * @license http://framework.zend.com/license/new-bsd New BSD License
  33. */
  34. abstract class Zend_Pdf_Action extends Zend_Pdf_Target
  35. {
  36. /**
  37. * Action dictionary
  38. *
  39. * @var Zend_Pdf_Element_Dictionary|Zend_Pdf_Element_Object|Zend_Pdf_Element_Reference
  40. */
  41. protected $_actionDictionary;
  42. /**
  43. * A list of next actions in actions tree (used for actions chaining)
  44. *
  45. * @var SplObjectStorage Contains Zend_Pdf_Action objects
  46. */
  47. protected $_next;
  48. /**
  49. * Parent object in Actions tree (or null if it's a root object)
  50. *
  51. * @var Zend_Pdf_Action
  52. */
  53. protected $_parent;
  54. /**
  55. * Object constructor
  56. *
  57. * @param Zend_Pdf_Element_Dictionary $dictionary
  58. * @param Zend_Pdf_Action|null $parentAction
  59. * @param SplObjectStorage $processedActions list of already processed action dictionaries, used to avoid cyclic references
  60. * @throws Zend_Pdf_Exception
  61. */
  62. public function __construct(Zend_Pdf_Element $dictionary, $parentAction, SplObjectStorage $processedActions)
  63. {
  64. if ($dictionary->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
  65. require_once 'Zend/Pdf/Exception.php';
  66. throw new Zend_Pdf_Exception('$dictionary mast be a direct or an indirect dictionary object.');
  67. }
  68. if ($parentAction !== null && !$parentAction instanceof Zend_Pdf_Action) {
  69. require_once 'Zend/Pdf/Exception.php';
  70. throw new Zend_Pdf_Exception('Zend_Pdf_Action constructor $parentAction parameter must be a Zend_Pdf_Action object.');
  71. }
  72. $this->_actionDictionary = $dictionary;
  73. $this->_parent = $parentAction;
  74. $this->_next = new SplObjectStorage();
  75. if ($dictionary->Next !== null) {
  76. if ($dictionary->Next instanceof Zend_Pdf_Element_Dictionary) {
  77. // Check if dictionary object is not already processed
  78. if (!$processedActions->contains($dictionary->Next)) {
  79. $processedActions->attach($dictionary->Next);
  80. $this->_next->attach(Zend_Pdf_Action::load($dictionary->Next, $this, $processedActions));
  81. }
  82. } else if ($dictionary->Next instanceof Zend_Pdf_Element_Array) {
  83. foreach ($dictionary->Next->items as $chainedActionDictionary) {
  84. // Check if dictionary object is not already processed
  85. if (!$processedActions->contains($chainedActionDictionary)) {
  86. $processedActions->attach($chainedActionDictionary);
  87. $this->_next->attach(Zend_Pdf_Action::load($chainedActionDictionary, $this, $processedActions));
  88. }
  89. }
  90. } else {
  91. require_once 'Zend/Pdf/Exception.php';
  92. throw new Zend_Pdf_Exception('PDF Action dictionary Next entry must be a dictionary or an array.');
  93. }
  94. }
  95. }
  96. /**
  97. * Load PDF action object using specified dictionary
  98. *
  99. * @param Zend_Pdf_Element $dictionary (It's actually Dictionary or Dictionary Object or Reference to a Dictionary Object)
  100. * @param Zend_Pdf_Action $parentAction
  101. * @param SplObjectStorage $processedActions list of already processed action dictionaries, used to avoid cyclic references
  102. * @return Zend_Pdf_Action
  103. * @throws Zend_Pdf_Exception
  104. */
  105. public static function load(Zend_Pdf_Element $dictionary, $parentAction = null, SplObjectStorage $processedActions = null)
  106. {
  107. if ($processedActions === null) {
  108. $processedActions = new SplObjectStorage();
  109. }
  110. if ($dictionary->getType() != Zend_Pdf_Element::TYPE_DICTIONARY) {
  111. require_once 'Zend/Pdf/Exception.php';
  112. throw new Zend_Pdf_Exception('$dictionary mast be a direct or an indirect dictionary object.');
  113. }
  114. if (isset($dictionary->Type) && $dictionary->Type->value != 'Action') {
  115. require_once 'Zend/Pdf/Exception.php';
  116. throw new Zend_Pdf_Exception('Action dictionary Type entry must be set to \'Action\'.');
  117. }
  118. if ($dictionary->S === null) {
  119. require_once 'Zend/Pdf/Exception.php';
  120. throw new Zend_Pdf_Exception('Action dictionary must have S entry');
  121. }
  122. switch ($dictionary->S->value) {
  123. case 'GoTo':
  124. require_once 'Zend/Pdf/Action/GoTo.php';
  125. return new Zend_Pdf_Action_GoTo($dictionary, $parentAction, $processedActions);
  126. brake;
  127. case 'GoToR':
  128. require_once 'Zend/Pdf/Action/GoToR.php';
  129. return new Zend_Pdf_Action_GoToR($dictionary, $parentAction, $processedActions);
  130. brake;
  131. case 'GoToE':
  132. require_once 'Zend/Pdf/Action/GoToE.php';
  133. return new Zend_Pdf_Action_GoToE($dictionary, $parentAction, $processedActions);
  134. brake;
  135. case 'Launch':
  136. require_once 'Zend/Pdf/Action/Launch.php';
  137. return new Zend_Pdf_Action_Launch($dictionary, $parentAction, $processedActions);
  138. brake;
  139. case 'Thread':
  140. require_once 'Zend/Pdf/Action/Thread.php';
  141. return new Zend_Pdf_Action_Thread($dictionary, $parentAction, $processedActions);
  142. brake;
  143. case 'URI':
  144. require_once 'Zend/Pdf/Action/URI.php';
  145. return new Zend_Pdf_Action_URI($dictionary, $parentAction, $processedActions);
  146. brake;
  147. case 'Sound':
  148. require_once 'Zend/Pdf/Action/Sound.php';
  149. return new Zend_Pdf_Action_Sound($dictionary, $parentAction, $processedActions);
  150. brake;
  151. case 'Movie':
  152. require_once 'Zend/Pdf/Action/Movie.php';
  153. return new Zend_Pdf_Action_Movie($dictionary, $parentAction, $processedActions);
  154. brake;
  155. case 'Hide':
  156. require_once 'Zend/Pdf/Action/Hide.php';
  157. return new Zend_Pdf_Action_Hide($dictionary, $parentAction, $processedActions);
  158. brake;
  159. case 'Named':
  160. require_once 'Zend/Pdf/Action/Named.php';
  161. return new Zend_Pdf_Action_Named($dictionary, $parentAction, $processedActions);
  162. brake;
  163. case 'SubmitForm':
  164. require_once 'Zend/Pdf/Action/SubmitForm.php';
  165. return new Zend_Pdf_Action_SubmitForm($dictionary, $parentAction, $processedActions);
  166. brake;
  167. case 'ResetForm':
  168. require_once 'Zend/Pdf/Action/ResetForm.php';
  169. return new Zend_Pdf_Action_ResetForm($dictionary, $parentAction, $processedActions);
  170. brake;
  171. case 'ImportData':
  172. require_once 'Zend/Pdf/Action/ImportData.php';
  173. return new Zend_Pdf_Action_ImportData($dictionary, $parentAction, $processedActions);
  174. brake;
  175. case 'JavaScript':
  176. require_once 'Zend/Pdf/Action/JavaScript.php';
  177. return new Zend_Pdf_Action_JavaScript($dictionary, $parentAction, $processedActions);
  178. brake;
  179. case 'SetOCGState':
  180. require_once 'Zend/Pdf/Action/SetOCGState.php';
  181. return new Zend_Pdf_Action_SetOCGState($dictionary, $parentAction, $processedActions);
  182. brake;
  183. case 'Rendition':
  184. require_once 'Zend/Pdf/Action/Rendition.php';
  185. return new Zend_Pdf_Action_Rendition($dictionary, $parentAction, $processedActions);
  186. brake;
  187. case 'Trans':
  188. require_once 'Zend/Pdf/Action/Trans.php';
  189. return new Zend_Pdf_Action_Trans($dictionary, $parentAction, $processedActions);
  190. brake;
  191. case 'GoTo3DView':
  192. require_once 'Zend/Pdf/Action/GoTo3DView.php';
  193. return new Zend_Pdf_Action_GoTo3DView($dictionary, $parentAction, $processedActions);
  194. brake;
  195. default:
  196. require_once 'Zend/Pdf/Action/Unknown.php';
  197. return new Zend_Pdf_Action_Unknown($dictionary, $parentAction, $processedActions);
  198. brake;
  199. }
  200. }
  201. /**
  202. * Extract action from the chain
  203. *
  204. * Returns root of the updated actions tree
  205. *
  206. * @return Zend_Pdf_Action
  207. */
  208. public function extract()
  209. {
  210. if (($parent = $this->_parent) !== null) {
  211. $parent->_next->detach($this);
  212. foreach ($this->_next as $chainedAction) {
  213. $parent->_next->attach($chainedAction);
  214. $chainedAction->_parent = $parent;
  215. }
  216. $this->_parent = null;
  217. $this->_next = new SplObjectStorage();
  218. return $parent->getRoot();
  219. } else {
  220. // This is a root node. Treat first subaction as a new root
  221. if ($this->_next->count() == 0) {
  222. // There is no any action in a tree now
  223. return null;
  224. }
  225. $this->_next->rewind();
  226. $root = $this->_next->current();
  227. $this->_next->detach($root);
  228. $root->_parent = null;
  229. foreach ($this->_next as $chainedAction) {
  230. $root->_next->attach($chainedAction);
  231. $chainedAction->_parent = $root;
  232. }
  233. $this->_next = new SplObjectStorage();
  234. return $root;
  235. }
  236. }
  237. /**
  238. * Destroy actions subtree
  239. *
  240. * Method has to be used to clean up resources after actions tree usage
  241. * since PHP doesn't do it automatically for objects with cyclic references
  242. */
  243. public function clean()
  244. {
  245. $this->_parent = null;
  246. foreach ($this->_next as $chainedAction) {
  247. $chainedAction->clean();
  248. }
  249. $this->_next = new SplObjectStorage();
  250. }
  251. /**
  252. * Get root of actions tree
  253. *
  254. * @return Zend_Pdf_Action
  255. */
  256. public function getRoot()
  257. {
  258. $root = $this;
  259. while ($root->_parent !== null) {
  260. $root = $root->_parent;
  261. }
  262. return $root;
  263. }
  264. /**
  265. * Return all subactions including this one
  266. *
  267. * @return SplObjectStorage
  268. */
  269. public function getAllActions()
  270. {
  271. $actions = new SplObjectStorage();
  272. $actions->attach($this);
  273. foreach ($this->_next as $chainedAction) {
  274. /** @todo Change to $actions->addAll($subAction->allActions()) when PHP 5.3.0+ is required for ZF */
  275. foreach ($chainedAction->getAllActions() as $action) {
  276. $actions->attach($action);
  277. }
  278. }
  279. return $actions;
  280. }
  281. /**
  282. * Get handler
  283. *
  284. * @param string $property
  285. * @return Zend_Pdf_Element | null
  286. */
  287. public function __get($property)
  288. {
  289. return $this->_actionDictionary->$property;
  290. }
  291. /**
  292. * Set handler
  293. *
  294. * @param string $property
  295. * @param mixed $value
  296. */
  297. public function __set($item, $value)
  298. {
  299. $this->_actionDictionary->$property = $value;
  300. }
  301. /**
  302. * Attach chained action
  303. *
  304. * @param Zend_Pdf_Action $action
  305. */
  306. public function attach(Zend_Pdf_Action $action)
  307. {
  308. $this->_next->attach($action);
  309. $action->_parent = $this;
  310. }
  311. /**
  312. * Rebuild PDF dictionaries corresponding to the current tree structure
  313. */
  314. public function rebuildSubtree()
  315. {
  316. switch (count($this->_next)) {
  317. case 0:
  318. $this->_actionDictionary->Next = null;
  319. break;
  320. case 1:
  321. $this->_next->rewind();
  322. $chainedAction = $this->_next->current();
  323. $chainedAction->rebuildSubtree();
  324. $this->_actionDictionary->Next = $chainedAction->_actionDictionary;
  325. break;
  326. default:
  327. $nextArray = new Zend_Pdf_Element_Array();
  328. foreach ($this->_next as $chainedAction) {
  329. $chainedAction->rebuildSubtree();
  330. $nextArray->items[] = $chainedAction->_actionDictionary;
  331. }
  332. $this->_actionDictionary->Next = $nextArray;
  333. break;
  334. }
  335. }
  336. /**
  337. * Get resource
  338. *
  339. * @internal
  340. * @return Zend_Pdf_Element
  341. */
  342. public function getResource()
  343. {
  344. return $this->_actionDictionary;
  345. }
  346. }