ClientLocal   F
last analyzed

Complexity

Total Complexity 77

Size/Duplication

Total Lines 743
Duplicated Lines 18.98 %

Coupling/Cohesion

Components 1
Dependencies 17

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 141
loc 743
ccs 0
cts 473
cp 0
rs 1.7391
c 0
b 0
f 0
wmc 77
lcom 1
cbo 17

49 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getTables() 0 8 1
A getTable() 0 4 1
A getColumns() 0 8 1
A getColumn() 0 6 1
A getItems() 0 6 1
A getItem() 0 7 1
A getUsers() 0 5 1
A getUser() 0 4 1
A getGroups() 0 4 1
A getGroup() 0 4 1
A getGroupPrivileges() 0 8 1
A getFiles() 0 4 1
A getFile() 0 4 1
A getSettings() 0 4 1
A getSettingsByCollection() 17 17 1
A updateSettings() 0 10 1
A getMessages() 14 14 2
A getMessage() 14 14 2
A createItem() 15 15 3
A updateItem() 15 15 3
B deleteItem() 0 23 4
A createUser() 0 4 1
A updateUser() 0 4 1
A deleteUser() 0 4 1
A createFile() 0 6 1
A updateFile() 0 8 2
A deleteFile() 0 4 1
A createPreferences() 0 11 2
A createBookmark() 0 20 1
A getBookmark() 0 4 1
A getBookmarks() 0 11 2
A createColumn() 0 10 1
A createGroup() 0 4 1
B createMessage() 0 52 6
A sendMessage() 0 4 1
A createPrivileges() 16 16 1
B createTable() 0 31 4
B createColumnUIOptions() 0 47 4
A getPreferences() 16 16 1
A deleteBookmark() 0 4 1
A deleteColumn() 17 17 2
A deleteGroup() 0 4 1
A deleteTable() 17 17 2
A getActivity() 0 10 1
A getRandom() 0 11 1
A getHash() 0 23 2
A getTableGateway() 0 9 2
A processDataOnDirectusUsers() 0 11 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ClientLocal often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ClientLocal, and based on these observations, apply Extract Interface, too.

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\Object\Column;
15
use Directus\Database\Object\Table;
16
use Directus\Database\TableGateway\BaseTableGateway;
17
use Directus\Database\TableGateway\DirectusActivityTableGateway;
18
use Directus\Database\TableGateway\DirectusMessagesTableGateway;
19
use Directus\Database\TableGateway\DirectusPreferencesTableGateway;
20
use Directus\Database\TableGateway\DirectusPrivilegesTableGateway;
21
use Directus\Database\TableGateway\DirectusSettingsTableGateway;
22
use Directus\Database\TableGateway\DirectusUiTableGateway;
23
use Directus\Database\TableGateway\DirectusUsersTableGateway;
24
use Directus\Database\TableGateway\RelationalTableGateway;
25
use Directus\Database\TableSchema;
26
use Directus\Util\ArrayUtils;
27
use Directus\Util\SchemaUtils;
28
use Directus\Util\StringUtils;
29
use Zend\Db\Sql\Predicate\In;
30
31
/**
32
 * Client Local
33
 *
34
 * Client to Interact with the database directly using Directus Database Component
35
 *
36
 * @author Welling Guzmán <[email protected]>
37
 */
38
class ClientLocal extends AbstractClient
39
{
40
    /**
41
     * @var BaseTableGateway[]
42
     */
43
    protected $tableGateways = [];
44
45
    /**
46
     * @var Connection
47
     */
48
    protected $connection = null;
49
50
    /**
51
     * ClientLocal constructor.
52
     *
53
     * @param $connection
54
     */
55
    public function __construct($connection)
56
    {
57
        $this->connection = $connection;
58
    }
59
60
    /**
61
     * @inheritDoc
62
     */
63
    public function getTables(array $params = [])
64
    {
65
        $tables = array_map(function(Table $table) {
66
            return $table->toArray();
67
        }, TableSchema::getTablesSchema($params));
68
69
        return $this->createResponseFromData(['data' => $tables]);
70
    }
71
72
    /**
73
     * @inheritDoc
74
     */
75
    public function getTable($tableName)
76
    {
77
        return $this->createResponseFromData(['data' => TableSchema::getSchemaArray($tableName)]);
78
    }
79
80
    /**
81
     * @inheritDoc
82
     */
83
    public function getColumns($tableName, array $params = [])
84
    {
85
        $columns = array_map(function(Column $column) {
86
            return $column->toArray();
87
        }, TableSchema::getTableColumnsSchema($tableName, $params));
88
89
        return $this->createResponseFromData(['data' => $columns]);
90
    }
91
92
    /**
93
     * @inheritDoc
94
     */
95
    public function getColumn($tableName, $columnName)
96
    {
97
        return $this->createResponseFromData([
98
            'data' => TableSchema::getColumnSchema($tableName, $columnName)->toArray()
99
        ]);
100
    }
101
102
    /**
103
     * @inheritDoc
104
     */
105
    public function getItems($tableName, array $params = [])
106
    {
107
        $tableGateway = $this->getTableGateway($tableName);
108
109
        return $this->createResponseFromData($tableGateway->getItems($params));
110
    }
111
112
    /**
113
     * @inheritDoc
114
     */
115
    public function getItem($tableName, $id, array $params = [])
116
    {
117
        // @TODO: Dynamic ID
118
        return $this->getItems($tableName, array_merge($params, [
119
            'id' => $id
120
        ]));
121
    }
122
123
    /**
124
     * @inheritDoc
125
     */
126
    public function getUsers(array $params = [])
127
    {
128
        // @TODO: store the directus tables somewhere (SchemaManager?)
129
        return $this->getItems('directus_users', $params);
130
    }
131
132
    /**
133
     * @inheritDoc
134
     */
135
    public function getUser($id, array $params = [])
136
    {
137
        return $this->getItem('directus_users', $id, $params);
138
    }
139
140
    /**
141
     * @inheritDoc
142
     */
143
    public function getGroups(array $params = [])
144
    {
145
        return $this->getItems('directus_groups', $params);
146
    }
147
148
    /**
149
     * @inheritDoc
150
     */
151
    public function getGroup($id, array $params = [])
152
    {
153
        return $this->getItem('directus_groups', $id, $params);
154
    }
155
156
    /**
157
     * @inheritDoc
158
     */
159
    public function getGroupPrivileges($groupID)
160
    {
161
        $this->getItems('directus_privileges', [
162
            'filter' => [
163
                'group_id' => ['eq' => $groupID]
164
            ]
165
        ]);
166
    }
167
168
    /**
169
     * @inheritDoc
170
     */
171
    public function getFiles(array $params = [])
172
    {
173
        return $this->getItems('directus_files', $params);
174
    }
175
176
    /**
177
     * @inheritDoc
178
     */
179
    public function getFile($id, array $params = [])
180
    {
181
        return $this->getItem('directus_files', $id, $params);
182
    }
183
184
    /**
185
     * @inheritDoc
186
     */
187
    public function getSettings()
188
    {
189
        return $this->getItems('directus_settings');
190
    }
191
192
    /**
193
     * @inheritDoc
194
     */
195 View Code Duplication
    public function getSettingsByCollection($collectionName)
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...
196
    {
197
        $connection = $this->container->get('connection');
198
        $acl = $this->container->get('acl');
199
        $tableGateway = new DirectusSettingsTableGateway($connection, $acl);
200
201
        $data = [
202
            'meta' => [
203
                'table' => 'directus_settings',
204
                'type' => 'entry',
205
                'settings_collection' => $collectionName
206
            ],
207
            'data' => $tableGateway->fetchCollection($collectionName)
208
        ];
209
210
        return $this->createResponseFromData($data);
211
    }
212
213
    /**
214
     * @inheritdoc
215
     */
216
    public function updateSettings($collection, array $data)
217
    {
218
        $connection = $this->container->get('connection');
219
        $acl = $this->container->get('acl');
220
        $tableGateway = new DirectusSettingsTableGateway($connection, $acl);
221
222
        $tableGateway->setValues($collection, $data);
223
224
        return $this->getSettingsByCollection($collection);
225
    }
226
227
    /**
228
     * @inheritDoc
229
     */
230 View Code Duplication
    public function getMessages($userId = null)
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...
231
    {
232
        $connection = $this->container->get('connection');
233
        $acl = $this->container->get('acl');
234
235
        if ($userId === null) {
236
            $userId = $acl->getUserId();
237
        }
238
239
        $messagesTableGateway = new DirectusMessagesTableGateway($connection, $acl);
240
        $result = $messagesTableGateway->fetchMessagesInboxWithHeaders($userId);
241
242
        return $this->createResponseFromData($result);
243
    }
244
245 View Code Duplication
    public function getMessage($id, $userId = null)
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...
246
    {
247
        $connection = $this->container->get('connection');
248
        $acl = $this->container->get('acl');
249
250
        if ($userId === null) {
251
            $userId = $acl->getUserId();
252
        }
253
254
        $messagesTableGateway = new DirectusMessagesTableGateway($connection, $acl);
255
        $message = $messagesTableGateway->fetchMessageWithRecipients($id, $userId);
256
257
        return $this->createResponseFromData($message);
258
    }
259
260
    /**
261
     * @inheritDoc
262
     */
263 View Code Duplication
    public function createItem($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...
264
    {
265
        $tableGateway = $this->getTableGateway($tableName);
266
        $data = $this->processData($tableName, $data);
267
268
        foreach($data as $key => $value) {
269
            if ($value instanceof File) {
270
                $data[$key] = $this->processFile($value);
271
            }
272
        }
273
274
        $newRecord = $tableGateway->manageRecordUpdate($tableName, $data);
275
276
        return $this->getItem($tableName, $newRecord[$tableGateway->primaryKeyFieldName]);
277
    }
278
279
    /**
280
     * @inheritDoc
281
     */
282 View Code Duplication
    public function updateItem($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...
283
    {
284
        $tableGateway = $this->getTableGateway($tableName);
285
        $data = $this->processData($tableName, $data);
286
287
        foreach($data as $key => $value) {
288
            if ($value instanceof File) {
289
                $data[$key] = $this->processFile($value);
290
            }
291
        }
292
293
        $updatedRecord = $tableGateway->manageRecordUpdate($tableName, array_merge($data, ['id' => $id]));
294
295
        return $this->getItem($tableName, $updatedRecord[$tableGateway->primaryKeyFieldName]);
296
    }
297
298
    /**
299
     * @inheritDoc
300
     */
301
    public function deleteItem($tableName, $ids, $hard = false)
302
    {
303
        // @TODO: Accept EntryCollection and Entry
304
        $tableGateway = $this->getTableGateway($tableName);
305
306
        if (!is_array($ids)) {
307
            $ids = [$ids];
308
        }
309
310
        if ($hard === true) {
311
            return $tableGateway->delete(function($delete) use ($ids) {
312
                return $delete->where->in('id', $ids);
313
            });
314
        }
315
316
        if (!$tableGateway->getTableSchema()->hasStatusColumn()) {
317
            throw new \Exception('Cannot soft-delete. Table has not status column.');
318
        }
319
320
        return $tableGateway->update([
321
            $tableGateway->getStatusColumnName() => $tableGateway->getDeletedValue()
322
        ], new In('id', $ids));
0 ignored issues
show
Documentation introduced by
new \Zend\Db\Sql\Predicate\In('id', $ids) is of type object<Zend\Db\Sql\Predicate\In>, but the function expects a string|array|object<Closure>|null.

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...
323
    }
324
325
    /**
326
     * @inheritDoc
327
     */
328
    public function createUser(array $data)
329
    {
330
        return $this->createItem('directus_users', $data);
331
    }
332
333
    /**
334
     * @inheritDoc
335
     */
336
    public function updateUser($id, array $data)
337
    {
338
        return $this->updateItem('directus_users', $id, $data);
339
    }
340
341
    /**
342
     * @inheritDoc
343
     */
344
    public function deleteUser($ids, $hard = false)
345
    {
346
        return $this->deleteItem('directus_users', $ids, $hard);
347
    }
348
349
    /**
350
     * @inheritDoc
351
     */
352
    public function createFile(File $file)
353
    {
354
        $data = $this->processFile($file);
355
356
        return $this->createItem('directus_files', $data);
357
    }
358
359
    /**
360
     * @inheritDoc
361
     */
362
    public function updateFile($id, $data)
363
    {
364
        if ($data instanceof File) {
365
            $data = $this->processFile($data);
366
        }
367
368
        return $this->updateItem('directus_files', $id, $data);
369
    }
370
371
    /**
372
     * @inheritDoc
373
     */
374
    public function deleteFile($ids, $hard = false)
375
    {
376
        return $this->deleteItem('directus_files', $ids, $hard);
377
    }
378
379
    public function createPreferences($data)
380
    {
381
        if (!ArrayUtils::contains($data, ['title', 'table_name'])) {
382
            throw new \Exception('title and table_name are required');
383
        }
384
385
        $acl = $this->container->get('acl');
386
        $data['user'] = $acl->getUserId();
387
388
        return $this->createItem('directus_preferences', $data);
389
    }
390
391
    /**
392
     * @inheritdoc
393
     */
394
    public function createBookmark($data)
395
    {
396
        $acl = $this->container->get('acl');
397
        $data['user'] = $acl->getUserId();
398
399
        $preferences = $this->createPreferences(ArrayUtils::pick($data, [
400
            'title', 'table_name', 'sort', 'status', 'search_string', 'sort_order', 'columns_visible', 'user'
401
        ]));
402
403
        $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...
404
        $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...
405
        $bookmarkData = [
406
            'section' => 'search',
407
            'title' => $title,
408
            'url' => 'tables/' . $tableName . '/pref/' . $title,
409
            'user' => $data['user']
410
        ];
411
412
        return $this->createItem('directus_bookmarks', $bookmarkData);
413
    }
414
415
    /**
416
     * @inheritdoc
417
     */
418
    public function getBookmark($id)
419
    {
420
        return $this->getItem('directus_bookmarks', $id);
421
    }
422
423
    /**
424
     * @inheritdoc
425
     */
426
    public function getBookmarks($userId = null)
427
    {
428
        $filters = [];
429
        if ($userId !== null) {
430
            $filters = [
431
                'filters' => ['user' => ['eq' => $userId]]
432
            ];
433
        }
434
435
        return $this->getItems('directus_bookmarks', $filters);
436
    }
437
438
    /**
439
     * @inheritdoc
440
     */
441
    public function createColumn($data)
442
    {
443
        $data = $this->parseColumnData($data);
444
445
        $tableGateway = $this->getTableGateway($data['table_name']);
446
447
        $tableGateway->addColumn($data['table_name'], ArrayUtils::omit($data, ['table_name']));
448
449
        return $this->getColumn($data['table_name'], $data['column_name']);
450
    }
451
452
    /**
453
     * @inheritdoc
454
     */
455
    public function createGroup(array $data)
456
    {
457
        return $this->createItem('directus_groups', $data);
458
    }
459
460
    /**
461
     * @inheritdoc
462
     */
463
    public function createMessage(array $data)
464
    {
465
        $this->requiredAttributes(['from', 'message', 'subject'], $data);
466
        $this->requiredOneAttribute(['to', 'toGroup'], $data);
467
468
        $recipients = $this->getMessagesTo($data);
469
        $recipients = explode(',', $recipients);
470
        ArrayUtils::remove($data, ['to', 'toGroup']);
471
472
        $groupRecipients = [];
473
        $userRecipients = [];
474
        foreach ($recipients as $recipient) {
475
            $typeAndId = explode('_', $recipient);
476
            if ($typeAndId[0] == 0) {
477
                $userRecipients[] = $typeAndId[1];
478
            } else {
479
                $groupRecipients[] = $typeAndId[1];
480
            }
481
        }
482
483
        $ZendDb = $this->container->get('connection');
0 ignored issues
show
Coding Style introduced by
$ZendDb does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
484
        $acl = $this->container->get('acl');
485
        if (count($groupRecipients) > 0) {
486
            $usersTableGateway = new DirectusUsersTableGateway($ZendDb, $acl);
0 ignored issues
show
Coding Style introduced by
$ZendDb does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
487
            $result = $usersTableGateway->findActiveUserIdsByGroupIds($groupRecipients);
488
            foreach ($result as $item) {
489
                $userRecipients[] = $item['id'];
490
            }
491
        }
492
493
        $userRecipients[] = $acl->getUserId();
494
495
        $messagesTableGateway = new DirectusMessagesTableGateway($ZendDb, $acl);
0 ignored issues
show
Coding Style introduced by
$ZendDb does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
496
        $id = $messagesTableGateway->sendMessage($data, array_unique($userRecipients), $acl->getUserId());
497
498
        if ($id) {
499
            $Activity = new DirectusActivityTableGateway($ZendDb, $acl);
0 ignored issues
show
Coding Style introduced by
$Activity does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
500
            $data['id'] = $id;
501
            $Activity->recordMessage($data, $acl->getUserId());
0 ignored issues
show
Coding Style introduced by
$Activity does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
502
        }
503
504
        $message = $messagesTableGateway->fetchMessageWithRecipients($id, $acl->getUserId());
505
        $response = [
506
            'meta' => [
507
                'type' => 'item',
508
                'table' => 'directus_messages'
509
            ],
510
            'data' => $message
511
        ];
512
513
        return $this->createResponseFromData($response);
514
    }
515
516
    /**
517
     * @inheritdoc
518
     */
519
    public function sendMessage(array $data)
520
    {
521
        return $this->createMessage($data);
522
    }
523
524 View Code Duplication
    public function createPrivileges(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...
525
    {
526
        $connection = $this->container->get('connection');
527
        $acl = $this->container->get('acl');
528
        $privileges = new DirectusPrivilegesTableGateway($connection, $acl);
529
530
        $response = [
531
            'meta' => [
532
                'type' => 'item',
533
                'table' => 'directus_privileges'
534
            ],
535
            'data' => $privileges->insertPrivilege($data)
536
        ];
537
538
        return $this->createResponseFromData($response);
539
    }
540
541
    public function createTable($name, array $data = [])
542
    {
543
        $isTableNameAlphanumeric = preg_match("/[a-z0-9]+/i", $name);
544
        $zeroOrMoreUnderscoresDashes = preg_match("/[_-]*/i", $name);
545
546
        if (!($isTableNameAlphanumeric && $zeroOrMoreUnderscoresDashes)) {
547
            return $this->createResponseFromData(['error' => ['message' => 'invalid_table_name']]);
548
        }
549
550
        $schema = $this->container->get('schemaManager');
551
        $emitter = $this->container->get('emitter');
552
        if (!$schema->tableExists($name)) {
553
            $emitter->run('table.create:before', $name);
554
            // Through API:
555
            // Remove spaces and symbols from table name
556
            // And in lowercase
557
            $name = SchemaUtils::cleanTableName($name);
558
            $schema->createTable($name);
559
            $emitter->run('table.create', $name);
560
            $emitter->run('table.create:after', $name);
561
        }
562
563
        $connection = $this->container->get('connection');
564
        $acl = $this->container->get('acl');
565
        $privileges = new DirectusPrivilegesTableGateway($connection, $acl);
566
567
        return $this->createResponseFromData($privileges->insertPrivilege([
568
            'group_id' => 1,
569
            'table_name' => $name
570
        ]));
571
    }
572
573
    /**
574
     * @inheritdoc
575
     */
576
    public function createColumnUIOptions(array $data)
577
    {
578
        $this->requiredAttributes(['table', 'column', 'ui', 'options'], $data);
579
        $tableGateway = $this->getTableGateway('directus_ui');
580
581
        $table = $data['table'];
582
        $column = $data['column'];
583
        $ui = $data['ui'];
584
585
        $data = $data['options'];
586
        $keys = ['table_name' => $table, 'column_name' => $column, 'ui_name' => $ui];
587
        $uis = to_name_value($data, $keys);
588
589
        $column_settings = [];
0 ignored issues
show
Coding Style introduced by
$column_settings does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
590
        foreach ($uis as $col) {
591
            $existing = $tableGateway->select(['table_name' => $table, 'column_name' => $column, 'ui_name' => $ui, 'name' => $col['name']])->toArray();
592
            if (count($existing) > 0) {
593
                $col['id'] = $existing[0]['id'];
594
            }
595
            array_push($column_settings, $col);
0 ignored issues
show
Coding Style introduced by
$column_settings does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
596
        }
597
        $tableGateway->updateCollection($column_settings);
0 ignored issues
show
Coding Style introduced by
$column_settings does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
598
599
        $connection = $this->container->get('connection');
600
        $acl = $this->container->get('acl');
601
        $UiOptions = new DirectusUiTableGateway($connection, $acl);
0 ignored issues
show
Coding Style introduced by
$UiOptions does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
602
        $response = $UiOptions->fetchOptions($table, $column, $ui);
0 ignored issues
show
Coding Style introduced by
$UiOptions does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
603
604
        if (!$response) {
605
            $response = [
606
                'error' => [
607
                    'message' => sprintf('unable_to_find_column_%s_options_for_%s', ['column' => $column, 'ui' => $ui])
608
                ],
609
                'success' => false
610
            ];
611
        } else {
612
            $response = [
613
                'meta' => [
614
                    'type' => 'item',
615
                    'table' => 'directus_ui'
616
                ],
617
                'data' => $response
618
            ];
619
        }
620
621
        return $this->createResponseFromData($response);
622
    }
623
624 View Code Duplication
    public function getPreferences($table, $user)
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...
625
    {
626
        $acl = $this->container->get('acl');
627
        $connection = $this->container->get('connection');
628
        $preferencesTableGateway = new DirectusPreferencesTableGateway($connection, $acl);
629
630
        $response = [
631
            'meta' => [
632
                'type' => 'item',
633
                'table' => 'directus_preferences'
634
            ],
635
            'data' => $preferencesTableGateway->fetchByUserAndTableAndTitle($user, $table)
636
        ];
637
638
        return $this->createResponseFromData($response);
639
    }
640
641
    /**
642
     * @inheritdoc
643
     */
644
    public function deleteBookmark($id, $hard = false)
645
    {
646
        return $this->deleteItem('directus_bookmarks', $id, $hard);
647
    }
648
649
    /**
650
     * @inheritdoc
651
     */
652 View Code Duplication
    public function deleteColumn($name, $table)
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...
653
    {
654
        $tableGateway = $this->getTableGateway($table);
655
        $success = $tableGateway->dropColumn($name);
656
657
        $response = [
658
            'success' => (bool) $success
659
        ];
660
661
        if (!$success) {
662
            $response['error'] = [
663
                'message' => sprintf('unable_to_remove_column_%s', ['column_name' => $name])
664
            ];
665
        }
666
667
        return $this->createResponseFromData($response);
668
    }
669
670
    /**
671
     * @inheritdoc
672
     */
673
    public function deleteGroup($id, $hard = false)
674
    {
675
        return $this->deleteItem('directus_groups', $id, $hard);
676
    }
677
678
    /**
679
     * @inheritdoc
680
     */
681 View Code Duplication
    public function deleteTable($name)
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...
682
    {
683
        $tableGateway = $this->getTableGateway($name);
684
        $success = $tableGateway->drop();
685
686
        $response = [
687
            'success' => (bool) $success
688
        ];
689
690
        if (!$success) {
691
            $response['error'] = [
692
                'message' => sprintf('unable_to_remove_table_%s', ['table_name' => $name])
693
            ];
694
        }
695
696
        return $this->createResponseFromData($response);
697
    }
698
699
    public function getActivity(array $params = [])
700
    {
701
        $connection = $this->container->get('connection');
702
        $acl = $this->container->get('acl');
703
        $tableGateway = new DirectusActivityTableGateway($connection, $acl);
704
705
        $data = $tableGateway->fetchFeed($params);
706
707
        return $this->createResponseFromData($data);
708
    }
709
710
    /**
711
     * @inheritdoc
712
     */
713
    public function getRandom(array $options = [])
714
    {
715
        $length = (int) ArrayUtils::get($options, 'length', 32);
716
717
        return $this->createResponseFromData([
718
            'success' => true,
719
            'data' => [
720
                'random' => StringUtils::randomString($length)
721
            ]
722
        ]);
723
    }
724
725
    /**
726
     * @inheritdoc
727
     */
728
    public function getHash($string, array $options = [])
729
    {
730
        $hashManager = $this->container->get('hashManager');
731
732
        try {
733
            $hash = $hashManager->hash($string, $options);
734
            $data = [
735
                'success' => true,
736
                'data' => [
737
                    'hash' => $hash
738
                ]
739
            ];
740
        } catch (\Exception $e) {
741
            $data = [
742
                'success' => false,
743
                'error' => [
744
                    'message' => $e->getMessage()
745
                ]
746
            ];
747
        }
748
749
        return $this->createResponseFromData($data);
750
    }
751
752
    /**
753
     * Get a table gateway for the given table name
754
     *
755
     * @param $tableName
756
     *
757
     * @return RelationalTableGateway
758
     */
759
    protected function getTableGateway($tableName)
760
    {
761
        if (!array_key_exists($tableName, $this->tableGateways)) {
762
            $acl = TableSchema::getAclInstance();
763
            $this->tableGateways[$tableName] = new RelationalTableGateway($tableName, $this->connection, $acl);
764
        }
765
766
        return $this->tableGateways[$tableName];
767
    }
768
769
    public function processDataOnDirectusUsers($data)
770
    {
771
        $data = parent::processDataOnDirectusUsers($data);
772
773
        if (ArrayUtils::has($data, 'password')) {
774
            // @TODO: use Auth hash password
775
            $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT, ['cost' => 12]);
776
        }
777
778
        return $data;
779
    }
780
}
781