1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29:
30: class Mage_Index_Model_Indexer
31: {
32: 33: 34: 35: 36:
37: protected $_processesCollection;
38:
39: 40: 41: 42: 43: 44:
45: protected $_lockFlag = false;
46:
47: 48: 49: 50: 51:
52: protected $_allowTableChanges = true;
53:
54: 55: 56: 57: 58: 59:
60: protected $_currentEvent = null;
61:
62: 63: 64:
65: public function __construct()
66: {
67: $this->_processesCollection = Mage::getResourceModel('index/process_collection');
68: }
69:
70: 71: 72: 73: 74:
75: public function getProcessesCollection()
76: {
77: return $this->_processesCollection;
78: }
79:
80: 81: 82: 83: 84: 85:
86: public function getProcessById($processId)
87: {
88: foreach ($this->_processesCollection as $process) {
89: if ($process->getId() == $processId) {
90: return $process;
91: }
92: }
93: return false;
94: }
95:
96: 97: 98: 99: 100: 101:
102: public function getProcessByCode($code)
103: {
104: foreach ($this->_processesCollection as $process) {
105: if ($process->getIndexerCode() == $code) {
106: return $process;
107: }
108: }
109: return false;
110: }
111:
112: 113: 114: 115: 116: 117:
118: public function lockIndexer()
119: {
120: $this->_lockFlag = true;
121: return $this;
122: }
123:
124: 125: 126: 127: 128: 129:
130: public function unlockIndexer()
131: {
132: $this->_lockFlag = false;
133: return $this;
134: }
135:
136: 137: 138: 139: 140: 141:
142: public function isLocked()
143: {
144: return $this->_lockFlag;
145: }
146:
147: 148: 149: 150: 151: 152: 153: 154:
155: public function indexEvents($entity=null, $type=null)
156: {
157: Mage::dispatchEvent('start_index_events' . $this->_getEventTypeName($entity, $type));
158:
159:
160: $resourceModel = Mage::getResourceSingleton('index/process');
161:
162: $allowTableChanges = $this->_allowTableChanges && !$resourceModel->isInTransaction();
163: if ($allowTableChanges) {
164: $this->_currentEvent = array($entity, $type);
165: $this->_changeKeyStatus(false);
166: }
167:
168: $resourceModel->beginTransaction();
169: $this->_allowTableChanges = false;
170: try {
171: $this->_runAll('indexEvents', array($entity, $type));
172: $resourceModel->commit();
173: } catch (Exception $e) {
174: $resourceModel->rollBack();
175: throw $e;
176: }
177: if ($allowTableChanges) {
178: $this->_allowTableChanges = true;
179: $this->_changeKeyStatus(true);
180: $this->_currentEvent = null;
181: }
182: Mage::dispatchEvent('end_index_events' . $this->_getEventTypeName($entity, $type));
183: return $this;
184: }
185:
186: 187: 188: 189: 190: 191:
192: public function indexEvent(Mage_Index_Model_Event $event)
193: {
194: $this->_runAll('safeProcessEvent', array($event));
195: return $this;
196: }
197:
198: 199: 200: 201: 202:
203: public function registerEvent(Mage_Index_Model_Event $event)
204: {
205: $this->_runAll('register', array($event));
206: return $this;
207: }
208:
209: 210: 211: 212: 213: 214: 215: 216: 217:
218: public function logEvent(Varien_Object $entity, $entityType, $eventType, $doSave=true)
219: {
220: $event = Mage::getModel('index/event')
221: ->setEntity($entityType)
222: ->setType($eventType)
223: ->setDataObject($entity)
224: ->setEntityPk($entity->getId());
225:
226: $this->registerEvent($event);
227: if ($doSave) {
228: $event->save();
229: }
230: return $event;
231: }
232:
233: 234: 235: 236: 237: 238: 239: 240: 241:
242: public function processEntityAction(Varien_Object $entity, $entityType, $eventType)
243: {
244: $event = $this->logEvent($entity, $entityType, $eventType, false);
245: 246: 247:
248: if ($event->getProcessIds()) {
249: Mage::dispatchEvent('start_process_event' . $this->_getEventTypeName($entityType, $eventType));
250:
251:
252: $resourceModel = Mage::getResourceSingleton('index/process');
253:
254: $allowTableChanges = $this->_allowTableChanges && !$resourceModel->isInTransaction();
255: if ($allowTableChanges) {
256: $this->_currentEvent = $event;
257: $this->_changeKeyStatus(false);
258: }
259:
260: $resourceModel->beginTransaction();
261: $this->_allowTableChanges = false;
262: try {
263: $this->indexEvent($event);
264: $resourceModel->commit();
265: } catch (Exception $e) {
266: $resourceModel->rollBack();
267: if ($allowTableChanges) {
268: $this->_allowTableChanges = true;
269: $this->_changeKeyStatus(true);
270: $this->_currentEvent = null;
271: }
272: throw $e;
273: }
274: if ($allowTableChanges) {
275: $this->_allowTableChanges = true;
276: $this->_changeKeyStatus(true);
277: $this->_currentEvent = null;
278: }
279: $event->save();
280: Mage::dispatchEvent('end_process_event' . $this->_getEventTypeName($entityType, $eventType));
281: }
282: return $this;
283: }
284:
285: 286: 287: 288: 289: 290: 291: 292: 293:
294: protected function _runAll($method, $args)
295: {
296: $checkLocks = $method != 'register';
297: $processed = array();
298: foreach ($this->_processesCollection as $process) {
299: $code = $process->getIndexerCode();
300: if (in_array($code, $processed)) {
301: continue;
302: }
303: $hasLocks = false;
304:
305: if ($process->getDepends()) {
306: foreach ($process->getDepends() as $processCode) {
307: $dependProcess = $this->getProcessByCode($processCode);
308: if ($dependProcess && !in_array($processCode, $processed)) {
309: if ($checkLocks && $dependProcess->isLocked()) {
310: $hasLocks = true;
311: } else {
312: call_user_func_array(array($dependProcess, $method), $args);
313: if ($checkLocks && $dependProcess->getMode() == Mage_Index_Model_Process::MODE_MANUAL) {
314: $hasLocks = true;
315: } else {
316: $processed[] = $processCode;
317: }
318: }
319: }
320: }
321: }
322:
323: if (!$hasLocks) {
324: call_user_func_array(array($process, $method), $args);
325: $processed[] = $code;
326: }
327: }
328: }
329:
330: 331: 332: 333: 334: 335:
336: protected function _changeKeyStatus($enable = true)
337: {
338: $processed = array();
339: foreach ($this->_processesCollection as $process) {
340: $code = $process->getIndexerCode();
341: if (in_array($code, $processed)) {
342: continue;
343: }
344:
345: if ($process->getDepends()) {
346: foreach ($process->getDepends() as $processCode) {
347: $dependProcess = $this->getProcessByCode($processCode);
348: if ($dependProcess && !in_array($processCode, $processed)) {
349: if ($this->_changeProcessKeyStatus($dependProcess, $enable)) {
350: $processed[] = $processCode;
351: }
352: }
353: }
354: }
355:
356: if ($this->_changeProcessKeyStatus($process, $enable)) {
357: $processed[] = $code;
358: }
359: }
360:
361: return $this;
362: }
363:
364: 365: 366: 367: 368: 369: 370:
371: protected function _changeProcessKeyStatus($process, $enable = true)
372: {
373: $event = $this->_currentEvent;
374: if ($process instanceof Mage_Index_Model_Process
375: && $process->getMode() !== Mage_Index_Model_Process::MODE_MANUAL
376: && !$process->isLocked()
377: && (is_null($event)
378: || ($event instanceof Mage_Index_Model_Event && $process->matchEvent($event))
379: || (is_array($event) && $process->matchEntityAndType($event[0], $event[1]))
380: )) {
381: if ($enable) {
382: $process->enableIndexerKeys();
383: } else {
384: $process->disableIndexerKeys();
385: }
386: return true;
387: }
388: return false;
389: }
390:
391: 392: 393: 394: 395:
396: public function allowTableChanges()
397: {
398: $this->_allowTableChanges = true;
399: return $this;
400: }
401:
402: 403: 404: 405: 406:
407: public function disallowTableChanges()
408: {
409: $this->_allowTableChanges = false;
410: return $this;
411: }
412:
413: 414: 415: 416: 417: 418: 419:
420: protected function _getEventTypeName($entityType = null, $eventType = null)
421: {
422: $eventName = $entityType . '_' . $eventType;
423: $eventName = trim($eventName, '_');
424: if (!empty($eventName)) {
425: $eventName = '_' . $eventName;
426: }
427: return $eventName;
428: }
429: }
430: