Completed
Pull Request — master (#186)
by
unknown
08:25 queued 05:05
created

NotifynderBuilder::setField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace Fenos\Notifynder\Builder;
4
5
use ArrayAccess;
6
use Carbon\Carbon;
7
use Fenos\Notifynder\Contracts\NotifynderCategory;
8
use Fenos\Notifynder\Exceptions\EntityNotIterableException;
9
use Fenos\Notifynder\Exceptions\IterableIsEmptyException;
10
use Fenos\Notifynder\Exceptions\NotificationBuilderException;
11
use Illuminate\Contracts\Config\Repository;
12
use Illuminate\Database\Eloquent\Model;
13
use Traversable;
14
use Closure;
15
16
/**
17
 * Class NotifynderBuilder.
18
 *
19
 * The builder is a main factor of Notifynder, it make sure
20
 * that the notification is decorated and validated before
21
 * are passed to the Sender Classes. It also helps you to
22
 * create multi notifications with the same simple and easy syntax.
23
 */
24
class NotifynderBuilder implements ArrayAccess
25
{
26
    use BuilderRules;
27
28
    /**
29
     * @var string notification to store
30
     */
31
    public $date;
32
33
    /**
34
     * Builder data.
35
     *
36
     * @var array
37
     */
38
    protected $notifications = [];
39
40
    /**
41
     * @var Repository
42
     */
43
    protected $config;
44
45
    /**
46
     * @var NotifynderCategory
47
     */
48
    private $notifynderCategory;
49
50
    /**
51
     * @param NotifynderCategory $notifynderCategory
52
     */
53
    public function __construct(NotifynderCategory $notifynderCategory)
54
    {
55
        $this->notifynderCategory = $notifynderCategory;
56
    }
57
58
    /**
59
     * Set who will send the notification.
60
     *
61
     * @return $this
62
     */
63
    public function from()
64
    {
65
        $from = func_get_args();
66
67
        $this->setEntityAction($from, 'from');
68
69
        return $this;
70
    }
71
72
    /**
73
     * Set who will receive the notification.
74
     *
75
     * @return $this
76
     */
77
    public function to()
78
    {
79
        $from = func_get_args();
80
81
        $this->setEntityAction($from, 'to');
82
83
        return $this;
84
    }
85
86
    /**
87
     * Set the url of the notification.
88
     *
89
     * @param $url
90
     * @return $this
91
     */
92
    public function url($url)
93
    {
94
        $this->isString($url);
95
96
        $this->setBuilderData('url', $url);
97
98
        return $this;
99
    }
100
101
    /**
102
     * Set expire time.
103
     *
104
     * @param $datetime
105
     * @return $this
106
     */
107
    public function expire($datetime)
108
    {
109
        $this->isCarbon($datetime);
110
        $this->setBuilderData('expire_time', $datetime);
111
112
        return $this;
113
    }
114
115
    /**
116
     * Set Category and covert it, to the id
117
     * if name of it given.
118
     *
119
     * @param $category
120
     * @return $this
121
     */
122
    public function category($category)
123
    {
124
        if (! is_numeric($category)) {
125
            $category = $this->notifynderCategory
126
                            ->findByName($category)->id;
127
        }
128
129
        $this->setBuilderData('category_id', $category);
130
131
        return $this;
132
    }
133
134
    /**
135
     * Set extra value.
136
     *
137
     * @param $extra
138
     * @return $this
139
     */
140
    public function extra(array $extra = [])
141
    {
142
        $this->isReadyArrToFormatInJson($extra);
143
144
        $jsonExtraValues = json_encode($extra);
145
146
        $this->setBuilderData('extra', $jsonExtraValues);
147
148
        return $this;
149
    }
150
151
    /**
152
     * Set additional fields value.
153
     *
154
     * @param $key
155
     * @param $value
156
     * @return $this
157
     */
158
    public function setField($key, $value)
159
    {
160
        $this->setBuilderData($key, $value);
161
162
        return $this;
163
    }
164
165
    /**
166
     * Build the array with the builder inside
167
     * a Closure, it has more flexibility for
168
     * the generation of your array.
169
     *
170
     *
171
     * @param callable|Closure $closure
172
     * @return array|false
173
     * @throws NotificationBuilderException
174
     */
175
    public function raw(Closure $closure)
176
    {
177
        $builder = $closure($this);
178
179
        if (! is_null($builder)) {
180
            return $this->toArray();
181
        }
182
183
        return false;
184
    }
185
186
    /**
187
     * Loop the data for create
188
     * multi notifications array.
189
     *
190
     * @param          $dataToIterate
191
     * @param  Closure $builder
192
     * @return $this
193
     * @throws \Fenos\Notifynder\Exceptions\IterableIsEmptyException
194
     * @throws \Fenos\Notifynder\Exceptions\EntityNotIterableException
195
     */
196
    public function loop($dataToIterate, Closure $builder)
197
    {
198
        if (! $this->isIterable($dataToIterate)) {
199
            throw new EntityNotIterableException('The data passed must be iterable');
200
        }
201
        if (count($dataToIterate) <= 0) {
202
            throw new IterableIsEmptyException('The Iterable passed must contain at least one element');
203
        }
204
205
        $notifications = [];
206
207
        $newBuilder = new self($this->notifynderCategory);
208
209
        foreach ($dataToIterate as $key => $data) {
210
            $builder($newBuilder, $data, $key);
211
            $notifications[] = $newBuilder->toArray();
212
        }
213
214
        $this->notifications = $notifications;
215
216
        return $this;
217
    }
218
219
    /**
220
     * Compose the builder to
221
     * the array.
222
     *
223
     * @throws NotificationBuilderException
224
     * @return mixed
225
     */
226
    public function toArray()
227
    {
228
        $hasMultipleNotifications = $this->isMultidimensionalArray($this->notifications);
229
230
        // If the builder is handling a single notification
231
        // we will validate only it
232
        if (! $hasMultipleNotifications) {
233
            $this->setDate();
234
235
            if ($this->hasRequiredFields($this->notifications)) {
236
                return $this->notifications;
237
            }
238
        }
239
240
        // If has multiple Notifications
241
        // we will validate one by one
242
        if ($hasMultipleNotifications) {
243
            $allow = [];
244
245
            foreach ($this->notifications as $index => $notification) {
246
                $allow[$index] = $this->hasRequiredFields($notification);
247
            }
248
249
            if (! in_array(false, $allow)) {
250
                return $this->notifications;
251
            }
252
        }
253
254
        $error = 'The fields: '.implode(',', $this->getRequiredFields()).' are required';
255
        throw new NotificationBuilderException($error);
256
    }
257
258
    /**
259
     * Refresh the state of the notifications.
260
     */
261
    public function refresh()
262
    {
263
        $this->notifications = [];
264
265
        return $this;
266
    }
267
268
    /**
269
     * @param $var
270
     * @return bool
271
     */
272
    protected function isIterable($var)
273
    {
274
        return is_array($var) || $var instanceof Traversable;
275
    }
276
277
    /**
278
     * It set the entity who will do
279
     * the action of receive or
280
     * send.
281
     *
282
     * @param $from
283
     * @param $property
284
     * @return array
285
     */
286
    protected function setEntityAction($from, $property)
287
    {
288
        // Check if has the entity as parameter
289
        // it should be the firstOne
290
        if ($this->hasEntity($from)) {
291
            $this->isString($from[0]);
292
            $this->isNumeric($from[1]);
293
294
            $this->setBuilderData("{$property}_type", $from[0]);
295
            $this->setBuilderData("{$property}_id", $from[1]);
296
        } elseif ($from[0] instanceof Model) {
297
            $this->setBuilderData("{$property}_type", $from[0]->getMorphClass());
298
            $this->setBuilderData("{$property}_id", $from[0]->getKey());
299
        } else {
300
            $this->isNumeric($from[0]);
301
            $this->setBuilderData("{$property}_id", $from[0]);
302
        }
303
    }
304
305
    /**
306
     * If the values passed are 2 or more,
307
     * it means that you specified the entity
308
     * over then the id.
309
     *
310
     * @param  array $info
311
     * @return bool
312
     */
313
    protected function hasEntity(array $info)
314
    {
315
        return count($info) >= 2;
316
    }
317
318
    /**
319
     * Set date on the array.
320
     */
321
    protected function setDate()
322
    {
323
        $this->date = $data = Carbon::now();
0 ignored issues
show
Documentation Bug introduced by
It seems like $data = \Carbon\Carbon::now() of type object<Carbon\Carbon> is incompatible with the declared type string of property $date.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
324
325
        $this->setBuilderData('updated_at', $data);
326
        $this->setBuilderData('created_at', $data);
327
    }
328
329
    /**
330
     * @return string
331
     */
332
    protected function getDate()
333
    {
334
        return $this->date;
335
    }
336
337
    /**
338
     * Set builder Data.
339
     *
340
     * @param $field
341
     * @param $data
342
     */
343
    public function setBuilderData($field, $data)
344
    {
345
        return $this->notifications[$field] = $data;
346
    }
347
348
    /**
349
     * @param mixed $offset
350
     * @return bool
351
     */
352
    public function offsetExists($offset)
353
    {
354
        return array_key_exists($offset, $this->notifications);
355
    }
356
357
    /**
358
     * @param mixed $offset
359
     * @return mixed
360
     */
361
    public function offsetGet($offset)
362
    {
363
        return $this->notifications[$offset];
364
    }
365
366
    /**
367
     * @param mixed $offset
368
     * @param mixed $value
369
     */
370
    public function offsetSet($offset, $value)
371
    {
372
        if (method_exists($this, $offset)) {
373
            return $this->{$offset}($value);
374
        }
375
376
        if ($this->isRequiredField($offset)) {
377
            $this->notifications[$offset] = $value;
378
        }
379
    }
380
381
    /**
382
     * @param Repository $config
383
     */
384
    public function setConfig(Repository $config)
385
    {
386
        $this->config = $config;
387
    }
388
389
    /**
390
     * @param mixed $offset
391
     * @return null
392
     */
393
    public function offsetUnset($offset)
394
    {
395
        unset($this->notifications[$offset]);
396
    }
397
}
398