Passed
Push — master ( 336aa4...192c12 )
by Fran
02:09
created

NOSQLService::parseCollection()   B

Complexity

Conditions 7
Paths 11

Size

Total Lines 26
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

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