Completed
Push — master ( ec3201...5305af )
by Ryan
08:02
created

StreamModel::getUnlockedAssignments()   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
dl 0
loc 6
rs 9.4285
c 1
b 0
f 1
cc 1
eloc 3
nc 1
nop 0
1
<?php namespace Anomaly\Streams\Platform\Stream;
2
3
use Anomaly\Streams\Platform\Addon\FieldType\FieldType;
4
use Anomaly\Streams\Platform\Addon\FieldType\FieldTypeQuery;
5
use Anomaly\Streams\Platform\Assignment\AssignmentCollection;
6
use Anomaly\Streams\Platform\Assignment\AssignmentModel;
7
use Anomaly\Streams\Platform\Assignment\AssignmentModelTranslation;
8
use Anomaly\Streams\Platform\Assignment\Contract\AssignmentInterface;
9
use Anomaly\Streams\Platform\Collection\CacheCollection;
10
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
11
use Anomaly\Streams\Platform\Entry\EntryModel;
12
use Anomaly\Streams\Platform\Field\Contract\FieldInterface;
13
use Anomaly\Streams\Platform\Field\FieldModel;
14
use Anomaly\Streams\Platform\Field\FieldModelTranslation;
15
use Anomaly\Streams\Platform\Model\EloquentCollection;
16
use Anomaly\Streams\Platform\Model\EloquentModel;
17
use Anomaly\Streams\Platform\Stream\Command\CompileStream;
18
use Anomaly\Streams\Platform\Stream\Command\MergeStreamConfig;
19
use Anomaly\Streams\Platform\Stream\Contract\StreamInterface;
20
use Robbo\Presenter\PresentableInterface;
21
use Robbo\Presenter\Robbo;
22
23
/**
24
 * Class StreamModel
25
 *
26
 * @link    http://anomaly.is/streams-platform
27
 * @author  AnomalyLabs, Inc. <[email protected]>
28
 * @author  Ryan Thompson <[email protected]>
29
 * @package Anomaly\Streams\Platform\Stream
30
 */
31
class StreamModel extends EloquentModel implements StreamInterface, PresentableInterface
32
{
33
34
    /**
35
     * The cache minutes.
36
     *
37
     * @var int
38
     */
39
    protected $cacheMinutes = 99999;
40
41
    /**
42
     * The foreign key for translations.
43
     *
44
     * @var string
45
     */
46
    protected $translationForeignKey = 'stream_id';
47
48
    /**
49
     * The translation model.
50
     *
51
     * @var string
52
     */
53
    protected $translationModel = 'Anomaly\Streams\Platform\Stream\StreamModelTranslation';
54
55
    /**
56
     * Translatable attributes.
57
     *
58
     * @var array
59
     */
60
    protected $translatedAttributes = [
61
        'name',
62
        'description'
63
    ];
64
65
    /**
66
     * The model's database table name.
67
     *
68
     * @var string
69
     */
70
    protected $table = 'streams_streams';
71
72
    /**
73
     * The streams store.
74
     *
75
     * @var StreamStore
76
     */
77
    protected static $store;
78
79
    /**
80
     * Boot the model.
81
     */
82
    protected static function boot()
83
    {
84
        self::$store = app('Anomaly\Streams\Platform\Stream\StreamStore');
85
86
        parent::boot();
87
    }
88
89
    /**
90
     * Make a Stream instance from the provided compile data.
91
     *
92
     * @param  array $data
93
     * @return StreamInterface
94
     */
95
    public function make(array $data)
96
    {
97
        $payload = $data;
98
99
        if ($stream = self::$store->get($data)) {
100
            return $stream;
101
        }
102
103
        $assignments = array();
104
105
        $streamModel        = new StreamModel();
106
        $streamTranslations = new EloquentCollection();
107
108
        $data['config'] = serialize(array_get($data, 'config', []));
109
110
        if ($translations = array_pull($data, 'translations')) {
111
            foreach ($translations as $attributes) {
112
113
                $translation = new StreamModelTranslation();
114
                $translation->setRawAttributes($attributes);
115
116
                $streamTranslations->push($translation);
117
            }
118
        }
119
120
        $streamModel->setRawAttributes($data);
121
122
        $streamModel->setRelation('translations', $streamTranslations);
123
124
        unset($this->translations);
125
126
        if (array_key_exists('assignments', $data)) {
127
128
            foreach ($data['assignments'] as $assignment) {
129
130
                if (isset($assignment['field'])) {
131
132
                    $assignment['field']['config'] = unserialize($assignment['field']['config']);
133
134
                    $fieldModel        = new FieldModel();
135
                    $fieldTranslations = new EloquentCollection();
136
137 View Code Duplication
                    if (isset($assignment['field']['translations'])) {
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...
138
                        foreach (array_pull($assignment['field'], 'translations') as $attributes) {
139
140
                            $translation = new FieldModelTranslation();
141
                            $translation->setRawAttributes($attributes);
142
143
                            $fieldTranslations->push($translation);
144
                        }
145
                    }
146
147
                    $assignment['field']['config'] = serialize($assignment['field']['config']);
148
149
                    $fieldModel->setRawAttributes($assignment['field']);
150
151
                    $fieldModel->setRelation('translations', $fieldTranslations);
152
153
                    unset($assignment['field']);
154
155
                    $assignmentModel        = new AssignmentModel();
156
                    $assignmentTranslations = new EloquentCollection();
157
158 View Code Duplication
                    if (isset($assignment['translations'])) {
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...
159
                        foreach (array_pull($assignment, 'translations') as $attributes) {
160
161
                            $translation = new AssignmentModelTranslation();
162
                            $translation->setRawAttributes($attributes);
163
164
                            $assignmentTranslations->push($translation);
165
                        }
166
                    }
167
168
                    $assignmentModel->setRawAttributes($assignment);
169
                    $assignmentModel->setRawAttributes($assignment);
170
171
                    $assignmentModel->setRelation('field', $fieldModel);
172
                    $assignmentModel->setRelation('stream', $streamModel);
173
                    $assignmentModel->setRelation('translations', $assignmentTranslations);
174
175
                    $assignments[] = $assignmentModel;
176
                }
177
            }
178
        }
179
180
        $assignmentsCollection = new AssignmentCollection($assignments);
181
182
        $streamModel->setRelation('assignments', $assignmentsCollection);
183
184
        $streamModel->assignments = $assignmentsCollection;
0 ignored issues
show
Documentation introduced by
The property assignments does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
185
186
        self::$store->put($payload, $streamModel);
187
188
        return $streamModel;
189
    }
190
191
    /**
192
     * Compile the entry models.
193
     *
194
     * @return mixed
195
     */
196
    public function compile()
197
    {
198
        $this->dispatch(new CompileStream($this));
199
    }
200
201
    /**
202
     * Flush the entry stream's cache.
203
     *
204
     * @return StreamInterface
205
     */
206
    public function flushCache()
207
    {
208
        (new CacheCollection())->setKey($this->getCacheCollectionKey())->flush();
209
        (new CacheCollection())->setKey((new FieldModel())->getCacheCollectionKey())->flush();
210
        (new CacheCollection())->setKey((new AssignmentModel())->getCacheCollectionKey())->flush();
211
212
        return $this;
213
    }
214
215
    /**
216
     * Because the stream record holds translatable data
217
     * we have a conflict. The streams table has translations
218
     * but not all streams are translatable. This helps avoid
219
     * the translatable conflict during specific procedures.
220
     *
221
     * @param  array $attributes
222
     * @return static
223
     */
224
    public static function create(array $attributes = [])
225
    {
226
        $model = parent::create($attributes);
227
228
        $model->saveTranslations();
229
230
        return $model;
231
    }
232
233
    /**
234
     * Get the ID.
235
     *
236
     * @return mixed
237
     */
238
    public function getId()
239
    {
240
        return $this->getKey();
241
    }
242
243
    /**
244
     * Get the namespace.
245
     *
246
     * @return mixed
247
     */
248
    public function getNamespace()
249
    {
250
        return $this->namespace;
0 ignored issues
show
Documentation introduced by
The property namespace does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
251
    }
252
253
    /**
254
     * Get the slug.
255
     *
256
     * @return mixed
257
     */
258
    public function getSlug()
259
    {
260
        return $this->slug;
0 ignored issues
show
Documentation introduced by
The property slug does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
261
    }
262
263
    /**
264
     * Get the prefix.
265
     *
266
     * @return mixed
267
     */
268
    public function getPrefix()
269
    {
270
        return $this->prefix;
0 ignored issues
show
Documentation introduced by
The property prefix does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
271
    }
272
273
    /**
274
     * Get the name.
275
     *
276
     * @return string
277
     */
278
    public function getName()
279
    {
280
        return $this->name;
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
281
    }
282
283
    /**
284
     * Get the description.
285
     *
286
     * @return string
287
     */
288
    public function getDescription()
289
    {
290
        return $this->description;
0 ignored issues
show
Documentation introduced by
The property description does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
291
    }
292
293
    /**
294
     * Get the config.
295
     *
296
     * @param null $key
297
     * @param null $default
298
     * @return mixed
299
     */
300
    public function getConfig($key = null, $default = null)
301
    {
302
        if (!isset($this->cache['cache'])) {
303
            $this->dispatch(new MergeStreamConfig($this));
304
        }
305
306
        $this->cache['cache'] = $this->config;
0 ignored issues
show
Documentation introduced by
The property config does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
307
308
        if ($key) {
309
            return array_get($this->config, $key, $default);
0 ignored issues
show
Documentation introduced by
The property config does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
310
        }
311
312
        return $this->config;
0 ignored issues
show
Documentation introduced by
The property config does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
313
    }
314
315
    /**
316
     * Merge configuration.
317
     *
318
     * @param array $config
319
     * @return $this
320
     */
321
    public function mergeConfig(array $config)
322
    {
323
        $this->config = array_merge($this->config, $config);
0 ignored issues
show
Documentation introduced by
The property config does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
Documentation introduced by
The property config does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
324
325
        return $this;
326
    }
327
328
    /**
329
     * Get the locked flag.
330
     *
331
     * @return bool
332
     */
333
    public function isLocked()
334
    {
335
        return $this->locked;
0 ignored issues
show
Documentation introduced by
The property locked does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
336
    }
337
338
    /**
339
     * Get the hidden flag.
340
     *
341
     * @return bool
342
     */
343
    public function isHidden()
344
    {
345
        return $this->hidden;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->hidden; (array) is incompatible with the return type declared by the interface Anomaly\Streams\Platform...reamInterface::isHidden of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
346
    }
347
348
    /**
349
     * Get the sortable flag.
350
     *
351
     * @return bool
352
     */
353
    public function isSortable()
354
    {
355
        return $this->sortable;
0 ignored issues
show
Documentation introduced by
The property sortable does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
356
    }
357
358
    /**
359
     * Get the trashable flag.
360
     *
361
     * @return bool
362
     */
363
    public function isTrashable()
364
    {
365
        return $this->trashable;
0 ignored issues
show
Documentation introduced by
The property trashable does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
366
    }
367
368
    /**
369
     * Get the translatable flag.
370
     *
371
     * @return bool
372
     */
373
    public function isTranslatable()
374
    {
375
        return $this->translatable;
0 ignored issues
show
Documentation introduced by
The property translatable does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
376
    }
377
378
    /**
379
     * Get the title column.
380
     *
381
     * @return mixed
382
     */
383
    public function getTitleColumn()
384
    {
385
        return $this->title_column;
0 ignored issues
show
Documentation introduced by
The property title_column does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
386
    }
387
388
    /**
389
     * Get the title field.
390
     *
391
     * @return null|FieldInterface
392
     */
393
    public function getTitleField()
394
    {
395
        return $this->getField($this->getTitleColumn());
396
    }
397
398
    /**
399
     * Get the related assignments.
400
     *
401
     * @return AssignmentCollection
402
     */
403
    public function getAssignments()
404
    {
405
        return $this->assignments;
0 ignored issues
show
Documentation introduced by
The property assignments does not exist on object<Anomaly\Streams\P...orm\Stream\StreamModel>. 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...
406
    }
407
408
    /**
409
     * Get the field slugs for assigned fields.
410
     *
411
     * @param null $prefix
412
     * @return array
413
     */
414
    public function getAssignmentFieldSlugs($prefix = null)
415
    {
416
        $assignments = $this->getAssignments();
417
418
        return $assignments->fieldSlugs($prefix);
419
    }
420
421
    /**
422
     * Get the related date assignments.
423
     *
424
     * @return AssignmentCollection
425
     */
426
    public function getDateAssignments()
427
    {
428
        $assignments = $this->getAssignments();
429
430
        return $assignments->dates();
431
    }
432
433
    /**
434
     * Get the unique translatable assignments.
435
     *
436
     * @return AssignmentCollection
437
     */
438
    public function getUniqueAssignments()
439
    {
440
        $assignments = $this->getAssignments();
441
442
        return $assignments->indexed();
443
    }
444
445
    /**
446
     * Get the only required assignments.
447
     *
448
     * @return AssignmentCollection
449
     */
450
    public function getRequiredAssignments()
451
    {
452
        $assignments = $this->getAssignments();
453
454
        return $assignments->required();
455
    }
456
457
    /**
458
     * Get the related unlocked assignments.
459
     *
460
     * @return AssignmentCollection
461
     */
462
    public function getUnlockedAssignments()
463
    {
464
        $assignments = $this->getAssignments();
465
466
        return $assignments->unlocked();
467
    }
468
469
    /**
470
     * Get the related translatable assignments.
471
     *
472
     * @return AssignmentCollection
473
     */
474
    public function getTranslatableAssignments()
475
    {
476
        $assignments = $this->getAssignments();
477
478
        return $assignments->translatable();
479
    }
480
481
    /**
482
     * Get the related relationship assignments.
483
     *
484
     * @return AssignmentCollection
485
     */
486
    public function getRelationshipAssignments()
487
    {
488
        $assignments = $this->getAssignments();
489
490
        return $assignments->relations();
491
    }
492
493
    /**
494
     * Get an assignment by it's field's slug.
495
     *
496
     * @param  $fieldSlug
497
     * @return AssignmentInterface
498
     */
499
    public function getAssignment($fieldSlug)
500
    {
501
        return $this->getAssignments()->findByFieldSlug($fieldSlug);
502
    }
503
504
    /**
505
     * Return whether a stream
506
     * has a field assigned.
507
     *
508
     * @param $fieldSlug
509
     * @return bool
510
     */
511
    public function hasAssignment($fieldSlug)
512
    {
513
        return (bool)$this->getAssignment($fieldSlug);
514
    }
515
516
    /**
517
     * Get a stream field by it's slug.
518
     *
519
     * @param  $slug
520
     * @return mixed
521
     */
522
    public function getField($slug)
523
    {
524
        if (!$assignment = $this->getAssignment($slug)) {
525
            return null;
526
        }
527
528
        return $assignment->getField();
529
    }
530
531
    /**
532
     * Get a field's type by the field's slug.
533
     *
534
     * @param                $fieldSlug
535
     * @param EntryInterface $entry
536
     * @param null|string    $locale
537
     * @return FieldType
538
     */
539
    public function getFieldType($fieldSlug, EntryInterface $entry = null, $locale = null)
540
    {
541
        if (!$assignment = $this->getAssignment($fieldSlug)) {
542
            return null;
543
        }
544
545
        return $assignment->getFieldType($entry, $locale);
0 ignored issues
show
Documentation introduced by
$entry is of type null|object<Anomaly\Stre...ontract\EntryInterface>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
The call to AssignmentInterface::getFieldType() has too many arguments starting with $locale.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
546
    }
547
548
    /**
549
     * Get a field's query utility by the field's slug.
550
     *
551
     * @param                $fieldSlug
552
     * @param EntryInterface $entry
553
     * @param null|string    $locale
554
     * @return FieldTypeQuery
555
     */
556
    public function getFieldTypeQuery($fieldSlug, EntryInterface $entry = null, $locale = null)
557
    {
558
        if (!$fieldType = $this->getFieldType($fieldSlug, $entry, $locale)) {
559
            return null;
560
        }
561
562
        return $fieldType->getQuery();
563
    }
564
565
    /**
566
     * Get the entry table name.
567
     *
568
     * @return string
569
     */
570
    public function getEntryTableName()
571
    {
572
        return $this->getPrefix() . $this->getSlug();
573
    }
574
575
    /**
576
     * Get the entry translations table name.
577
     *
578
     * @return string
579
     */
580
    public function getEntryTranslationsTableName()
581
    {
582
        return $this->getEntryTableName() . '_translations';
583
    }
584
585
    /**
586
     * Get the entry model.
587
     *
588
     * @return EntryModel
589
     */
590
    public function getEntryModel()
591
    {
592
        return app($this->getEntryModelName());
593
    }
594
595
    /**
596
     * Get the entry name.
597
     *
598
     * @return EntryModel
599
     */
600
    public function getEntryModelName()
601
    {
602
        $slug      = ucfirst(camel_case($this->getSlug()));
603
        $namespace = ucfirst(camel_case($this->getNamespace()));
604
605
        return "Anomaly\\Streams\\Platform\\Model\\{$namespace}\\{$namespace}{$slug}EntryModel";
606
    }
607
608
    /**
609
     * Get the foreign key.
610
     *
611
     * @return string
612
     */
613
    public function getForeignKey()
614
    {
615
        return str_singular($this->getSlug()) . '_id';
616
    }
617
618
    /**
619
     * Set the config attribute.
620
     *
621
     * @param $config
622
     */
623
    public function setConfigAttribute($config)
624
    {
625
        $this->attributes['config'] = serialize((array)$config);
626
    }
627
628
    /**
629
     * Get the config attribute.
630
     *
631
     * @param  $viewOptions
632
     * @return mixed
633
     */
634
    public function getConfigAttribute($config)
635
    {
636
        return unserialize($config);
637
    }
638
639
    /**
640
     * Set the locked attribute.
641
     *
642
     * @param $locked
643
     */
644
    public function setLockedAttribute($locked)
645
    {
646
        $this->attributes['locked'] = filter_var($locked, FILTER_VALIDATE_BOOLEAN);
647
    }
648
649
    /**
650
     * Set the hidden attribute.
651
     *
652
     * @param $hidden
653
     */
654
    public function setHiddenAttribute($hidden)
655
    {
656
        $this->attributes['hidden'] = filter_var($hidden, FILTER_VALIDATE_BOOLEAN);
657
    }
658
659
    /**
660
     * Set the sortable attribute.
661
     *
662
     * @param $sortable
663
     */
664
    public function setSortableAttribute($sortable)
665
    {
666
        $this->attributes['sortable'] = filter_var($sortable, FILTER_VALIDATE_BOOLEAN);
667
    }
668
669
    /**
670
     * Set the trashable attribute.
671
     *
672
     * @param $trashable
673
     */
674
    public function setTrashableAttribute($trashable)
675
    {
676
        $this->attributes['trashable'] = filter_var($trashable, FILTER_VALIDATE_BOOLEAN);
677
    }
678
679
    /**
680
     * Set the translatable attribute.
681
     *
682
     * @param $translatable
683
     */
684
    public function setTranslatableAttribute($translatable)
685
    {
686
        $this->attributes['translatable'] = filter_var($translatable, FILTER_VALIDATE_BOOLEAN);
687
    }
688
689
    /**
690
     * Return a created presenter.
691
     *
692
     * @return \Robbo\Presenter\Presenter
693
     */
694
    public function getPresenter()
695
    {
696
        return new StreamPresenter($this);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \Anomaly\Stre...StreamPresenter($this); (Anomaly\Streams\Platform\Stream\StreamPresenter) is incompatible with the return type declared by the interface Robbo\Presenter\PresentableInterface::getPresenter of type Robbo\Presenter\Robbo\Presenter\Presenter.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
697
    }
698
699
    /**
700
     * Return the assignments relation.
701
     *
702
     * @return mixed
703
     */
704
    public function assignments()
705
    {
706
        return $this->hasMany(
707
            'Anomaly\Streams\Platform\Assignment\AssignmentModel',
708
            'stream_id'
709
        )->orderBy('sort_order');
710
    }
711
}
712