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 ( c9fbaa...a5234a )
by Robbie
02:04
created

WorkflowInstance::getTarget()   C

Complexity

Conditions 8
Paths 6

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 6.6037
c 0
b 0
f 0
cc 8
eloc 14
nc 6
nop 1
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
            $targetObject = null;
256
257
            if (!$versionable && $getLive) {
258
                return;
259
            }
260
            if ($versionable) {
261
                $targetObject = Versioned::get_by_stage(
262
                    $this->TargetClass,
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...
263
                    $getLive ? Versioned::LIVE : Versioned::DRAFT
264
                )->byID($this->TargetID);
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...
265
            }
266
            if (!$targetObject) {
267
                $targetObject = 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...
268
            }
269
270
            return $targetObject;
271
        }
272
    }
273
274
    /**
275
     *
276
     * @param boolean $getLive
277
     * @see {@link {$this->getTarget()}
278
     * @return null|DataObject
279
     */
280
    public function Target($getLive = false)
281
    {
282
        return $this->getTarget($getLive);
283
    }
284
285
    /**
286
     * Returns the field differences between the older version and current version of Target
287
     *
288
     * @return ArrayList
289
     */
290
    public function getTargetDiff()
291
    {
292
        $liveTarget = $this->Target(true);
293
        $draftTarget = $this->Target();
294
295
        $diff = DataDifferencer::create($liveTarget, $draftTarget);
296
        $diff->ignoreFields($this->config()->get('diff_ignore_fields'));
297
298
        $fields = $diff->ChangedFields();
299
300
        return $fields;
301
    }
302
303
    /**
304
     * Start a workflow based on a particular definition for a particular object.
305
     *
306
     * The object is optional; if not specified, it is assumed that this workflow
307
     * is simply a task based checklist type of workflow.
308
     *
309
     * @param WorkflowDefinition $definition
310
     * @param DataObject $for
311
     */
312
    public function beginWorkflow(WorkflowDefinition $definition, DataObject $for = null)
313
    {
314
        if (!$this->ID) {
315
            $this->write();
316
        }
317
318
        if ($for
319
            && ($for->hasExtension(WorkflowApplicable::class)
320
                || $for->hasExtension(FileWorkflowApplicable::class))
321
        ) {
322
            $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...
323
            $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...
324
        }
325
326
        // lets create the first WorkflowActionInstance.
327
        $action = $definition->getInitialAction()->getInstanceForWorkflow();
328
        $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...
329
        $action->write();
330
331
        $title = $for && $for->hasField('Title')
332
            ? 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...
333
            : 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...
334
335
        $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...
336
        $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...
337
        $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...
338
        $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...
339
        $this->write();
340
341
        $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...
342
        $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...
343
    }
344
345
    /**
346
     * Execute this workflow. In rare cases this will actually execute all actions,
347
     * but typically, it will stop and wait for the user to input something
348
     *
349
     * The basic process is to get the current action, and see whether it has been finished
350
     * by some process, if not it attempts to execute it.
351
     *
352
     * If it has been finished, we check to see if there's some transitions to follow. If there's
353
     * only one transition, then we execute that immediately.
354
     *
355
     * If there's multiple transitions, we just stop and wait for the user to manually
356
     * trigger a transition.
357
     *
358
     * If there's no transitions, we make the assumption that we've finished the workflow and
359
     * mark it as such.
360
     *
361
     *
362
     */
363
    public function execute()
364
    {
365
        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...
366
            throw new Exception(
367
                sprintf(_t(
368
                    'WorkflowInstance.EXECUTE_EXCEPTION',
369
                    'Attempted to start an invalid workflow instance #%s!'
370
                ), $this->ID)
371
            );
372
        }
373
374
        $action     = $this->CurrentAction();
375
        $transition = false;
376
377
        // if the action has already finished, it means it has either multiple (or no
378
        // transitions at the time), so a subsequent check should be run.
379
        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...
380
            $transition = $this->checkTransitions($action);
381
        } else {
382
            $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...
383
384
            // if the action was successful, then the action has finished running and
385
            // next transition should be run (if only one).
386
            // input.
387
            if ($result) {
388
                $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...
389
                $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...
390
                $action->write();
391
                $transition = $this->checkTransitions($action);
392
            }
393
        }
394
395
        // if the action finished, and there's only one available transition then
396
        // move onto that step - otherwise check if the workflow has finished.
397
        if ($transition) {
398
            $this->performTransition($transition);
399
        } else {
400
            // see if there are any transitions available, even if they are not valid.
401
            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...
402
                $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...
403
                $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...
404
            } else {
405
                $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...
406
            }
407
408
            $this->write();
409
        }
410
    }
411
412
    /**
413
     * Evaluate all the transitions of an action and determine whether we should
414
     * follow any of them yet.
415
     *
416
     * @param  WorkflowActionInstance $action
417
     * @return WorkflowTransition
418
     */
419
    protected function checkTransitions(WorkflowActionInstance $action)
420
    {
421
        $transitions = $action->getValidTransitions();
422
        // if there's JUST ONE transition, then we need should
423
        // immediately follow it.
424
        if ($transitions && $transitions->count() == 1) {
425
            return $transitions->First();
426
        }
427
    }
428
429
    /**
430
     * Transitions a workflow to the next step defined by the given transition.
431
     *
432
     * After transitioning, the action is 'executed', and next steps
433
     * determined.
434
     *
435
     * @param WorkflowTransition $transition
436
     */
437
    public function performTransition(WorkflowTransition $transition)
438
    {
439
        // first make sure that the transition is valid to execute!
440
        $action          = $this->CurrentAction();
441
        $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...
442
443
        $valid = $allTransitions->find('ID', $transition->ID);
444
        if (!$valid) {
445
            throw new Exception(
446
                sprintf(_t(
447
                    'WorkflowInstance.WORKFLOW_TRANSITION_EXCEPTION',
448
                    'Invalid transition state for action #%s'
449
                ), $action->ID)
450
            );
451
        }
452
453
        $action->actionComplete($transition);
454
455
        $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...
456
        $action = $definition->getInstanceForWorkflow();
457
        $action->WorkflowID   = $this->ID;
458
        $action->write();
459
460
        $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...
461
        $this->write();
462
        $this->components = array(); // manually clear the has_one cache
463
464
        $action->actionStart($transition);
465
466
        $transition->extend('onTransition');
467
        $this->execute();
468
    }
469
470
    /**
471
     * Returns a list of all Members that are assigned to this instance, either directly or via a group.
472
     *
473
     * @todo   This could be made more efficient.
474
     * @return ArrayList
475
     */
476 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...
477
    {
478
        $list   = new ArrayList();
479
        $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...
480
481
        $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...
482
483
        foreach ($groups as $group) {
484
            $list->merge($group->Members());
485
        }
486
487
        $list->removeDuplicates();
488
        return $list;
489
    }
490
491
    /**
492
     *
493
     * @param Member $member
494
     * @return boolean
495
     */
496
    public function canView($member = null)
497
    {
498
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 496 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...
499
        if ($extended !== null) {
500
            return $extended;
501
        }
502
503
        $hasAccess = $this->userHasAccess($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 496 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...
504
        /*
505
         * If the next action is AssignUsersToWorkflowAction, execute() resets all user+group relations.
506
         * Therefore current user no-longer has permission to view this WorkflowInstance in PendingObjects
507
         * Gridfield, even though;
508
         * - She had permissions granted via the workflow definition to run the preceeding Action that took her here.
509
         */
510
        if (!$hasAccess) {
511
            if ($this->getMostRecentActionForUser($member)) {
512
                return true;
513
            }
514
        }
515
        return $hasAccess;
516
    }
517
518
    /**
519
     *
520
     * @param Member $member
521
     * @return boolean
522
     */
523
    public function canEdit($member = null)
524
    {
525
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 523 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...
526
        if ($extended !== null) {
527
            return $extended;
528
        }
529
530
        return $this->userHasAccess($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 523 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...
531
    }
532
533
    /**
534
     *
535
     * @param Member $member
536
     * @return boolean
537
     */
538
    public function canDelete($member = null)
539
    {
540
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by parameter $member on line 538 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...
541
        if ($extended !== null) {
542
            return $extended;
543
        }
544
545
        if (Permission::checkMember($member, "DELETE_WORKFLOW")) {
546
            return true;
547
        }
548
        return false;
549
    }
550
551
    /**
552
     * Checks whether the given user is in the list of users assigned to this
553
     * workflow
554
     *
555
     * @param Member $member
556
     */
557
    protected function userHasAccess($member)
558
    {
559
        if (!$member) {
560
            if (!Security::getCurrentUser()) {
561
                return false;
562
            }
563
            $member = Security::getCurrentUser();
564
        }
565
566
        if (Permission::checkMember($member, "ADMIN")) {
567
            return true;
568
        }
569
570
        // This method primarily "protects" access to a WorkflowInstance, but assumes access only to be granted to
571
        // users assigned-to that WorkflowInstance. However; lowly authors (users entering items into a workflow) are
572
        // not assigned - but we still wish them to see their submitted content.
573
        $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...
574
        // This method is used in more than just the ModelAdmin. Check for the current controller to determine where
575
        // canView() expectations differ
576
        if ($this->getTarget() && Controller::curr()->getAction() == 'index' && !$inWorkflowGroupOrUserTables) {
577
            if ($this->getVersionedConnection($this->getTarget()->ID, $member->ID)) {
578
                return true;
579
            }
580
            return false;
581
        }
582
        return $inWorkflowGroupOrUserTables;
583
    }
584
585
    /**
586
     * Can documents in the current workflow state be edited?
587
     */
588
    public function canEditTarget()
589
    {
590
        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...
591
            return $this->CurrentAction()->canEditTarget($target);
592
        }
593
    }
594
595
    /**
596
     * Does this action restrict viewing of the document?
597
     *
598
     * @return boolean
599
     */
600
    public function canViewTarget()
601
    {
602
        $action = $this->CurrentAction();
603
        if ($action) {
604
            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...
605
        }
606
        return true;
607
    }
608
609
    /**
610
     * Does this action restrict the publishing of a document?
611
     *
612
     * @return boolean
613
     */
614
    public function canPublishTarget()
615
    {
616
        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...
617
            return $this->CurrentAction()->canPublishTarget($target);
618
        }
619
    }
620
621
    /**
622
     * Get the current set of transitions that are valid for the current workflow state,
623
     * and are available to the current user.
624
     *
625
     * @return array
626
     */
627
    public function validTransitions()
628
    {
629
        $action    = $this->CurrentAction();
630
        $transitions = $action->getValidTransitions();
631
632
        // Filter by execute permission
633
        return $transitions->filterByCallback(function ($transition) {
634
            return $transition->canExecute($this);
635
        });
636
    }
637
638
    /* UI RELATED METHODS */
639
640
    /**
641
     * Gets fields for managing this workflow instance in its current step
642
     *
643
     * @return FieldList
644
     */
645
    public function getWorkflowFields()
646
    {
647
        $action    = $this->CurrentAction();
648
        $options   = $this->validTransitions();
649
        $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...
650
        $fields    = new FieldList();
651
652
        $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...
653
654
        $fields->push(HiddenField::create('TransitionID', ''));
655
        // Let the Active Action update the fields that the user can interact with so that data can be
656
        // stored for the workflow.
657
        $action->updateWorkflowFields($fields);
658
        $action->invokeWithExtensions('updateWorkflowFields', $fields);
659
        return $fields;
660
    }
661
662
    /**
663
     * Gets Front-End form fields from current Action
664
     *
665
     * @return FieldList
666
     */
667
    public function getFrontEndWorkflowFields()
668
    {
669
        $action = $this->CurrentAction();
670
671
        $fields = new FieldList();
672
        $action->updateFrontEndWorkflowFields($fields);
673
674
        return $fields;
675
    }
676
677
    /**
678
     * Gets Transitions for display as Front-End Form Actions
679
     *
680
     * @return FieldList
681
     */
682
    public function getFrontEndWorkflowActions()
683
    {
684
        $action    = $this->CurrentAction();
685
        $options   = $action->getValidTransitions();
686
        $actions   = new FieldList();
687
688
        $hide_disabled_actions_on_frontend = $this->config()->hide_disabled_actions_on_frontend;
689
690
        foreach ($options as $option) {
691
            $btn = new FormAction("transition_{$option->ID}", $option->Title);
692
693
            // add cancel class to passive actions, this prevents js validation (using jquery.validate)
694
            if ($option->Type == 'Passive') {
695
                $btn->addExtraClass('cancel');
696
            }
697
698
            // disable the button if canExecute() returns false
699
            if (!$option->canExecute($this)) {
700
                if ($hide_disabled_actions_on_frontend) {
701
                    continue;
702
                }
703
704
                $btn = $btn->performReadonlyTransformation();
705
                $btn->addExtraClass('hide');
706
            }
707
708
            $actions->push($btn);
709
        }
710
711
        $action->updateFrontEndWorkflowActions($actions);
712
713
        return $actions;
714
    }
715
716
    /**
717
     * Gets Front-End DataObject
718
     *
719
     * @return DataObject
720
     */
721
    public function getFrontEndDataObject()
722
    {
723
        $action = $this->CurrentAction();
724
        $obj = $action->getFrontEndDataObject();
725
726
        return $obj;
727
    }
728
729
    /**
730
     * Gets Front-End DataObject
731
     *
732
     * @return DataObject
733
     */
734
    public function getFrontEndRequiredFields()
735
    {
736
        $action = $this->CurrentAction();
737
        $validator = $action->getRequiredFields();
738
739
        return $validator;
740
    }
741
742
    public function setFrontendFormRequirements()
743
    {
744
        $action = $this->CurrentAction();
745
        $action->setFrontendFormRequirements();
746
    }
747
748
    public function doFrontEndAction(array $data, Form $form, HTTPRequest $request)
749
    {
750
        $action = $this->CurrentAction();
751
        $action->doFrontEndAction($data, $form, $request);
752
    }
753
754
    /**
755
     * We need a way to "associate" an author with this WorkflowInstance and its Target() to see if she is "allowed"
756
     * to view WorkflowInstances within GridFields
757
     * @see {@link $this->userHasAccess()}
758
     *
759
     * @param number $recordID
760
     * @param number $userID
761
     * @param number $wasPublished
762
     * @return boolean
763
     */
764
    public function getVersionedConnection($recordID, $userID, $wasPublished = 0)
765
    {
766
        // Turn this into an array and run through implode()
767
        $filter = "RecordID = {$recordID} AND AuthorID = {$userID} AND WasPublished = {$wasPublished}";
768
        $query = new SQLSelect();
769
        $query->setFrom('"SiteTree_Versions"')->setSelect('COUNT("ID")')->setWhere($filter);
770
        $query->firstRow();
771
        $hasAuthored = $query->execute();
772
        if ($hasAuthored) {
773
            return true;
774
        }
775
        return false;
776
    }
777
778
    /**
779
     * Simple method to retrieve the current action, on the current WorkflowInstance
780
     */
781
    public function getCurrentAction()
782
    {
783
        $join = '"WorkflowAction"."ID" = "WorkflowActionInstance"."BaseActionID"';
784
        $action = WorkflowAction::get()
785
            /** @skipUpgrade */
786
            ->leftJoin('WorkflowActionInstance', $join)
787
            ->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...
788
            ->first();
789
        if (!$action) {
790
            return 'N/A';
791
        }
792
        return $action->getField('Title');
793
    }
794
795
    /**
796
     * Tells us if $member has had permissions over some part of the current WorkflowInstance.
797
     *
798
     * @param $member
799
     * @return WorkflowAction|boolean
800
     */
801
    public function getMostRecentActionForUser($member = null)
802
    {
803
        if (!$member) {
804
            if (!Security::getCurrentUser()) {
805
                return false;
806
            }
807
            $member = Security::getCurrentUser();
808
        }
809
810
        // WorkflowActionInstances in reverse creation-order so we get the most recent one's first
811
        $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...
812
            'Finished' =>1,
813
            'BaseAction.ClassName' => AssignUsersToWorkflowAction::class
814
        ))->Sort('Created', 'DESC');
815
816
        $i = 0;
817
        foreach ($history as $inst) {
818
            /*
819
             * This iteration represents the 1st instance in the list - the most recent AssignUsersToWorkflowAction
820
             * in $history.
821
             * If there's no match for $member here or on the _previous_ AssignUsersToWorkflowAction, then bail out:
822
             */
823
            $assignedMembers = $inst->BaseAction()->getAssignedMembers();
824
            if ($i <= 1 && $assignedMembers->count() > 0 && $assignedMembers->find('ID', $member->ID)) {
825
                return $inst;
826
            }
827
            ++$i;
828
        }
829
        return false;
830
    }
831
}
832