public function execute(WorkflowInstance $workflow) { if (!($target = $workflow->getTarget())) { return true; } if (class_exists('AbstractQueuedJob') && $this->UnpublishDelay) { $job = new WorkflowPublishTargetJob($target, "unpublish"); $days = $this->UnpublishDelay; $after = date('Y-m-d H:i:s', strtotime("+{$days} days")); singleton('QueuedJobService')->queueJob($job, $after); } else { if ($target->hasExtension('WorkflowEmbargoExpiryExtension')) { // setting future date stuff if needbe // set these values regardless $target->DesiredUnPublishDate = ''; $target->DesiredPublishDate = ''; $target->write(); if ($target->hasMethod('doUnpublish')) { $target->doUnpublish(); } } else { if ($target->hasMethod('doUnpublish')) { $target->doUnpublish(); } } } return true; }
public function execute(WorkflowInstance $workflow) { if (!($target = $workflow->getTarget())) { return true; } if ($target->hasField($this->Property)) { $target->setField($this->Property, $this->Value); } $target->write(); return true; }
/** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { $entity = \App\Document::find($id); $wi = new \WorkflowInstance('material-request', $entity->id, $entity->state, $entity); if ($request->get('op_type') == 'state_change') { $new_state = $request->get('new_state'); $wi->setState($new_state); $entity->state = $new_state; $entity->save(); } // end if op_type is state_change return Redirect('/'); }
public function execute(WorkflowInstance $workflow) { if (!($target = $workflow->getTarget())) { return true; } if (class_exists('AbstractQueuedJob') && $this->PublishDelay) { $job = new WorkflowPublishTargetJob($target); $days = $this->PublishDelay; $after = date('Y-m-d H:i:s', strtotime("+{$days} days")); singleton('QueuedJobService')->queueJob($job, $after); } else { $target->doPublish(); } return true; }
public function run($request) { $sent = 0; if (WorkflowInstance::get()->count()) { // Don't attempt the filter if no instances -- prevents a crash $active = WorkflowInstance::get()->innerJoin('WorkflowDefinition', '"DefinitionID" = "WorkflowDefinition"."ID"')->filter(array('WorkflowStatus' => array('Active', 'Paused'), 'RemindDays:GreaterThan' => '0')); $active->filter(array('RemindDays:GreaterThan' => '0')); if ($active) { foreach ($active as $instance) { $edited = strtotime($instance->LastEdited); $days = $instance->Definition()->RemindDays; if ($edited + $days * 3600 * 24 > time()) { continue; } $email = new Email(); $bcc = ''; $members = $instance->getAssignedMembers(); $target = $instance->getTarget(); if (!$members || !count($members)) { continue; } $email->setSubject("Workflow Reminder: {$instance->Title}"); $email->setBcc(implode(', ', $members->column('Email'))); $email->setTemplate('WorkflowReminderEmail'); $email->populateTemplate(array('Instance' => $instance, 'Link' => $target instanceof SiteTree ? "admin/show/{$target->ID}" : '')); $email->send(); $sent++; $instance->LastEdited = time(); $instance->write(); } } } echo "Sent {$sent} workflow reminder emails.\n"; }
public function testExecuteImmediateWorkflow() { $def = $this->createDefinition(); $actions = $def->Actions(); $firstAction = $def->getInitialAction(); $this->assertEquals('Step One', $firstAction->Title); $instance = new WorkflowInstance(); $instance->beginWorkflow($def); $this->assertTrue($instance->CurrentActionID > 0); $instance->execute(); // the instance should be complete, and have two finished workflow action // instances. $actions = $instance->Actions(); $this->assertEquals(2, $actions->Count()); foreach ($actions as $action) { $this->assertTrue((bool) $action->Finished); } }
public function execute(WorkflowInstance $workflow) { $workflow->Users()->removeAll(); $workflow->Groups()->removeAll(); $workflow->Users()->addMany($this->Users()); $workflow->Groups()->addMany($this->Groups()); if ($this->AssignInitiator) { $workflow->Users()->add($workflow->Initiator()); } return true; }
public function execute(WorkflowInstance $workflow) { $members = $workflow->getAssignedMembers(); if (!$members || !count($members)) { return true; } $member = Member::currentUser(); $initiator = $workflow->Initiator(); $contextFields = $this->getContextFields($workflow->getTarget()); $memberFields = $this->getMemberFields($member); $initiatorFields = $this->getMemberFields($initiator); $variables = array(); foreach ($contextFields as $field => $val) { $variables["\$Context.{$field}"] = $val; } foreach ($memberFields as $field => $val) { $variables["\$Member.{$field}"] = $val; } foreach ($initiatorFields as $field => $val) { $variables["\$Initiator.{$field}"] = $val; } $pastActions = $workflow->Actions()->sort('Created DESC'); $variables["\$CommentHistory"] = $this->customise(array('PastActions' => $pastActions, 'Now' => SS_Datetime::now()))->renderWith('CommentHistory'); $from = str_replace(array_keys($variables), array_values($variables), $this->EmailFrom); $subject = str_replace(array_keys($variables), array_values($variables), $this->EmailSubject); if ($this->config()->whitelist_template_variables) { $item = new ArrayData(array('Initiator' => new ArrayData($initiatorFields), 'Member' => new ArrayData($memberFields), 'Context' => new ArrayData($contextFields), 'CommentHistory' => $variables["\$CommentHistory"])); } else { $item = $workflow->customise(array('Items' => $workflow->Actions(), 'Member' => $member, 'Context' => new ArrayData($contextFields), 'CommentHistory' => $variables["\$CommentHistory"])); } if ($this->ListingTemplateID) { $template = DataObject::get_by_id('ListingTemplate', $this->ListingTemplateID); $view = SSViewer::fromString($template->ItemTemplate); } else { $view = SSViewer::fromString($this->EmailTemplate); } $body = $view->process($item); foreach ($members as $member) { if ($member->Email) { $email = new Email(); $email->setTo($member->Email); $email->setSubject($subject); $email->setFrom($from); $email->setBody($body); $email->send(); } } return true; }
public function process() { $sent = 0; $filter = array('WorkflowStatus' => array('Active', 'Paused'), 'Definition.RemindDays:GreaterThan' => 0); $active = WorkflowInstance::get()->filter($filter); foreach ($active as $instance) { $edited = strtotime($instance->LastEdited); $days = $instance->Definition()->RemindDays; if ($edited + $days * 3600 * 24 > time()) { continue; } $email = new Email(); $bcc = ''; $members = $instance->getAssignedMembers(); $target = $instance->getTarget(); if (!$members || !count($members)) { continue; } $email->setSubject("Workflow Reminder: {$instance->Title}"); $email->setBcc(implode(', ', $members->column('Email'))); $email->setTemplate('WorkflowReminderEmail'); $email->populateTemplate(array('Instance' => $instance, 'Link' => $target instanceof SiteTree ? "admin/show/{$target->ID}" : '')); $email->send(); $sent++; // add a comment to the workflow if possible $action = $instance->CurrentAction(); $currentComment = $action->Comment; $action->Comment = sprintf(_t('AdvancedWorkflow.JOB_REMINDER_COMMENT', '%s: Reminder email sent\\n\\n'), date('Y-m-d H:i:s')) . $currentComment; try { $action->write(); } catch (Exception $ex) { SS_Log::log($ex, SS_Log::WARN); } $instance->LastEdited = time(); try { $instance->write(); } catch (Exception $ex) { SS_Log::log($ex, SS_Log::WARN); } } $this->currentStep = 2; $this->isComplete = true; $nextDate = date('Y-m-d H:i:s', time() + $this->repeatInterval); $this->queuedJobService->queueJob(new WorkflowReminderJob($this->repeatInterval), $nextDate); }
public function execute(WorkflowInstance $workflow) { $workflow->Users()->removeAll(); //Due to http://open.silverstripe.org/ticket/8258, there are errors occuring if Group has been extended //We use a direct delete query here before ticket 8258 fixed //$workflow->Groups()->removeAll(); $workflowID = $workflow->ID; $query = <<<SQL \t\tDELETE FROM "WorkflowInstance_Groups" WHERE ("WorkflowInstance_Groups"."WorkflowInstanceID" = '{$workflowID}'); SQL; DB::query($query); $workflow->Users()->addMany($this->Users()); $workflow->Groups()->addMany($this->Groups()); if ($this->AssignInitiator) { $workflow->Users()->add($workflow->Initiator()); } return true; }
public function execute(WorkflowInstance $workflow) { $email = new Email(); $members = $workflow->getAssignedMembers(); $emails = ''; if (!$members || !count($members)) { return; } foreach ($members as $member) { if ($member->Email) { $emails .= "{$member->Email}, "; } } $context = $this->getContextFields($workflow->getTarget()); $member = $this->getMemberFields(); $variables = array(); foreach ($context as $field => $val) { $variables["\$Context.{$field}"] = $val; } foreach ($member as $field => $val) { $variables["\$Member.{$field}"] = $val; } $subject = str_replace(array_keys($variables), array_values($variables), $this->EmailSubject); if ($this->ListingTemplateID) { $item = $workflow->customise(array('Items' => $workflow->Actions(), 'Member' => Member::currentUser(), 'Context' => $workflow->getTarget())); $template = DataObject::get_by_id('ListingTemplate', $this->ListingTemplateID); $view = SSViewer::fromString($template->ItemTemplate); $body = $view->process($item); } else { $body = str_replace(array_keys($variables), array_values($variables), $this->EmailTemplate); } $email->setSubject($subject); $email->setFrom($this->EmailFrom); $email->setBcc(substr($emails, 0, -2)); $email->setBody($body); $email->send(); return true; }
/** * For a context around this test, see: https://github.com/silverstripe-australia/advancedworkflow/issues/141 * * 1). Create a workflow definition * 2). Step the content into that workflow * 3). Delete the workflow * 4). Check that the content: * i). Has no remaining related actions * ii). Can be re-assigned a new Workflow * 5). Check that the object under workflow, maintains its status (Draft, Published etc) */ public function testDeleteWorkflowTargetStillWorks() { // 1). Create a workflow definition $def = $this->createDefinition(); $page = Page::create(); $page->Title = 'dummy test'; $page->WorkflowDefinitionID = $def->ID; // Normally done via CMS Versioned::reading_stage('Stage'); $page->write(); // Check $page is in draft, pre-deletion $status = $page->getIsAddedToStage() && !$page->getExistsOnLive(); $this->assertTrue($status); // 2). Step the content into that workflow $instance = new WorkflowInstance(); $instance->beginWorkflow($def, $page); $instance->execute(); // Check the content is assigned $testPage = DataObject::get_by_id('Page', $page->ID); $this->assertEquals($instance->TargetID, $testPage->ID); // 3). Delete the workflow $def->delete(); // Check $testPage is _still_ in draft, post-deletion $status = $testPage->getIsAddedToStage() && !$testPage->getExistsOnLive(); $this->assertTrue($status); /* * 4). i). Check that the content: Has no remaining related actions * Note: WorkflowApplicable::WorkflowDefinitionID does _not_ get updated until assigned a new workflow * so we can use it to check that all related actions are gone */ $defID = $testPage->WorkflowDefinitionID; $this->assertEquals(0, DataObject::get('WorkflowAction')->filter('WorkflowDefID', $defID)->count()); /* * 4). ii). Check that the content: Can be re-assigned a new Workflow Definition */ $newDef = $this->createDefinition(); $testPage->WorkflowDefinitionID = $newDef->ID; // Normally done via CMS $instance = new WorkflowInstance(); $instance->beginWorkflow($newDef, $testPage); $instance->execute(); // Check the content is assigned to the new Workflow Definition correctly $this->assertEquals($newDef->ID, $testPage->WorkflowDefinitionID); $this->assertEquals($newDef->Actions()->count(), DataObject::get('WorkflowAction')->filter('WorkflowDefID', $newDef->ID)->count()); // 5). Check that the object under workflow, maintains its status $newDef2 = $this->createDefinition(); // Login so SiteTree::canPublish() returns true $testPage->WorkflowDefinitionID = $newDef2->ID; // Normally done via CMS $this->logInWithPermission(); $testPage->doPublish(); // Check $testPage is published, pre-deletion (getStatusFlags() returns empty array) $this->assertTrue($testPage->getExistsOnLive()); $instance = new WorkflowInstance(); $instance->beginWorkflow($newDef2, $testPage); $instance->execute(); // Now delete the related WorkflowDefinition and ensure status is the same (i.e. so it's not 'modified' for example) $newDef2->delete(); // Check $testPage is _still_ published, post-deletion (getStatusFlags() returns empty array) $this->assertTrue($testPage->getExistsOnLive()); }
/** * Need to override the whole process method to be able to catch the fact * that we might be editing a resumed entry * * @param Array Data * @param Form Form * @return Redirection */ public function process($data, $form) { Session::set("FormInfo.{$form->FormName()}.data", $data); Session::clear("FormInfo.{$form->FormName()}.errors"); foreach ($this->Fields() as $field) { $messages[$field->Name] = $field->getErrorMessage()->HTML(); $formField = $field->getFormField(); if ($field->Required && $field->CustomRules()->Count() == 0) { if (isset($data[$field->Name])) { $formField->setValue($data[$field->Name]); } if (!isset($data[$field->Name]) || !$data[$field->Name] || !$formField->validate($form->getValidator())) { $form->addErrorMessage($field->Name, $field->getErrorMessage(), 'bad'); } } } if (Session::get("FormInfo.{$form->FormName()}.errors")) { Controller::curr()->redirectBack(); return; } $submission = $this->processSubmission($data, $form); if ($submission) { if ($this->data()->WorkflowID) { $submission->SubmissionStatus = EditableUserDefinedForm::PENDING; } else { $submission->SubmissionStatus = EditableUserDefinedForm::COMPLETE; } $submission->write(); if ($submission->SubmissionStatus == EditableUserDefinedForm::PENDING) { $instance = new WorkflowInstance(); $instance->beginWorkflow($this->data()->getSubmissionWorkflow(), $submission); $instance->execute(); } } // set a session variable from the security ID to stop people accessing // the finished method directly. if (!$this->DisableAuthenicatedFinishAction) { if (isset($data['SecurityID'])) { Session::set('FormProcessed', $data['SecurityID']); } else { // if the form has had tokens disabled we still need to set FormProcessed // to allow us to get through the finshed method if (!$this->Form()->getSecurityToken()->isEnabled()) { $randNum = rand(1, 1000); $randHash = md5($randNum); Session::set('FormProcessed', $randHash); Session::set('FormProcessedNum', $randNum); } } } if (!$this->DisableSaveSubmissions) { Session::set('userformssubmission' . $this->ID, $submission->ID); } $referrer = isset($data['Referrer']) ? '?referrer=' . urlencode($data['Referrer']) : ""; return $this->redirect($this->Link('finished') . $referrer . $this->config()->finished_anchor); }
public function WorkflowInstances() { return WorkflowInstance::get()->filter(array('TargetClass' => $this->ownerBaseClass, 'TargetID' => $this->owner->ID)); }
/** * When deleting an action from a workflow definition, make sure that workflows currently paused on that action * are deleted * Also removes all outbound transitions */ public function onAfterDelete() { parent::onAfterDelete(); $wfActionInstances = WorkflowActionInstance::get()->leftJoin("WorkflowInstance", '"WorkflowInstance"."ID" = "WorkflowActionInstance"."WorkflowID"')->where(sprintf('"BaseActionID" = %d AND ("WorkflowStatus" IN (\'Active\',\'Paused\'))', $this->ID)); foreach ($wfActionInstances as $wfActionInstance) { $wfInstances = WorkflowInstance::get()->filter('CurrentActionID', $wfActionInstance->ID); foreach ($wfInstances as $wfInstance) { $wfInstance->Groups()->removeAll(); $wfInstance->Users()->removeAll(); $wfInstance->delete(); } $wfActionInstance->delete(); } // Delete outbound transitions $transitions = WorkflowTransition::get()->filter('ActionID', $this->ID); foreach ($transitions as $transition) { $transition->Groups()->removeAll(); $transition->Users()->removeAll(); $transition->delete(); } }
/** * Starts the workflow for the given data object, assuming it or a parent has * a definition specified. * * @param DataObject $object */ public function startWorkflow(DataObject $object, $workflowID = null) { $existing = $this->getWorkflowFor($object); if ($existing) { throw new ExistingWorkflowException(_t('WorkflowService.EXISTING_WORKFLOW_ERROR', "That object already has a workflow running")); } $definition = null; if ($workflowID) { // Retrieve the workflow definition that has been triggered. $definition = $this->getDefinitionByID($object, $workflowID); } if (is_null($definition)) { // Fall back to the main workflow definition. $definition = $this->getDefinitionFor($object); } if ($definition) { $instance = new WorkflowInstance(); $instance->beginWorkflow($definition, $object); $instance->execute(); } }
public function testPastPublishWithWorkflowInEffect() { $definition = $this->createDefinition(); $page = new Page(); $page->Title = 'My page'; $page->WorkflowDefinitionID = $definition->ID; $page->write(); // No publish $this->assertEmpty($page->PublishJobID); $this->assertEmpty($page->UnPublishJobID); // Set a past publish date $page->DesiredPublishDate = '2010-01-01 00:00:00'; $page->write(); // Workflow is in effect. No jobs have been created yet as it's not approved. $this->assertEmpty($page->PublishJobID); $this->assertEmpty($page->UnPublishJobID); // Advance the workflow so we can see what happens $instance = new WorkflowInstance(); $instance->beginWorkflow($definition, $page); $instance->execute(); // execute the "publish" workflow action $action = new PublishItemWorkflowAction(); $action->execute($instance); // re-fetch the Page again. $page = Page::get()->byId($page->ID); // We now have a PublishOnDate field set $this->assertEquals('2010-01-01 00:00:00', $page->PublishOnDate); $this->assertEmpty($page->DesiredPublishDate); // Publish job has been setup $this->assertNotEmpty($page->PublishJobID); $this->assertEmpty($page->UnPublishJobID); // Check that this publish job is set for immediate run $publish = strtotime($page->PublishJob()->StartAfter); $this->assertEmpty($publish); }
/** * Starts the workflow for the given data object, assuming it or a parent has * a definition specified. * * @param DataObject $object */ public function startWorkflow(DataObject $object) { $existing = $this->getWorkflowFor($object); if ($existing) { throw new ExistingWorkflowException(_t('WorkflowService.EXISTING_WORKFLOW_ERROR', "That object already has a workflow running")); } $definition = $this->getDefinitionFor($object); if ($definition) { $instance = new WorkflowInstance(); $instance->beginWorkflow($definition, $object); $instance->execute(); } }