Completed
Pull Request — master (#111)
by
unknown
04:36 queued 02:14
created

NotifynderBuilder::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php namespace Fenos\Notifynder\Builder;
2
3
use ArrayAccess;
4
use Carbon\Carbon;
5
use Fenos\Notifynder\Contracts\NotifynderCategory;
6
use Fenos\Notifynder\Exceptions\NotificationBuilderException;
7
use Illuminate\Contracts\Config\Repository;
8
use Illuminate\Database\Eloquent\Model;
9
use InvalidArgumentException;
10
use Traversable;
11
use Closure;
12
13
/**
14
 * Class NotifynderBuilder
15
 *
16
 * The builder is a main factor of Notifynder, it make sure
17
 * that the notification is decorated and validated before
18
 * are passed to the Sender Classes. It also helps you to
19
 * create multi notifications with the same simple and easy sintax.
20
 *
21
 * @package Fenos\Notifynder\Builder
22
 */
23
class NotifynderBuilder implements ArrayAccess
24
{
25
    use BuilderRules;
26
27
    /**
28
     * @var string notification to store
29
     */
30
    public $date;
31
32
    /**
33
     * Builder data
34
     *
35
     * @var array
36
     */
37
    protected $notifications = [];
38
39
    /**
40
     * @var Repository
41
     */
42
    protected $config;
43
44
    /**
45
     * @var NotifynderCategory
46
     */
47
    private $notifynderCategory;
48
49
    /**
50
     * @param NotifynderCategory $notifynderCategory
51
     */
52
    function __construct(NotifynderCategory $notifynderCategory)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
53
    {
54
        $this->notifynderCategory = $notifynderCategory;
55
    }
56
57
    /**
58
     * Set who will send the notification
59
     *
60
     * @return $this
61
     */
62
    public function from()
63
    {
64
        $from = func_get_args();
65
66
        $this->setEntityAction($from, 'from');
67
68
        return $this;
69
    }
70
71
    /**
72
     * Set who will receive the notification
73
     *
74
     * @return $this
75
     */
76
    public function to()
77
    {
78
        $from = func_get_args();
79
80
        $this->setEntityAction($from, 'to');
81
82
        return $this;
83
    }
84
85
    /**
86
     * Set the url of the notification
87
     *
88
     * @param $url
89
     * @return $this
90
     */
91
    public function url($url)
92
    {
93
        $this->isString($url);
94
95
        $this->setBuilderData('url', $url);
96
97
        return $this;
98
    }
99
100
    /**
101
     * Set expire time
102
     *
103
     * @param $datetime
104
     * @return $this
105
     */
106
    public function expire($datetime)
107
    {
108
        $this->isCarbon($datetime);
109
        $this->setBuilderData('expire_time', $datetime);
110
111
        return $this;
112
    }
113
114
    /**
115
     * Set Category and covert it, to the id
116
     * if name of it given
117
     *
118
     * @param $category
119
     * @return $this
120
     */
121
    public function category($category)
122
    {
123
        if (!is_numeric($category)) {
124
            $category = $this->notifynderCategory
125
                            ->findByName($category)->id;
126
        }
127
128
        $this->setBuilderData('category_id', $category);
129
130
        return $this;
131
    }
132
133
    /**
134
     * Set extra value
135
     *
136
     * @param $extra
137
     * @return $this
138
     */
139
    public function extra(array $extra = [])
140
    {
141
        $this->isReadyArrToFormatInJson($extra);
142
143
        $jsonExtraValues = json_encode($extra);
144
145
        $this->setBuilderData('extra', $jsonExtraValues);
146
147
        return $this;
148
    }
149
150
    /**
151
     * Build the array with the builder inside
152
     * a Closure, it has more flexibility for
153
     * the generation of your array
154
     *
155
     *
156
     * @param callable|Closure $closure
157
     * @return array|false
158
     * @throws NotificationBuilderException
159
     */
160
    public function raw(Closure $closure)
161
    {
162
        $builder = $closure($this);
163
164
        if (! is_null($builder)) {
165
            return $this->toArray();
166
        }
167
168
        return false;
169
    }
170
171
    /**
172
     * Loop the datas for create
173
     * multi notifications array
174
     *
175
     * @param          $dataToIterate
176
     * @param  Closure $builder
177
     * @return $this
178
     * @throws NotificationBuilderException
179
     */
180
    public function loop($dataToIterate, Closure $builder)
181
    {
182
        if ($this->isIterable($dataToIterate)) {
183
            $notifications = [];
184
185
            $newBuilder = new self($this->notifynderCategory);
186
187
            foreach ($dataToIterate as $key => $data) {
188
                $builder($newBuilder, $data, $key);
189
                $notifications[] = $newBuilder->toArray();
190
            }
191
192
            $this->notifications = $notifications;
193
            return $this;
194
        }
195
196
        $error = "The data passed must be itarable";
197
        throw new InvalidArgumentException($error);
198
    }
199
200
    /**
201
     * Compose the builder to
202
     * the array
203
     *
204
     * @throws NotificationBuilderException
205
     * @return mixed
206
     */
207
    public function toArray()
208
    {
209
        $hasMultipleNotifications = $this->isMultidimensionalArray($this->notifications);
210
211
        // If the builder is handling a single notification
212
        // we will validate only it
213
        if (! $hasMultipleNotifications) {
214
215
            $this->setDate();
216
217
            if ($this->hasRequiredFields($this->notifications)) {
218
                return $this->notifications;
219
            }
220
        }
221
222
        // If has multiple Notifications
223
        // we will validate one by one
224
        if ($hasMultipleNotifications) {
225
226
            $allow = [];
227
228
            foreach($this->notifications as $index => $notification) {
229
                $allow[$index] = $this->hasRequiredFields($notification);
230
            }
231
232
            if (! in_array(false,$allow)) {
233
                return $this->notifications;
234
            }
235
        }
236
237
        $error = "The fields: ".implode(',', $this->getRequiredFields())." are required";
238
        throw new NotificationBuilderException($error);
239
    }
240
241
    /**
242
     * Refresh the state of the notifications
243
     */
244
    public function refresh()
245
    {
246
        $this->notifications = [];
247
248
        return $this;
249
    }
250
251
    /**
252
     * @param $var
253
     * @return bool
254
     */
255
    protected function isIterable($var)
256
    {
257
        return (is_array($var) || $var instanceof Traversable);
258
    }
259
260
    /**
261
     * It set the entity who will do
262
     * the action of receive or
263
     * send
264
     *
265
     * @param $from
266
     * @param $property
267
     * @return array
268
     */
269
    protected function setEntityAction($from, $property)
270
    {
271
        // Check if has the entity as parameter
272
        // it should be the firstOne
273
        if ($this->hasEntity($from)) {
274
            $this->isString($from[0]);
275
            $this->isNumeric($from[1]);
276
277
            $this->setBuilderData("{$property}_type", $from[0]);
278
            $this->setBuilderData("{$property}_id", $from[1]);
279
        } elseif($from[0] instanceof Model) {
280
            $this->setBuilderData("{$property}_type", get_class($from[0]));
281
            $this->setBuilderData("{$property}_id", $from[0]->getKey());
282
        } else {
283
            $this->isNumeric($from[0]);
284
            $this->setBuilderData("{$property}_id", $from[0]);
285
        }
286
    }
287
288
    /**
289
     * If the values passed are 2 or more,
290
     * it means that you spefied the entity
291
     * over then the id
292
     *
293
     * @param  array $info
294
     * @return bool
295
     */
296
    protected function hasEntity(array $info)
297
    {
298
        return count($info) >= 2;
299
    }
300
301
    /**
302
     * Set date on the array
303
     */
304
    protected function setDate()
305
    {
306
        $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...
307
308
        $this->setBuilderData('updated_at', $data);
309
        $this->setBuilderData('created_at', $data);
310
    }
311
312
    /**
313
     * @return string
314
     */
315
    protected function getDate()
316
    {
317
        return $this->date;
318
    }
319
320
    /**
321
     * Set builder Data
322
     *
323
     * @param $field
324
     * @param $data
325
     */
326
    public function setBuilderData($field, $data)
327
    {
328
        return $this->notifications[$field] = $data;
329
    }
330
331
332
    /**
333
     * @param mixed $offset
334
     * @return bool
335
     */
336
    public function offsetExists($offset)
337
    {
338
        return array_key_exists($offset,$this->notifications);
339
    }
340
341
342
    /**
343
     * @param mixed $offset
344
     * @return mixed
345
     */
346
    public function offsetGet($offset)
347
    {
348
        return $this->notifications[$offset];
349
    }
350
351
352
    /**
353
     * @param mixed $offset
354
     * @param mixed $value
355
     */
356
    public function offsetSet($offset, $value)
357
    {
358
        if (method_exists($this, $offset)) {
359
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