GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 99ec42...de979d )
by Robbie
9s
created

WorkflowInstance::getCMSFields()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 52
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 52
rs 7.2396
c 0
b 0
f 0
cc 7
eloc 32
nc 12
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Symbiote\AdvancedWorkflow\DataObjects;
4
5
use Exception;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\Control\HTTPRequest;
8
use SilverStripe\Core\Injector\Injector;
9
use SilverStripe\Forms\CheckboxSetField;
10
use SilverStripe\Forms\DropdownField;
11
use SilverStripe\Forms\FieldList;
12
use SilverStripe\Forms\Form;
13
use SilverStripe\Forms\FormAction;
14
use SilverStripe\Forms\GridField\GridField;
15
use SilverStripe\Forms\HeaderField;
16
use SilverStripe\Forms\HiddenField;
17
use SilverStripe\Forms\Tab;
18
use SilverStripe\Forms\TabSet;
19
use SilverStripe\Forms\TreeMultiselectField;
20
use SilverStripe\ORM\ArrayList;
21
use SilverStripe\ORM\DataObject;
22
use SilverStripe\ORM\Queries\SQLSelect;
23
use SilverStripe\Security\Group;
24
use SilverStripe\Security\Member;
25
use SilverStripe\Security\Permission;
26
use SilverStripe\Security\Security;
27
use SilverStripe\Versioned\DataDifferencer;
28
use SilverStripe\Versioned\Versioned;
29
use Symbiote\AdvancedWorkflow\Actions\AssignUsersToWorkflowAction;
30
use Symbiote\AdvancedWorkflow\Extensions\WorkflowApplicable;
31
use Symbiote\AdvancedWorkflow\Extensions\FileWorkflowApplicable;
32
use Symbiote\AdvancedWorkflow\Services\WorkflowService;
33
34
/**
35
 * A WorkflowInstance is created whenever a user 'starts' a workflow.
36
 *
37
 * This 'start' is triggered automatically when the user clicks the relevant
38
 * button (eg 'apply for approval'). This creates a standalone object
39
 * that maintains the state of the workflow process.
40
 *
41
 * @method WorkflowDefinition Definition()
42
 * @method WorkflowActionInstance CurrentAction()
43
 * @method Member Initiator()
44
 *
45
 * @author  [email protected]
46
 * @license BSD License (http://silverstripe.org/bsd-license/)
47
 * @package advancedworkflow
48
 */
49
class WorkflowInstance extends DataObject
50
{
51
    private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
52
        'Title'             => 'Varchar(128)',
53
        'WorkflowStatus'    => "Enum('Active,Paused,Complete,Cancelled','Active')",
54
        'TargetClass'       => 'Varchar(255)',
55
        'TargetID'          => 'Int',
56
    );
57
58
    private static $has_one = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
59
        'Definition'    => WorkflowDefinition::class,
60
        'CurrentAction' => WorkflowActionInstance::class,
61
        'Initiator'     => Member::class,
62
    );
63
64
    private static $has_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $has_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
65
        'Actions' => WorkflowActionInstance::class,
66
    );
67
68
    /**
69
     * The list of users who are responsible for performing the current WorkflowAction
70
     *
71
     * @var array
72
     */
73
    private static $many_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $many_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
74
        'Users'  => Member::class,
75
        'Groups' => Group::class,
76
    );
77
78
    private static $summary_fields = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $summary_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
79
        'Title',
80
        'WorkflowStatus',
81
        'Created'
82
    );
83
84
    private static $default_sort = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $default_sort is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
85
        '"Created"' => 'DESC'
86
    );
87
88
    /**
89
     * If set to true, actions that cannot be executed by the user will not show
90
     * on the frontend (just like the backend).
91
     *
92
     * @var boolean
93
     */
94
    private static $hide_disabled_actions_on_frontend = false;
0 ignored issues
show
Unused Code introduced by
The property $hide_disabled_actions_on_frontend is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
95
96
    /**
97
     * Fields to ignore when generating a diff for data objects.
98
     */
99
    private static $diff_ignore_fields = array(
0 ignored issues
show
Unused Code introduced by
The property $diff_ignore_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
100
        'LastEdited',
101
        'Created',
102
        'workflowService',
103
        'ParentID',
104
        'Sort',
105
        'PublishJobID',
106
        'UnPublishJobID'
107
    );
108
109
    private static $table_name = 'WorkflowInstance';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $table_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
110
111
    /**
112
     * Get the CMS view of the instance. This is used to display the log of
113
     * this workflow, and options to reassign if the workflow hasn't been
114
     * finished yet
115
     *
116
     * @return FieldList
117
     */
118
    public function getCMSFields()
119
    {
120
        $fields = new FieldList();
121
        $fields->push(new TabSet('Root', new Tab('Main')));
122
123
        if (Permission::check('REASSIGN_ACTIVE_WORKFLOWS')) {
124
            if ($this->WorkflowStatus == 'Paused' || $this->WorkflowStatus == 'Active') {
0 ignored issues
show
Documentation introduced by
The property WorkflowStatus does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
125
                $cmsUsers = Member::mapInCMSGroups();
126
127
                $fields->addFieldsToTab('Root.Main', array(
128
                    new HiddenField('DirectUpdate', '', 1),
129
                    new HeaderField(
130
                        'InstanceReassignHeader',
131
                        _t('WorkflowInstance.REASSIGN_HEADER', 'Reassign workflow')
132
                    ),
133
                    new CheckboxSetField('Users', _t('WorkflowDefinition.USERS', 'Users'), $cmsUsers),
134
                    new TreeMultiselectField('Groups', _t('WorkflowDefinition.GROUPS', 'Groups'), Group::class)
135
                ));
136
            }
137
        }
138
139
        if ($this->canEdit()) {
140
            $action = $this->CurrentAction();
141
            if ($action->exists()) {
142
                $actionFields = $this->getWorkflowFields();
143
                $fields->addFieldsToTab('Root.Main', $actionFields);
0 ignored issues
show
Documentation introduced by
$actionFields is of type object<SilverStripe\Forms\FieldList>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
144
145
                $transitions = $action->getValidTransitions();
146
                if ($transitions) {
147
                    $fields->replaceField(
148
                        'TransitionID',
149
                        DropdownField::create("TransitionID", "Next action", $transitions->map())
150
                    );
151
                }
152
            }
153
        }
154
155
        $items = WorkflowActionInstance::get()->filter(array(
156
            'Finished'   => 1,
157
            'WorkflowID' => $this->ID
158
        ));
159
160
        $grid = new GridField(
161
            'Actions',
162
            _t('WorkflowInstance.ActionLogTitle', 'Log'),
163
            $items
164
        );
165
166
        $fields->addFieldsToTab('Root.Main', $grid);
0 ignored issues
show
Documentation introduced by
$grid is of type object<SilverStripe\Forms\GridField\GridField>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
167
168
        return $fields;
169
    }
170
171
    public function fieldLabels($includerelations = true)
172
    {
173
        $labels = parent::fieldLabels($includerelations);
174
        $labels['Title'] = _t('WorkflowInstance.TitleLabel', 'Title');
175
        $labels['WorkflowStatus'] = _t('WorkflowInstance.WorkflowStatusLabel', 'Workflow Status');
176
        $labels['TargetClass'] = _t('WorkflowInstance.TargetClassLabel', 'Target Class');
177
        $labels['TargetID'] = _t('WorkflowInstance.TargetIDLabel', 'Target');
178
179
        return $labels;
180
    }
181
182
    /**
183
     * See if we've been saved in context of managing the workflow directly
184
     */
185
    public function onBeforeWrite()
186
    {
187
        parent::onBeforeWrite();
188
189
        $vars = $this->record;
190
191
        if (isset($vars['DirectUpdate'])) {
192
            // Unset now so that we don't end up in an infinite loop!
193
            unset($this->record['DirectUpdate']);
194
            $this->updateWorkflow($vars);
0 ignored issues
show
Documentation introduced by
$vars is of type array<string,?,{"DirectUpdate":"?"}>, but the function expects a object<Symbiote\Advanced...kflow\DataObjects\type>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195
        }
196
    }
197
198
    /**
199
     * Update the current state of the workflow
200
     *
201
     * Typically, this is triggered by someone modifiying the workflow instance via the modeladmin form
202
     * side of things when administering things, such as re-assigning or manually approving a stuck workflow
203
     *
204
     * Note that this is VERY similar to AdvancedWorkflowExtension::updateworkflow
205
     * but without the formy bits. These two implementations should PROBABLY
206
     * be merged
207
     *
208
     * @todo refactor with AdvancedWorkflowExtension
209
     *
210
     * @param type $data
211
     * @return
212
     */
213
    public function updateWorkflow($data)
214
    {
215
        $action = $this->CurrentAction();
216
217
        if (!$this->getTarget() || !$this->getTarget()->canEditWorkflow()) {
218
            return;
219
        }
220
221
        $allowedFields = $this->getWorkflowFields()->saveableFields();
222
        unset($allowedFields['TransitionID']);
223
        foreach ($allowedFields as $field) {
224
            $fieldName = $field->getName();
225
            $action->$fieldName = $data[$fieldName];
226
        }
227
        $action->write();
228
229
        $svc = singleton(WorkflowService::class);
230
        if (isset($data['TransitionID']) && $data['TransitionID']) {
231
            $svc->executeTransition($this->getTarget(), $data['TransitionID']);
232
        } else {
233
            // otherwise, just try to execute the current workflow to see if it
234
            // can now proceed based on user input
235
            $this->execute();
236
        }
237
    }
238
239
    /**
240
     * Get the target-object that this WorkflowInstance "points" to.
241
     *
242
     * Workflows are not restricted to being active on SiteTree objects,
243
     * so we need to account for being attached to anything.
244
     *
245
     * Sets Versioned::set_reading_mode() to allow fetching of Draft _and_ Published
246
     * content.
247
     *
248
     * @param boolean $getLive
249
     * @return null|DataObject
250
     */
251
    public function getTarget($getLive = false)
252
    {
253
        if ($this->TargetID && $this->TargetClass) {
0 ignored issues
show
Documentation introduced by
The property TargetID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property TargetClass does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
254
            $versionable = Injector::inst()->get($this->TargetClass)->has_extension(Versioned::class);
0 ignored issues
show
Documentation introduced by
The property TargetClass does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
255
256
            if (!$versionable && $getLive) {
257
                return;
258
            }
259
            if ($versionable) {
260
                Versioned::set_stage($getLive ? Versioned::LIVE : Versioned::DRAFT);
261
            }
262
263
            // Default
264
            return DataObject::get_by_id($this->TargetClass, $this->TargetID);
0 ignored issues
show
Documentation introduced by
The property TargetClass does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property TargetID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
265
        }
266
    }
267
268
    /**
269
     *
270
     * @param boolean $getLive
271
     * @see {@link {$this->getTarget()}
272
     * @return null|DataObject
273
     */
274
    public function Target($getLive = false)
275
    {
276
        return $this->getTarget($getLive);
277
    }
278
279
    /**
280
     * Returns the field differences between the older version and current version of Target
281
     *
282
     * @return ArrayList
283
     */
284
    public function getTargetDiff()
285
    {
286
        $liveTarget = $this->Target(true);
287
        $draftTarget = $this->Target();
288
289
        $diff = DataDifferencer::create($liveTarget, $draftTarget);
290
        $diff->ignoreFields($this->config()->get('diff_ignore_fields'));
291
292
        $fields = $diff->ChangedFields();
293
294
        return $fields;
295
    }
296
297
    /**
298
     * Start a workflow based on a particular definition for a particular object.
299
     *
300
     * The object is optional; if not specified, it is assumed that this workflow
301
     * is simply a task based checklist type of workflow.
302
     *
303
     * @param WorkflowDefinition $definition
304
     * @param DataObject $for
305
     */
306
    public function beginWorkflow(WorkflowDefinition $definition, DataObject $for = null)
307
    {
308
        if (!$this->ID) {
309
            $this->write();
310
        }
311
312
        if ($for
313
            && ($for->hasExtension(WorkflowApplicable::class)
314
                || $for->hasExtension(FileWorkflowApplicable::class))
315
        ) {
316
            $this->TargetClass = DataObject::getSchema()->baseDataClass($for);
0 ignored issues
show
Documentation introduced by
The property TargetClass does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
317
            $this->TargetID = $for->ID;
0 ignored issues
show
Documentation introduced by
The property TargetID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
318
        }
319
320
        // lets create the first WorkflowActionInstance.
321
        $action = $definition->getInitialAction()->getInstanceForWorkflow();
322
        $action->WorkflowID = $this->ID;
0 ignored issues
show
Documentation introduced by
The property WorkflowID does not exist on object<Symbiote\Advanced...WorkflowActionInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
323
        $action->write();
324
325
        $title = $for && $for->hasField('Title')
326
            ? sprintf(_t('WorkflowInstance.TITLE_FOR_DO', '%s - %s'), $definition->Title, $for->Title)
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<Symbiote\Advanced...cts\WorkflowDefinition>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
327
            : sprintf(_t('WorkflowInstance.TITLE_STUB', 'Instance #%s of %s'), $this->ID, $definition->Title);
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<Symbiote\Advanced...cts\WorkflowDefinition>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
328
329
        $this->Title           = $title;
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
330
        $this->DefinitionID    = $definition->ID;
0 ignored issues
show
Documentation introduced by
The property DefinitionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
331
        $this->CurrentActionID = $action->ID;
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
332
        $this->InitiatorID     = Security::getCurrentUser()->ID;
0 ignored issues
show
Documentation introduced by
The property InitiatorID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
333
        $this->write();
334
335
        $this->Users()->addMany($definition->Users());
0 ignored issues
show
Documentation Bug introduced by
The method Users does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Documentation Bug introduced by
The method Users does not exist on object<Symbiote\Advanced...cts\WorkflowDefinition>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
336
        $this->Groups()->addMany($definition->Groups());
0 ignored issues
show
Documentation Bug introduced by
The method Groups does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Documentation Bug introduced by
The method Groups does not exist on object<Symbiote\Advanced...cts\WorkflowDefinition>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
337
    }
338
339
    /**
340
     * Execute this workflow. In rare cases this will actually execute all actions,
341
     * but typically, it will stop and wait for the user to input something
342
     *
343
     * The basic process is to get the current action, and see whether it has been finished
344
     * by some process, if not it attempts to execute it.
345
     *
346
     * If it has been finished, we check to see if there's some transitions to follow. If there's
347
     * only one transition, then we execute that immediately.
348
     *
349
     * If there's multiple transitions, we just stop and wait for the user to manually
350
     * trigger a transition.
351
     *
352
     * If there's no transitions, we make the assumption that we've finished the workflow and
353
     * mark it as such.
354
     *
355
     *
356
     */
357
    public function execute()
358
    {
359
        if (!$this->CurrentActionID) {
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
360
            throw new Exception(
361
                sprintf(_t(
362
                    'WorkflowInstance.EXECUTE_EXCEPTION',
363
                    'Attempted to start an invalid workflow instance #%s!'
364
                ), $this->ID)
365
            );
366
        }
367
368
        $action     = $this->CurrentAction();
369
        $transition = false;
370
371
        // if the action has already finished, it means it has either multiple (or no
372
        // transitions at the time), so a subsequent check should be run.
373
        if ($action->Finished) {
0 ignored issues
show
Documentation introduced by
The property Finished does not exist on object<Symbiote\Advanced...WorkflowActionInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
374
            $transition = $this->checkTransitions($action);
375
        } else {
376
            $result = $action->BaseAction()->execute($this);
0 ignored issues
show
Documentation Bug introduced by
The method BaseAction does not exist on object<Symbiote\Advanced...WorkflowActionInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
377
378
            // if the action was successful, then the action has finished running and
379
            // next transition should be run (if only one).
380
            // input.
381
            if ($result) {
382
                $action->MemberID = Security::getCurrentUser()->ID;
0 ignored issues
show
Documentation introduced by
The property MemberID does not exist on object<Symbiote\Advanced...WorkflowActionInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
383
                $action->Finished = true;
0 ignored issues
show
Documentation introduced by
The property Finished does not exist on object<Symbiote\Advanced...WorkflowActionInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
384
                $action->write();
385
                $transition = $this->checkTransitions($action);
386
            }
387
        }
388
389
        // if the action finished, and there's only one available transition then
390
        // move onto that step - otherwise check if the workflow has finished.
391
        if ($transition) {
392
            $this->performTransition($transition);
393
        } else {
394
            // see if there are any transitions available, even if they are not valid.
395
            if ($action->Finished && !count($action->BaseAction()->Transitions())) {
0 ignored issues
show
Documentation introduced by
The property Finished does not exist on object<Symbiote\Advanced...WorkflowActionInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation Bug introduced by
The method BaseAction does not exist on object<Symbiote\Advanced...WorkflowActionInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
396
                $this->WorkflowStatus  = 'Complete';
0 ignored issues
show
Documentation introduced by
The property WorkflowStatus does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
397
                $this->CurrentActionID = 0;
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
398
            } else {
399
                $this->WorkflowStatus = 'Paused';
0 ignored issues
show
Documentation introduced by
The property WorkflowStatus does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
400
            }
401
402
            $this->write();
403
        }
404
    }
405
406
    /**
407
     * Evaluate all the transitions of an action and determine whether we should
408
     * follow any of them yet.
409
     *
410
     * @param  WorkflowActionInstance $action
411
     * @return WorkflowTransition
412
     */
413
    protected function checkTransitions(WorkflowActionInstance $action)
414
    {
415
        $transitions = $action->getValidTransitions();
416
        // if there's JUST ONE transition, then we need should
417
        // immediately follow it.
418
        if ($transitions && $transitions->count() == 1) {
419
            return $transitions->First();
420
        }
421
    }
422
423
    /**
424
     * Transitions a workflow to the next step defined by the given transition.
425
     *
426
     * After transitioning, the action is 'executed', and next steps
427
     * determined.
428
     *
429
     * @param WorkflowTransition $transition
430
     */
431
    public function performTransition(WorkflowTransition $transition)
432
    {
433
        // first make sure that the transition is valid to execute!
434
        $action          = $this->CurrentAction();
435
        $allTransitions  = $action->BaseAction()->Transitions();
0 ignored issues
show
Documentation Bug introduced by
The method BaseAction does not exist on object<Symbiote\Advanced...WorkflowActionInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
436
437
        $valid = $allTransitions->find('ID', $transition->ID);
438
        if (!$valid) {
439
            throw new Exception(
440
                sprintf(_t(
441
                    'WorkflowInstance.WORKFLOW_TRANSITION_EXCEPTION',
442
                    'Invalid transition state for action #%s'
443
                ), $action->ID)
444
            );
445
        }
446
447
        $action->actionComplete($transition);
448
449
        $definition = DataObject::get_by_id(WorkflowAction::class, $transition->NextActionID);
0 ignored issues
show
Documentation introduced by
The property NextActionID does not exist on object<Symbiote\Advanced...cts\WorkflowTransition>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
450
        $action = $definition->getInstanceForWorkflow();
451
        $action->WorkflowID   = $this->ID;
452
        $action->write();
453
454
        $this->CurrentActionID = $action->ID;
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
455
        $this->write();
456
        $this->components = array(); // manually clear the has_one cache
457
458
        $action->actionStart($transition);
459
460
        $transition->extend('onTransition');
461
        $this->execute();
462
    }
463
464
    /**
465
     * Returns a list of all Members that are assigned to this instance, either directly or via a group.
466
     *
467
     * @todo   This could be made more efficient.
468
     * @return ArrayList
469
     */
470 View Code Duplication
    public function getAssignedMembers()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
471
    {
472
        $list   = new ArrayList();
473
        $groups = $this->Groups();
0 ignored issues
show
Documentation Bug introduced by
The method Groups does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
474
475
        $list->merge($this->Users());
0 ignored issues
show
Documentation Bug introduced by
The method Users does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
476
477
        foreach ($groups as $group) {
478
            $list->merge($group->Members());
479
        }
480
481
        $list->removeDuplicates();
482
        return $list;
483
    }
484
485
    /**
486
     *
487
     * @param Member $member
488
     * @return boolean
489
     */
490
    public function canView($member = null)
491
    {
492
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 490 can be null; however, SilverStripe\ORM\DataObject::extendedCan() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
493
        if ($extended !== null) {
494
            return $extended;
495
        }
496
497
        $hasAccess = $this->userHasAccess($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 490 can be null; however, Symbiote\AdvancedWorkflo...stance::userHasAccess() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
498
        /*
499
         * If the next action is AssignUsersToWorkflowAction, execute() resets all user+group relations.
500
         * Therefore current user no-longer has permission to view this WorkflowInstance in PendingObjects
501
         * Gridfield, even though;
502
         * - She had permissions granted via the workflow definition to run the preceeding Action that took her here.
503
         */
504
        if (!$hasAccess) {
505
            if ($this->getMostRecentActionForUser($member)) {
506
                return true;
507
            }
508
        }
509
        return $hasAccess;
510
    }
511
512
    /**
513
     *
514
     * @param Member $member
515
     * @return boolean
516
     */
517
    public function canEdit($member = null)
518
    {
519
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 517 can be null; however, SilverStripe\ORM\DataObject::extendedCan() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
520
        if ($extended !== null) {
521
            return $extended;
522
        }
523
524
        return $this->userHasAccess($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 517 can be null; however, Symbiote\AdvancedWorkflo...stance::userHasAccess() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
525
    }
526
527
    /**
528
     *
529
     * @param Member $member
530
     * @return boolean
531
     */
532
    public function canDelete($member = null)
533
    {
534
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 532 can be null; however, SilverStripe\ORM\DataObject::extendedCan() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
535
        if ($extended !== null) {
536
            return $extended;
537
        }
538
539
        if (Permission::checkMember($member, "DELETE_WORKFLOW")) {
540
            return true;
541
        }
542
        return false;
543
    }
544
545
    /**
546
     * Checks whether the given user is in the list of users assigned to this
547
     * workflow
548
     *
549
     * @param Member $member
550
     */
551
    protected function userHasAccess($member)
552
    {
553
        if (!$member) {
554
            if (!Security::getCurrentUser()) {
555
                return false;
556
            }
557
            $member = Security::getCurrentUser();
558
        }
559
560
        if (Permission::checkMember($member, "ADMIN")) {
561
            return true;
562
        }
563
564
        // This method primarily "protects" access to a WorkflowInstance, but assumes access only to be granted to
565
        // users assigned-to that WorkflowInstance. However; lowly authors (users entering items into a workflow) are
566
        // not assigned - but we still wish them to see their submitted content.
567
        $inWorkflowGroupOrUserTables = ($member->inGroups($this->Groups()) || $this->Users()->find('ID', $member->ID));
0 ignored issues
show
Documentation Bug introduced by
The method Groups does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
Bug introduced by
It seems like $member is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
Documentation Bug introduced by
The method Users does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
568
        // This method is used in more than just the ModelAdmin. Check for the current controller to determine where
569
        // canView() expectations differ
570
        if ($this->getTarget() && Controller::curr()->getAction() == 'index' && !$inWorkflowGroupOrUserTables) {
571
            if ($this->getVersionedConnection($this->getTarget()->ID, $member->ID)) {
572
                return true;
573
            }
574
            return false;
575
        }
576
        return $inWorkflowGroupOrUserTables;
577
    }
578
579
    /**
580
     * Can documents in the current workflow state be edited?
581
     */
582
    public function canEditTarget()
583
    {
584
        if ($this->CurrentActionID && ($target = $this->getTarget())) {
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
585
            return $this->CurrentAction()->canEditTarget($target);
586
        }
587
    }
588
589
    /**
590
     * Does this action restrict viewing of the document?
591
     *
592
     * @return boolean
593
     */
594
    public function canViewTarget()
595
    {
596
        $action = $this->CurrentAction();
597
        if ($action) {
598
            return $action->canViewTarget($this->getTarget());
0 ignored issues
show
Bug introduced by
It seems like $this->getTarget() can be null; however, canViewTarget() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
599
        }
600
        return true;
601
    }
602
603
    /**
604
     * Does this action restrict the publishing of a document?
605
     *
606
     * @return boolean
607
     */
608
    public function canPublishTarget()
609
    {
610
        if ($this->CurrentActionID && ($target = $this->getTarget())) {
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
611
            return $this->CurrentAction()->canPublishTarget($target);
612
        }
613
    }
614
615
    /**
616
     * Get the current set of transitions that are valid for the current workflow state,
617
     * and are available to the current user.
618
     *
619
     * @return array
620
     */
621
    public function validTransitions()
622
    {
623
        $action    = $this->CurrentAction();
624
        $transitions = $action->getValidTransitions();
625
626
        // Filter by execute permission
627
        return $transitions->filterByCallback(function ($transition) {
628
            return $transition->canExecute($this);
629
        });
630
    }
631
632
    /* UI RELATED METHODS */
633
634
    /**
635
     * Gets fields for managing this workflow instance in its current step
636
     *
637
     * @return FieldList
638
     */
639
    public function getWorkflowFields()
640
    {
641
        $action    = $this->CurrentAction();
642
        $options   = $this->validTransitions();
643
        $wfOptions = $options->map('ID', 'Title', ' ');
0 ignored issues
show
Unused Code introduced by
The call to ArrayList::map() has too many arguments starting with ' '.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Unused Code introduced by
$wfOptions is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
644
        $fields    = new FieldList();
645
646
        $fields->push(new HeaderField('WorkflowHeader', $action->Title));
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<Symbiote\Advanced...WorkflowActionInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
647
648
        $fields->push(HiddenField::create('TransitionID', ''));
649
        // Let the Active Action update the fields that the user can interact with so that data can be
650
        // stored for the workflow.
651
        $action->updateWorkflowFields($fields);
652
        $action->invokeWithExtensions('updateWorkflowFields', $fields);
653
        return $fields;
654
    }
655
656
    /**
657
     * Gets Front-End form fields from current Action
658
     *
659
     * @return FieldList
660
     */
661
    public function getFrontEndWorkflowFields()
662
    {
663
        $action = $this->CurrentAction();
664
665
        $fields = new FieldList();
666
        $action->updateFrontEndWorkflowFields($fields);
667
668
        return $fields;
669
    }
670
671
    /**
672
     * Gets Transitions for display as Front-End Form Actions
673
     *
674
     * @return FieldList
675
     */
676
    public function getFrontEndWorkflowActions()
677
    {
678
        $action    = $this->CurrentAction();
679
        $options   = $action->getValidTransitions();
680
        $actions   = new FieldList();
681
682
        $hide_disabled_actions_on_frontend = $this->config()->hide_disabled_actions_on_frontend;
683
684
        foreach ($options as $option) {
685
            $btn = new FormAction("transition_{$option->ID}", $option->Title);
686
687
            // add cancel class to passive actions, this prevents js validation (using jquery.validate)
688
            if ($option->Type == 'Passive') {
689
                $btn->addExtraClass('cancel');
690
            }
691
692
            // disable the button if canExecute() returns false
693
            if (!$option->canExecute($this)) {
694
                if ($hide_disabled_actions_on_frontend) {
695
                    continue;
696
                }
697
698
                $btn = $btn->performReadonlyTransformation();
699
                $btn->addExtraClass('hide');
700
            }
701
702
            $actions->push($btn);
703
        }
704
705
        $action->updateFrontEndWorkflowActions($actions);
706
707
        return $actions;
708
    }
709
710
    /**
711
     * Gets Front-End DataObject
712
     *
713
     * @return DataObject
714
     */
715
    public function getFrontEndDataObject()
716
    {
717
        $action = $this->CurrentAction();
718
        $obj = $action->getFrontEndDataObject();
719
720
        return $obj;
721
    }
722
723
    /**
724
     * Gets Front-End DataObject
725
     *
726
     * @return DataObject
727
     */
728
    public function getFrontEndRequiredFields()
729
    {
730
        $action = $this->CurrentAction();
731
        $validator = $action->getRequiredFields();
732
733
        return $validator;
734
    }
735
736
    public function setFrontendFormRequirements()
737
    {
738
        $action = $this->CurrentAction();
739
        $action->setFrontendFormRequirements();
740
    }
741
742
    public function doFrontEndAction(array $data, Form $form, HTTPRequest $request)
743
    {
744
        $action = $this->CurrentAction();
745
        $action->doFrontEndAction($data, $form, $request);
746
    }
747
748
    /**
749
     * We need a way to "associate" an author with this WorkflowInstance and its Target() to see if she is "allowed"
750
     * to view WorkflowInstances within GridFields
751
     * @see {@link $this->userHasAccess()}
752
     *
753
     * @param number $recordID
754
     * @param number $userID
755
     * @param number $wasPublished
756
     * @return boolean
757
     */
758
    public function getVersionedConnection($recordID, $userID, $wasPublished = 0)
759
    {
760
        // Turn this into an array and run through implode()
761
        $filter = "RecordID = {$recordID} AND AuthorID = {$userID} AND WasPublished = {$wasPublished}";
762
        $query = new SQLSelect();
763
        $query->setFrom('"SiteTree_Versions"')->setSelect('COUNT("ID")')->setWhere($filter);
764
        $query->firstRow();
765
        $hasAuthored = $query->execute();
766
        if ($hasAuthored) {
767
            return true;
768
        }
769
        return false;
770
    }
771
772
    /**
773
     * Simple method to retrieve the current action, on the current WorkflowInstance
774
     */
775
    public function getCurrentAction()
776
    {
777
        $join = '"WorkflowAction"."ID" = "WorkflowActionInstance"."BaseActionID"';
778
        $action = WorkflowAction::get()
779
            /** @skipUpgrade */
780
            ->leftJoin('WorkflowActionInstance', $join)
781
            ->where('"WorkflowActionInstance"."ID" = '.$this->CurrentActionID)
0 ignored issues
show
Documentation introduced by
The property CurrentActionID does not exist on object<Symbiote\Advanced...jects\WorkflowInstance>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
782
            ->first();
783
        if (!$action) {
784
            return 'N/A';
785
        }
786
        return $action->getField('Title');
787
    }
788
789
    /**
790
     * Tells us if $member has had permissions over some part of the current WorkflowInstance.
791
     *
792
     * @param $member
793
     * @return WorkflowAction|boolean
794
     */
795
    public function getMostRecentActionForUser($member = null)
796
    {
797
        if (!$member) {
798
            if (!Security::getCurrentUser()) {
799
                return false;
800
            }
801
            $member = Security::getCurrentUser();
802
        }
803
804
        // WorkflowActionInstances in reverse creation-order so we get the most recent one's first
805
        $history = $this->Actions()->filter(array(
0 ignored issues
show
Bug introduced by
The method Actions() does not exist on Symbiote\AdvancedWorkflo...bjects\WorkflowInstance. Did you maybe mean getFrontEndWorkflowActions()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
806
            'Finished' =>1,
807
            'BaseAction.ClassName' => AssignUsersToWorkflowAction::class
808
        ))->Sort('Created', 'DESC');
809
810
        $i = 0;
811
        foreach ($history as $inst) {
812
            /*
813
             * This iteration represents the 1st instance in the list - the most recent AssignUsersToWorkflowAction
814
             * in $history.
815
             * If there's no match for $member here or on the _previous_ AssignUsersToWorkflowAction, then bail out:
816
             */
817
            $assignedMembers = $inst->BaseAction()->getAssignedMembers();
818
            if ($i <= 1 && $assignedMembers->count() > 0 && $assignedMembers->find('ID', $member->ID)) {
819
                return $inst;
820
            }
821
            ++$i;
822
        }
823
        return false;
824
    }
825
}
826