/
Progress.php
331 lines (287 loc) · 10.8 KB
/
Progress.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
<?php
namespace Concrete\Core\Workflow\Progress;
use Concrete\Core\Entity\Notification\WorkflowProgressNotification;
use Concrete\Core\Foundation\ConcreteObject;
use Concrete\Core\Notification\Subject\SubjectInterface;
use Concrete\Core\Workflow\Workflow;
use Concrete\Core\Workflow\Request\Request as WorkflowRequest;
use Concrete\Core\Workflow\EmptyWorkflow;
use Concrete\Core\Workflow\Progress\Category as WorkflowProgressCategory;
use Concrete\Core\Package\PackageList;
use Database;
use Core;
use Events;
use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Base class for workflow progresses.
*
* @method static Progress add(string $wpCategoryHandle, Workflow $wf, WorkflowRequest $wr) Deprecated method. Use Progress::create instead.
*/
abstract class Progress extends ConcreteObject implements SubjectInterface
{
protected $wrID = null;
protected $wpID;
protected $wpDateAdded;
protected $wfID;
protected $response;
protected $wpDateLastAction;
public function getNotificationDate()
{
return \Core::make('date')->toDateTime($this->wpDateAdded);
}
public function getUsersToExcludeFromNotification()
{
return array();
}
/**
* Gets the Workflow object attached to this WorkflowProgress object.
*
* @return Workflow
*/
public function getWorkflowObject()
{
if ($this->wfID > 0) {
$wf = Workflow::getByID($this->wfID);
} else {
$wf = new EmptyWorkflow();
}
return $wf;
}
/**
* Gets an optional WorkflowResponse object. This is set in some cases.
*/
public function getWorkflowProgressResponseObject()
{
return $this->response;
}
public function setWorkflowProgressResponseObject($obj)
{
$this->response = $obj;
}
/**
* Gets the date of the last action.
*/
public function getWorkflowProgressDateLastAction()
{
return $this->wpDateLastAction;
}
/**
* Gets the ID of the progress object.
*/
public function getWorkflowProgressID()
{
return $this->wpID;
}
/**
* Gets the ID of the progress object.
*/
public function getWorkflowProgressCategoryHandle()
{
return $this->wpCategoryHandle;
}
/**
* Get the category ID.
*/
public function getWorkflowProgressCategoryID()
{
return $this->wpCategoryID;
}
/**
* Gets the date the WorkflowProgress object was added.
*
* @return datetime
*/
public function getWorkflowProgressDateAdded()
{
return $this->wpDateAdded;
}
/**
* Get the WorkflowRequest object for the current WorkflowProgress object.
*
* @return WorkflowRequest
*/
public function getWorkflowRequestObject()
{
if ($this->wrID > 0) {
$cat = WorkflowProgressCategory::getByID($this->wpCategoryID);
$handle = $cat->getWorkflowProgressCategoryHandle();
$class = '\\Core\\Workflow\\Request\\' . Core::make('helper/text')->camelcase($handle) . 'Request';
$pkHandle = $cat->getPackageHandle();
$class = core_class($class, $pkHandle);
$wr = $class::getByID($this->wrID);
if (is_object($wr)) {
$wr->setCurrentWorkflowProgressObject($this);
return $wr;
}
}
}
public static function __callStatic($name, $arguments)
{
if (strcasecmp($name, 'add') === 0) {
return call_user_func_array('static::create', $arguments);
}
trigger_error("Call to undefined method ".__CLASS__."::$name()", E_USER_ERROR);
}
/**
* Creates a WorkflowProgress object (which will be assigned to a Page, File, etc... in our system.
*
* @param string $wpCategoryHandle
* @param Workflow $wf
* @param WorkflowRequest $wr
*
* @return self
*/
public static function create($wpCategoryHandle, Workflow $wf, WorkflowRequest $wr)
{
$db = Database::connection();
$wpDateAdded = Core::make('helper/date')->getOverridableNow();
$wpCategoryID = $db->fetchColumn('select wpCategoryID from WorkflowProgressCategories where wpCategoryHandle = ?', array($wpCategoryHandle));
$db->executeQuery('insert into WorkflowProgress (wfID, wrID, wpDateAdded, wpCategoryID) values (?, ?, ?, ?)', array(
$wf->getWorkflowID(), $wr->getWorkflowRequestID(), $wpDateAdded, $wpCategoryID,
));
$wp = self::getByID($db->lastInsertId());
$wp->addWorkflowProgressHistoryObject($wr);
if (!($wf instanceof EmptyWorkflow)) {
$application = \Core::getFacadeApplication();
$type = $application->make('manager/notification/types')->driver('workflow_progress');
$notifier = $type->getNotifier();
$subscription = $type->getSubscription($wp);
$notified = $notifier->getUsersToNotify($subscription, $wp);
$notification = $type->createNotification($wp);
$notifier->notify($notified, $notification);
}
return $wp;
}
public function delete()
{
$db = Database::connection();
$wr = $this->getWorkflowRequestObject();
$db->executeQuery('delete from WorkflowProgress where wpID = ?', array($this->wpID));
// now we clean up any WorkflowRequests that aren't in use any longer
$cnt = $db->fetchColumn('select count(wpID) from WorkflowProgress where wrID = ?', array($this->wrID));
if ($cnt == 0) {
// We used to delete this but we might need it around for attaching to an EmptyWorkflow if we're
// skipping workflows.
//$wr->delete();
if (!($this->getWorkflowObject() instanceof EmptyWorkflow)) {
// Remove the associated notification
$em = $db->getEntityManager();
$r = $em->getRepository('Concrete\Core\Entity\Notification\WorkflowProgressNotification');
$notification = $r->findOneBy(array('wpID' => $this->getWorkflowProgressID()));
if (is_object($notification)) {
// The refresh is needed because the relation is lazy loaded
$em->refresh($notification);
$em->remove($notification);
$em->flush();
}
}
}
}
public static function getByID($wpID)
{
$db = Database::connection();
$r = $db->fetchAssoc('select WorkflowProgress.*, WorkflowProgressCategories.wpCategoryHandle, WorkflowProgressCategories.pkgID from WorkflowProgress inner join WorkflowProgressCategories on WorkflowProgress.wpCategoryID = WorkflowProgressCategories.wpCategoryID where wpID = ?', array($wpID));
if (!is_array($r) || (!$r['wpID'])) {
return false;
}
$class = '\\Core\\Workflow\\Progress\\' . Core::make('helper/text')->camelcase($r['wpCategoryHandle']) . 'Progress';
$pkgHandle = $r['pkgID'] ? PackageList::getHandle($r['pkgID']) : null;
$class = core_class($class, $pkgHandle);
$wp = Core::make($class);
$wp->setPropertiesFromArray($r);
$wp->loadDetails();
return $wp;
}
public static function getRequestedTask()
{
$task = '';
foreach ($_POST as $key => $value) {
if (strpos($key, 'action_') > -1) {
return substr($key, 7);
}
}
}
/**
* The function that is automatically run when a workflowprogress object is started.
*/
public function start()
{
$wf = $this->getWorkflowObject();
if (is_object($wf)) {
$r = $wf->start($this);
$this->updateOnAction($wf);
}
return $r;
}
public function updateOnAction(Workflow $wf)
{
$db = Database::connection();
$num = $wf->getWorkflowProgressCurrentStatusNum($this);
$time = Core::make('helper/date')->getOverridableNow();
$db->executeQuery('update WorkflowProgress set wpDateLastAction = ?, wpCurrentStatus = ? where wpID = ?', array($time, $num, $this->wpID));
}
/**
* Attempts to run a workflow task on the bound WorkflowRequest object first, then if that doesn't exist, attempts to run
* it on the current WorkflowProgress object.
*
* @return WorkflowProgressResponse
*/
public function runTask($task, $args = array())
{
$wf = $this->getWorkflowObject();
if (in_array($task, $wf->getAllowedTasks())) {
$wpr = call_user_func_array(array($wf, $task), array($this, $args));
$this->updateOnAction($wf);
}
if (!($wpr instanceof Response)) {
$wpr = new Response();
}
$event = new GenericEvent();
$event->setArgument('response', $wpr);
Events::dispatch('workflow_progressed', $event);
return $wpr;
}
public function getWorkflowProgressActions($additionalActions = true)
{
$w = $this->getWorkflowObject();
$req = $this->getWorkflowRequestObject();
if ($additionalActions) {
$actions = $req->getWorkflowRequestAdditionalActions($this);
} else {
$actions = array();
}
$actions = array_merge($actions, $w->getWorkflowProgressActions($this));
return $actions;
}
abstract public function getWorkflowProgressFormAction();
abstract public function loadDetails();
public function getWorkflowProgressHistoryObjectByID($wphID)
{
$class = '\\Concrete\\Core\\Workflow\\Progress\\' . camelcase($this->getWorkflowProgressCategoryHandle()) . 'History';
$db = Database::connection();
$row = $db->fetchAssoc('select * from WorkflowProgressHistory where wphID = ?', array($wphID));
if (is_array($row) && ($row['wphID'])) {
$obj = new $class();
$obj->setPropertiesFromArray($row);
$obj->object = @unserialize($row['object']);
return $obj;
}
}
public function addWorkflowProgressHistoryObject($obj)
{
$db = Database::connection();
$db->executeQuery('insert into WorkflowProgressHistory (wpID, object) values (?, ?)', array($this->wpID, serialize($obj)));
}
public function markCompleted()
{
$wf = $this->getWorkflowObject();
$db = Database::connection();
$db->executeQuery('update WorkflowProgress set wpIsCompleted = 1 where wpID = ?', array($this->wpID));
if (!($wf instanceof EmptyWorkflow)) {
$application = \Core::getFacadeApplication();
$type = $application->make('manager/notification/types')->driver('workflow_progress');
$type->clearNotification($this);
}
}
abstract public function getPendingWorkflowProgressList();
}