Skip to content

Commit 47dafc6

Browse files
committed
initial commit
1 parent e3c5019 commit 47dafc6

20 files changed

+1278
-2
lines changed

CONTRIBUTING.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Contributing
2+
3+
Contributions are **welcome** and will be fully **credited**.
4+
5+
We accept contributions via Pull Requests on [Github](https://github.com/cornernote/yii2-returnurl).
6+
7+
8+
## Pull Requests
9+
10+
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
11+
12+
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
13+
14+
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
15+
16+
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
17+
18+
- **Create feature branches** - Don't ask us to pull from your master branch.
19+
20+
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
21+
22+
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
23+
24+
25+
## Running Tests
26+
27+
``` bash
28+
$ phpunit
29+
```
30+
31+
32+
**Happy coding**!

LICENSE.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# The BSD License (BSD)
2+
3+
Copyright (c) 2013-2015, Mr PHP <[email protected]>
4+
5+
> Redistribution and use in source and binary forms, with or without modification,
6+
> are permitted provided that the following conditions are met:
7+
>
8+
> Redistributions of source code must retain the above copyright notice, this
9+
> list of conditions and the following disclaimer.
10+
>
11+
> Redistributions in binary form must reproduce the above copyright notice, this
12+
> list of conditions and the following disclaimer in the documentation and/or
13+
> other materials provided with the distribution.
14+
>
15+
> Neither the name of Mr PHP. nor the names of its
16+
> contributors may be used to endorse or promote products derived from
17+
> this software without specific prior written permission.
18+
>
19+
>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
>ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
>WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
>DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23+
>ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24+
>(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25+
>LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26+
>ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
>(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28+
>SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

+62-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,62 @@
1-
# yii2-workflow-manager
2-
Workflow Manager for Yii2
1+
# Yii2 Workflow Manager
2+
3+
[![Latest Version](https://img.shields.io/github/tag/cornernote/yii2-workflow-manager.svg?style=flat-square&label=release)](https://github.com/cornernote/yii2-workflow-manager/tags)
4+
[![Software License](https://img.shields.io/badge/license-BSD-brightgreen.svg?style=flat-square)](LICENSE.md)
5+
[![Build Status](https://img.shields.io/travis/cornernote/yii2-workflow-manager/master.svg?style=flat-square)](https://travis-ci.org/cornernote/yii2-workflow-manager)
6+
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/cornernote/yii2-workflow-manager.svg?style=flat-square)](https://scrutinizer-ci.com/g/cornernote/yii2-workflow-manager/code-structure)
7+
[![Quality Score](https://img.shields.io/scrutinizer/g/cornernote/yii2-workflow-manager.svg?style=flat-square)](https://scrutinizer-ci.com/g/cornernote/yii2-workflow-manager)
8+
[![Total Downloads](https://img.shields.io/packagist/dt/cornernote/yii2-workflow-manager.svg?style=flat-square)](https://packagist.org/packages/cornernote/yii2-workflow-manager)
9+
10+
Workflow Manager for Yii2.
11+
12+
13+
## Features
14+
15+
16+
## Installation
17+
18+
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
19+
20+
Either run
21+
22+
```
23+
$ composer require cornernote/yii2-workflow-manager "*"
24+
```
25+
26+
or add
27+
28+
```
29+
"cornernote/yii2-workflow-manager": "*"
30+
```
31+
32+
to the `require` section of your `composer.json` file.
33+
34+
35+
## Configuration
36+
37+
```php
38+
$config = [
39+
'modules' => [
40+
'workflow' => [
41+
'class' => 'cornernote\workflow\manager\Module',
42+
],
43+
],
44+
];
45+
```
46+
47+
## License
48+
49+
- Author: Brett O'Donnell <[email protected]>
50+
- Source Code: https://github.com/cornernote/yii2-return-url
51+
- Copyright © 2015 Mr PHP <[email protected]>
52+
- License: BSD-3-Clause https://raw.github.com/cornernote/yii2-return-url/master/LICENSE
53+
54+
55+
## Links
56+
57+
- [Yii2 Extension](http://www.yiiframework.com/extension/yii2-return-url)
58+
- [Composer Package](https://packagist.org/packages/cornernote/yii2-return-url)
59+
- [MrPHP](http://mrphp.com.au)
60+
61+
62+
[![Mr PHP](https://raw.github.com/cornernote/mrphp-assets/master/img/code-banner.png)](http://mrphp.com.au)

composer.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "cornernote/yii2-workflow-manager",
3+
"description": "Workflow Manager for Yii2.",
4+
"keywords": ["yii2", "workflow"],
5+
"type": "yii2-extension",
6+
"license": "BSD-3-Clause",
7+
"authors": [
8+
{
9+
"name": "Brett O'Donnell",
10+
"email": "[email protected]",
11+
"homepage": "http://mrphp.com.au/"
12+
}
13+
],
14+
"require": {
15+
"yiisoft/yii2": "*",
16+
"raoul2000/yii2-workflow": "*",
17+
"raoul2000/yii2-workflow-view": "*"
18+
},
19+
"require-dev": {
20+
"phpunit/phpunit": "4.*",
21+
"scrutinizer/ocular": "~1.1"
22+
},
23+
"autoload": {
24+
"psr-4": {"cornernote\\workflow\\manager\\": "src"}
25+
}
26+
}

src/Module.php

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace cornernote\workflow\manager;
4+
5+
/**
6+
* Class Module
7+
* @package cornernote\workflow\manager
8+
*/
9+
class Module extends \yii\base\Module
10+
{
11+
/**
12+
* @var string
13+
*/
14+
public $controllerNamespace = 'cornernote\workflow\manager\controllers';
15+
/**
16+
* @var string
17+
*/
18+
public $layout = 'main';
19+
}

src/components/WorkflowDbSource.php

+216
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
<?php
2+
namespace cornernote\workflow\manager\components;
3+
4+
use raoul2000\workflow\base\Status;
5+
use raoul2000\workflow\base\Transition;
6+
use raoul2000\workflow\base\Workflow;
7+
use raoul2000\workflow\base\WorkflowException;
8+
use raoul2000\workflow\source\IWorkflowSource;
9+
use Yii;
10+
use yii\base\Object;
11+
use yii\helpers\Inflector;
12+
13+
/**
14+
* WorkflowDbSource component is dedicated to read workflow definition from DB.
15+
*
16+
* It doesn't implement many features available in the WorkflowFileSource component
17+
* released with yii2-workflow but can be used as a starting point to develop
18+
* a production ready component.
19+
*
20+
* Among missing features :
21+
* - Status, Transition and Workflow class mapping to allow usage of custom classes for those objects
22+
* - metadata
23+
* - short id usage (in this version canonical status ids must be used)
24+
* - robust test for method arguments (in particular ids)
25+
*
26+
* The underlying DB schema is also very simple and only include those columns
27+
* which are required by yii2-workflow.
28+
*
29+
*/
30+
class WorkflowDbSource extends Object implements IWorkflowSource
31+
{
32+
const SEPARATOR_STATUS_NAME = '/';
33+
/**
34+
* @var Workflow[] list of workflow instances indexed by workflow id
35+
*/
36+
private $_w = [];
37+
/**
38+
* @var Status[] list status instances indexed by their id
39+
*/
40+
private $_s = [];
41+
private $_allStatusLoaded = false;
42+
/**
43+
* @var Transition[] list of out-going Transition instances indexed by the start status id
44+
*/
45+
private $_t = [];
46+
47+
/**
48+
* @see \raoul2000\workflow\source\IWorkflowSource::getStatus()
49+
* @param mixed $id
50+
* @param null $model
51+
* @return Status|\raoul2000\workflow\base\StatusInterface
52+
* @throws WorkflowException
53+
* @throws \yii\base\InvalidConfigException
54+
*/
55+
public function getStatus($id, $model = null)
56+
{
57+
list($wId, $stId) = $this->parseStatusId($id);
58+
59+
$canonicalStId = $wId . self::SEPARATOR_STATUS_NAME . $stId;
60+
61+
// TODO : implement status class map
62+
if (!array_key_exists($canonicalStId, $this->_s)) {
63+
64+
$statusModel = \cornernote\workflow\manager\models\Status::findOne([
65+
'workflow_id' => $wId,
66+
'id' => $stId
67+
]);
68+
if ($statusModel == null) {
69+
throw new WorkflowException('No status found with id ' . $id);
70+
}
71+
$this->_s[$canonicalStId] = Yii::createObject([
72+
'class' => 'raoul2000\workflow\base\Status',
73+
'id' => $canonicalStId,
74+
'workflowId' => $statusModel->workflow_id,
75+
'label' => isset($statusModel->label) ? $statusModel->label : Inflector::camel2words($stId, true),
76+
'source' => $this
77+
]);
78+
}
79+
return $this->_s[$canonicalStId];
80+
}
81+
82+
/**
83+
* @see \raoul2000\workflow\source\IWorkflowSource::getAllStatuses()
84+
* @param string $workflowId
85+
* @return \raoul2000\workflow\base\Status[]|\raoul2000\workflow\base\StatusInterface[]
86+
* @throws \yii\base\InvalidConfigException
87+
*/
88+
public function getAllStatuses($workflowId)
89+
{
90+
if (!$this->_allStatusLoaded) {
91+
92+
$loadedStatusIds = array_keys($this->_s);
93+
94+
$dbStatus = \cornernote\workflow\manager\models\Status::find()
95+
->where(['workflow_id' => $workflowId])
96+
->andWhere(['NOT IN', 'id', $loadedStatusIds])
97+
->all();
98+
99+
foreach ($dbStatus as $status) {
100+
$canonicalStId = $status->workflow_id . self::SEPARATOR_STATUS_NAME . $status->id;
101+
102+
$this->_s[$canonicalStId] = Yii::createObject([
103+
'class' => 'raoul2000\workflow\base\Status',
104+
'id' => $canonicalStId,
105+
'workflowId' => $status->workflow_id,
106+
'label' => isset($status->label) ? $status->label : Inflector::camel2words($status->id, true),
107+
'source' => $this
108+
]);
109+
}
110+
$this->_allStatusLoaded = true;
111+
}
112+
return $this->_s;
113+
}
114+
115+
/**
116+
* @see \raoul2000\workflow\source\IWorkflowSource::getTransitions()
117+
* @param mixed $startStatusId
118+
* @param null $model
119+
* @return Transition|\raoul2000\workflow\base\TransitionInterface[]
120+
* @throws WorkflowException
121+
* @throws \yii\base\InvalidConfigException
122+
*/
123+
public function getTransitions($startStatusId, $model = null)
124+
{
125+
list($wId, $stId) = $this->parseStatusId($startStatusId);
126+
$startId = $wId . self::SEPARATOR_STATUS_NAME . $stId;
127+
128+
if (!array_key_exists($startId, $this->_t)) {
129+
130+
$transInstance = [];
131+
$transitions = \cornernote\workflow\manager\models\Transition::findAll([
132+
'start_status_id' => $stId,
133+
'start_status_workflow_id' => $wId
134+
]);
135+
foreach ($transitions as $transition) {
136+
// TODO : implement transition class map
137+
$endId = $transition->end_status_workflow_id . self::SEPARATOR_STATUS_NAME . $transition->end_status_id;
138+
$transInstance[] = Yii::createObject([
139+
'class' => 'raoul2000\workflow\base\Transition',
140+
'start' => $this->getStatus($startId),
141+
'end' => $this->getStatus($endId),
142+
'source' => $this
143+
]);
144+
}
145+
$this->_t[$startId] = $transInstance;
146+
}
147+
return $this->_t[$startId];
148+
}
149+
150+
/**
151+
* @see \raoul2000\workflow\source\IWorkflowSource::getTransition()
152+
* @param string $startId
153+
* @param string $endId
154+
* @param null $defaultWorkflowId
155+
* @return null|\raoul2000\workflow\base\TransitionInterface
156+
*/
157+
public function getTransition($startId, $endId, $defaultWorkflowId = null)
158+
{
159+
$tr = $this->getTransitions($startId, $defaultWorkflowId);
160+
if (count($tr) > 0) {
161+
foreach ($tr as $aTransition) {
162+
if ($aTransition->getEndStatus()->getId() == $endId) {
163+
return $aTransition;
164+
}
165+
}
166+
}
167+
return null;
168+
}
169+
170+
/**
171+
* @see \raoul2000\workflow\source\IWorkflowSource::getWorkflow()
172+
* @param mixed $id
173+
* @return Workflow|\raoul2000\workflow\base\WorkflowInterface
174+
* @throws WorkflowException
175+
* @throws \yii\base\InvalidConfigException
176+
*/
177+
public function getWorkflow($id)
178+
{
179+
180+
// TODO : validate that initial status is valid
181+
// TODO : implement status class map
182+
183+
if (!array_key_exists($id, $this->_w)) {
184+
$workflowModel = \cornernote\workflow\manager\models\Workflow::findOne([
185+
'id' => $id
186+
]);
187+
188+
if ($workflowModel == null) {
189+
throw new WorkflowException('No workflow found with id ' . $id);
190+
}
191+
$initialStatusId = $workflowModel->id . self::SEPARATOR_STATUS_NAME . $workflowModel->initial_status_id;
192+
$this->_w[$id] = Yii::createObject([
193+
'class' => 'raoul2000\workflow\base\Workflow',
194+
'id' => $id,
195+
'initialStatusId' => $initialStatusId,
196+
'source' => $this
197+
]);
198+
}
199+
return $this->_w[$id];
200+
}
201+
202+
/**
203+
*
204+
* @param string $val canonical id (e.g. myWorkflow/myStatus)
205+
* @return array:
206+
*/
207+
public function parseStatusId($val)
208+
{
209+
210+
// TODO : validate $val and once splitted in workflow_id and status_id
211+
// ensure they are both valid
212+
213+
$tokens = array_map('trim', explode(self::SEPARATOR_STATUS_NAME, $val));
214+
return $tokens;
215+
}
216+
}

0 commit comments

Comments
 (0)