WorkflowDatabaseTiein
[ ]
[ ]
[ ]
[ ]
[ ]
Source for file execution.php
Documentation is available at execution.php
1. <?php
2. /**
3. * File containing the ezcWorkflowDatabaseExecution class.
4. *
5. * @package WorkflowDatabaseTiein
6. * @version //autogen//
7. * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
8. * @license http://ez.no/licenses/new_bsd New BSD License
9. */
10.
11. /**
12. * Workflow executer that suspends and resumes workflow
13. * execution states to and from a database.
14. *
15. * @package WorkflowDatabaseTiein
16. * @version //autogen//
17. */
18. class ezcWorkflowDatabaseExecution extends ezcWorkflowExecution
19. {
20. /**
21. * ezcDbHandler instance to be used.
22. *
23. * @var ezcDbHandler
24. */
25. protected $db;
26.
27. /**
28. * Flag that indicates whether the execution has been loaded.
29. *
30. * @var boolean
31. */
32. protected $loaded = false;
33.
34. /**
35. * Container to hold the properties
36. *
37. * @var array(string=>mixed)
38. */
39. protected $properties = array(
40. 'definitionStorage' => null,
41. 'workflow' => null,
42. 'options' => null
43. );
44.
45. /**
46. * Construct a new database execution.
47. *
48. * This constructor is a tie-in.
49. *
50. * @param ezcDbHandler $db
51. * @param int $executionId
52. * @throws ezcWorkflowExecutionException
53. */
54. public function __construct ( ezcDbHandler $db, $executionId = null )
55. {
56. if ( $executionId !== null && !is_int( $executionId ) )
57. {
58. throw new ezcWorkflowExecutionException( '$executionId must be an integer.' );
59. }
60.
61. $this->db = $db;
62. $this->properties['definitionStorage'] = new ezcWorkflowDatabaseDefinitionStorage( $db );
63. $this->properties['options'] = new ezcWorkflowDatabaseOptions;
64.
65. if ( is_int( $executionId ) )
66. {
67. $this->loadExecution( $executionId );
68. }
69. }
70.
71. /**
72. * Property get access.
73. *
74. * @param string $propertyName
75. * @return mixed
76. * @throws ezcBasePropertyNotFoundException
77. * If the given property could not be found.
78. * @ignore
79. */
80. public function __get( $propertyName )
81. {
82. switch ( $propertyName )
83. {
84. case 'definitionStorage':
85. case 'workflow':
86. case 'options':
87. return $this->properties[$propertyName];
88. }
89.
90. throw new ezcBasePropertyNotFoundException( $propertyName );
91. }
92.
93. /**
94. * Property set access.
95. *
96. * @param string $propertyName
97. * @param string $propertyValue
98. * @throws ezcBasePropertyNotFoundException
99. * If the given property could not be found.
100. * @throws ezcBaseValueException
101. * If the value for the property options is not an ezcWorkflowDatabaseOptions object.
102. * @ignore
103. */
104. public function __set( $propertyName, $propertyValue )
105. {
106. switch ( $propertyName )
107. {
108. case 'definitionStorage':
109. case 'workflow':
110. return parent::__set( $propertyName, $propertyValue );
111. case 'options':
112. if ( !( $propertyValue instanceof ezcWorkflowDatabaseOptions ) )
113. {
114. throw new ezcBaseValueException(
115. $propertyName,
116. $propertyValue,
117. 'ezcWorkflowDatabaseOptions'
118. );
119. }
120. break;
121. default:
122. throw new ezcBasePropertyNotFoundException( $propertyName );
123. }
124. $this->properties[$propertyName] = $propertyValue;
125. }
126.
127. /**
128. * Property isset access.
129. *
130. * @param string $propertyName
131. * @return bool
132. * @ignore
133. */
134. public function __isset( $propertyName )
135. {
136. switch ( $propertyName )
137. {
138. case 'definitionStorage':
139. case 'workflow':
140. case 'options':
141. return true;
142. }
143.
144. return false;
145. }
146.
147. /**
148. * Start workflow execution.
149. *
150. * @param int $parentId
151. * @throws ezcDbException
152. */
153. protected function doStart( $parentId )
154. {
155. $this->db->beginTransaction();
156.
157. $query = $this->db->createInsertQuery();
158.
159. $query->insertInto( $this->db->quoteIdentifier( $this->options['prefix'] . 'execution' ) )
160. ->set( $this->db->quoteIdentifier( 'workflow_id' ), $query->bindValue( (int)$this->workflow->id ) )
161. ->set( $this->db->quoteIdentifier( 'execution_parent' ), $query->bindValue( (int)$parentId ) )
162. ->set( $this->db->quoteIdentifier( 'execution_started' ), $query->bindValue( time() ) )
163. ->set( $this->db->quoteIdentifier( 'execution_variables' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $this->variables ) ) )
164. ->set( $this->db->quoteIdentifier( 'execution_waiting_for' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $this->waitingFor ) ) )
165. ->set( $this->db->quoteIdentifier( 'execution_threads' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $this->threads ) ) )
166. ->set( $this->db->quoteIdentifier( 'execution_next_thread_id' ), $query->bindValue( (int)$this->nextThreadId ) );
167.
168. $statement = $query->prepare();
169. $statement->execute();
170.
171. $this->id = (int)$this->db->lastInsertId( 'execution_execution_id_seq' );
172. }
173.
174. /**
175. * Suspend workflow execution.
176. *
177. * @throws ezcDbException
178. */
179. protected function doSuspend()
180. {
181. $this->cleanupTable( 'execution_state' );
182.
183. $query = $this->db->createUpdateQuery();
184.
185. $query->update( $this->db->quoteIdentifier( $this->options['prefix'] . 'execution' ) )
186. ->where( $query->expr->eq( $this->db->quoteIdentifier( 'execution_id' ), $query->bindValue( (int)$this->id ) ) )
187. ->set( $this->db->quoteIdentifier( 'execution_suspended' ), $query->bindValue( time() ) )
188. ->set( $this->db->quoteIdentifier( 'execution_variables' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $this->variables ) ) )
189. ->set( $this->db->quoteIdentifier( 'execution_waiting_for' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $this->waitingFor ) ) )
190. ->set( $this->db->quoteIdentifier( 'execution_threads' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $this->threads ) ) )
191. ->set( $this->db->quoteIdentifier( 'execution_next_thread_id' ), $query->bindValue( (int)$this->nextThreadId ) );
192.
193. $statement = $query->prepare();
194. $statement->execute();
195.
196. foreach ( $this->activatedNodes as $node )
197. {
198. $query = $this->db->createInsertQuery();
199.
200. $query->insertInto( $this->db->quoteIdentifier( $this->options['prefix'] . 'execution_state' ) )
201. ->set( $this->db->quoteIdentifier( 'execution_id' ), $query->bindValue( (int)$this->id ) )
202. ->set( $this->db->quoteIdentifier( 'node_id' ), $query->bindValue( (int)$node->getId() ) )
203. ->set( $this->db->quoteIdentifier( 'node_state' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $node->getState() ) ) )
204. ->set( $this->db->quoteIdentifier( 'node_activated_from' ), $query->bindValue( ezcWorkflowDatabaseUtil::serialize( $node->getActivatedFrom() ) ) )
205. ->set( $this->db->quoteIdentifier( 'node_thread_id' ), $query->bindValue( (int)$node->getThreadId() ) );
206.
207. $statement = $query->prepare();
208. $statement->execute();
209. }
210.
211. $this->db->commit();
212. }
213.
214. /**
215. * Resume workflow execution.
216. *
217. * @throws ezcDbException
218. */
219. protected function doResume()
220. {
221. $this->db->beginTransaction();
222. }
223.
224. /**
225. * End workflow execution.
226. *
227. * @throws ezcDbException
228. */
229. protected function doEnd()
230. {
231. $this->cleanupTable( 'execution' );
232. $this->cleanupTable( 'execution_state' );
233.
234. if ( !$this->isCancelled() )
235. {
236. $this->db->commit();
237. }
238. }
239.
240. /**
241. * Returns a new execution object for a sub workflow.
242. *
243. * @param int $id
244. * @return ezcWorkflowExecution
245. */
246. protected function doGetSubExecution( $id = null )
247. {
248. return new ezcWorkflowDatabaseExecution( $this->db, $id );
249. }
250.
251. /**
252. * Cleanup execution / execution_state tables.
253. *
254. * @param string $tableName
255. * @throws ezcDbException
256. */
257. protected function cleanupTable( $tableName )
258. {
259. $query = $this->db->createDeleteQuery();
260. $query->deleteFrom( $this->db->quoteIdentifier( $this->options['prefix'] . $tableName ) );
261.
262. $id = $query->expr->eq( $this->db->quoteIdentifier( 'execution_id' ), $query->bindValue( (int)$this->id ) );
263.
264. if ( $tableName == 'execution' )
265. {
266. $parent = $query->expr->eq( $this->db->quoteIdentifier( 'execution_parent' ), $query->bindValue( (int)$this->id ) );
267. $query->where( $query->expr->lOr( $id, $parent ) );
268. }
269. else
270. {
271. $query->where( $id );
272. }
273.
274. $statement = $query->prepare();
275. $statement->execute();
276. }
277.
278. /**
279. * Load execution state.
280. *
281. * @param int $executionId ID of the execution to load.
282. * @throws ezcWorkflowExecutionException
283. */
284. protected function loadExecution( $executionId )
285. {
286. $query = $this->db->createSelectQuery();
287.
288. $query->select( $this->db->quoteIdentifier( 'workflow_id' ) )
289. ->select( $this->db->quoteIdentifier( 'execution_variables' ) )
290. ->select( $this->db->quoteIdentifier( 'execution_threads' ) )
291. ->select( $this->db->quoteIdentifier( 'execution_next_thread_id' ) )
292. ->select( $this->db->quoteIdentifier( 'execution_waiting_for' ) )
293. ->from( $this->db->quoteIdentifier( $this->options['prefix'] . 'execution' ) )
294. ->where( $query->expr->eq( $this->db->quoteIdentifier( 'execution_id' ),
295. $query->bindValue( (int)$executionId ) ) );
296.
297. $stmt = $query->prepare();
298. $stmt->execute();
299.
300. $result = $stmt->fetchAll( PDO::FETCH_ASSOC );
301.
302. if ( $result === false || empty( $result ) )
303. {
304. throw new ezcWorkflowExecutionException(
305. 'Could not load execution state.'
306. );
307. }
308.
309. $this->id = $executionId;
310. $this->nextThreadId = $result[0]['execution_next_thread_id'];
311.
312. $this->threads = ezcWorkflowDatabaseUtil::unserialize( $result[0]['execution_threads'] );
313. $this->variables = ezcWorkflowDatabaseUtil::unserialize( $result[0]['execution_variables'] );
314. $this->waitingFor = ezcWorkflowDatabaseUtil::unserialize( $result[0]['execution_waiting_for'] );
315.
316. $workflowId = $result[0]['workflow_id'];
317. $this->workflow = $this->properties['definitionStorage']->loadById( $workflowId );
318.
319. $query = $this->db->createSelectQuery();
320.
321. $query->select( $this->db->quoteIdentifier( 'node_id' ) )
322. ->select( $this->db->quoteIdentifier( 'node_state' ) )
323. ->select( $this->db->quoteIdentifier( 'node_activated_from' ) )
324. ->select( $this->db->quoteIdentifier( 'node_thread_id' ) )
325. ->from( $this->db->quoteIdentifier( $this->options['prefix'] . 'execution_state' ) )
326. ->where( $query->expr->eq( $this->db->quoteIdentifier( 'execution_id' ),
327. $query->bindValue( (int)$executionId ) ) );
328.
329. $stmt = $query->prepare();
330. $stmt->execute();
331.
332. $result = $stmt->fetchAll( PDO::FETCH_ASSOC );
333. $active = array();
334.
335. foreach ( $result as $row )
336. {
337. $active[$row['node_id']] = array(
338. 'activated_from' => ezcWorkflowDatabaseUtil::unserialize(
339. $row['node_activated_from']
340. ),
341. 'state' => ezcWorkflowDatabaseUtil::unserialize(
342. $row['node_state'], null
343. ),
344. 'thread_id' => $row['node_thread_id']
345. );
346. }
347.
348. foreach ( $this->workflow->nodes as $node )
349. {
350. $nodeId = $node->getId();
351.
352. if ( isset( $active[$nodeId] ) )
353. {
354. $node->setActivationState( ezcWorkflowNode::WAITING_FOR_EXECUTION );
355. $node->setThreadId( $active[$nodeId]['thread_id'] );
356. $node->setState( $active[$nodeId]['state'], null );
357. $node->setActivatedFrom( $active[$nodeId]['activated_from'] );
358.
359. $this->activate( $node, false );
360. }
361. }
362.
363. $this->cancelled = false;
364. $this->ended = false;
365. $this->loaded = true;
366. $this->resumed = false;
367. $this->suspended = true;
368. }
369. }
370. ?>
Last updated: Mon, 21 Dec 2009