Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
chain.php
1<?php
9
10use Bitrix\Main;
14
18
19Loc::loadMessages(__FILE__);
20
37final class ChainTable extends Entity\DataManager implements \Serializable
38{
39 const STEP_SIZE = 10000;
40 const MTU = 9999;
41
42 protected $procData = array();
43 protected $indexInserter = null;
44
45 public static function getFilePath()
46 {
47 return __FILE__;
48 }
49
50 public static function getTableName()
51 {
52 return 'b_sale_loc_search_chain';
53 }
54
55 public function serialize()
56 {
57 return serialize($this->procData);
58 }
59
60 public function unserialize($data): void
61 {
62 $this->procData = unserialize($data, ['allowed_classes' => false]);
63 $this->initInsertHandles();
64 }
65
66 public function __serialize()
67 {
68 return $this->procData;
69 }
70
71 public function __unserialize($data): void
72 {
73 if (is_array($data))
74 {
75 $this->procData = $data;
76 $this->initInsertHandles();
77 }
78 }
79
80 public function __construct($parameters = array())
81 {
82 $this->resetProcess();
83
84 if(is_array($parameters['TYPES']) && !empty($parameters['TYPES']))
85 {
86 $this->procData['ALLOWED_TYPES'] = array_unique($parameters['TYPES']);
87 }
88
89 $typeSort = array();
90 $res = Location\TypeTable::getList(array('select' => array('ID', 'CODE', 'DISPLAY_SORT')));
91
92 $this->procData['TYPES'] = array();
93 $this->procData['TYPE_SORT'] = array();
94
95 while($item = $res->fetch())
96 {
97 if(!is_array($this->procData['ALLOWED_TYPES']) || (is_array($this->procData['ALLOWED_TYPES']) && in_array($item['ID'], $this->procData['ALLOWED_TYPES'])))
98 $this->procData['TYPES'][$item['CODE']] = $item['ID'];
99
100 $this->procData['TYPE_SORT'][$item['ID']] = $item['DISPLAY_SORT'];
101 }
102
103 $this->procData['TYPES_BACK'] = array_flip($this->procData['TYPES']);
104
105 $this->initInsertHandles();
106 }
107
108 public function initInsertHandles()
109 {
110 $this->indexInserter = new BlockInserter(array(
111 'entityName' => '\Bitrix\Sale\Location\Search\ChainTable',
112 'exactFields' => array(
113 'LOCATION_ID', 'RELEVANCY', 'POSITION'
114 ),
115 'parameters' => array(
116 'mtu' => static::MTU
117 )
118 ));
119 }
120
121 public function resetProcess()
122 {
123 $this->procData = array(
124 'OFFSET' => 0,
125 'DEPTH' => 0,
126 'PATH' => array(),
127 );
128 }
129
130 public function getOffset()
131 {
132 return $this->procData['OFFSET'];
133 }
134
135 public static function cleanUpData()
136 {
137 Helper::dropTable(static::getTableName());
138
139 Main\HttpApplication::getConnection()->query("create table ".static::getTableName()." (
140
141 LOCATION_ID ".Helper::getSqlForDataType('int').",
142 RELEVANCY ".Helper::getSqlForDataType('int')." default '0',
143 POSITION ".Helper::getSqlForDataType('int')." default '0',
144
145 primary key (POSITION, LOCATION_ID)
146
147 )");
148 }
149
150 public static function getFilterForInitData($parameters = array())
151 {
152 $filter = array();
153
154 if(!is_array($parameters))
155 $parameters = array();
156
157 if(is_array($parameters['TYPES']) && !empty($parameters['TYPES']))
158 $filter['=TYPE_ID'] = array_unique($parameters['TYPES']);
159
160 return $filter;
161 }
162
163 protected static function rarefact($sorts, $window = 10000)
164 {
165 if(!intval($window))
166 $window = 10000;
167
168 $rSorts = array();
169 $w = $window;
170 if(is_array($sorts))
171 {
172 asort($sorts);
173
174 foreach($sorts as $id => $sort)
175 {
176 $rSorts[$id] = $w;
177 $w += $window;
178 }
179 }
180
181 return $rSorts;
182 }
183
184 public function initializeData()
185 {
186 $dbConnection = Main\HttpApplication::getConnection();
187
188 $res = Location\LocationTable::getList(array(
189 'select' => array(
190 'ID',
191 'TYPE_ID',
192 'DEPTH_LEVEL',
193 'SORT'
194 ),
195 //'filter' => static::getFilterForInitData(array('TYPES' => $this->procData['ALLOWED_TYPES'])),
196 'order' => array(
197 'LEFT_MARGIN' => 'asc'
198 ),
199 'limit' => self::STEP_SIZE,
200 'offset' => $this->procData['OFFSET']
201 ));
202
203 $this->procData['TYPE_SORT'] = $this->rarefact($this->procData['TYPE_SORT']);
204
205 $cnt = 0;
206 while($item = $res->fetch())
207 {
208 // tmp!!!!
209 //$name = Location\Name\LocationTable::getList(array('select' => array('NAME'), 'filter' => array('=LOCATION_ID' => $item['ID'], '=LANGUAGE_ID' => 'ru')))->fetch();
210
211 if($item['DEPTH_LEVEL'] < $this->procData['DEPTH'])
212 {
213 $newPC = array();
214
215 foreach($this->procData['PATH'] as $dl => $id)
216 {
217 if($dl >= $item['DEPTH_LEVEL'])
218 break;
219
220 $newPC[$dl] = $id;
221 }
222
223 $this->procData['PATH'] = $newPC;
224 }
225
226 $this->procData['PATH'][$item['DEPTH_LEVEL']] = array(
227 'TYPE' => $item['TYPE_ID'],
228 'ID' => $item['ID']
229 );
230
231 if(is_array($this->procData['ALLOWED_TYPES']) && in_array($item['TYPE_ID'], $this->procData['ALLOWED_TYPES']))
232 {
233 $data = array(
234 'LOCATION_ID' => $item['ID'],
235 'RELEVANCY' => $this->procData['TYPE_SORT'][$item['TYPE_ID']] + $item['SORT'],// * $item['DEPTH_LEVEL'], // tmp, will be more complicated calc here later
236 );
237 $wordsAdded = array();
238
239 /*
240 _dump_r('############################');
241 _dump_r('LOCATION: '.$name['NAME']);
242 _dump_r('TYPE RELEVANCY: '.$data['RELEVANCY']);
243 _dump_r('PATH:');
244 _dump_r($this->procData['PATH']);
245 */
246
247 $this->procData['DEPTH'] = $item['DEPTH_LEVEL'];
248
249 // pre-load missing words
250 $wordCount = 0;
251 foreach($this->procData['PATH'] as &$pathItem)
252 {
253 if(!isset($pathItem['WORDS'])) // words were not loaded previously for this part of the path
254 {
255 $sql = "
256 select WS.POSITION from ".WordTable::getTableNameWord2Location()." WL
257 inner join ".WordTable::getTableName()." WS on WL.WORD_ID = WS.ID
258 where
259 WL.LOCATION_ID = '".intval($pathItem['ID'])."'
260 ";
261
262 $wordRes = $dbConnection->query($sql);
263
264 $pathItem['WORDS'] = array();
265 while($wordItem = $wordRes->fetch())
266 {
267 $pathItem['WORDS'][] = $wordItem['POSITION'];
268 }
269 $pathItem['WORDS'] = array_unique($pathItem['WORDS']);
270 }
271
272 $wordCount += count($pathItem['WORDS']);
273 }
274
275 // count words
276 //_dump_r('Words total: '.$wordCount);
277
278 $wOffset = 0;
279 foreach($this->procData['PATH'] as &$pathItem)
280 {
281 foreach($pathItem['WORDS'] as $i => $position)
282 {
283 $wordWeight = $wordCount - $wOffset;
284
285 $tmpData = $data;
286 $tmpData['RELEVANCY'] += $wordWeight;
287
288 //_dump_r(' Word relevancy: '.$data['RELEVANCY'].' ==>> '.$tmpData['RELEVANCY']);
289
290 if(!isset($wordsAdded[$position]))
291 {
292 $this->indexInserter->insert(array_merge(array('POSITION' => $position), $tmpData));
293 $wordsAdded[$position] = true;
294 }
295
296 $wOffset++;
297 }
298 }
299 unset($pathItem);
300
301 }
302
303 $cnt++;
304 }
305
306 $this->indexInserter->flush();
307
308 $this->procData['OFFSET'] += self::STEP_SIZE;
309
310 return !$cnt;
311 }
312
313 public static function createIndex()
314 {
315 Helper::createIndex(static::getTableName(), 'LPR', array('LOCATION_ID', 'POSITION', 'RELEVANCY'));
316 }
317
318 public static function getMap()
319 {
320 return array(
321
322 'LOCATION_ID' => array(
323 'data_type' => 'integer',
324 'primary' => true
325 ),
326 'POSITION' => array(
327 'data_type' => 'integer',
328 'primary' => true
329 ),
330
331 'RELEVANCY' => array(
332 'data_type' => 'integer',
333 )
334 );
335 }
336}
337
static loadMessages($file)
Definition loc.php:64
static getFilterForInitData($parameters=array())
Definition chain.php:150
__construct($parameters=array())
Definition chain.php:80
static rarefact($sorts, $window=10000)
Definition chain.php:163