Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / consolidation / robo / src / Collection / TaskForEach.php
1 <?php
2 namespace Robo\Collection;
3
4 use Robo\Result;
5 use Robo\TaskInfo;
6 use Robo\Task\BaseTask;
7 use Robo\Contract\BuilderAwareInterface;
8 use Robo\Common\BuilderAwareTrait;
9
10 /**
11  * Creates a task wrapper that converts any Callable into an
12  * object that will execute the callback once for each item in the
13  * provided collection.
14  *
15  * It is not necessary to use this class directly; Collection::addIterable
16  * will automatically create one when it is called.
17  */
18 class TaskForEach extends BaseTask implements NestedCollectionInterface, BuilderAwareInterface
19 {
20     use BuilderAwareTrait;
21
22     /**
23      * @var callable[]
24      */
25     protected $functionStack = [];
26
27     /**
28      * @var callable[]
29      */
30     protected $countingStack = [];
31
32     /**
33      * @var string
34      */
35     protected $message;
36
37     /**
38      * @var array
39      */
40     protected $context = [];
41
42     /**
43      * @var array $iterable
44      */
45     protected $iterable = [];
46
47     /**
48      * @var \Robo\Collection\NestedCollectionInterface
49      */
50     protected $parentCollection;
51
52     /**
53      * @var array $iterable
54      */
55     public function __construct($iterable = [])
56     {
57         $this->setIterable($iterable);
58     }
59
60     /**
61      * @param array $iterable
62      *
63      * @return $this
64      */
65     public function setIterable($iterable)
66     {
67         $this->iterable = $iterable;
68
69         return $this;
70     }
71
72     /**
73      * @param string $message
74      * @param array $context
75      *
76      * @return $this
77      */
78     public function iterationMessage($message, $context = [])
79     {
80         $this->message = $message;
81         $this->context = $context + ['name' => 'Progress'];
82         return $this;
83     }
84
85     /**
86      * @param int|string $key
87      * @param mixed $value
88      */
89     protected function showIterationMessage($key, $value)
90     {
91         if ($this->message) {
92             $context = ['key' => $key, 'value' => $value];
93             $context += $this->context;
94             $context += TaskInfo::getTaskContext($this);
95             $this->printTaskInfo($this->message, $context);
96         }
97     }
98
99     /**
100      * @param callable $fn
101      *
102      * @return $this
103      */
104     public function withEachKeyValueCall(callable $fn)
105     {
106         $this->functionStack[] = $fn;
107         return $this;
108     }
109
110     /**
111      * @param callable $fn
112      *
113      * @return \Robo\Collection\TaskForEach
114      */
115     public function call(callable $fn)
116     {
117         return $this->withEachKeyValueCall(
118             function ($key, $value) use ($fn) {
119                 return call_user_func($fn, $value);
120             }
121         );
122     }
123
124     /**
125      * @param callable $fn
126      *
127      * @return \Robo\Collection\TaskForEach
128      */
129     public function withBuilder(callable $fn)
130     {
131         $this->countingStack[] =
132             function ($key, $value) use ($fn) {
133                 // Create a new builder for every iteration
134                 $builder = $this->collectionBuilder();
135                 // The user function should build task operations using
136                 // the $key / $value parameters; we will call run() on
137                 // the builder thus constructed.
138                 call_user_func($fn, $builder, $key, $value);
139                 return $builder->getCollection()->progressIndicatorSteps();
140             };
141         return $this->withEachKeyValueCall(
142             function ($key, $value) use ($fn) {
143                 // Create a new builder for every iteration
144                 $builder = $this->collectionBuilder()
145                     ->setParentCollection($this->parentCollection);
146                 // The user function should build task operations using
147                 // the $key / $value parameters; we will call run() on
148                 // the builder thus constructed.
149                 call_user_func($fn, $builder, $key, $value);
150                 return $builder->run();
151             }
152         );
153     }
154
155     /**
156      * {@inheritdoc}
157      */
158     public function setParentCollection(NestedCollectionInterface $parentCollection)
159     {
160         $this->parentCollection = $parentCollection;
161         return $this;
162     }
163
164     /**
165      * {@inheritdoc}
166      */
167     public function progressIndicatorSteps()
168     {
169         $multiplier = count($this->functionStack);
170         if (!empty($this->countingStack) && count($this->iterable)) {
171             $value = reset($this->iterable);
172             $key = key($this->iterable);
173             foreach ($this->countingStack as $fn) {
174                 $multiplier += call_user_func($fn, $key, $value);
175             }
176         }
177         return count($this->iterable) * $multiplier;
178     }
179
180     /**
181      * {@inheritdoc}
182      */
183     public function run()
184     {
185         $finalResult = Result::success($this);
186         $this->startProgressIndicator();
187         foreach ($this->iterable as $key => $value) {
188             $this->showIterationMessage($key, $value);
189             try {
190                 foreach ($this->functionStack as $fn) {
191                     $result = call_user_func($fn, $key, $value);
192                     $this->advanceProgressIndicator();
193                     if (!isset($result)) {
194                         $result = Result::success($this);
195                     }
196                     // If the function returns a result, it must either return
197                     // a \Robo\Result or an exit code.  In the later case, we
198                     // convert it to a \Robo\Result.
199                     if (!$result instanceof Result) {
200                         $result = new Result($this, $result);
201                     }
202                     if (!$result->wasSuccessful()) {
203                         return $result;
204                     }
205                     $finalResult = $result->merge($finalResult);
206                 }
207             } catch (\Exception $e) {
208                 return Result::fromException($result, $e);
209             }
210         }
211         $this->stopProgressIndicator();
212         return $finalResult;
213     }
214 }