Completed
Pull Request — master (#93)
by
unknown
02:11
created

NotifynderBuilder::setBuilderData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 1
Metric Value
c 3
b 2
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 2
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 InvalidArgumentException;
8
use Traversable;
9
use Closure;
10
11
/**
12
 * Class NotifynderBuilder
13
 *
14
 * The builder is a main factor of Notifynder, it make sure
15
 * that the notification is decorated and validated before
16
 * are passed to the Sender Classes. It also helps you to
17
 * create multi notifications with the same simple and easy sintax.
18
 *
19
 * @package Fenos\Notifynder\Builder
20
 */
21
class NotifynderBuilder implements ArrayAccess
22
{
23
    use BuilderRules;
24
25
    /**
26
     * @var string notification to store
27
     */
28
    public $date;
29
30
    /**
31
     * Builder data
32
     *
33
     * @var array
34
     */
35
    protected $notifications = [];
36
37
    /**
38
     * @var NotifynderCategory
39
     */
40
    private $notifynderCategory;
41
42
    /**
43
     * @param NotifynderCategory $notifynderCategory
44
     */
45
    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...
46
    {
47
        $this->notifynderCategory = $notifynderCategory;
48
    }
49
50
   /**
51
     * Start with a fresh empty notification
52
     *
53
     * @return $this
54
     */
55
    public function begin() 
56
    {
57
        $this->notifications = [];
58
59
        return $this;
60
    }
61
62
    /**
63
     * Set who will send the notification
64
     *
65
     * @return $this
66
     */
67
    public function from()
68
    {
69
        $from = func_get_args();
70
71
        $this->setEntityAction($from, 'from');
72
73
        return $this;
74
    }
75
76
    /**
77
     * Set who will receive the notification
78
     *
79
     * @return $this
80
     */
81
    public function to()
82
    {
83
        $from = func_get_args();
84
85
        $this->setEntityAction($from, 'to');
86
87
        return $this;
88
    }
89
90
    /**
91
     * Set the url of the notification
92
     *
93
     * @param $url
94
     * @return $this
95
     */
96
    public function url($url)
97
    {
98
        $this->isString($url);
99
100
        $this->setBuilderData('url', $url);
101
102
        return $this;
103
    }
104
105
    /**
106
     * Set expire time
107
     *
108
     * @param $datetime
109
     * @return $this
110
     */
111
    public function expire($datetime)
112
    {
113
        $this->isCarbon($datetime);
114
        $this->setBuilderData('expire_time', $datetime);
115
116
        return $this;
117
    }
118
119
    /**
120
     * Set Category and covert it, to the id
121
     * if name of it given
122
     *
123
     * @param $category
124
     * @return $this
125
     */
126
    public function category($category)
127
    {
128
        if (!is_numeric($category)) {
129
            $category = $this->notifynderCategory
130
                            ->findByName($category)->id;
131
        }
132
133
        $this->setBuilderData('category_id', $category);
134
135
        return $this;
136
    }
137
138
    /**
139
     * Set extra value
140
     *
141
     * @param $extra
142
     * @return $this
143
     */
144
    public function extra(array $extra = [])
145
    {
146
        $this->isReadyArrToFormatInJson($extra);
147
148
        $jsonExtraValues = json_encode($extra);
149
150
        $this->setBuilderData('extra', $jsonExtraValues);
151
152
        return $this;
153
    }
154
155
    /**
156
     * Build the array with the builder inside
157
     * a Closure, it has more flexibility for
158
     * the generation of your array
159
     *
160
     *
161
     * @param callable|Closure $closure
162
     * @return array|false
163
     * @throws NotificationBuilderException
164
     */
165
    public function raw(Closure $closure)
166
    {
167
        $builder = $closure($this);
168
169
        if (! is_null($builder)) {
170
            return $this->toArray();
171
        }
172
173
        return false;
174
    }
175
176
    /**
177
     * Loop the datas for create
178
     * multi notifications array
179
     *
180
     * @param          $dataToIterate
181
     * @param  Closure $builder
182
     * @return $this
183
     * @throws NotificationBuilderException
184
     */
185
    public function loop($dataToIterate, Closure $builder)
186
    {
187
        if ($this->isIterable($dataToIterate)) {
188
            $notifications = [];
189
190
            $newBuilder = new self($this->notifynderCategory);
191
192
            foreach ($dataToIterate as $key => $data) {
193
                $builder($newBuilder, $data, $key);
194
                $notifications[] = $newBuilder->toArray();
195
            }
196
197
            $this->notifications = $notifications;
198
            return $this;
199
        }
200
201
        $error = "The data passed must be itarable";
202
        throw new InvalidArgumentException($error);
203
    }
204
205
    /**
206
     * Compose the builder to
207
     * the array
208
     *
209
     * @throws NotificationBuilderException
210
     * @return mixed
211
     */
212
    public function toArray()
213
    {
214
        $hasMultipleNotifications = $this->isMultidimensionalArray($this->notifications);
215
216
        // If the builder is handling a single notification
217
        // we will validate only it
218
        if (! $hasMultipleNotifications) {
219
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
231
            $allow = [];
232
233
            foreach($this->notifications as $index => $notification) {
234
                $allow[$index] = $this->hasRequiredFields($notification);
235
            }
236
237
            if (! in_array(false,$allow)) {
238
                return $this->notifications;
239
            }
240
        }
241
242
        $error = "The fields:  'from_id' , 'to_id', 'url', 'category_id' are required";
243
        throw new NotificationBuilderException($error);
244
    }
245
246
    /**
247
     * @param $var
248
     * @return bool
249
     */
250
    protected function isIterable($var)
251
    {
252
        return (is_array($var) || $var instanceof Traversable);
253
    }
254
255
    /**
256
     * It set the entity who will do
257
     * the action of receive or
258
     * send
259
     *
260
     * @param $from
261
     * @param $property
262
     * @return array
263
     */
264
    protected function setEntityAction($from, $property)
265
    {
266
        // Check if has the entity as parameter
267
        // it should be the firstOne
268
        if ($this->hasEntity($from)) {
269
            $this->isString($from[0]);
270
            $this->isNumeric($from[1]);
271
272
            $this->setBuilderData("{$property}_type", $from[0]);
273
            $this->setBuilderData("{$property}_id", $from[1]);
274
        } else {
275
            $this->isNumeric($from[0]);
276
            $this->setBuilderData("{$property}_id", $from[0]);
277
        }
278
    }
279
280
    /**
281
     * If the values passed are 2 or more,
282
     * it means that you spefied the entity
283
     * over then the id
284
     *
285
     * @param  array $info
286
     * @return bool
287
     */
288
    protected function hasEntity(array $info)
289
    {
290
        return count($info) >= 2;
291
    }
292
293
    /**
294
     * Set date on the array
295
     */
296
    protected function setDate()
297
    {
298
        $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...
299
300
        $this->setBuilderData('updated_at', $data);
301
        $this->setBuilderData('created_at', $data);
302
    }
303
304
    /**
305
     * @return string
306
     */
307
    protected function getDate()
308
    {
309
        return $this->date;
310
    }
311
312
    /**
313
     * Set builder Data
314
     *
315
     * @param $field
316
     * @param $data
317
     */
318
    protected function setBuilderData($field, $data)
319
    {
320
        return $this->notifications[$field] = $data;
321
    }
322
323
324
    /**
325
     * @param mixed $offset
326
     * @return bool
327
     */
328
    public function offsetExists($offset)
329
    {
330
        return array_key_exists($offset,$this->notifications);
331
    }
332
333
334
    /**
335
     * @param mixed $offset
336
     * @return mixed
337
     */
338
    public function offsetGet($offset)
339
    {
340
        return $this->notifications[$offset];
341
    }
342
343
344
    /**
345
     * @param mixed $offset
346
     * @param mixed $value
347
     */
348
    public function offsetSet($offset, $value)
349
    {
350
        if (method_exists($this, $offset)) {
351
352
            return $this->{$offset}($value);
353
        }
354
355
        if ($this->isRequiredField($offset)) {
356
            $this->notifications[$offset] = $value;
357
        }
358
    }
359
360
361
    /**
362
     * @param mixed $offset
363
     * @return null
364
     */
365
    public function offsetUnset($offset)
366
    {
367
        unset($this->notifications[$offset]);
368
}}
369