Completed
Pull Request — master (#211)
by Ryan
07:26
created

EloquentModel::offsetExists()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 2
eloc 2
nc 2
nop 1
1
<?php namespace Anomaly\Streams\Platform\Model;
2
3
use Anomaly\Streams\Platform\Collection\CacheCollection;
4
use Anomaly\Streams\Platform\Traits\Hookable;
5
use Illuminate\Contracts\Support\Arrayable;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\Collection;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Foundation\Bus\DispatchesJobs;
10
11
/**
12
 * Class EloquentModel
13
 *
14
 * @link    http://anomaly.is/streams-platform
15
 * @author  AnomalyLabs, Inc. <[email protected]>
16
 * @author  Ryan Thompson <[email protected]>
17
 * @package Anomaly\Streams\Platform\Model
18
 */
19
class EloquentModel extends Model implements Arrayable
20
{
21
22
    use DispatchesJobs;
23
    use Hookable;
24
25
    /**
26
     * Disable timestamps for this model.
27
     *
28
     * @var bool
29
     */
30
    public $timestamps = false;
31
32
    /**
33
     * Translatable attributes.
34
     *
35
     * @var array
36
     */
37
    protected $translatedAttributes = [];
38
39
    /**
40
     * The number of minutes to cache query results.
41
     *
42
     * @var null|false|int
43
     */
44
    protected $ttl = false;
45
46
    /**
47
     * The attributes that are
48
     * not mass assignable. Let upper
49
     * models handle this themselves.
50
     *
51
     * @var array
52
     */
53
    protected $guarded = [];
54
55
    /**
56
     * The title key.
57
     *
58
     * @var string
59
     */
60
    protected $titleKey = 'id';
61
62
    /**
63
     * Observable model events.
64
     *
65
     * @var array
66
     */
67
    protected $observables = [
68
        'updatingMultiple',
69
        'updatedMultiple',
70
        'deletingMultiple',
71
        'deletedMultiple'
72
    ];
73
74
    /**
75
     * Runtime cache.
76
     *
77
     * @var array
78
     */
79
    protected $cache = [];
80
81
    /**
82
     * Get the ID.
83
     *
84
     * @return integer
85
     */
86
    public function getId()
87
    {
88
        return $this->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
89
    }
90
91
    /**
92
     * Return the object's ETag fingerprint.
93
     *
94
     * @return string
95
     */
96
    public function etag()
97
    {
98
        return md5(get_class($this) . json_encode($this->toArray()));
99
    }
100
101
    /**
102
     * Alias for $this->setTtl($ttl)
103
     *
104
     * @param $ttl
105
     * @return EloquentModel
106
     */
107
    public function cache($ttl)
108
    {
109
        return $this->setTtl($ttl);
110
    }
111
112
    /**
113
     * Fire a model event.
114
     *
115
     * @param $event
116
     * @return mixed
117
     */
118
    public function fireEvent($event)
119
    {
120
        return $this->fireModelEvent($event);
121
    }
122
123
    /**
124
     * Return a new collection class with our models.
125
     *
126
     * @param  array $items
127
     * @return Collection
128
     */
129 View Code Duplication
    public function newCollection(array $items = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
130
    {
131
        $collection = substr(get_class($this), 0, -5) . 'Collection';
132
133
        if (class_exists($collection)) {
134
            return new $collection($items);
135
        }
136
137
        return new EloquentCollection($items);
138
    }
139
140
    /**
141
     * Return the translatable flag.
142
     *
143
     * @return bool
144
     */
145
    public function isTranslatable()
146
    {
147
        return isset($this->translationModel);
148
    }
149
150
    /**
151
     * Set the translatable flag.
152
     *
153
     * @param $translatable
154
     * @return $this
155
     */
156
    public function setTranslatable($translatable)
157
    {
158
        $this->translatable = $translatable;
0 ignored issues
show
Documentation introduced by
The property translatable does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
159
160
        return $this;
161
    }
162
163
    /**
164
     * Set the ttl.
165
     *
166
     * @param  $ttl
167
     * @return $this
168
     */
169
    public function setTtl($ttl)
170
    {
171
        $this->ttl = $ttl;
172
173
        return $this;
174
    }
175
176
    /**
177
     * Get the ttl.
178
     *
179
     * @return int|mixed
180
     */
181
    public function getTtl()
182
    {
183
        return $this->ttl;
184
    }
185
186
    /**
187
     * Get cache collection key.
188
     *
189
     * @return string
190
     */
191
    public function getCacheCollectionKey()
192
    {
193
        return get_called_class();
194
    }
195
196
    /**
197
     * Get the model title.
198
     *
199
     * @return mixed
200
     */
201
    public function getTitle()
202
    {
203
        return $this->{$this->getTitleName()};
204
    }
205
206
    /**
207
     * Get the title key.
208
     *
209
     * @return string
210
     */
211
    public function getTitleName()
212
    {
213
        return $this->titleName ?: 'id';
0 ignored issues
show
Documentation introduced by
The property titleName does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
214
    }
215
216
    /**
217
     * Return if a row is deletable or not.
218
     *
219
     * @return bool
220
     */
221
    public function isDeletable()
222
    {
223
        return true;
224
    }
225
226
    /**
227
     * Return if the model is restorable or not.
228
     *
229
     * @return bool
230
     */
231
    public function isRestorable()
232
    {
233
        return true;
234
    }
235
236
    /**
237
     * Return whether the model is being
238
     * force deleted or not.
239
     *
240
     * @return bool
241
     */
242
    public function isForceDeleting()
243
    {
244
        return isset($this->forceDeleting) && $this->forceDeleting == true;
0 ignored issues
show
Documentation introduced by
The property forceDeleting does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
245
    }
246
247
    /**
248
     * Flush the model's cache.
249
     *
250
     * @return $this
251
     */
252
    public function flushCache()
253
    {
254
        (new CacheCollection())->setKey($this->getCacheCollectionKey())->flush();
255
256
        return $this;
257
    }
258
259
    /**
260
     * Get a new query builder for the model's table.
261
     *
262
     * @return \Illuminate\Database\Eloquent\Builder
263
     */
264 View Code Duplication
    public function newQuery()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
    {
266
        $builder = new EloquentQueryBuilder($this->newBaseQueryBuilder());
267
268
        // Once we have the query builders, we will set the model instances so the
269
        // builder can easily access any information it may need from the model
270
        // while it is constructing and executing various queries against it.
271
        $builder->setModel($this)->with($this->with);
272
273
        return $this->applyGlobalScopes($builder);
274
    }
275
276
    /*
277
     * Alias for getTranslation()
278
     */
279
    public function translate($locale = null, $withFallback = false)
280
    {
281
        return $this->getTranslation($locale, $withFallback);
282
    }
283
284
    /*
285
     * Alias for getTranslation()
286
     */
287
    public function translateOrDefault($locale)
288
    {
289
        return $this->getTranslation($locale, true) ?: $this;
290
    }
291
292
    /*
293
     * Alias for getTranslationOrNew()
294
     */
295
    public function translateOrNew($locale)
296
    {
297
        return $this->getTranslationOrNew($locale);
298
    }
299
300
    /**
301
     * Get related translations.
302
     *
303
     * @return EloquentCollection
304
     */
305
    public function getTranslations()
306
    {
307
        foreach ($translations = $this->translations()->get() as $translation) {
308
            $translation->setRelation('parent', $this);
309
        }
310
311
        return $translations;
312
    }
313
314
    /**
315
     * @param null      $locale
316
     * @param bool|null $withFallback
317
     * @return Model|null
318
     */
319
    public function getTranslation($locale = null, $withFallback = false)
320
    {
321
        $locale = $locale ?: $this->getFallbackLocale();
322
323
        if ($translation = $this->getTranslationByLocaleKey($locale)) {
324
            return $translation;
325
        } elseif ($withFallback
326
            && $this->getFallbackLocale()
327
            && $this->getTranslationByLocaleKey($this->getFallbackLocale())
328
        ) {
329
            return $this->getTranslationByLocaleKey($this->getFallbackLocale());
330
        }
331
332
        return null;
333
    }
334
335
    public function hasTranslation($locale = null)
336
    {
337
        $locale = $locale ?: $this->getFallbackLocale();
338
339 View Code Duplication
        foreach ($this->translations as $translation) {
0 ignored issues
show
Documentation introduced by
The property translations does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
340
341
            $translation->setRelation('parent', $this);
342
343
            if ($translation->getAttribute($this->getLocaleKey()) == $locale) {
344
                return true;
345
            }
346
        }
347
348
        return false;
349
    }
350
351
    /**
352
     * Get the translation model.
353
     *
354
     * @return EloquentModel
355
     */
356
    public function getTranslationModel()
357
    {
358
        return new $this->translationModel;
0 ignored issues
show
Documentation introduced by
The property translationModel does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
359
    }
360
361
    /**
362
     * Get the translation model name.
363
     *
364
     * @return string
365
     */
366
    public function getTranslationModelName()
367
    {
368
        return $this->translationModel;
0 ignored issues
show
Documentation introduced by
The property translationModel does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
369
    }
370
371
    /**
372
     * Get the translation table name.
373
     *
374
     * @return string
375
     */
376
    public function getTranslationTableName()
377
    {
378
        $model = $this->getTranslationModel();
379
380
        return $model->getTableName();
381
    }
382
383
    public function getTranslationModelNameDefault()
384
    {
385
        return get_class($this) . 'Translation';
386
    }
387
388
    public function getRelationKey()
389
    {
390
        return $this->translationForeignKey ?: $this->getForeignKey();
0 ignored issues
show
Documentation introduced by
The property translationForeignKey does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
391
    }
392
393
    public function getLocaleKey()
394
    {
395
        return $this->localeKey ?: 'locale';
0 ignored issues
show
Documentation introduced by
The property localeKey does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
396
    }
397
398
    public function translations()
399
    {
400
        return $this->hasMany($this->getTranslationModelName(), $this->getRelationKey());
401
    }
402
403
    public function getAttribute($key)
404
    {
405
        if ($this->isTranslatedAttribute($key)) {
406
            if ($this->getTranslation() === null) {
407
                return null;
408
            }
409
410
            $translation = $this->getTranslation();
411
412
            $translation->setRelation('parent', $this);
413
414
            return $translation->$key;
415
        }
416
417
        return parent::getAttribute($key);
418
    }
419
420
    public function setAttribute($key, $value)
421
    {
422
        if (in_array($key, $this->translatedAttributes)) {
423
            $this->getTranslationOrNew(config('app.locale'))->$key = $value;
424
        } else {
425
            parent::setAttribute($key, $value);
426
        }
427
    }
428
429
    /**
430
     * Save the model.
431
     *
432
     * We have some customization here to
433
     * accommodate translations. First sa
434
     * then save translations is translatable.
435
     *
436
     * @param array $options
437
     * @return bool
438
     */
439
    public function save(array $options = array())
440
    {
441
        if (!$this->getTranslationModelName()) {
442
            return $this->saveModel($options);
443
        }
444
445
        if ($this->exists) {
446
447
            if (count($this->getDirty()) > 0) {
448
449
                // If $this->exists and dirty, $this->saveModel() has to return true. If not,
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
450
                // an error has occurred. Therefore we shouldn't save the translations.
451
                if ($this->saveModel($options)) {
452
                    return $this->saveTranslations();
453
                }
454
455
                return false;
456
            } else {
457
458
                // If $this->exists and not dirty, $this->saveModel() skips saving and returns
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
459
                // false. So we have to save the translations
460
                return $this->saveTranslations();
461
            }
462
        } elseif ($this->saveModel($options)) {
463
464
            // We save the translations only if the instance is saved in the database.
465
            return $this->saveTranslations();
466
        }
467
468
        return false;
469
    }
470
471
    /**
472
     * Save the model to the database.
473
     *
474
     * This is a direct port from Eloquent
475
     * with the only exception being that if
476
     * the model is translatable it will NOT
477
     * fire the saved event. The saveTranslations
478
     * method will do that instead.
479
     *
480
     * @param  array $options
481
     * @return bool
482
     */
483
    public function saveModel(array $options = array())
484
    {
485
        $query = $this->newQueryWithoutScopes();
486
487
        // If the "saving" event returns false we'll bail out of the save and return
488
        // false, indicating that the save failed. This provides a chance for any
489
        // listeners to cancel save operations if validations fail or whatever.
490
        if ($this->fireModelEvent('saving') === false) {
491
            return false;
492
        }
493
494
        // If the model already exists in the database we can just update our record
495
        // that is already in this database using the current IDs in this "where"
496
        // clause to only update this model. Otherwise, we'll just insert them.
497
        if ($this->exists) {
498
            $saved = $this->performUpdate($query, $options);
499
        }
500
501
        // If the model is brand new, we'll insert it into our database and set the
502
        // ID attribute on the model to the value of the newly inserted row's ID
503
        // which is typically an auto-increment value managed by the database.
504
        else {
505
            $saved = $this->performInsert($query, $options);
506
        }
507
508
        if ($saved && !$this->isTranslatable()) {
509
            $this->finishSave($options);
510
        }
511
512
        return $saved;
513
    }
514
515
    /**
516
     * Save translations to the database.
517
     *
518
     * @return bool
519
     */
520 View Code Duplication
    protected function saveTranslations()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
521
    {
522
        $saved = true;
523
524
        foreach ($this->translations as $translation) {
0 ignored issues
show
Documentation introduced by
The property translations does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
525
526
            $translation->setRelation('parent', $this);
527
528
            /* @var EloquentModel $translation */
529
            if ($saved && $this->isTranslationDirty($translation)) {
530
531
                $translation->setAttribute($this->getRelationKey(), $this->getKey());
532
533
                $saved = $translation->save();
534
            }
535
        }
536
537
        $this->finishSave([]);
538
539
        return $saved;
540
    }
541
542
    protected function getTranslationOrNew($locale)
543
    {
544
        if (($translation = $this->getTranslation($locale, false)) === null) {
545
            $translation = $this->getNewTranslation($locale);
546
        }
547
548
        return $translation;
549
    }
550
551
    public function fill(array $attributes)
552
    {
553
        foreach ($attributes as $key => $values) {
554
            if (is_array($values) && $this->isKeyALocale($key)) {
555
                foreach ($values as $translationAttribute => $translationValue) {
556
                    if ($this->alwaysFillable() || $this->isFillable($translationAttribute)) {
557
                        $this->getTranslationOrNew($key)->$translationAttribute = $translationValue;
558
                    }
559
                }
560
                unset($attributes[$key]);
561
            }
562
        }
563
564
        return parent::fill($attributes);
565
    }
566
567
    private function getTranslationByLocaleKey($key)
568
    {
569 View Code Duplication
        foreach ($this->translations as $translation) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Documentation introduced by
The property translations does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
570
571
            $translation->setRelation('parent', $this);
572
573
            if ($translation->getAttribute($this->getLocaleKey()) == $key) {
574
                return $translation;
575
            }
576
        }
577
578
        return null;
579
    }
580
581
    public function isTranslatedAttribute($key)
582
    {
583
        return in_array($key, $this->translatedAttributes);
584
    }
585
586
    protected function isTranslationAttribute($key)
587
    {
588
        return in_array($key, $this->translatedAttributes);
589
    }
590
591
    protected function isKeyALocale($key)
592
    {
593
        return config('streams::locales.supported.' . $key) !== null;
594
    }
595
596
    protected function isTranslationDirty(Model $translation)
597
    {
598
        $dirtyAttributes = $translation->getDirty();
599
        unset($dirtyAttributes[$this->getLocaleKey()]);
600
601
        return count($dirtyAttributes) > 0;
602
    }
603
604 View Code Duplication
    public function getNewTranslation($locale)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
605
    {
606
        $modelName = $this->getTranslationModelName();
607
608
        /* @var EloquentModel $translation */
609
        $translation = new $modelName;
610
611
        $translation->setRelation('parent', $this);
612
613
        $translation->setAttribute($this->getLocaleKey(), $locale);
614
        $translation->setAttribute($this->getRelationKey(), $this->getKey());
615
616
        $this->translations->add($translation);
0 ignored issues
show
Documentation introduced by
The property translations does not exist on object<Anomaly\Streams\P...rm\Model\EloquentModel>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
617
618
        return $translation;
619
    }
620
621
    public function scopeTranslatedIn(Builder $query, $locale)
622
    {
623
        return $query->whereHas(
624
            'translations',
625
            function (Builder $q) use ($locale) {
626
                $q->where($this->getLocaleKey(), '=', $locale);
627
            }
628
        );
629
    }
630
631
    public function scopeTranslated(Builder $query)
632
    {
633
        return $query->has('translations');
634
    }
635
636
    /**
637
     * Return unguarded attributes.
638
     *
639
     * @return array
640
     */
641
    public function getUnguardedAttributes()
642
    {
643
        foreach ($attributes = $this->getAttributes() as $attribute => $value) {
644
            $attributes[$attribute] = $this->{$attribute};
645
        }
646
647
        return array_diff_key($attributes, array_flip($this->getGuarded()));
648
    }
649
650
    /**
651
     * Get the fallback locale.
652
     *
653
     * @return string
654
     */
655
    protected function getFallbackLocale()
656
    {
657
        if (isset($this->cache['fallback_locale'])) {
658
            return $this->cache['fallback_locale'];
659
        }
660
661
        return $this->cache['fallback_locale'] = config('app.fallback_locale');
662
    }
663
664
    /**
665
     * This is to keep consistency with the
666
     * entry interface above us.
667
     *
668
     * @return string
669
     */
670
    public function getTableName()
671
    {
672
        return $this->getTable();
673
    }
674
675
    /**
676
     * Return if the entry is trashed or not.
677
     *
678
     * @return bool
679
     */
680
    public function trashed()
681
    {
682
        return parent::trashed();
683
    }
684
685
    public function toArray()
686
    {
687
        $attributes = $this->attributesToArray();
688
689
        foreach ($this->translatedAttributes as $field) {
690
            if ($translation = $this->getTranslation()) {
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $translation is correct as $this->getTranslation() (which targets Anomaly\Streams\Platform...Model::getTranslation()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
691
                $attributes[$field] = $translation->$field;
692
            }
693
        }
694
695
        return $attributes;
696
    }
697
698
    private function alwaysFillable()
699
    {
700
        return false;
701
    }
702
    
703
    /**
704
     * Determine if the given attribute exists.
705
     * Make sure to skip where there could be an
706
     * issue with relational "looking" properties.
707
     *
708
     * @param  mixed $offset
709
     * @return bool
710
     */
711
    public function offsetExists($offset)
712
    {
713
        return !method_exists($this, $offset) && isset($this->$offset);
714
    }
715
716
    public function __get($key)
717
    {
718
        if ($this->hasHook($key)) {
719
            return $this->call($key, []);
720
        }
721
722
        return parent::__get($key); // TODO: Change the autogenerated stub
723
    }
724
725
    public function __call($method, $parameters)
726
    {
727
        if ($this->hasHook($hook = snake_case($method))) {
728
            return $this->call($hook, $parameters);
729
        }
730
731
        return parent::__call($method, $parameters);
732
    }
733
734
    /**
735
     * Check if an attribute exists.
736
     *
737
     * @param string $key
738
     * @return bool
739
     */
740
    public function __isset($key)
741
    {
742
        return (in_array($key, $this->translatedAttributes) || parent::__isset($key));
743
    }
744
745
    /**
746
     * Return the string form of the model.
747
     *
748
     * @return string
749
     */
750
    function __toString()
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...
751
    {
752
        return json_encode($this->toArray());
753
    }
754
}
755