Completed
Pull Request — master (#272)
by Ryan
06:54
created

EloquentCriteria::__toString()   A

Complexity

Conditions 1
Paths 1

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 1
eloc 2
nc 1
nop 0
1
<?php namespace Anomaly\Streams\Platform\Model;
2
3
use Anomaly\Streams\Platform\Entry\Contract\EntryInterface;
4
use Anomaly\Streams\Platform\Entry\EntryPresenter;
5
use Anomaly\Streams\Platform\Support\Collection;
6
use Anomaly\Streams\Platform\Support\Decorator;
7
use Anomaly\Streams\Platform\Support\Presenter;
8
use Anomaly\Streams\Platform\Traits\Hookable;
9
use Illuminate\Database\Eloquent\Builder;
10
use Illuminate\Foundation\Bus\DispatchesJobs;
11
12
/**
13
 * Class EloquentCriteria
14
 *
15
 * @link          http://anomaly.is/streams-platform
16
 * @author        AnomalyLabs, Inc. <[email protected]>
17
 * @author        Ryan Thompson <[email protected]>
18
 * @package       Anomaly\Streams\Platform\Model
19
 */
20
class EloquentCriteria
21
{
22
23
    use Hookable;
24
    use DispatchesJobs;
25
26
    /**
27
     * Safe builder methods.
28
     *
29
     * @var array
30
     */
31
    private $disabled = [
32
        'delete',
33
        'update',
34
    ];
35
36
    /**
37
     * The query builder.
38
     *
39
     * @var Builder|\Illuminate\Database\Query\Builder
40
     */
41
    protected $query;
42
43
    /**
44
     * Set the get method.
45
     *
46
     * @var string
47
     */
48
    protected $method;
49
50
    /**
51
     * Create a new EntryCriteria instance.
52
     *
53
     * @param Builder $query
54
     * @param string  $method
55
     */
56
    public function __construct(Builder $query, $method = 'get')
57
    {
58
        $this->query  = $query;
59
        $this->method = $method;
60
    }
61
62
    /**
63
     * Get the paginated entries.
64
     *
65
     * @param array $columns
66
     * @return Collection|Presenter|EntryPresenter
67
     */
68
    public function paginate($perPage = 15, array $columns = ['*'])
69
    {
70
        return (new Decorator())->decorate($this->query->paginate($perPage, $columns));
71
    }
72
73
    /**
74
     * Get the entries.
75
     *
76
     * @param array $columns
77
     * @return Collection|Presenter|EntryPresenter
78
     */
79
    public function get(array $columns = ['*'])
80
    {
81
        return (new Decorator())->decorate($this->query->{$this->method}($columns));
82
    }
83
84
    /**
85
     * Find an entry.
86
     *
87
     * @param       $identifier
88
     * @param array $columns
89
     * @return Presenter|EntryPresenter
90
     */
91
    public function find($identifier, array $columns = ['*'])
92
    {
93
        return (new Decorator())->decorate($this->query->find($identifier, $columns));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return (new \Anomaly\Str...identifier, $columns)); (object|integer|double|string|null|boolean|array) is incompatible with the return type documented by Anomaly\Streams\Platform...\EloquentCriteria::find of type Anomaly\Streams\Platform\Support\Presenter|null.

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...
94
    }
95
96
    /**
97
     * Find an entry by column value.
98
     *
99
     * @param       $column
100
     * @param       $value
101
     * @param array $columns
102
     * @return Presenter|EntryPresenter
103
     */
104
    public function findBy($column, $value, array $columns = ['*'])
105
    {
106
        $this->query->where($column, $value);
107
108
        return (new Decorator())->decorate($this->query->first($columns));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return (new \Anomaly\Str...uery->first($columns)); (object|integer|double|string|null|boolean|array) is incompatible with the return type documented by Anomaly\Streams\Platform...loquentCriteria::findBy of type Anomaly\Streams\Platform\Support\Presenter|null.

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...
109
    }
110
111
    /**
112
     * Return the first entry.
113
     *
114
     * @param array $columns
115
     * @return EloquentModel|EntryInterface
116
     */
117
    public function first(array $columns = ['*'])
118
    {
119
        return (new Decorator())->decorate($this->query->first($columns));
120
    }
121
122
    /**
123
     * Return whether the method is safe or not.
124
     *
125
     * @param $name
126
     * @return bool
127
     */
128
    protected function methodIsSafe($name)
129
    {
130
        return (!in_array($name, $this->disabled));
131
    }
132
133
    /**
134
     * Route through __call.
135
     *
136
     * @param $name
137
     * @return Builder|null
138
     */
139
    function __get($name)
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...
140
    {
141
        return $this->__call($name, []);
142
    }
143
144
    /**
145
     * Call the method on the query.
146
     *
147
     * @param $name
148
     * @param $arguments
149
     * @return Builder|null
150
     */
151
    function __call($name, $arguments)
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...
152
    {
153
154
        if ($this->hasHook($name)) {
155
            return $this->call($name, $arguments);
156
        }
157
158
        if ($this->methodIsSafe($name)) {
159
            call_user_func_array([$this->query, $name], $arguments);
160
161
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Anomaly\Streams\Platform\Model\EloquentCriteria) is incompatible with the return type documented by Anomaly\Streams\Platform...loquentCriteria::__call of type Illuminate\Database\Eloquent\Builder|null.

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...
162
        }
163
164 View Code Duplication
        if (starts_with($name, 'findBy') && $column = snake_case(substr($name, 6))) {
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...
165
166
            call_user_func_array([$this->query, 'where'], array_merge([$column], $arguments));
167
168
            return $this->first();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->first(); (object|integer|double|string|null|boolean|array) is incompatible with the return type documented by Anomaly\Streams\Platform...loquentCriteria::__call of type Illuminate\Database\Eloquent\Builder|null.

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...
169
        }
170
171 View Code Duplication
        if (starts_with($name, 'where') && $column = snake_case(substr($name, 5))) {
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...
172
            call_user_func_array([$this->query, 'where'], array_merge([$column], $arguments));
173
174
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Anomaly\Streams\Platform\Model\EloquentCriteria) is incompatible with the return type documented by Anomaly\Streams\Platform...loquentCriteria::__call of type Illuminate\Database\Eloquent\Builder|null.

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...
175
        }
176
177
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Anomaly\Streams\Platform\Model\EloquentCriteria) is incompatible with the return type documented by Anomaly\Streams\Platform...loquentCriteria::__call of type Illuminate\Database\Eloquent\Builder|null.

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...
178
    }
179
    
180
    /**
181
     * Return the string.
182
     *
183
     * @return string
184
     */
185
    public function __toString()
186
    {
187
        return '';
188
    }
189
}
190