Completed
Push — master ( 957a77...d1fc9e )
by Fran
02:04
created

NOSQLService::createIndexes()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nc 3
nop 2
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, $collection) {
171
        try {
172
            $collection = $db->selectCollection($collection['name']);
173
            $collection->createIndex(['$**' => 'text'], ['name' => 'idx_text']);
174
        } catch (\Exception $exception) {
175
            Logger::log($exception->getMessage(), LOG_DEBUG);
176
        }
177
    }
178
179
    /**
180
     * @param $module
181
     * @return bool
182
     * @throws \PSFS\base\exception\GeneratorException
183
     */
184
    public function syncCollections($module) {
185
        $db = ParserService::getInstance()->createConnection($module);
186
        $collections = $this->getCollections($module);
187
        $success = true;
188
        foreach($collections as $raw) {
189
            $jsonSchema = $this->parseCollection($raw);
190
            try {
191
                /** @var BSONDocument $result */
192
                $result = $db->createCollection($raw['name'], [
193
                    'validation' => [
194
                        '$jsonSchema' => $jsonSchema->toArray(),
195
                    ]
196
                ]);
197
                $response = $result->getArrayCopy();
198
                $success = array_key_exists('ok', $response) && $response['ok'] > 0;
199
            } catch(\Exception $exception) {
200
                if($exception->getCode() !== 48) {
201
                    $success = false;
202
                }
203
            }
204
            $this->createIndexes($db, $raw);
205
        }
206
        return $success;
207
    }
208
209
    /**
210
     * @param array $raw
211
     * @return JsonSchemaDto
212
     * @throws \PSFS\base\exception\GeneratorException
213
     */
214
    private function parseCollection($raw)
215
    {
216
        $jsonSchema = new JsonSchemaDto(false);
217
        foreach ($raw['properties'] as $rawProperty) {
218
            switch ($rawProperty['type']) {
219
                case NOSQLBase::NOSQL_TYPE_INTEGER:
220
                case NOSQLBase::NOSQL_TYPE_DOUBLE:
221
                case NOSQLBase::NOSQL_TYPE_LONG:
222
                    $property = new NumberPropertyDto(false);
223
                    break;
224
                case NOSQLBase::NOSQL_TYPE_ENUM:
225
                    $property = new EnumPropertyDto(false);
226
                    $property->enum = explode('|', $rawProperty['enum']);
227
                    break;
228
                default:
229
                    $property = new StringPropertyDto(false);
230
                    break;
231
            }
232
            if(array_key_exists('type', $rawProperty)) {
233
                $property->bsonType = $rawProperty['type'];
234
            }
235
            if(array_key_exists('description', $rawProperty)) {
236
                $property->description = $rawProperty['description'];
237
            }
238
            if (array_key_exists('required', $rawProperty) && $rawProperty['required']) {
239
                $jsonSchema->required[] = $rawProperty['name'];
240
            }
241
            $jsonSchema->properties[$rawProperty['name']] = $property->toArray();
242
        }
243
        return $jsonSchema;
244
    }
245
246
    /**
247
     * @return array
248
     * @throws \ReflectionException
249
     */
250
    public function getValidations() {
251
        $fieldTypes = new \ReflectionClass(Field::class);
252
        $validations = [];
253
        foreach($fieldTypes->getConstants() as $validation) {
254
            $validations[] = $validation;
255
        }
256
        return $validations;
257
    }
258
}
259