Issues (569)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

tests/integration/CollectionTest.php (24 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Robo;
3
4
use PHPUnit\Framework\TestCase;
5
use Robo\Collection\Temporary;
6
use Robo\Exception\AbortTasksException;
7
use Robo\Traits\TestTasksTrait;
8
9
class CollectionTest extends TestCase
10
{
11
    use TestTasksTrait;
12
    use Collection\loadTasks;
13
    use Task\File\loadTasks;
14
    use Task\Filesystem\loadTasks;
15
    use Task\Filesystem\loadShortcuts;
16
    use Task\TestHelperTasks;
17
18
    protected $fixtures;
19
20
    public function setUp()
21
    {
22
        $this->fixtures = new Fixtures();
23
        $this->initTestTasksTrait();
24
        $this->fixtures->createAndCdToSandbox();
25
    }
26
27
    public function tearDown()
28
    {
29
        $this->fixtures->cleanup();
30
    }
31
32 View Code Duplication
    public function testSimulateDirCreation()
0 ignored issues
show
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...
33
    {
34
        // Set up a collection to add tasks to
35
        $collection = $this->collectionBuilder();
36
        $collection->simulated(true);
37
38
        // Set up a filesystem stack
39
        $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
40
            ->mkdir('simulatedir')
41
            ->touch('simulatedir/error.txt');
42
43
        // Run the task collection; the files would be present were this
44
        // operation not simulated.
45
        $result = $collection->run();
46
        $this->assertTrue($result->wasSuccessful());
47
        // Nothing should be created in simulated mode
48
        $this->assertFileNotExists('simulatedir/error.txt');
49
        $this->assertOutputContains('[Simulator] Simulating Filesystem\FilesystemStack()');
50
    }
51
52
53
    public function testRunMultipleTasksViaACollectionBuilder()
54
    {
55
        // This tests creating multiple tasks in a single builder,
56
        // which implicitly adds them to a collection.  To keep things
57
        // simple, we are only going to use taskFilesystemStack.  It
58
        // would be possible, of course, to do these operations with
59
        // a single FilesystemStack, but our goal is to test creating
60
        // multiple tasks with a builder, and ensure that a propper
61
        // collection is built.
62
        $collection = $this->collectionBuilder();
63
        $result = $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
64
                ->mkdir('a')
65
                ->touch('a/a.txt')
66
            ->rollback(
67
                $this->taskDeleteDir('a')
68
            )
69
            ->taskFilesystemStack()
70
                ->mkdir('a/b')
71
                ->touch('a/b/b.txt')
72
            ->taskFilesystemStack()
73
                ->mkdir('a/c')
74
                ->touch('a/c/c.txt')
75
            ->run();
76
77
        $this->assertTrue($result->wasSuccessful(), $result->getMessage());
78
79
        $this->assertEquals(0, $result->getExitCode());
80
81
        // All of the tasks created by the builder should be added
82
        // to a collection, and `run()` should run them all.
83
        $this->assertFileExists('a');
84
        $this->assertFileExists('a/a.txt');
85
        $this->assertFileExists('a/b');
86
        $this->assertFileExists('a/b/b.txt');
87
        $this->assertFileExists('a/c');
88
        $this->assertFileExists('a/c/c.txt');
89
    }
90
91
    public function testUsingAWorkingDirWithACollectionBuilder()
92
    {
93
        // Run the same test with a working directory.  The working
94
        // directory path will point to a temporary directory which
95
        // will be moved into place once the tasks complete.
96
        $collection = $this->collectionBuilder();
97
        $workDirPath = $collection->workDir("build");
98
        $this->assertNotEquals("build", basename($workDirPath));
99
        $result = $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
100
                ->mkdir("{$workDirPath}/a")
101
                ->touch("{$workDirPath}/a/a.txt")
102
            ->taskFilesystemStack()
103
                ->mkdir("{$workDirPath}/a/b")
104
                ->touch("{$workDirPath}/a/b/b.txt")
105
            ->taskFilesystemStack()
106
                ->mkdir("{$workDirPath}/a/c")
107
                ->touch("{$workDirPath}/a/c/c.txt")
108
            ->run();
109
110
        $this->assertTrue($result->wasSuccessful(), $result->getMessage());
111
112
        // All of the tasks created by the builder should be added
113
        // to a collection, and `run()` should run them all.
114
        $this->assertFileExists('build/a');
115
        $this->assertFileExists('build/a/a.txt');
116
        $this->assertFileExists('build/a/b');
117
        $this->assertFileExists('build/a/b/b.txt');
118
        $this->assertFileExists('build/a/c');
119
        $this->assertFileExists('build/a/c/c.txt');
120
    }
121
122 View Code Duplication
    public function testRollbackAfterFailureViaACollectionBuilder()
0 ignored issues
show
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...
123
    {
124
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
125
        // except we force an error at the end, and confirm that the
126
        // rollback function is called.
127
        $collection = $this->collectionBuilder();
128
        $result = $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
129
                ->mkdir('j')
130
                ->touch('j/j.txt')
131
            ->rollback(
132
                $this->taskDeleteDir('j')
133
            )
134
            ->taskFilesystemStack()
135
                ->mkdir('j/k')
136
                ->touch('j/k/k.txt')
137
            ->taskFilesystemStack()
138
                ->mkdir('j/k/m')
139
                ->touch('j/k/m/m.txt')
140
            ->taskCopyDir(['doesNotExist' => 'copied'])
141
            ->run();
142
143
        $this->assertEquals(1, $result->getExitCode(), $result->getMessage());
144
145
        // All of the tasks created by the builder should be added
146
        // to a collection, and `run()` should run them all.
147
        $this->assertFileNotExists('q/q.txt');
148
        $this->assertFileNotExists('j/j.txt');
149
        $this->assertFileNotExists('j/k/k.txt');
150
        $this->assertFileNotExists('j/k/m/m.txt');
151
    }
152
153 View Code Duplication
    public function testAbortRollbackOrCompletion()
0 ignored issues
show
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...
154
    {
155
        // This is like the previous test, except we throw a ForcedException()
156
        // inside the rollback to abort the rollback.
157
        $collection = $this->collectionBuilder();
158
        $result = $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
159
            ->mkdir('j')
160
            ->touch('j/j.txt')
161
            ->rollback(
162
                $this->taskDeleteDir('j')
163
            )
164
            ->rollbackCode(function () {
165
                throw new AbortTasksException('Aborting rollback.');
166
            })
167
            ->taskFilesystemStack()
168
            ->mkdir('j/k')
169
            ->touch('j/k/k.txt')
170
            ->taskFilesystemStack()
171
            ->mkdir('j/k/m')
172
            ->touch('j/k/m/m.txt')
173
            ->taskCopyDir(['doesNotExist' => 'copied'])
174
            ->run();
175
176
        $this->assertEquals(1, $result->getExitCode(), $result->getMessage());
177
178
        // All of the tasks created by the builder should be added
179
        // to a collection, and `run()` should run them all.
180
        $this->assertFileExists('j/j.txt');
181
        $this->assertFileExists('j/k/k.txt');
182
        $this->assertFileExists('j/k/m/m.txt');
183
    }
184
185
    public function testRollbackAWorkingDir()
186
    {
187
        // Run the same test with a working directory.  The working
188
        // directory path will point to a temporary directory which
189
        // will be moved into place once the tasks complete.
190
        $collection = $this->collectionBuilder();
191
        $workDirPath = $collection->workDir("build");
192
        $this->assertNotEquals("build", basename($workDirPath));
193
        $result = $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
194
                ->mkdir("{$workDirPath}/a")
195
                ->touch("{$workDirPath}/a/a.txt")
196
            ->taskFilesystemStack()
197
                ->mkdir("{$workDirPath}/a/b")
198
                ->touch("{$workDirPath}/a/b/b.txt")
199
            ->taskFilesystemStack()
200
                ->mkdir("{$workDirPath}/a/c")
201
                ->touch("{$workDirPath}/a/c/c.txt")
202
            ->taskCopyDir(['doesNotExist' => 'copied'])
203
            ->run();
204
205
        $this->assertEquals(1, $result->getExitCode(), $result->getMessage());
206
207
        // All of the tasks created by the builder should be added
208
        // to a collection, and `run()` should run them all.
209
        $this->assertFileNotExists('build/a');
210
        $this->assertFileNotExists($workDirPath);
211
    }
212
213
    public function testBuildFilesViaAddIterable()
214
    {
215
        $processList = ['cats', 'dogs', 'sheep', 'fish', 'horses', 'cows'];
216
217
        $collection = $this->collectionBuilder();
218
        $result = $collection
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
219
            ->taskFilesystemStack()
220
                ->mkdir('stuff')
221
            ->taskForEach($processList)
222
                ->withBuilder(
223
                    function ($builder, $key, $value) {
224
                        return $builder
225
                            ->taskFilesystemStack()
226
                                ->touch("stuff/{$value}.txt");
227
                    }
228
                )
229
            ->run();
230
231
        $this->assertEquals(0, $result->getExitCode(), $result->getMessage());
232
233
        $this->assertFileExists('stuff/cats.txt');
234
        $this->assertFileExists('stuff/dogs.txt');
235
        $this->assertFileExists('stuff/sheep.txt');
236
        $this->assertFileExists('stuff/fish.txt');
237
        $this->assertFileExists('stuff/horses.txt');
238
        $this->assertFileExists('stuff/cows.txt');
239
    }
240
241
    public function testRollbackANestedCollection()
242
    {
243
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
244
        // except we force an error at the end, and confirm that the
245
        // rollback function is called.
246
        $collection = $this->collectionBuilder();
247
        $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
248
                ->mkdir('j')
249
                ->touch('j/j.txt')
250
            ->rollback(
251
                $this->taskDeleteDir('j')
252
            )
253
            ->taskFilesystemStack()
254
                ->mkdir('j/k')
255
                ->touch('j/k/k.txt')
256
            ->taskFilesystemStack()
257
                ->mkdir('j/k/m')
258
                ->touch('j/k/m/m.txt');
259
260
        $result = $this->collectionBuilder()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
261
            ->taskFilesystemStack()
262
                ->mkdir('q')
263
                ->touch('q/q.txt')
264
            ->addTask($collection)
265
            ->taskCopyDir(['doesNotExist' => 'copied'])
266
            ->run();
267
268
        $this->assertEquals(1, $result->getExitCode(), $result->getMessage());
269
270
        // All of the tasks created by the builder should be added
271
        // to a collection, and `run()` should run them all.
272
        $this->assertFileExists('q/q.txt');
273
        $this->assertFileNotExists('j/j.txt');
274
        $this->assertFileNotExists('j/k/k.txt');
275
        $this->assertFileNotExists('j/k/m/m.txt');
276
    }
277
278
    public function testRollbackInCorrectOrder()
279
    {
280
        $expected_order = [6,5,4,3,2,1];
281
        $actual_order = [];
282
        $collection = $this->collectionBuilder();
283
        $collection->rollbackCode(function () use (&$actual_order) {
284
            $actual_order[] = 1;
285
        });
286
        $collection->rollbackCode(function () use (&$actual_order) {
287
            $actual_order[] = 2;
288
        });
289
        $collection->rollbackCode(function () use (&$actual_order) {
290
            $actual_order[] = 3;
291
        });
292
        // Add a nested collection with rollbacks.
293
        $nested_collection = $this->collectionBuilder();
294
        $nested_collection->rollbackCode(function () use (&$actual_order) {
295
            $actual_order[] = 4;
296
        });
297
        $nested_collection->rollbackCode(function () use (&$actual_order) {
298
            $actual_order[] = 5;
299
        });
300
        $collection->addTask($nested_collection);
301
302
        $collection->rollbackCode(function () use (&$actual_order) {
303
            $actual_order[] = 6;
304
        });
305
        $collection->addCode(function () {
306
            return Result::EXITCODE_ERROR;
307
        });
308
        $result = $collection->run();
309
        $this->assertFalse($result->wasSuccessful(), $result->getMessage());
310
        $this->assertEquals($expected_order, $actual_order);
311
    }
312
313 View Code Duplication
    public function testCreateDirViaCollection()
0 ignored issues
show
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...
314
    {
315
        // Set up a collection to add tasks to
316
        $collection = $this->collectionBuilder();
317
318
        // Set up a filesystem stack
319
        $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
320
            ->mkdir('log')
321
            ->touch('log/error.txt');
322
323
        // FilesystemStack has not run yet, so file should not be found.
324
        $this->assertFileNotExists('log/error.txt');
325
326
        // Run the task collection; now the files should be present
327
        $result = $collection->run();
328
        $this->assertTrue($result->wasSuccessful(), $result->getMessage());
329
        $this->assertFileExists('log/error.txt');
330
        $this->assertFileExists('log');
331
    }
332
333
    public function testUseATmpDirAndConfirmItIsDeleted()
334
    {
335
        // Set up a collection to add tasks to
336
        $collection = $this->collectionBuilder();
337
338
        // Get a temporary directory to work in. Note that we get a
339
        // name back, but the directory is not created until the task
340
        // runs.  This technically is not thread-safe, but we create
341
        // a random name, so it is unlikely to conflict.
342
        $tmpPath = $collection->tmpDir();
343
344
        // Set up a filesystem stack, but use a collection to defer execution
345
        $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
346
            ->mkdir("$tmpPath/tmp")
347
            ->touch("$tmpPath/tmp/error.txt")
348
            ->rename("$tmpPath/tmp", "$tmpPath/log");
349
350
        // Copy our tmp directory to a location that is not transient
351
        $collection->taskCopyDir([$tmpPath => 'copied']);
0 ignored issues
show
Documentation Bug introduced by
The method taskCopyDir does not exist on object<Robo\Collection\CollectionBuilder>? 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...
352
353
        // FilesystemStack has not run yet, so no files should be found.
354
        $this->assertFileNotExists("$tmpPath/tmp/error.txt");
355
        $this->assertFileNotExists("$tmpPath/log/error.txt");
356
        $this->assertFileNotExists('copied/log/error.txt');
357
358
        // Run the task collection
359
        $result = $collection->run();
360
        $this->assertEquals(0, $result->getExitCode(), $result->getMessage());
361
        $this->assertEquals($result['path'], $tmpPath, "Tmp dir result matches accessor.");
362
363
        // The file 'error.txt' should have been copied into the "copied" dir.
364
        // This also proves that the tmp directory was created.
365
        $this->assertFileExists('copied/log/error.txt');
366
        // $tmpPath should be deleted after $collection->run() completes.
367
        $this->assertFileNotExists("$tmpPath/tmp/error.txt");
368
        $this->assertFileNotExists("$tmpPath/log/error.txt");
369
        $this->assertFileNotExists("$tmpPath");
370
    }
371
372
    public function testUseATmpDirAndChangeWorkingDirectory()
373
    {
374
        // Set up a collection to add tasks to
375
        $collection = $this->collectionBuilder();
376
377
        $cwd = getcwd();
378
379
        $tmpPath = $collection->taskTmpDir()
0 ignored issues
show
The method taskTmpDir() does not exist on Robo\Collection\CollectionBuilder. Did you maybe mean tmpDir()?

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...
380
            ->cwd()
381
            ->getPath();
382
383
        // Set up a filesystem stack, but use a collection to defer execution.
384
        // Note that since we used 'cwd()' above, the relative file paths
385
        // used below will be inside the temporary directory.
386
        $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
387
            ->mkdir("log")
388
            ->touch("log/error.txt");
389
390
        // Copy our tmp directory to a location that is not transient
391
        $collection->taskCopyDir(['log' => "$cwd/copied2"]);
0 ignored issues
show
Documentation Bug introduced by
The method taskCopyDir does not exist on object<Robo\Collection\CollectionBuilder>? 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...
392
393
        // FilesystemStack has not run yet, so no files should be found.
394
        $this->assertFileNotExists("$tmpPath/log/error.txt");
395
        $this->assertFileNotExists('$cwd/copied2/log/error.txt');
396
397
        // Run the task collection
398
        $result = $collection->run();
399
        $this->assertEquals(0, $result->getExitCode(), $result->getMessage());
400
401
        // The file 'error.txt' should have been copied into the "copied" dir
402
        $this->assertFileExists("$cwd/copied2/error.txt");
403
        // $tmpPath should be deleted after $collection->run() completes.
404
        $this->assertFileNotExists("$tmpPath/log/error.txt");
405
        // Make sure that 'log' was created in the temporary directory, not
406
        // at the current working directory.
407
        $this->assertFileNotExists("$cwd/log/error.txt");
408
409
        // Make sure that our working directory was restored.
410
        $finalWorkingDir = getcwd();
411
        $this->assertEquals($cwd, $finalWorkingDir);
412
    }
413
414
    public function testCreateATmpFileAndConfirmItIsDeleted()
415
    {
416
        // Set up a collection to add tasks to
417
        $collection = $this->collectionBuilder();
418
419
        // Write to a temporary file. Note that we can get the path
420
        // to the tempoary file that will be created, even though the
421
        // the file is not created until the task collecction runs.
422
        $tmpPath = $collection->taskTmpFile('tmp', '.txt')
0 ignored issues
show
Documentation Bug introduced by
The method taskTmpFile does not exist on object<Robo\Collection\CollectionBuilder>? 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...
423
            ->line("This is a test file")
424
            ->getPath();
425
426
        // Copy our tmp directory to a location that is not transient
427
        $collection->taskFilesystemStack()
0 ignored issues
show
Documentation Bug introduced by
The method taskFilesystemStack does not exist on object<Robo\Collection\CollectionBuilder>? 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...
428
            ->copy($tmpPath, 'copied.txt');
429
430
        // FilesystemStack has not run yet, so no files should be found.
431
        $this->assertFileNotExists("$tmpPath");
432
        $this->assertFileNotExists('copied.txt');
433
434
        // Run the task collection
435
        $result = $collection->run();
436
        $this->assertEquals(0, $result->getExitCode(), $result->getMessage());
437
438
        // The file 'copied.txt' should have been copied from the tmp file
439
        $this->assertFileExists('copied.txt');
440
        // $tmpPath should be deleted after $collection->run() completes.
441
        $this->assertFileNotExists("$tmpPath");
442
    }
443
444
    public function testUseATmpDirWithAlternateSyntax()
445
    {
446
        $collection = $this->collectionBuilder();
447
448
        // This test is equivalent to toUseATmpDirAndConfirmItIsDeleted,
449
        // but uses a different technique to create a collection of tasks.
450
        $tmpPath = $collection->tmpDir();
451
452
        // Now, rather than creating the tasks with a collection builder,
453
        // which automatically adds the tasks to the collection as they are
454
        // created, we will instead create them individually and then add
455
        // them to the collection via the addTaskList() method.
456
        $result = $collection->addTaskList(
457
            [
458
                $this->taskFilesystemStack()->mkdir("$tmpPath/log")->touch("$tmpPath/log/error.txt"),
0 ignored issues
show
The method mkdir does only exist in Robo\Task\Filesystem\FilesystemStack, but not in Robo\Collection\CollectionBuilder.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
459
                $this->taskCopyDir([$tmpPath => 'copied3']),
460
            ]
461
        )->run();
462
463
        // The results of this operation should be the same.
464
        $this->assertEquals(0, $result->getExitCode(), $result->getMessage());
465
        $this->assertFileExists('copied3/log/error.txt');
466
        $this->assertFileNotExists("$tmpPath/log/error.txt");
467
    }
468
469
    public function testCreateATmpDirWithoutACollection()
470
    {
471
        // Create a temporary directory, using our function name as
472
        // the prefix for the directory name.
473
        $tmpDirTask = $this->taskTmpDir(__FUNCTION__);
474
        $tmpPath = $tmpDirTask->getPath();
0 ignored issues
show
The method getPath does only exist in Robo\Task\Filesystem\WorkDir, but not in Robo\Collection\CollectionBuilder.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
475
        $this->assertFileNotExists($tmpPath);
476
        $result = $tmpDirTask->run();
477
        $this->assertTrue($result->wasSuccessful(), $result->getMessage());
478
        $this->assertFileExists($tmpPath);
479
        // Creating a temporary directory without a task collection will
480
        // cause the temporary directory to be deleted when the program
481
        // terminates.  We can force it to clean up sooner by calling
482
        // TransientManager::complete(); note that this deletes ALL global tmp
483
        // directories, so this is not thread-safe!  Useful in tests, though.
484
        Temporary::complete();
485
        $this->assertFileNotExists($tmpPath);
486
    }
487
488
    public function testCreateATmpDirUsingShortcut()
489
    {
490
        // Create a temporary directory, using our function name as
491
        // the prefix for the directory name.
492
        $tmpPath = $this->_tmpDir(__FUNCTION__);
493
        $this->assertFileExists($tmpPath);
494
        // Creating a temporary directory without a task collection will
495
        // cause the temporary directory to be deleted when the program
496
        // terminates.  We can force it to clean up sooner by calling
497
        // TransientManager::complete(); note that this deletes ALL global tmp
498
        // directories, so this is not thread-safe!  Useful in tests, though.
499
        Temporary::complete();
500
        $this->assertFileNotExists($tmpPath);
501
    }
502
503
    public function testThrowAnExceptionAndConfirmItIsCaught()
504
    {
505
        $collection = $this->collectionBuilder();
506
507
        $collection->addCode(
508
            function () {
509
                throw new \RuntimeException('Error');
510
            }
511
        );
512
        $result = $collection->run();
513
        $this->assertEquals('Error', $result->getMessage());
514
        $this->assertEquals(1, $result->getExitCode());
515
    }
516
517
    public function testChainData()
518
    {
519
        $collection = $this->collectionBuilder();
520
521
        $result = $collection
0 ignored issues
show
Documentation Bug introduced by
The method taskValueProvider does not exist on object<Robo\Collection\CollectionBuilder>? 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...
522
            ->taskValueProvider()
523
                ->provideMessage('1st') // Sets Result's message to '1st'
524
                ->storeState('one') // Copy Result's message to $state['one']
525
            ->taskValueProvider()
526
                ->provideMessage('2nd')
527
                ->storeState('two')
528
            ->taskValueProvider()
529
                ->deferTaskConfiguration('provideItem', 'one') // Same as ->proivdeItem($state['one']), but runs immediately before this task's run() method.
530
                ->deferTaskConfiguration('provideMessage', 'two')
531
                ->storeState('final')
532
            ->run();
533
534
        $this->assertTrue($result->wasSuccessful(), $result->getMessage());
535
536
        $state = $collection->getState();
537
        $this->assertEquals('1st', $state['one']);
538
        $this->assertEquals('1st', $state['item']);
539
        $this->assertEquals('2nd', $state['final']);
540
    }
541
542
}
543
544
545