Completed
Push — d64 ( 885ace...e16005 )
by Welling
02:19
created

ClientFactory::create()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 2
dl 0
loc 15
ccs 8
cts 10
cp 0.8
crap 3.072
rs 9.4285
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\DirectusSettingsTableGateway;
16
use Directus\Filesystem\Files;
17
use Directus\Filesystem\Filesystem;
18
use Directus\Filesystem\FilesystemFactory;
19
use Directus\Hook\Emitter;
20
use Directus\Util\ArrayUtils;
21
use Directus\Database\TableSchema;
22
23
/**
24
 * Client
25
 *
26
 * @author Welling Guzmán <[email protected]>
27
 */
28
class ClientFactory
29
{
30
    /**
31
     * @var ClientFactory
32
     */
33
    protected static $instance = null;
34
35
    /**
36
     * @var Container
37
     */
38
    protected $container;
39
40
    /**
41
     * @var array
42
     */
43
    protected $config = [];
44
45
    protected $settings = [];
46
47
    protected $emitter;
48
49
    protected $files;
50
51
    /**
52
     * @var array
53
     */
54
    protected $defaultConfig = [
55
        'environment' => 'development',
56
        'database' => [
57
            'driver' => 'pdo_mysql'
58
        ],
59
        'status' => [
60
            'column_name' => 'active',
61
            'deleted_value' => 0,
62
            'active_value' => 1,
63
            'draft_value' => 2,
64
            'mapping' => [
65
                0 => [
66
                    'name' => 'Delete',
67
                    'color' => '#C1272D',
68
                    'sort' => 3
69
                ],
70
                1 => [
71
                    'name' => 'Active',
72
                    'color' => '#5B5B5B',
73
                    'sort' => 1
74
                ],
75
                2 => [
76
                    'name' => 'Draft',
77
                    'color' => '#BBBBBB',
78
                    'sort' => 2
79
                ]
80
            ]
81
        ],
82
        'filesystem' => [
83
            'adapter' => 'local',
84
            // By default media directory are located at the same level of directus root
85
            // To make them a level up outsite the root directory
86
            // use this instead
87
            // Ex: 'root' => realpath(BASE_PATH.'/../storage/uploads'),
88
            // Note: BASE_PATH constant doesn't end with trailing slash
89
            'root' => '/storage/uploads',
90
            // This is the url where all the media will be pointing to
91
            // here all assets will be (yourdomain)/storage/uploads
92
            // same with thumbnails (yourdomain)/storage/uploads/thumbs
93
            'root_url' => '/storage/uploads',
94
            'root_thumb_url' => '/storage/uploads/thumbs',
95
            //   'key'    => 's3-key',
96
            //   'secret' => 's3-key',
97
            //   'region' => 's3-region',
98
            //   'version' => 's3-version',
99
            //   'bucket' => 's3-bucket'
100
        ],
101
    ];
102
103
    /**
104
     * @param $userToken
105
     * @param array $options
106
     *
107
     * @return ClientLocal|ClientRemote
108
     */
109 38
    public static function create($userToken, $options = [])
110
    {
111 38
        if (static::$instance == null) {
112 2
            static::$instance = new static;
113 2
        }
114
115 38
        if (!is_array($userToken)) {
116 38
            $newClient = static::$instance->createRemoteClient($userToken, $options);
117 38
        } else {
118
            $options = $userToken;
119
            $newClient = static::$instance->createLocalClient($options);
120
        }
121
122 38
        return $newClient;
123
    }
124
125
    /**
126
     * Creates a new local client instance
127
     *
128
     * @param array $options
129
     *
130
     * @return ClientLocal
131
     */
132
    public function createLocalClient(array $options)
133
    {
134
        $this->container = $container = new Container();
135
136
        $options = ArrayUtils::defaults($this->defaultConfig, $options);
137
        $container->set('config', $options);
138
139
        $dbConfig = ArrayUtils::get($options, 'database', []);
140
141
        $config = ArrayUtils::omit($options, 'database');
142
        // match the actual directus status mapping config key
143
        $config['statusMapping'] = $config['status']['mapping'];
144
        unset($config['status']['mapping']);
145
146
        if (!defined('STATUS_DELETED_NUM')) {
147
            define('STATUS_DELETED_NUM', ArrayUtils::get($config, 'status.deleted_value', 0));
148
        }
149
150
        if (!defined('STATUS_ACTIVE_NUM')) {
151
            define('STATUS_ACTIVE_NUM', ArrayUtils::get($config, 'status.active_value', 1));
152
        }
153
154
        if (!defined('STATUS_DRAFT_NUM')) {
155
            define('STATUS_DRAFT_NUM', ArrayUtils::get($config, 'status.draft_value', 2));
156
        }
157
158
        if (!defined('STATUS_COLUMN_NAME')) {
159
            define('STATUS_COLUMN_NAME', ArrayUtils::get($config, 'status.column_name', 'active'));
160
        }
161
162
        if (!defined('DIRECTUS_ENV')) {
163
            define('DIRECTUS_ENV', ArrayUtils::get($config, 'environment', 'development'));
164
        }
165
166
        $connection = new Connection($dbConfig);
167
        $connection->connect();
168
        $container->set('connection', $connection);
169
170
        $acl = new \Directus\Permissions\Acl();
171
        $acl->setUserId(1);
172
        $acl->setGroupId(1);
173
        $acl->setGroupPrivileges([
174
            '*' => [
175
                'id' => 1,
176
                'table_name' => '*',
177
                'group_id' => 1,
178
                'read_field_blacklist' => [],
179
                'write_field_blacklist' => [],
180
                'nav_listed' => 1,
181
                'status_id' => 0,
182
                'allow_view' => 2,
183
                'allow_add' => 1,
184
                'allow_edit' => 2,
185
                'allow_delete' => 2,
186
                'allow_alter' => 1
187
            ]
188
        ]);
189
        $container->set('acl', $acl);
190
191
        $schema = new \Directus\Database\Schemas\Sources\MySQLSchema($connection);
192
        $container->set('schemaSource', $schema);
193
        $schema = new \Directus\Database\SchemaManager($schema);
194
        $container->set('schemaManager', $schema);
195
        TableSchema::setSchemaManagerInstance($schema);
196
        TableSchema::setAclInstance($acl);
197
        TableSchema::setConnectionInstance($connection);
198
        TableSchema::setConfig($config);
199
200
        $container->singleton('emitter', function() {
201
            return $this->getEmitter();
202
        });
203
        $container->set('settings', function(Container $container) {
204
            $adapter = $container->get('connection');
205
            $acl = $container->get('acl');
206
            $Settings = new DirectusSettingsTableGateway($adapter, $acl);
207
208
            return $Settings->fetchCollection('files', [
209
                'thumbnail_size', 'thumbnail_quality', 'thumbnail_crop_enabled'
210
            ]);
211
        });
212
        $container->singleton('files', function() {
213
            return $this->getFiles();
214
        });
215
216
        BaseTableGateway::setHookEmitter($container->get('emitter'));
217
        BaseTableGateway::setContainer($container);
218
219
        $client = new ClientLocal($connection);
220
        $client->setContainer($container);
221
222
        return $client;
223
    }
224
225
    public function getFiles()
226
    {
227
        static $files = null;
228
        if ($files == null) {
229
            $config = $this->container->get('config');
230
            $filesystemConfig = ArrayUtils::get($config, 'filesystem', []);
231
            $filesystem = new Filesystem(FilesystemFactory::createAdapter($filesystemConfig));
0 ignored issues
show
Bug introduced by
It seems like \Directus\Filesystem\Fil...pter($filesystemConfig) can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
232
            $settings = $this->container->get('settings');
233
            $emitter = $this->container->get('emitter');
234
            $files = new Files($filesystem, $filesystemConfig, $settings, $emitter);
235
        }
236
237
        return $files;
238
    }
239
240
    protected function getEmitter()
241
    {
242
        static $emitter = null;
243
        if ($emitter) {
244
            return $emitter;
245
        }
246
247
        $emitter = new Emitter();
248
        $acl = $this->container->get('acl');
249
        $adapter = $this->container->get('connection');
250
251
        $emitter->addAction('table.insert.directus_groups', function ($data) use ($acl, $adapter) {
252
            $privilegesTable = new DirectDirectusPrivilegesTableGateway($adapter, $acl);
253
254
            $privilegesTable->insertPrivilege([
255
                'group_id' => $data['id'],
256
                'allow_view' => 1,
257
                'allow_add' => 0,
258
                'allow_edit' => 1,
259
                'allow_delete' => 0,
260
                'allow_alter' => 0,
261
                'table_name' => 'directus_users',
262
                'read_field_blacklist' => 'token',
263
                'write_field_blacklist' => 'group,token'
264
            ]);
265
        });
266
267
        $emitter->addFilter('table.insert:before', function($payload) {
268
            // $tableName, $data
269
            if (func_num_args() == 2) {
270
                $tableName = func_get_arg(0);
271
                $data = func_get_arg(1);
272
            } else {
273
                $tableName = $payload->tableName;
274
                $data = $payload->data;
275
            }
276
277
            if ($tableName == 'directus_files') {
278
                unset($data['data']);
279
                $data['user'] = 1;
280
            }
281
282
            return func_num_args() == 2 ? $data : $payload;
283
        });
284
285
        // Add file url and thumb url
286
        $config = $this->container->get('config');
287
        $files = $this->container->get('files');
288
        $emitter->addFilter('table.select', function($payload) use ($config, $files) {
289
            if (func_num_args() == 2) {
290
                $result = func_get_arg(0);
291
                $selectState = func_get_arg(1);
292
            } else {
293
                $selectState = $payload->selectState;
294
                $result = $payload->result;
295
            }
296
297
            if ($selectState['table'] == 'directus_files') {
298
                $fileRows = $result->toArray();
299
                foreach ($fileRows as &$row) {
300
                    $fileURL = ArrayUtils::get($config, 'filesystem.root_url', '');
301
                    $thumbnailURL = ArrayUtils::get($config, 'filesystem.root_thumb_url', '');
302
                    $thumbnailFilenameParts = explode('.', $row['name']);
303
                    $thumbnailExtension = array_pop($thumbnailFilenameParts);
304
305
                    $row['url'] = $fileURL . '/' . $row['name'];
306
                    if (in_array($thumbnailExtension, ['tif', 'tiff', 'psd', 'pdf'])) {
307
                        $thumbnailExtension = 'jpg';
308
                    }
309
310
                    $thumbnailFilename = $row['id'] . '.' . $thumbnailExtension;
311
                    $row['thumbnail_url'] = $thumbnailURL . '/' . $thumbnailFilename;
312
313
                    // filename-ext-100-100-true.jpg
314
                    // @TODO: This should be another hook listener
315
                    $row['thumbnail_url'] = null;
316
                    $filename = implode('.', $thumbnailFilenameParts);
317
                    if ($row['type'] == 'embed/vimeo') {
318
                        $oldThumbnailFilename = $row['name'] . '-vimeo-220-124-true.jpg';
319
                    } else {
320
                        $oldThumbnailFilename = $filename . '-' . $thumbnailExtension . '-160-160-true.jpg';
321
                    }
322
323
                    // 314551321-vimeo-220-124-true.jpg
324
                    // hotfix: there's not thumbnail for this file
325
                    if ($files->exists('thumbs/' . $oldThumbnailFilename)) {
326
                        $row['thumbnail_url'] = $thumbnailURL . '/' . $oldThumbnailFilename;
327
                    }
328
329
                    if ($files->exists('thumbs/' . $thumbnailFilename)) {
330
                        $row['thumbnail_url'] = $thumbnailURL . '/' . $thumbnailFilename;
331
                    }
332
333
                    /*
334
                    $embedManager = Bootstrap::get('embedManager');
335
                    $provider = $embedManager->getByType($row['type']);
336
                    $row['html'] = null;
337
                    if ($provider) {
338
                        $row['html'] = $provider->getCode($row);
339
                    }
340
                    */
341
                }
342
343
                $filesArrayObject = new \ArrayObject($fileRows);
344
                $result->initialize($filesArrayObject->getIterator());
345
            }
346
347
            return (func_num_args() == 2) ? $result : $payload;
348
        });
349
350
        return $emitter;
351
    }
352
353
    /**
354
     * Create a new remote client instance
355
     *
356
     * @param $userToken
357
     * @param array $options
358
     *
359
     * @return ClientRemote
360
     */
361 38
    public function createRemoteClient($userToken, array $options = [])
362
    {
363 38
        return new ClientRemote($userToken, $options);
364
    }
365
}