Completed
Push — issue-103 ( 69239e...9bd575 )
by
unknown
03:24
created

NotifynderBuilder::offsetUnset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
c 3
b 2
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
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 sintax.
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
     * Build the array with the builder inside
153
     * a Closure, it has more flexibility for
154
     * the generation of your array.
155
     *
156
     *
157
     * @param callable|Closure $closure
158
     * @return array|false
159
     * @throws NotificationBuilderException
160
     */
161
    public function raw(Closure $closure)
162
    {
163
        $builder = $closure($this);
164
165
        if (! is_null($builder)) {
166
            return $this->toArray();
167
        }
168
169
        return false;
170
    }
171
172
    /**
173
     * Loop the datas for create
174
     * multi notifications array.
175
     *
176
     * @param          $dataToIterate
177
     * @param  Closure $builder
178
     * @return $this
179
     * @throws \Fenos\Notifynder\Exceptions\IterableIsEmptyException
180
     * @throws \Fenos\Notifynder\Exceptions\EntityNotIterableException
181
     */
182
    public function loop($dataToIterate, Closure $builder)
183
    {
184
        if ($this->isIterable($dataToIterate)) {
185
            if (count($dataToIterate) > 0) {
186
                $notifications = [];
187
188
                $newBuilder = new self($this->notifynderCategory);
189
190
                foreach ($dataToIterate as $key => $data) {
191
                    $builder($newBuilder, $data, $key);
192
                    $notifications[] = $newBuilder->toArray();
193
                }
194
195
                $this->notifications = $notifications;
196
197
                return $this;
198
            } else {
199
                throw new IterableIsEmptyException('The Iterable passed must contain at least one element');
200
            }
201
        } else {
202
            throw new EntityNotIterableException('The data passed must be itarable');
203
        }
204
    }
205
206
    /**
207
     * Compose the builder to
208
     * the array.
209
     *
210
     * @throws NotificationBuilderException
211
     * @return mixed
212
     */
213
    public function toArray()
214
    {
215
        $hasMultipleNotifications = $this->isMultidimensionalArray($this->notifications);
216
217
        // If the builder is handling a single notification
218
        // we will validate only it
219
        if (! $hasMultipleNotifications) {
220
            $this->setDate();
221
222
            if ($this->hasRequiredFields($this->notifications)) {
223
                return $this->notifications;
224
            }
225
        }
226
227
        // If has multiple Notifications
228
        // we will validate one by one
229
        if ($hasMultipleNotifications) {
230
            $allow = [];
231
232
            foreach ($this->notifications as $index => $notification) {
233
                $allow[$index] = $this->hasRequiredFields($notification);
234
            }
235
236
            if (! in_array(false, $allow)) {
237
                return $this->notifications;
238
            }
239
        }
240
241
        $error = 'The fields: '.implode(',', $this->getRequiredFields()).' are required';
242
        throw new NotificationBuilderException($error);
243
    }
244
245
    /**
246
     * Refresh the state of the notifications.
247
     */
248
    public function refresh()
249
    {
250
        $this->notifications = [];
251
252
        return $this;
253
    }
254
255
    /**
256
     * @param $var
257
     * @return bool
258
     */
259
    protected function isIterable($var)
260
    {
261
        return is_array($var) || $var instanceof Traversable;
262
    }
263
264
    /**
265
     * It set the entity who will do
266
     * the action of receive or
267
     * send.
268
     *
269
     * @param $from
270
     * @param $property
271
     * @return array
272
     */
273
    protected function setEntityAction($from, $property)
274
    {
275
        // Check if has the entity as parameter
276
        // it should be the firstOne
277
        if ($this->hasEntity($from)) {
278
            $this->isString($from[0]);
279
            $this->isNumeric($from[1]);
280
281
            $this->setBuilderData("{$property}_type", $from[0]);
282
            $this->setBuilderData("{$property}_id", $from[1]);
283
        } elseif ($from[0] instanceof Model) {
284
            $this->setBuilderData("{$property}_type", $from[0]->getMorphClass());
285
            $this->setBuilderData("{$property}_id", $from[0]->getKey());
286
        } else {
287
            $this->isNumeric($from[0]);
288
            $this->setBuilderData("{$property}_id", $from[0]);
289
        }
290
    }
291
292
    /**
293
     * If the values passed are 2 or more,
294
     * it means that you spefied the entity
295
     * over then the id.
296
     *
297
     * @param  array $info
298
     * @return bool
299
     */
300
    protected function hasEntity(array $info)
301
    {
302
        return count($info) >= 2;
303
    }
304
305
    /**
306
     * Set date on the array.
307
     */
308
    protected function setDate()
309
    {
310
        $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...
311
312
        $this->setBuilderData('updated_at', $data);
313
        $this->setBuilderData('created_at', $data);
314
    }
315
316
    /**
317
     * @return string
318
     */
319
    protected function getDate()
320
    {
321
        return $this->date;
322
    }
323
324
    /**
325
     * Set builder Data.
326
     *
327
     * @param $field
328
     * @param $data
329
     */
330
    public function setBuilderData($field, $data)
331
    {
332
        return $this->notifications[$field] = $data;
333
    }
334
335
    /**
336
     * @param mixed $offset
337
     * @return bool
338
     */
339
    public function offsetExists($offset)
340
    {
341
        return array_key_exists($offset, $this->notifications);
342
    }
343
344
    /**
345
     * @param mixed $offset
346
     * @return mixed
347
     */
348
    public function offsetGet($offset)
349
    {
350
        return $this->notifications[$offset];
351
    }
352
353
    /**
354
     * @param mixed $offset
355
     * @param mixed $value
356
     */
357
    public function offsetSet($offset, $value)
358
    {
359
        if (method_exists($this, $offset)) {
360
            return $this->{$offset}($value);
361
        }
362
363
        if ($this->isRequiredField($offset)) {
364
            $this->notifications[$offset] = $value;
365
        }
366
    }
367
368
    /**
369
     * @param Repository $config
370
     */
371
    public function setConfig(Repository $config)
372
    {
373
        $this->config = $config;
374
    }
375
376
    /**
377
     * @param mixed $offset
378
     * @return null
379
     */
380
    public function offsetUnset($offset)
381
    {
382
        unset($this->notifications[$offset]);
383
    }
384
}
385