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.

WorkflowAction   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 282
Duplicated Lines 3.19 %

Coupling/Cohesion

Components 3
Dependencies 18

Importance

Changes 0
Metric Value
wmc 25
lcom 3
cbo 18
dl 9
loc 282
rs 10
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A canEditTarget() 9 9 3
A canViewTarget() 0 4 1
A canPublishTarget() 0 4 1
A canCreate() 0 4 1
A canEdit() 0 4 1
A canDelete() 0 4 1
A canAddTransition() 0 4 1
A getInstanceForWorkflow() 0 7 1
A execute() 0 4 1
A onBeforeWrite() 0 8 2
A onAfterDelete() 0 24 4
A targetUpdated() 0 3 1
A numChildren() 0 4 1
A getCMSFields() 0 32 1
A getValidator() 0 4 1
A summaryFields() 0 7 1
A fieldLabels() 0 13 1
A updateFrontendWorkflowFields() 0 3 1
A Icon() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Symbiote\AdvancedWorkflow\DataObjects;
4
5
use SilverStripe\Core\Manifest\ModuleResourceLoader;
6
use SilverStripe\Forms\CheckboxField;
7
use SilverStripe\Forms\DropdownField;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\ReadonlyField;
10
use SilverStripe\Forms\RequiredFields;
11
use SilverStripe\Forms\TabSet;
12
use SilverStripe\Forms\TextField;
13
use SilverStripe\ORM\DataObject;
14
use SilverStripe\ORM\DB;
15
use SilverStripe\Security\Member;
16
use SilverStripe\Security\Permission;
17
use SilverStripe\Security\Security;
18
19
/**
20
 * A workflow action describes a the 'state' a workflow can be in, and
21
 * the action(s) that occur while in that state. An action can then have
22
 * subsequent transitions out of the current state.
23
 *
24
 * @method WorkflowDefinition WorkflowDef()
25
 * @author  [email protected]
26
 * @license BSD License (http://silverstripe.org/bsd-license/)
27
 * @package advancedworkflow
28
 */
29
class WorkflowAction extends DataObject
30
{
31
    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...
32
        'Title'             => 'Varchar(255)',
33
        'Comment'           => 'Text',
34
        'Type'              => "Enum('Dynamic,Manual','Manual')",  // is this used?
35
        'Executed'          => 'Boolean',
36
        'AllowEditing'      => "Enum('By Assignees,Content Settings,No','No')",         // can this item be edited?
37
        'Sort'              => 'Int',
38
        'AllowCommenting'   => 'Boolean'
39
    );
40
41
    private static $defaults = 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...
42
        'AllowCommenting'   => '1',
43
    );
44
45
    private static $default_sort = 'Sort';
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...
46
47
    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...
48
        'WorkflowDef' => WorkflowDefinition::class,
49
        'Member'      => Member::class
50
    );
51
52
    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...
53
        'Transitions' => WorkflowTransition::class . '.Action'
54
    );
55
56
    /**
57
     * The type of class to use for instances of this workflow action that are used for storing the
58
     * data of the instance.
59
     *
60
     * @var string
61
     */
62
    private static $instance_class = WorkflowActionInstance::class;
63
64
    private static $icon = 'symbiote/silverstripe-advancedworkflow:images/action.png';
65
66
    private static $table_name = 'WorkflowAction';
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...
67
68
    /**
69
     * Can documents in the current workflow state be edited?
70
     *
71
     * Only return true or false if this is an absolute value; the WorkflowActionInstance
72
     * will try and figure out an appropriate value for the actively running workflow
73
     * if null is returned from this method.
74
     *
75
     * Admin level users can always edit.
76
     *
77
     * @param  DataObject $target
78
     * @return bool
79
     */
80 View Code Duplication
    public function canEditTarget(DataObject $target)
0 ignored issues
show
Unused Code introduced by
The parameter $target is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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...
81
    {
82
        $currentUser = Security::getCurrentUser();
83
        if ($currentUser && Permission::checkMember($currentUser, 'ADMIN')) {
84
            return true;
85
        }
86
87
        return null;
88
    }
89
90
    /**
91
     * Does this action restrict viewing of the document?
92
     *
93
     * @param  DataObject $target
94
     * @return bool
95
     */
96
    public function canViewTarget(DataObject $target)
0 ignored issues
show
Unused Code introduced by
The parameter $target is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
97
    {
98
        return null;
99
    }
100
101
    /**
102
     * Does this action restrict the publishing of a document?
103
     *
104
     * @param  DataObject $target
105
     * @return bool
106
     */
107
    public function canPublishTarget(DataObject $target)
0 ignored issues
show
Unused Code introduced by
The parameter $target is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
108
    {
109
        return null;
110
    }
111
112
    /**
113
     * Allows users who have permission to create a WorkflowDefinition, to create actions on it too.
114
     *
115
     * @param Member $member
116
     * @param array $context
117
     * @return bool
118
     */
119
    public function canCreate($member = null, $context = array())
120
    {
121
        return $this->WorkflowDef()->canCreate($member, $context);
122
    }
123
124
    /**
125
     * @param  Member $member
126
     * @return bool
127
     */
128
    public function canEdit($member = null)
129
    {
130
        return $this->canCreate($member);
131
    }
132
133
    /**
134
     * @param  Member $member
135
     * @return bool
136
     */
137
    public function canDelete($member = null)
138
    {
139
        return $this->WorkflowDef()->canDelete($member);
140
    }
141
142
    /*
143
     * If there is only a single action defined for a workflow, there's no sense
144
     * in allowing users to add a transition to it (and causing errors).
145
     * Hide the "Add Transition" button in this case
146
     *
147
     * @return boolean true if we should disable the button, false otherwise
148
     */
149
    public function canAddTransition()
150
    {
151
        return ($this->WorkflowDef()->numChildren() >1);
152
    }
153
154
    /**
155
     * Gets an object that is used for saving the actual state of things during
156
     * a running workflow. It still uses the workflow action def for managing the
157
     * functional execution, however if you need to store additional data for
158
     * the state, you can specify your own WorkflowActionInstance instead of
159
     * the default to capture these elements
160
     *
161
     * @return WorkflowActionInstance
162
     */
163
    public function getInstanceForWorkflow()
164
    {
165
        $instanceClass = $this->config()->get('instance_class');
166
        $instance = new $instanceClass();
167
        $instance->BaseActionID = $this->ID;
168
        return $instance;
169
    }
170
171
    /**
172
     * Perform whatever needs to be done for this action. If this action can be considered executed, then
173
     * return true - if not (ie it needs some user input first), return false and 'execute' will be triggered
174
     * again at a later point in time after the user has provided more data, either directly or indirectly.
175
     *
176
     * @param  WorkflowInstance $workflow
177
     * @return bool Returns true if this action has finished.
178
     */
179
    public function execute(WorkflowInstance $workflow)
180
    {
181
        return true;
182
    }
183
184
    public function onBeforeWrite()
185
    {
186
        if (!$this->Sort) {
0 ignored issues
show
Documentation introduced by
The property Sort does not exist on object<Symbiote\Advanced...Objects\WorkflowAction>. 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...
187
            $this->Sort = DB::query('SELECT MAX("Sort") + 1 FROM "WorkflowAction"')->value();
0 ignored issues
show
Documentation introduced by
The property Sort does not exist on object<Symbiote\Advanced...Objects\WorkflowAction>. 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...
188
        }
189
190
        parent::onBeforeWrite();
191
    }
192
193
    /**
194
     * When deleting an action from a workflow definition, make sure that workflows currently paused on that action
195
     * are deleted
196
     * Also removes all outbound transitions
197
     */
198
    public function onAfterDelete()
199
    {
200
        parent::onAfterDelete();
201
        $wfActionInstances = WorkflowActionInstance::get()
202
            /** @skipUpgrade */
203
            ->leftJoin('WorkflowInstance', '"WorkflowInstance"."ID" = "WorkflowActionInstance"."WorkflowID"')
204
            ->where(sprintf('"BaseActionID" = %d AND ("WorkflowStatus" IN (\'Active\',\'Paused\'))', $this->ID));
205
        foreach ($wfActionInstances as $wfActionInstance) {
206
            $wfInstances = WorkflowInstance::get()->filter('CurrentActionID', $wfActionInstance->ID);
207
            foreach ($wfInstances as $wfInstance) {
208
                $wfInstance->Groups()->removeAll();
209
                $wfInstance->Users()->removeAll();
210
                $wfInstance->delete();
211
            }
212
            $wfActionInstance->delete();
213
        }
214
        // Delete outbound transitions
215
        $transitions = WorkflowTransition::get()->filter('ActionID', $this->ID);
216
        foreach ($transitions as $transition) {
217
            $transition->Groups()->removeAll();
218
            $transition->Users()->removeAll();
219
            $transition->delete();
220
        }
221
    }
222
223
    /**
224
     * Called when the current target of the workflow has been updated
225
     */
226
    public function targetUpdated(WorkflowInstance $workflow)
0 ignored issues
show
Unused Code introduced by
The parameter $workflow is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
227
    {
228
    }
229
230
    /* CMS RELATED FUNCTIONALITY... */
231
232
233
    public function numChildren()
234
    {
235
        return $this->Transitions()->count();
0 ignored issues
show
Documentation Bug introduced by
The method Transitions does not exist on object<Symbiote\Advanced...Objects\WorkflowAction>? 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...
236
    }
237
238
    public function getCMSFields()
239
    {
240
241
        $fields = new FieldList(new TabSet('Root'));
242
        $typeLabel = _t('WorkflowAction.CLASS_LABEL', 'Action Class');
243
        $fields->addFieldToTab(
244
            'Root.Main',
245
            new ReadOnlyField('WorkflowActionClass', $typeLabel, $this->singular_name())
246
        );
247
        $titleField = new TextField('Title', $this->fieldLabel('Title'));
248
        $titleField->setDescription(_t(
249
            'WorkflowAction.TitleDescription',
250
            'The Title is used as the button label for this Workflow Action'
251
        ));
252
        $fields->addFieldToTab('Root.Main', $titleField);
253
        $fields->addFieldToTab('Root.Main', new DropdownField(
254
            'AllowEditing',
255
            $this->fieldLabel('AllowEditing'),
256
            array(
257
                'By Assignees' => _t('AllowEditing.ByAssignees', 'By Assignees'),
258
                'Content Settings' => _t('AllowEditing.ContentSettings', 'Content Settings'),
259
                'No' => _t('AllowEditing.NoString', 'No')
260
            ),
261
            _t('AllowEditing.NoString', 'No')
262
        ));
263
        $fields->addFieldToTab(
264
            'Root.Main',
265
            new CheckboxField('AllowCommenting', $this->fieldLabel('AllowCommenting'), $this->AllowCommenting)
0 ignored issues
show
Documentation introduced by
The property AllowCommenting does not exist on object<Symbiote\Advanced...Objects\WorkflowAction>. 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...
266
        );
267
        $this->extend('updateCMSFields', $fields);
268
        return $fields;
269
    }
270
271
    public function getValidator()
272
    {
273
        return new RequiredFields('Title');
274
    }
275
276
    public function summaryFields()
277
    {
278
        return array(
279
            'Title' => $this->fieldLabel('Title'),
280
            'Transitions' => $this->fieldLabel('Transitions'),
281
        );
282
    }
283
284
    public function fieldLabels($includerelations = true)
285
    {
286
        $labels = parent::fieldLabels($includerelations);
287
        $labels['Comment'] = _t('WorkflowAction.CommentLabel', 'Comment');
288
        $labels['Type'] = _t('WorkflowAction.TypeLabel', 'Type');
289
        $labels['Executed'] = _t('WorkflowAction.ExecutedLabel', 'Executed');
290
        $labels['AllowEditing'] = _t('WorkflowAction.ALLOW_EDITING', 'Allow editing during this step?');
291
        $labels['Title'] = _t('WorkflowAction.TITLE', 'Title');
292
        $labels['AllowCommenting'] = _t('WorkflowAction.ALLOW_COMMENTING', 'Allow Commenting?');
293
        $labels['Transitions'] = _t('WorkflowAction.Transitions', 'Transitions');
294
295
        return $labels;
296
    }
297
298
    /**
299
     * Used for Front End Workflows
300
     */
301
    public function updateFrontendWorkflowFields($fields, $workflow)
0 ignored issues
show
Unused Code introduced by
The parameter $fields is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $workflow is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
302
    {
303
    }
304
305
    public function Icon()
306
    {
307
        $icon = $this->config()->get('icon');
308
        return ModuleResourceLoader::singleton()->resolveURL($icon);
309
    }
310
}
311