PageRenderTime 59ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Pdf/ElementFactory.php

https://bitbucket.org/ksekar/campus
PHP | 446 lines | 183 code | 61 blank | 202 comment | 20 complexity | b345efbca94238c6c1dfd61d88a279c1 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT
  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. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: ElementFactory.php 24594 2012-01-05 21:27:01Z matthew $
  20. */
  21. /** Zend_Pdf_ElementFactory_Interface */
  22. require_once 'Zend/Pdf/ElementFactory/Interface.php';
  23. /**
  24. * PDF element factory.
  25. * Responsibility is to log PDF changes
  26. *
  27. * @package Zend_Pdf
  28. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Pdf_ElementFactory implements Zend_Pdf_ElementFactory_Interface
  32. {
  33. /**
  34. * List of the modified objects.
  35. * Also contains new and removed objects
  36. *
  37. * Array: ojbectNumber => Zend_Pdf_Element_Object
  38. *
  39. * @var array
  40. */
  41. private $_modifiedObjects = array();
  42. /**
  43. * List of the removed objects
  44. *
  45. * Array: ojbectNumber => Zend_Pdf_Element_Object
  46. *
  47. * @var SplObjectStorage
  48. */
  49. private $_removedObjects;
  50. /**
  51. * List of registered objects.
  52. * Used for resources clean up when factory is destroyed.
  53. *
  54. * Array of Zend_Pdf_Element objects
  55. *
  56. * @var array
  57. */
  58. private $_registeredObjects = array();
  59. /**
  60. * PDF object counter.
  61. * Actually it's an object number for new PDF object
  62. *
  63. * @var integer
  64. */
  65. private $_objectCount;
  66. /**
  67. * List of the attached object factories.
  68. * Array of Zend_Pdf_ElementFactory_Interface objects
  69. *
  70. * @var array
  71. */
  72. private $_attachedFactories = array();
  73. /**
  74. * Factory internal id
  75. *
  76. * @var integer
  77. */
  78. private $_factoryId;
  79. /**
  80. * Identity, used for factory id generation
  81. *
  82. * @var integer
  83. */
  84. private static $_identity = 0;
  85. /**
  86. * Internal cache to save calculated shifts
  87. *
  88. * @var array
  89. */
  90. private $_shiftCalculationCache = array();
  91. /**
  92. * Object constructor
  93. *
  94. * @param integer $objCount
  95. */
  96. public function __construct($objCount)
  97. {
  98. $this->_objectCount = (int)$objCount;
  99. $this->_factoryId = self::$_identity++;
  100. $this->_removedObjects = new SplObjectStorage();
  101. }
  102. /**
  103. * Get factory
  104. *
  105. * @return Zend_Pdf_ElementFactory_Interface
  106. */
  107. public function getFactory()
  108. {
  109. return $this;
  110. }
  111. /**
  112. * Factory generator
  113. *
  114. * @param integer $objCount
  115. * @return Zend_Pdf_ElementFactory_Interface
  116. */
  117. static public function createFactory($objCount)
  118. {
  119. require_once 'Zend/Pdf/ElementFactory/Proxy.php';
  120. return new Zend_Pdf_ElementFactory_Proxy(new Zend_Pdf_ElementFactory($objCount));
  121. }
  122. /**
  123. * Close factory and clean-up resources
  124. *
  125. * @internal
  126. */
  127. public function close()
  128. {
  129. $this->_modifiedObjects = null;
  130. $this->_removedObjects = null;
  131. $this->_attachedFactories = null;
  132. foreach ($this->_registeredObjects as $obj) {
  133. $obj->cleanUp();
  134. }
  135. $this->_registeredObjects = null;
  136. }
  137. /**
  138. * Get source factory object
  139. *
  140. * @return Zend_Pdf_ElementFactory
  141. */
  142. public function resolve()
  143. {
  144. return $this;
  145. }
  146. /**
  147. * Get factory ID
  148. *
  149. * @return integer
  150. */
  151. public function getId()
  152. {
  153. return $this->_factoryId;
  154. }
  155. /**
  156. * Set object counter
  157. *
  158. * @param integer $objCount
  159. */
  160. public function setObjectCount($objCount)
  161. {
  162. $this->_objectCount = (int)$objCount;
  163. }
  164. /**
  165. * Get object counter
  166. *
  167. * @return integer
  168. */
  169. public function getObjectCount()
  170. {
  171. $count = $this->_objectCount;
  172. foreach ($this->_attachedFactories as $attached) {
  173. $count += $attached->getObjectCount() - 1; // -1 as "0" object is a special case and shared between factories
  174. }
  175. return $count;
  176. }
  177. /**
  178. * Attach factory to the current;
  179. *
  180. * @param Zend_Pdf_ElementFactory_Interface $factory
  181. */
  182. public function attach(Zend_Pdf_ElementFactory_Interface $factory)
  183. {
  184. if ( $factory === $this || isset($this->_attachedFactories[$factory->getId()])) {
  185. /**
  186. * Don't attach factory twice.
  187. * We do not check recusively because of nature of attach operation
  188. * (Pages are always attached to the Documents, Fonts are always attached
  189. * to the pages even if pages already use Document level object factory and so on)
  190. */
  191. return;
  192. }
  193. $this->_attachedFactories[$factory->getId()] = $factory;
  194. }
  195. /**
  196. * Calculate object enumeration shift.
  197. *
  198. * @param Zend_Pdf_ElementFactory_Interface $factory
  199. * @return integer
  200. */
  201. public function calculateShift(Zend_Pdf_ElementFactory_Interface $factory)
  202. {
  203. if ($factory === $this) {
  204. return 0;
  205. }
  206. if (isset($this->_shiftCalculationCache[$factory->_factoryId])) {
  207. return $this->_shiftCalculationCache[$factory->_factoryId];
  208. }
  209. $shift = $this->_objectCount - 1;
  210. foreach ($this->_attachedFactories as $subFactory) {
  211. $subFactoryShift = $subFactory->calculateShift($factory);
  212. if ($subFactoryShift != -1) {
  213. // context found
  214. $this->_shiftCalculationCache[$factory->_factoryId] = $shift + $subFactoryShift;
  215. return $shift + $subFactoryShift;
  216. } else {
  217. $shift += $subFactory->getObjectCount()-1;
  218. }
  219. }
  220. $this->_shiftCalculationCache[$factory->_factoryId] = -1;
  221. return -1;
  222. }
  223. /**
  224. * Clean enumeration shift cache.
  225. * Has to be used after PDF render operation to let followed updates be correct.
  226. */
  227. public function cleanEnumerationShiftCache()
  228. {
  229. $this->_shiftCalculationCache = array();
  230. foreach ($this->_attachedFactories as $attached) {
  231. $attached->cleanEnumerationShiftCache();
  232. }
  233. }
  234. /**
  235. * Retrive object enumeration shift.
  236. *
  237. * @param Zend_Pdf_ElementFactory_Interface $factory
  238. * @return integer
  239. * @throws Zend_Pdf_Exception
  240. */
  241. public function getEnumerationShift(Zend_Pdf_ElementFactory_Interface $factory)
  242. {
  243. if (($shift = $this->calculateShift($factory)) == -1) {
  244. require_once 'Zend/Pdf/Exception.php';
  245. throw new Zend_Pdf_Exception('Wrong object context');
  246. }
  247. return $shift;
  248. }
  249. /**
  250. * Mark object as modified in context of current factory.
  251. *
  252. * @param Zend_Pdf_Element_Object $obj
  253. * @throws Zend_Pdf_Exception
  254. */
  255. public function markAsModified(Zend_Pdf_Element_Object $obj)
  256. {
  257. if ($obj->getFactory() !== $this) {
  258. require_once 'Zend/Pdf/Exception.php';
  259. throw new Zend_Pdf_Exception('Object is not generated by this factory');
  260. }
  261. $this->_modifiedObjects[$obj->getObjNum()] = $obj;
  262. }
  263. /**
  264. * Remove object in context of current factory.
  265. *
  266. * @param Zend_Pdf_Element_Object $obj
  267. * @throws Zend_Pdf_Exception
  268. */
  269. public function remove(Zend_Pdf_Element_Object $obj)
  270. {
  271. if (!$obj->compareFactory($this)) {
  272. require_once 'Zend/Pdf/Exception.php';
  273. throw new Zend_Pdf_Exception('Object is not generated by this factory');
  274. }
  275. $this->_modifiedObjects[$obj->getObjNum()] = $obj;
  276. $this->_removedObjects->attach($obj);
  277. }
  278. /**
  279. * Generate new Zend_Pdf_Element_Object
  280. *
  281. * @todo Reusage of the freed object. It's not a support of new feature, but only improvement.
  282. *
  283. * @param Zend_Pdf_Element $objectValue
  284. * @return Zend_Pdf_Element_Object
  285. */
  286. public function newObject(Zend_Pdf_Element $objectValue)
  287. {
  288. require_once 'Zend/Pdf/Element/Object.php';
  289. $obj = new Zend_Pdf_Element_Object($objectValue, $this->_objectCount++, 0, $this);
  290. $this->_modifiedObjects[$obj->getObjNum()] = $obj;
  291. return $obj;
  292. }
  293. /**
  294. * Generate new Zend_Pdf_Element_Object_Stream
  295. *
  296. * @todo Reusage of the freed object. It's not a support of new feature, but only improvement.
  297. *
  298. * @param mixed $objectValue
  299. * @return Zend_Pdf_Element_Object_Stream
  300. */
  301. public function newStreamObject($streamValue)
  302. {
  303. require_once 'Zend/Pdf/Element/Object/Stream.php';
  304. $obj = new Zend_Pdf_Element_Object_Stream($streamValue, $this->_objectCount++, 0, $this);
  305. $this->_modifiedObjects[$obj->getObjNum()] = $obj;
  306. return $obj;
  307. }
  308. /**
  309. * Enumerate modified objects.
  310. * Returns array of Zend_Pdf_UpdateInfoContainer
  311. *
  312. * @param Zend_Pdf_ElementFactory_Interface $rootFactory
  313. * @return array
  314. */
  315. public function listModifiedObjects($rootFactory = null)
  316. {
  317. if ($rootFactory == null) {
  318. $rootFactory = $this;
  319. $shift = 0;
  320. } else {
  321. $shift = $rootFactory->getEnumerationShift($this);
  322. }
  323. ksort($this->_modifiedObjects);
  324. $result = array();
  325. require_once 'Zend/Pdf/UpdateInfoContainer.php';
  326. foreach ($this->_modifiedObjects as $objNum => $obj) {
  327. if ($this->_removedObjects->contains($obj)) {
  328. $result[$objNum+$shift] = new Zend_Pdf_UpdateInfoContainer($objNum + $shift,
  329. $obj->getGenNum()+1,
  330. true);
  331. } else {
  332. $result[$objNum+$shift] = new Zend_Pdf_UpdateInfoContainer($objNum + $shift,
  333. $obj->getGenNum(),
  334. false,
  335. $obj->dump($rootFactory));
  336. }
  337. }
  338. foreach ($this->_attachedFactories as $factory) {
  339. $result += $factory->listModifiedObjects($rootFactory);
  340. }
  341. return $result;
  342. }
  343. /**
  344. * Register object in the factory
  345. *
  346. * It's used to clear "parent object" referencies when factory is closed and clean up resources
  347. *
  348. * @param string $refString
  349. * @param Zend_Pdf_Element_Object $obj
  350. */
  351. public function registerObject(Zend_Pdf_Element_Object $obj, $refString)
  352. {
  353. $this->_registeredObjects[$refString] = $obj;
  354. }
  355. /**
  356. * Fetch object specified by reference
  357. *
  358. * @param string $refString
  359. * @return Zend_Pdf_Element_Object|null
  360. */
  361. public function fetchObject($refString)
  362. {
  363. if (!isset($this->_registeredObjects[$refString])) {
  364. return null;
  365. }
  366. return $this->_registeredObjects[$refString];
  367. }
  368. /**
  369. * Check if PDF file was modified
  370. *
  371. * @return boolean
  372. */
  373. public function isModified()
  374. {
  375. if (count($this->_modifiedObjects) != 0) {
  376. return true;
  377. }
  378. foreach ($this->_attachedFactories as $subFactory) {
  379. if ($subFactory->isModified()) {
  380. return true;
  381. }
  382. }
  383. return false;
  384. }
  385. }