Completed
Push — d64 ( a95f31...4968c1 )
by Welling
02:45
created

ClientLocal::createColumnUIOptions()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 47
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 32
nc 6
nop 1
dl 0
loc 47
ccs 0
cts 41
cp 0
crap 20
rs 8.6845
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Directus – <http://getdirectus.com>
5
 *
6
 * @link      The canonical repository – <https://github.com/directus/directus>
7
 * @copyright Copyright 2006-2016 RANGER Studio, LLC – <http://rangerstudio.com>
8
 * @license   GNU General Public License (v3) – <http://www.gnu.org/copyleft/gpl.html>
9
 */
10
11
namespace Directus\SDK;
12
13
use Directus\Database\Connection;
14
use Directus\Database\TableGateway\BaseTableGateway;
15
use Directus\Database\TableGateway\DirectusActivityTableGateway;
16
use Directus\Database\TableGateway\DirectusMessagesTableGateway;
17
use Directus\Database\TableGateway\DirectusPrivilegesTableGateway;
18
use Directus\Database\TableGateway\DirectusUiTableGateway;
19
use Directus\Database\TableGateway\DirectusUsersTableGateway;
20
use Directus\Database\TableGateway\RelationalTableGateway;
21
use Directus\Database\TableSchema;
22
use Directus\Util\ArrayUtils;
23
use Directus\Util\SchemaUtils;
24
25
/**
26
 * Client Local
27
 *
28
 * Client to Interact with the database directly using Directus Database Component
29
 *
30
 * @author Welling Guzmán <[email protected]>
31
 */
32
class ClientLocal extends AbstractClient
33
{
34
    /**
35
     * @var BaseTableGateway[]
36
     */
37
    protected $tableGateways = [];
38
39
    /**
40
     * @var Connection
41
     */
42
    protected $connection = null;
43
44
    /**
45
     * ClientLocal constructor.
46
     *
47
     * @param $connection
48
     */
49
    public function __construct($connection)
50
    {
51
        $this->connection = $connection;
52
    }
53
54
    /**
55
     * @inheritDoc
56
     */
57
    public function getTables(array $params = [])
58
    {
59
        return $this->createResponseFromData(TableSchema::getTablesSchema($params));
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFro...TablesSchema($params)); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\Entry to the return on line 59 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getTables of type Directus\SDK\Response\EntryCollection.
Loading history...
60
    }
61
62
    /**
63
     * @inheritDoc
64
     */
65
    public function getTable($tableName)
66
    {
67
        return $this->createResponseFromData(TableSchema::getSchemaArray($tableName));
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFro...hemaArray($tableName)); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 67 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getTable of type Directus\SDK\Response\Entry.
Loading history...
68
    }
69
70
    /**
71
     * @inheritDoc
72
     */
73
    public function getColumns($tableName, array $params = [])
74
    {
75
        return $this->createResponseFromData(TableSchema::getColumnSchemaArray($tableName, $params));
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFro...($tableName, $params)); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\Entry to the return on line 75 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getColumns of type Directus\SDK\Response\EntryCollection.
Loading history...
76
    }
77
78
    /**
79
     * @inheritDoc
80
     */
81
    public function getColumn($tableName, $columnName)
82
    {
83
        return $this->createResponseFromData(TableSchema::getColumnSchema($tableName, $columnName)->toArray());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFro...olumnName)->toArray()); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 83 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getColumn of type Directus\SDK\Response\Entry.
Loading history...
84
    }
85
86
    /**
87
     * @inheritDoc
88
     */
89
    public function getEntries($tableName, array $params = [])
90
    {
91
        $tableGateway = $this->getTableGateway($tableName);
92
93
        return $this->createResponseFromData($tableGateway->getEntries($params));
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFro...->getEntries($params)); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\Entry to the return on line 93 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getEntries of type Directus\SDK\Response\EntryCollection.
Loading history...
94
    }
95
96
    /**
97
     * @inheritDoc
98
     */
99
    public function getEntry($tableName, $id, array $params = [])
100
    {
101
        // @TODO: Dynamic ID
102
        return $this->getEntries($tableName, array_merge($params, [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getEntries..., array('id' => $id))); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getEntry of type Directus\SDK\Response\Entry.

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...
103
            'id' => $id
104
        ]));
105
    }
106
107
    /**
108
     * @inheritDoc
109
     */
110
    public function getUsers(array $params = [])
111
    {
112
        // @TODO: store the directus tables somewhere (SchemaManager?)
113
        return $this->getEntries('directus_users', $params);
114
    }
115
116
    /**
117
     * @inheritDoc
118
     */
119
    public function getUser($id, array $params = [])
120
    {
121
        return $this->getEntry('directus_users', $id, $params);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getEntry('..._users', $id, $params); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getUser of type Directus\SDK\Response\Entry.

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...
122
    }
123
124
    /**
125
     * @inheritDoc
126
     */
127
    public function getGroups(array $params = [])
128
    {
129
        return $this->getEntries('directus_groups', $params);
130
    }
131
132
    /**
133
     * @inheritDoc
134
     */
135
    public function getGroup($id, array $params = [])
136
    {
137
        return $this->getEntry('directus_groups', $id, $params);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getEntry('...groups', $id, $params); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getGroup of type Directus\SDK\Response\Entry.

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...
138
    }
139
140
    /**
141
     * @inheritDoc
142
     */
143
    public function getGroupPrivileges($groupID)
144
    {
145
        $this->getEntries('directus_privileges', [
146
            'filter' => [
147
                'group_id' => ['eq' => $groupID]
148
            ]
149
        ]);
150
    }
151
152
    /**
153
     * @inheritDoc
154
     */
155
    public function getFiles(array $params = [])
156
    {
157
        return $this->getEntries('directus_files', $params);
158
    }
159
160
    /**
161
     * @inheritDoc
162
     */
163
    public function getFile($id, array $params = [])
164
    {
165
        return $this->getEntry('directus_files', $id, $params);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getEntry('..._files', $id, $params); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getFile of type Directus\SDK\Response\Entry.

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...
166
    }
167
168
    /**
169
     * @inheritDoc
170
     */
171
    public function getSettings()
172
    {
173
        return $this->getEntries('directus_settings');
174
    }
175
176
    /**
177
     * @inheritDoc
178
     */
179
    public function getSettingsByCollection($collectionName)
180
    {
181
        return $this->getEntries('directus_settings', [
182
            'filter' => [
183
                'collection' => ['eq' => $collectionName]
184
            ]
185
        ]);
186
    }
187
188
    /**
189
     * @inheritDoc
190
     */
191
    public function getMessages($userId)
192
    {
193
        $messagesTableGateway = new DirectusMessagesTableGateway($this->connection, null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<Directus\Permissions\Acl>.

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...
194
        $result = $messagesTableGateway->fetchMessagesInboxWithHeaders($userId);
195
196
        return $this->createResponseFromData($result);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFromData($result); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\Entry to the return on line 196 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::getMessages of type Directus\SDK\Response\EntryCollection.
Loading history...
197
    }
198
199
    /**
200
     * @inheritDoc
201
     */
202 View Code Duplication
    public function createEntry($tableName, array $data)
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...
203
    {
204
        $tableGateway = $this->getTableGateway($tableName);
205
        $data = $this->processData($tableName, $data);
206
207
        foreach($data as $key => $value) {
208
            if ($value instanceof File) {
209
                $data[$key] = $this->processFile($value);
210
            }
211
        }
212
213
        $newRecord = $tableGateway->manageRecordUpdate($tableName, $data);
214
215
        return $this->getEntry($tableName, $newRecord[$tableGateway->primaryKeyFieldName]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getEntry($...>primaryKeyFieldName]); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createEntry of type Directus\SDK\Response\Entry.

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...
216
    }
217
218
    /**
219
     * @inheritDoc
220
     */
221 View Code Duplication
    public function updateEntry($tableName, $id, array $data)
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...
222
    {
223
        $tableGateway = $this->getTableGateway($tableName);
224
        $data = $this->processData($tableName, $data);
225
226
        foreach($data as $key => $value) {
227
            if ($value instanceof File) {
228
                $data[$key] = $this->processFile($value);
229
            }
230
        }
231
232
        $updatedRecord = $tableGateway->manageRecordUpdate($tableName, array_merge($data, ['id' => $id]));
233
234
        return $this->getEntry($tableName, $updatedRecord[$tableGateway->primaryKeyFieldName]);
235
    }
236
237
    /**
238
     * @inheritDoc
239
     */
240
    public function deleteEntry($tableName, $ids)
241
    {
242
        // @TODO: Accept EntryCollection and Entry
243
        $tableGateway = $this->getTableGateway($tableName);
244
245
        if (!is_array($ids)) {
246
            $ids = [$ids];
247
        }
248
249
        return $tableGateway->delete(function($delete) use ($ids) {
250
            return $delete->where->in('id', $ids);
251
        });
252
    }
253
254
    /**
255
     * @inheritDoc
256
     */
257
    public function createUser(array $data)
258
    {
259
        return $this->createEntry('directus_users', $data);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->createEntr...irectus_users', $data); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createUser of type Directus\SDK\Response\Entry.

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...
260
    }
261
262
    /**
263
     * @inheritDoc
264
     */
265
    public function updateUser($id, array $data)
266
    {
267
        return $this->updateEntry('directus_users', $id, $data);
268
    }
269
270
    /**
271
     * @inheritDoc
272
     */
273
    public function deleteUser($ids)
274
    {
275
        return $this->deleteEntry('directus_users', $ids);
276
    }
277
278
    /**
279
     * @inheritDoc
280
     */
281
    public function createFile(File $file)
282
    {
283
        $data = $this->processFile($file);
284
285
        return $this->createEntry('directus_files', $data);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->createEntr...irectus_files', $data); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createFile of type Directus\SDK\Response\Entry.

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...
286
    }
287
288
    /**
289
     * @inheritDoc
290
     */
291
    public function updateFile($id, array $data)
292
    {
293
        return $this->updateEntry('directus_files', $id, $data);
294
    }
295
296
    /**
297
     * @inheritDoc
298
     */
299
    public function deleteFile($ids)
300
    {
301
        return $this->deleteEntry('directus_files', $ids);
302
    }
303
304
    public function createPreferences($data)
305
    {
306
        if (!ArrayUtils::contains($data, ['title', 'table_name'])) {
307
            throw new \Exception('title and table_name are required');
308
        }
309
310
        $acl = $this->container->get('acl');
311
        $data['user'] = $acl->getUserId();
312
313
        return $this->createEntry('directus_preferences', $data);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->createEntr...s_preferences', $data); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createPreferences of type Directus\SDK\Response\Entry.

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...
314
    }
315
316
    /**
317
     * @inheritdoc
318
     */
319
    public function createBookmark($data)
320
    {
321
        $acl = $this->container->get('acl');
322
        $data['user'] = $acl->getUserId();
323
324
        $preferences = $this->createPreferences(ArrayUtils::pick($data, [
325
            'title', 'table_name', 'sort', 'status', 'search_string', 'sort_order', 'columns_visible', 'user'
326
        ]));
327
328
        $title = $preferences->title;
0 ignored issues
show
Bug introduced by
The property title does not seem to exist in Directus\SDK\Response\EntryCollection.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
329
        $tableName = $preferences->table_name;
0 ignored issues
show
Bug introduced by
The property table_name does not seem to exist in Directus\SDK\Response\EntryCollection.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
330
        $bookmarkData = [
331
            'section' => 'search',
332
            'title' => $title,
333
            'url' => 'tables/' . $tableName . '/pref/' . $title,
334
            'user' => $data['user']
335
        ];
336
337
        return $this->createEntry('directus_bookmarks', $bookmarkData);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->createEntr...marks', $bookmarkData); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createBookmark of type Directus\SDK\Response\Entry.

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...
338
    }
339
340
    /**
341
     * @inheritdoc
342
     */
343
    public function createColumn($data)
344
    {
345
        $data = $this->parseColumnData($data);
346
347
        $tableGateway = $this->getTableGateway($data['table_name']);
348
349
        $tableGateway->addColumn($data['table_name'], ArrayUtils::omit($data, ['table_name']));
350
351
        return $this->getColumn($data['table_name'], $data['column_name']);
352
    }
353
354
    /**
355
     * @inheritdoc
356
     */
357
    public function createGroup(array $data)
358
    {
359
        return $this->createEntry('directus_groups', $data);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->createEntr...rectus_groups', $data); (Directus\SDK\Response\EntryCollection) is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createGroup of type Directus\SDK\Response\Entry.

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...
360
    }
361
362
    /**
363
     * @inheritdoc
364
     */
365
    public function createMessage(array $data)
366
    {
367
        $this->requiredAttributes(['from', 'message', 'subject'], $data);
368
        $this->requiredOneAttribute(['to', 'toGroup'], $data);
369
370
        $recipients = $this->getMessagesTo($data);
371
        $recipients = explode(',', $recipients);
372
        ArrayUtils::remove($data, ['to', 'toGroup']);
373
374
        $groupRecipients = [];
375
        $userRecipients = [];
376
        foreach ($recipients as $recipient) {
377
            $typeAndId = explode('_', $recipient);
378
            if ($typeAndId[0] == 0) {
379
                $userRecipients[] = $typeAndId[1];
380
            } else {
381
                $groupRecipients[] = $typeAndId[1];
382
            }
383
        }
384
385
        $ZendDb = $this->container->get('connection');
386
        $acl = $this->container->get('acl');
387
        if (count($groupRecipients) > 0) {
388
            $usersTableGateway = new DirectusUsersTableGateway($ZendDb, $acl);
389
            $result = $usersTableGateway->findActiveUserIdsByGroupIds($groupRecipients);
390
            foreach ($result as $item) {
391
                $userRecipients[] = $item['id'];
392
            }
393
        }
394
395
        $userRecipients[] = $acl->getUserId();
396
397
        $messagesTableGateway = new DirectusMessagesTableGateway($ZendDb, $acl);
398
        $id = $messagesTableGateway->sendMessage($data, array_unique($userRecipients), $acl->getUserId());
399
400
        if ($id) {
401
            $Activity = new DirectusActivityTableGateway($ZendDb, $acl);
402
            $data['id'] = $id;
403
            $Activity->recordMessage($data, $acl->getUserId());
404
        }
405
406
        $message = $messagesTableGateway->fetchMessageWithRecipients($id, $acl->getUserId());
407
        $response = [
408
            'meta' => [
409
                'type' => 'entry',
410
                'table' => 'directus_messages'
411
            ],
412
            'data' => $message
413
        ];
414
415
        return $this->createResponseFromData($response);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFromData($response); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 415 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createMessage of type Directus\SDK\Response\Entry.
Loading history...
416
    }
417
418
    /**
419
     * @inheritdoc
420
     */
421
    public function sendMessage(array $data)
422
    {
423
        return $this->createMessage($data);
424
    }
425
426
    public function createPrivileges(array $data)
427
    {
428
        $connection = $this->container->get('connection');
429
        $acl = $this->container->get('acl');
430
        $privileges = new DirectusPrivilegesTableGateway($connection, $acl);
431
432
        $response = [
433
            'meta' => [
434
                'type' => 'entry',
435
                'table' => 'directus_privileges'
436
            ],
437
            'data' => $privileges->insertPrivilege($data)
438
        ];
439
440
        return $this->createResponseFromData($response);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFromData($response); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 440 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createPrivileges of type Directus\SDK\Response\Entry.
Loading history...
441
    }
442
443
    public function createTable($name, array $data = [])
444
    {
445
        $isTableNameAlphanumeric = preg_match("/[a-z0-9]+/i", $name);
446
        $zeroOrMoreUnderscoresDashes = preg_match("/[_-]*/i", $name);
447
448
        if (!($isTableNameAlphanumeric && $zeroOrMoreUnderscoresDashes)) {
449
            return $this->createResponseFromData(['error' => ['message' => 'invalid_table_name']]);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFro...invalid_table_name'))); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 449 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createTable of type Directus\SDK\Response\Entry.
Loading history...
450
        }
451
452
        $schema = $this->container->get('schemaManager');
453
        $emitter = $this->container->get('emitter');
454
        if (!$schema->tableExists($name)) {
455
            $emitter->run('table.create:before', $name);
456
            // Through API:
457
            // Remove spaces and symbols from table name
458
            // And in lowercase
459
            $name = SchemaUtils::cleanTableName($name);
460
            $schema->createTable($name);
461
            $emitter->run('table.create', $name);
462
            $emitter->run('table.create:after', $name);
463
        }
464
465
        $connection = $this->container->get('connection');
466
        $acl = $this->container->get('acl');
467
        $privileges = new DirectusPrivilegesTableGateway($connection, $acl);
468
469
        return $this->createResponseFromData($privileges->insertPrivilege([
1 ignored issue
show
Bug Compatibility introduced by
The expression $this->createResponseFro...able_name' => $name))); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 469 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInterface::createTable of type Directus\SDK\Response\Entry.
Loading history...
470
            'group_id' => 1,
471
            'table_name' => $name
472
        ]));
473
    }
474
475
    /**
476
     * @inheritdoc
477
     */
478
    public function createColumnUIOptions(array $data)
479
    {
480
        $this->requiredAttributes(['table', 'column', 'ui', 'options'], $data);
481
        $tableGateway = $this->getTableGateway('directus_ui');
482
483
        $table = $data['table'];
484
        $column = $data['column'];
485
        $ui = $data['ui'];
486
487
        $data = $data['options'];
488
        $keys = ['table_name' => $table, 'column_name' => $column, 'ui_name' => $ui];
489
        $uis = to_name_value($data, $keys);
490
491
        $column_settings = [];
492
        foreach ($uis as $col) {
493
            $existing = $tableGateway->select(['table_name' => $table, 'column_name' => $column, 'ui_name' => $ui, 'name' => $col['name']])->toArray();
494
            if (count($existing) > 0) {
495
                $col['id'] = $existing[0]['id'];
496
            }
497
            array_push($column_settings, $col);
498
        }
499
        $tableGateway->updateCollection($column_settings);
500
501
        $connection = $this->container->get('connection');
502
        $acl = $this->container->get('acl');
503
        $UiOptions = new DirectusUiTableGateway($connection, $acl);
504
        $response = $UiOptions->fetchOptions($table, $column, $ui);
505
506
        if (!$response) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $response of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
507
            $response = [
508
                'error' => [
509
                    'message' => sprintf('unable_to_find_column_%s_options_for_%s', ['column' => $column, 'ui' => $ui])
510
                ],
511
                'success' => false
512
            ];
513
        } else {
514
            $response = [
515
                'meta' => [
516
                    'type' => 'entry',
517
                    'table' => 'directus_ui'
518
                ],
519
                'data' => $response
520
            ];
521
        }
522
523
        return $this->createResponseFromData($response);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createResponseFromData($response); of type Directus\SDK\Response\En...ctus\SDK\Response\Entry adds the type Directus\SDK\Response\EntryCollection to the return on line 523 which is incompatible with the return type declared by the interface Directus\SDK\RequestsInt...::createColumnUIOptions of type Directus\SDK\Response\Entry.
Loading history...
524
    }
525
526
    /**
527
     * Get a table gateway for the given table name
528
     *
529
     * @param $tableName
530
     *
531
     * @return RelationalTableGateway
532
     */
533
    protected function getTableGateway($tableName)
534
    {
535
        if (!array_key_exists($tableName, $this->tableGateways)) {
536
            $acl = TableSchema::getAclInstance();
537
            $this->tableGateways[$tableName] = new RelationalTableGateway($tableName, $this->connection, $acl);
538
        }
539
540
        return $this->tableGateways[$tableName];
541
    }
542
}
543