Completed
Push — master ( 64eab5...f30352 )
by Fran
02:01
created

NOSQLService   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 239
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 43
eloc 113
dl 0
loc 239
rs 8.96
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getCollections() 0 7 2
A getDomains() 0 12 4
A getTypes() 0 3 1
A setTypes() 0 3 1
A setCollections() 0 27 5
A init() 0 4 1
A writeTemplateToFile() 0 14 4
A extractTypes() 0 8 3
B parseCollection() 0 30 10
A getValidations() 0 7 2
A syncCollections() 0 23 5
A createIndexes() 0 14 5

How to fix   Complexity   

Complex Class

Complex classes like NOSQLService 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.

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 NOSQLService, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace NOSQL\Services;
3
4
use MongoDB\Database;
5
use MongoDB\Model\BSONDocument;
6
use NOSQL\Dto\CollectionDto;
7
use NOSQL\Dto\Validation\EnumPropertyDto;
8
use NOSQL\Dto\Validation\JsonSchemaDto;
9
use NOSQL\Dto\Validation\NumberPropertyDto;
10
use NOSQL\Dto\Validation\StringPropertyDto;
11
use NOSQL\Services\Base\NOSQLBase;
12
use PSFS\base\Cache;
13
use PSFS\base\dto\Field;
14
use PSFS\base\Logger;
15
use PSFS\base\Service;
16
use PSFS\base\Template;
17
use PSFS\base\types\helpers\GeneratorHelper;
18
19
/**
20
* Class NOSQLService
21
* @package NOSQL\Services
22
* @author Fran López <[email protected]>
23
* @version 1.0
24
* Autogenerated service [2019-01-03 15:23:58]
25
*/
26
class NOSQLService extends Service {
27
28
    /**
29
     * @Injectable
30
     * @var \PSFS\base\Cache
31
     */
32
    protected $cache;
33
34
    /**
35
     * @var array
36
     */
37
    private $types = [];
38
39
    /**
40
     * @return array
41
     */
42
    public function getTypes()
43
    {
44
        return $this->types;
45
    }
46
47
    /**
48
     * @param array $types
49
     */
50
    public function setTypes($types)
51
    {
52
        $this->types = $types;
53
    }
54
55
    /**
56
     * @throws \ReflectionException
57
     */
58
    private function extractTypes() {
59
        $baseClass = new \ReflectionClass(NOSQLBase::class);
60
        if(null !== $baseClass) {
61
            $types = [];
62
            foreach($baseClass->getConstants() as $constant) {
63
                $types[] = $constant;
64
            }
65
            $this->setTypes($types);
66
        }
67
    }
68
69
    /**
70
     * @throws \ReflectionException
71
     */
72
    public function init()
73
    {
74
        parent::init();
75
        $this->extractTypes();
76
    }
77
78
    /**
79
     * @return array
80
     */
81
    public function getDomains() {
82
        $domains = [];
83
        $storedDomains = $this->cache->getDataFromFile(CONFIG_DIR . DIRECTORY_SEPARATOR . 'domains.json', Cache::JSON, TRUE);
84
        if(!empty($storedDomains)) {
85
            foreach($storedDomains as $domain => $data) {
86
                $domainLabel = str_replace(['@', '/'], '', $domain);
87
                if('ROOT' !== $domainLabel) {
88
                    $domains[] = $domainLabel;
89
                }
90
            }
91
        }
92
        return $domains;
93
    }
94
95
    /**
96
     * @param string $module
97
     * @return array
98
     */
99
    public function getCollections($module) {
100
        $collections = [];
101
        $schemaFilename = CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Config' . DIRECTORY_SEPARATOR . 'schema.json';
102
        if(file_exists($schemaFilename)) {
103
            $collections = $this->cache->getDataFromFile($schemaFilename, Cache::JSON, TRUE);
104
        }
105
        return $collections;
106
    }
107
108
    /**
109
     * @param string $module
110
     * @param array $collections
111
     * @throws \PSFS\base\exception\GeneratorException
112
     */
113
    public function setCollections($module, $collections) {
114
        $schemaFilename = CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Config' . DIRECTORY_SEPARATOR . 'schema.json';
115
        $this->cache->storeData($schemaFilename, $collections, Cache::JSON, true);
116
        $tpl = Template::getInstance();
117
        $tpl->addPath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'Templates', 'NOSQL');
118
        $files = [
119
            '@NOSQL/generator/model.base.php.twig' => CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Models' . DIRECTORY_SEPARATOR . 'Base',
120
            '@NOSQL/generator/model.php.twig' => CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Models',
121
            '@NOSQL/generator/api.php.twig' => CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Api',
122
            '@NOSQL/generator/api.base.php.twig' => CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Api' . DIRECTORY_SEPARATOR . 'Base',
123
            '@NOSQL/generator/dto.php.twig' => CORE_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'Dto' . DIRECTORY_SEPARATOR . 'Models',
124
        ];
125
        foreach($collections as $raw) {
126
            $collection = new CollectionDto(false);
127
            $collection->fromArray($raw);
128
            foreach($files as $template => $path) {
129
                GeneratorHelper::createDir($path);
130
                $templateDump = $tpl->dump($template, [
131
                    'domain' => $module,
132
                    'model' => $collection->name,
133
                    'properties' => $collection->properties,
134
                ]);
135
                $force = false;
136
                if(false !== strpos($template, 'dto') || false !== strpos(strtolower($template), 'base')) {
137
                    $force = true;
138
                }
139
                $this->writeTemplateToFile($templateDump, $path . DIRECTORY_SEPARATOR . $collection->name . '.php', $force);
140
            }
141
        }
142
    }
143
144
    /**
145
     * @param string $fileContent
146
     * @param string $filename
147
     * @param bool $force
148
     * @return bool
149
     */
150
    private function writeTemplateToFile($fileContent, $filename, $force = false)
151
    {
152
        $created = false;
153
        if ($force || !file_exists($filename)) {
154
            try {
155
                $this->cache->storeData($filename, $fileContent, Cache::TEXT, true);
156
                $created = true;
157
            } catch (\Exception $e) {
158
                Logger::log($e->getMessage(), LOG_ERR);
159
            }
160
        } else {
161
            Logger::log($filename . t(' not exists or cant write'), LOG_ERR);
162
        }
163
        return $created;
164
    }
165
166
    /**
167
     * @param Database $db
168
     * @param $collection
169
     */
170
    private function createIndexes(Database $db, $collectionDto) {
171
        try {
172
            $collection = $db->selectCollection($collectionDto['name']);
173
            $textIndexes = [];
174
            foreach($collectionDto['properties'] as $property) {
175
                if(in_array($property['type'], [NOSQLBase::NOSQL_TYPE_STRING, NOSQLBase::NOSQL_TYPE_OBJECT])) {
176
                    $textIndexes[$property['name']] = 'text';
177
                }
178
            }
179
            if(count($textIndexes)) {
180
                $collection->createIndex($textIndexes, ['name' => 'idx_text_' . $collectionDto['name']]);
181
            }
182
        } catch (\Exception $exception) {
183
            Logger::log($exception->getMessage(), LOG_DEBUG);
184
        }
185
    }
186
187
    /**
188
     * @param $module
189
     * @return bool
190
     * @throws \PSFS\base\exception\GeneratorException
191
     */
192
    public function syncCollections($module) {
193
        $db = ParserService::getInstance()->createConnection($module);
194
        $collections = $this->getCollections($module);
195
        $success = true;
196
        foreach($collections as $raw) {
197
            $jsonSchema = $this->parseCollection($raw);
198
            try {
199
                /** @var BSONDocument $result */
200
                $result = $db->createCollection($raw['name'], [
201
                    'validation' => [
202
                        '$jsonSchema' => $jsonSchema->toArray(),
203
                    ]
204
                ]);
205
                $response = $result->getArrayCopy();
206
                $success = array_key_exists('ok', $response) && $response['ok'] > 0;
207
            } catch(\Exception $exception) {
208
                if($exception->getCode() !== 48) {
209
                    $success = false;
210
                }
211
            }
212
            $this->createIndexes($db, $raw);
213
        }
214
        return $success;
215
    }
216
217
    /**
218
     * @param array $raw
219
     * @return JsonSchemaDto
220
     * @throws \PSFS\base\exception\GeneratorException
221
     */
222
    private function parseCollection($raw)
223
    {
224
        $jsonSchema = new JsonSchemaDto(false);
225
        foreach ($raw['properties'] as $rawProperty) {
226
            switch ($rawProperty['type']) {
227
                case NOSQLBase::NOSQL_TYPE_INTEGER:
228
                case NOSQLBase::NOSQL_TYPE_DOUBLE:
229
                case NOSQLBase::NOSQL_TYPE_LONG:
230
                    $property = new NumberPropertyDto(false);
231
                    break;
232
                case NOSQLBase::NOSQL_TYPE_ENUM:
233
                    $property = new EnumPropertyDto(false);
234
                    $property->enum = explode('|', $rawProperty['enum']);
235
                    break;
236
                default:
237
                    $property = new StringPropertyDto(false);
238
                    break;
239
            }
240
            if(array_key_exists('type', $rawProperty)) {
241
                $property->bsonType = $rawProperty['type'];
242
            }
243
            if(array_key_exists('description', $rawProperty)) {
244
                $property->description = $rawProperty['description'];
245
            }
246
            if (array_key_exists('required', $rawProperty) && $rawProperty['required']) {
247
                $jsonSchema->required[] = $rawProperty['name'];
248
            }
249
            $jsonSchema->properties[$rawProperty['name']] = $property->toArray();
250
        }
251
        return $jsonSchema;
252
    }
253
254
    /**
255
     * @return array
256
     * @throws \ReflectionException
257
     */
258
    public function getValidations() {
259
        $fieldTypes = new \ReflectionClass(Field::class);
260
        $validations = [];
261
        foreach($fieldTypes->getConstants() as $validation) {
262
            $validations[] = $validation;
263
        }
264
        return $validations;
265
    }
266
}
267