SchemaBuilder   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 23
eloc 99
dl 0
loc 228
ccs 101
cts 101
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A buildInfoBlock() 0 30 3
A updateProperty() 0 15 3
A generateBitrixFields() 0 15 4
A build() 0 11 3
A getBitrixInfoBlock() 0 12 1
A getSiteCodes() 0 9 2
A assert() 0 4 2
A getBitrixProperty() 0 12 1
A addProperty() 0 12 2
A buildProperty() 0 22 2
1
<?php
2
3
namespace BitrixToolkit\BitrixEntityMapper;
4
5
use CIBlock;
6
use CIBlockProperty;
7
use CSite;
8
use InvalidArgumentException;
9
use BitrixToolkit\BitrixEntityMapper\Annotation\Entity\InfoBlock;
10
use BitrixToolkit\BitrixEntityMapper\Annotation\Property\Property;
11
use BitrixToolkit\BitrixEntityMapper\Map\EntityMap;
12
13
class SchemaBuilder
14
{
15
    /**
16
     * @param EntityMap $entityMap
17
     * @return bool
18
     * @throws InvalidArgumentException
19
     */
20 3
    public static function build(EntityMap $entityMap)
21
    {
22 3
        self::buildInfoBlock($entityMap->getAnnotation());
23 2
        foreach ($entityMap->getProperties() as $propertyMap) {
24 2
            $propAnnotation = $propertyMap->getAnnotation();
25 2
            if ($propAnnotation instanceof Property) {
26 2
                self::buildProperty($entityMap->getAnnotation(), $propAnnotation);
27
            }
28
        }
29
30 2
        return true;
31
    }
32
33
    /**
34
     * @param InfoBlock $annotation
35
     * @return int
36
     * @throws InvalidArgumentException
37
     */
38 3
    protected static function buildInfoBlock(InfoBlock $annotation)
39
    {
40 3
        $type = $annotation->getType();
41 3
        self::assert($type, 'Не указан тип инфоблока.');
42 2
        $code = $annotation->getCode();
43 2
        self::assert($code, 'Не указан код инфоблока.');
44 2
        $name = $annotation->getName();
45
46 2
        $fields = [
47 2
            'LID' => self::getSiteCodes(),
48 2
            'CODE' => $code,
49 2
            'IBLOCK_TYPE_ID' => $type,
50 2
            'NAME' => $name ? $name : $code,
51 2
            'GROUP_ID' => ['1' => 'X', '2' => 'W']
52 2
        ];
53
54 2
        $exist = self::getBitrixInfoBlock($type, $code);
55 2
        if (!empty($exist['ID'])) {
56 1
            $iBlockId = $exist['ID'];
57 1
            $cIBlock = new CIBlock();
58 1
            $isUpdated = $cIBlock->Update($iBlockId, $fields);
59 1
            self::assert($isUpdated, strip_tags($cIBlock->LAST_ERROR));
60
        } else {
61 1
            $cIBlock = new CIBlock();
62
            /** @var int|bool $iBlockId */
63 1
            $iBlockId = $cIBlock->Add($fields);
64 1
            self::assert($iBlockId, strip_tags($cIBlock->LAST_ERROR));
65
        }
66
67 2
        return $iBlockId;
68
    }
69
70
    /**
71
     * @return string[]
72
     */
73 2
    protected static function getSiteCodes()
74
    {
75 2
        $siteCodes = [];
76 2
        $rs = CSite::GetList($by, $order);
77 2
        while ($site = $rs->Fetch()) {
78 2
            $siteCodes[] = $site['LID'];
79
        }
80
81 2
        return $siteCodes;
82
    }
83
84
    /**
85
     * @param mixed $term
86
     * @param string $msg
87
     * @throws InvalidArgumentException
88
     */
89 3
    protected static function assert($term, $msg)
90
    {
91 3
        if (!$term) {
92 1
            throw new InvalidArgumentException($msg);
93
        }
94
    }
95
96
    /**
97
     * @param string $type
98
     * @param string $code
99
     * @return array
100
     * @throws InvalidArgumentException
101
     */
102 2
    protected static function getBitrixInfoBlock($type, $code)
103
    {
104 2
        self::assert($type, 'Не указан тип инфоблока.');
105 2
        self::assert($code, 'Не указан код инфоблока.');
106
107 2
        $iBlock = CIBlock::GetList(null, [
108 2
            '=TYPE' => $type,
109 2
            '=CODE' => $code,
110 2
            'CHECK_PERMISSIONS' => 'N'
111 2
        ])->Fetch();
112
113 2
        return $iBlock;
114
    }
115
116
    /**
117
     * @param int $iBlockId
118
     * @param string $code
119
     * @return array|null
120
     * @throws InvalidArgumentException
121
     */
122 2
    protected static function getBitrixProperty($iBlockId, $code)
123
    {
124 2
        self::assert($iBlockId, 'Не указан ID инфоблока.');
125 2
        self::assert($code, 'Не указан код свойства.');
126
127 2
        $prop = CIBlockProperty::GetList(null, [
128 2
            'IBLOCK_ID' => $iBlockId,
129 2
            'CODE' => $code,
130 2
            'CHECK_PERMISSIONS' => 'N'
131 2
        ])->Fetch();
132
133 2
        return $prop;
134
    }
135
136
    protected static $propertyMap = [
137
        Property::TYPE_INTEGER => ['PROPERTY_TYPE' => 'N', 'USER_TYPE' => false],
138
        Property::TYPE_FLOAT => ['PROPERTY_TYPE' => 'N', 'USER_TYPE' => false],
139
        Property::TYPE_DATETIME => ['PROPERTY_TYPE' => 'S', 'USER_TYPE' => 'DateTime'],
140
        Property::TYPE_FILE => ['PROPERTY_TYPE' => 'F', 'USER_TYPE' => false],
141
        Property::TYPE_BOOLEAN => ['PROPERTY_TYPE' => 'L', 'LIST_TYPE' => 'C', 'USER_TYPE' => false],
142
        Property::TYPE_ENTITY => ['PROPERTY_TYPE' => 'E', 'USER_TYPE' => false],
143
        Property::TYPE_STRING => ['PROPERTY_TYPE' => 'S', 'USER_TYPE' => false],
144
    ];
145
146
    /**
147
     * @param InfoBlock $entityAnnotation
148
     * @param Property $propertyAnnotation
149
     * @return bool
150
     * @throws InvalidArgumentException
151
     */
152 2
    protected static function buildProperty(InfoBlock $entityAnnotation, Property $propertyAnnotation)
153
    {
154 2
        self::assert($propertyAnnotation->getCode(), 'Не указан код свойства.');
155 2
        self::assert($propertyAnnotation->getType(), 'Не указан тип свойства.');
156
157 2
        $iBlock = self::getBitrixInfoBlock($entityAnnotation->getType(), $entityAnnotation->getCode());
158 2
        self::assert(
159 2
            !empty($iBlock['ID']),
160 2
            "Инфоблок с кодом {$entityAnnotation->getCode()} и типом {$entityAnnotation->getType()} не найден."
161 2
        );
162
163 2
        $fields = self::generateBitrixFields($iBlock['ID'], $propertyAnnotation);
164
165 2
        $exist = self::getBitrixProperty($iBlock['ID'], $propertyAnnotation->getCode());
166 2
        if (!empty($exist['ID'])) {
167 1
            $propId = $exist['ID'];
168 1
            self::updateProperty($propId, $propertyAnnotation, $fields);
169
        } else {
170 1
            $propId = self::addProperty($propertyAnnotation, $fields);
171
        }
172
173 2
        return $propId;
174
    }
175
176
    /**
177
     * @param int $iBlockId
178
     * @param Property $propertyAnnotation
179
     * @return array
180
     * @throws InvalidArgumentException
181
     */
182 2
    protected static function generateBitrixFields($iBlockId, Property $propertyAnnotation)
183
    {
184 2
        $fields = [
185 2
            'IBLOCK_ID' => $iBlockId,
186 2
            'CODE' => $propertyAnnotation->getCode(),
187 2
            'NAME' => $propertyAnnotation->getName() ? $propertyAnnotation->getName() : $propertyAnnotation->getCode(),
188 2
            'MULTIPLE' => $propertyAnnotation->isMultiple() ? 'Y' : 'N',
189 2
            'FILTRABLE' => 'Y'
190 2
        ];
191
192 2
        if (array_key_exists($propertyAnnotation->getType(), self::$propertyMap)) {
193 2
            $fields += self::$propertyMap[$propertyAnnotation->getType()];
194
        }
195
196 2
        return $fields;
197
    }
198
199
    /**
200
     * @param int $propId
201
     * @param Property $propertyAnnotation
202
     * @param array $fields
203
     * @return bool
204
     * @throws InvalidArgumentException
205
     */
206 1
    protected static function updateProperty($propId, Property $propertyAnnotation, array $fields)
207
    {
208 1
        $type = $propertyAnnotation->getType();
209 1
        if ($type === Property::TYPE_BOOLEAN) {
210 1
            $existEnum = CIBlockProperty::GetPropertyEnum($propId, null, ['XML_ID' => 'Y', 'VALUE' => 'Y'])->Fetch();
211 1
            if (!$existEnum) {
212 1
                $fields += ['VALUES' => [['XML_ID' => 'Y', 'VALUE' => 'Y', 'DEF' => 'N']]];
213
            }
214
        }
215
216 1
        $cIBlockProperty = new CIBlockProperty();
217 1
        $isUpdated = $cIBlockProperty->Update($propId, $fields);
218 1
        self::assert($isUpdated, strip_tags($cIBlockProperty->LAST_ERROR));
219
220 1
        return $isUpdated;
221
    }
222
223
    /**
224
     * @param Property $propertyAnnotation
225
     * @param array $fields
226
     * @return int
227
     * @throws InvalidArgumentException
228
     */
229 1
    protected static function addProperty(Property $propertyAnnotation, array $fields)
230
    {
231 1
        $type = $propertyAnnotation->getType();
232 1
        if ($type === Property::TYPE_BOOLEAN) {
233 1
            $fields += ['VALUES' => [['XML_ID' => 'Y', 'VALUE' => 'Y', 'DEF' => 'N']]];
234
        }
235
236 1
        $cIBlockProperty = new CIBlockProperty();
237 1
        $propId = $cIBlockProperty->Add($fields);
238 1
        self::assert($propId, strip_tags($cIBlockProperty->LAST_ERROR));
239
240 1
        return $propId;
241
    }
242
}