Passed
Push — master ( 1a00b5...984447 )
by y
03:02
created

Project::_getDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Helix\Asana;
4
5
use Helix\Asana\Base\AbstractEntity;
6
use Helix\Asana\Base\AbstractEntity\CrudTrait;
7
use Helix\Asana\Base\AbstractEntity\WorkspaceTrait;
8
use Helix\Asana\Event\ProjectEvent;
9
use Helix\Asana\Event\StoryEvent;
10
use Helix\Asana\Event\TaskEvent;
11
use Helix\Asana\Project\Section;
12
use Helix\Asana\Project\Status;
13
use Helix\Asana\Webhook\ProjectWebhook;
14
15
/**
16
 * A project.
17
 *
18
 * @see https://developers.asana.com/docs/asana-projects
19
 * @see https://developers.asana.com/docs/project
20
 *
21
 * @method bool         isArchived          ()
22
 * @method $this        setArchived         (bool $archived)
23
 * @method string       getColor            ()
24
 * @method $this        setColor            (null|string $color)
25
 * @method string       getCreatedAt        ()
26
 * @method null|Status  getCurrentStatus    ()
27
 * @method CustomField[] getCustomFields    ()
28
 * @method string       getDueOn            ()
29
 * @method $this        setDueOn            (string $date)
30
 * @method User[]       getFollowers        ()
31
 * @method string       getHtmlNotes        ()
32
 * @method $this        setHtmlNotes        (string $notes)
33
 * @method string       getLayout           ()
34
 * @method $this        setLayout           (string $layout)
35
 * @method User[]       getMembers          ()
36
 * @method string       getModifiedAt       ()
37
 * @method string       getName             ()
38
 * @method $this        setName             (string $name)
39
 * @method string       getNotes            ()
40
 * @method $this        setNotes            (string $notes)
41
 * @method null|User    getOwner            ()
42
 * @method $this        setOwner            (User $owner)
43
 * @method bool         isPublic            ()
44
 * @method $this        setPublic           (bool $public)
45
 * @method string       getStartOn          ()
46
 * @method $this        setStartOn          (string $date)
47
 * @method null|Team    getTeam             ()
48
 * @method bool         hasTeam             ()
49
 */
50
class Project extends AbstractEntity {
51
52
    use CrudTrait;
53
    use WorkspaceTrait;
54
55
    const TYPE = 'project';
56
57
    const LAYOUT_BOARD = 'board';
58
    const LAYOUT_LIST = 'list';
59
60
    protected static $map = [
61
        'current_status' => Status::class,
62
        'custom_fields' => [CustomField::class],
63
        'followers' => [User::class],
64
        'members' => [User::class],
65
        'owner' => User::class,
66
        'team' => Team::class,
67
        'workspace' => Workspace::class
68
    ];
69
70
    final public function __toString (): string {
71
        return "projects/{$this->getGid()}";
72
    }
73
74
    final protected function _getDir (): string {
75
        return 'projects';
76
    }
77
78
    /**
79
     * @depends after-create
80
     * @param User $user
81
     * @return $this
82
     */
83
    public function addMember (User $user) {
84
        return $this->addMembers([$user]);
85
    }
86
87
    /**
88
     * @depends after-create
89
     * @param User[] $users
90
     * @return $this
91
     */
92
    public function addMembers (array $users) {
93
        $this->api->post("{$this}/addMembers", ['members' => static::_getGids($users)]);
94
        $this->_merge('members', $users);
95
        return $this;
96
    }
97
98
    /**
99
     * @depends after-create
100
     * @param string $target
101
     * @return ProjectWebhook
102
     */
103
    public function addWebhook (string $target) {
104
        /** @var ProjectWebhook $webhook */
105
        $webhook = $this->factory(ProjectWebhook::class);
106
        return $webhook->create($this, $target);
107
    }
108
109
    /**
110
     * Duplicates the project.
111
     *
112
     * @see https://developers.asana.com/docs/#duplicate-a-project
113
     *
114
     * If `$team` is `null`, the duplicate will inherit the existing team.
115
     *
116
     * If `$schedule` is given:
117
     * - It must have either `due_on` or `start_on`
118
     * - `task_dates` is automatically added to `$include`
119
     * - `should_skip_weekends` defaults to `true` if not given.
120
     *
121
     * @depends after-create
122
     * @param string $name
123
     * @param string[] $include
124
     * @param Team|null $team
125
     * @param array $schedule
126
     * @return Job
127
     */
128
    public function duplicate (string $name, array $include, Team $team = null, array $schedule = []) {
129
        $data = ['name' => $name];
130
        if ($team) {
131
            $data['team'] = $team->getGid();
132
        }
133
        if ($schedule) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $schedule of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
134
            $include[] = 'task_dates';
135
            $schedule += ['should_skip_weekends' => true];
136
            $data['schedule_dates'] = $schedule;
137
        }
138
        $data['include'] = array_values($include);
139
        $remote = $this->api->post("{$this}/duplicate", $data);
140
        return $this->factory(Job::class, $remote);
1 ignored issue
show
Bug introduced by
It seems like $remote can also be of type null; however, parameter $data of Helix\Asana\Base\Data::factory() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

140
        return $this->factory(Job::class, /** @scrutinizer ignore-type */ $remote);
Loading history...
141
    }
142
143
    /**
144
     * Returns events since the last sync.
145
     *
146
     * @depends after-create
147
     * @param null|string $token
148
     * @return ProjectEvent[]|TaskEvent[]|StoryEvent[]
149
     */
150
    public function getEvents (&$token) {
151
        return $this->api->sync($this, $token);
152
    }
153
154
    /**
155
     * @depends after-create
156
     * @return Section[]
157
     */
158
    public function getSections () {
159
        return $this->loadAll(Section::class, "{$this}/sections");
160
    }
161
162
    /**
163
     * @depends after-create
164
     * @return Status[]
165
     */
166
    public function getStatuses () {
167
        return $this->loadAll(Status::class, "{$this}/project_statuses");
168
    }
169
170
    /**
171
     * @depends after-create
172
     * @param array $query
173
     * @return Task[]
174
     */
175
    public function getTasks (array $query = []) {
176
        $query['project'] = $this->getGid();
177
        return $this->loadAll(Task::class, "tasks", $query);
178
    }
179
180
    /**
181
     * @depends after-create
182
     * @return string
183
     */
184
    public function getUrl (): string {
185
        return "https://app.asana.com/0/{$this->getGid()}";
186
    }
187
188
    /**
189
     * @return ProjectWebhook[]
190
     */
191
    public function getWebhooks () {
192
        return $this->loadAll(ProjectWebhook::class, 'webhooks', [
193
            'workspace' => $this->getWorkspace()->getGid(),
194
            'resource' => $this->getGid()
195
        ]);
196
    }
197
198
    public function isBoard (): bool {
199
        return $this->getLayout() === self::LAYOUT_BOARD;
200
    }
201
202
    public function isList (): bool {
203
        return $this->getLayout() === self::LAYOUT_LIST;
204
    }
205
206
    /**
207
     * @depends after-create
208
     * @return Section
209
     */
210
    public function newSection () {
211
        return $this->factory(Section::class, ['projects' => [$this]]);
212
    }
213
214
    /**
215
     * @depends after-create
216
     * @return Status
217
     */
218
    public function newStatus () {
219
        return $this->factory(Status::class);
220
    }
221
222
    /**
223
     * Instantiates and returns a new task in the default section.
224
     *
225
     * @depends after-create
226
     * @return Task
227
     */
228
    public function newTask () {
229
        return $this->getSections()[0]->newTask();
230
    }
231
232
    /**
233
     * @depends after-create
234
     * @param User $user
235
     * @return $this
236
     */
237
    public function removeMember (User $user) {
238
        return $this->removeMembers([$user]);
239
    }
240
241
    /**
242
     * @depends after-create
243
     * @param User[] $users
244
     * @return $this
245
     */
246
    public function removeMembers (array $users) {
247
        $this->api->post("{$this}/removeMembers", ['members' => static::_getGids($users)]);
248
        $this->_remove('members', $users);
249
        return $this;
250
    }
251
252
    /**
253
     * @depends create-only
254
     * @param null|Team $team
255
     * @return $this
256
     */
257
    public function setTeam (?Team $team) {
258
        assert(!$this->hasGid());
259
        if ($team and !$this->hasWorkspace()) {
260
            $this->setWorkspace($team->getOrganization());
261
        }
262
        return $this->_set('team', $team);
263
    }
264
}