Passed
Push — master ( 311d79...92ccf2 )
by Fran
05:42
created

NOSQLService::getDomainPaths()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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