Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_Index_Adminhtml_ProcessController
  • Mage_Index_Block_Adminhtml_Notifications
  • Mage_Index_Block_Adminhtml_Process
  • Mage_Index_Block_Adminhtml_Process_Edit
  • Mage_Index_Block_Adminhtml_Process_Edit_Form
  • Mage_Index_Block_Adminhtml_Process_Edit_Tab_Main
  • Mage_Index_Block_Adminhtml_Process_Edit_Tabs
  • Mage_Index_Block_Adminhtml_Process_Grid
  • Mage_Index_Block_Adminhtml_Process_Grid_Massaction
  • Mage_Index_Helper_Data
  • Mage_Index_Model_Event
  • Mage_Index_Model_Indexer
  • Mage_Index_Model_Indexer_Abstract
  • Mage_Index_Model_Mysql4_Abstract
  • Mage_Index_Model_Mysql4_Event
  • Mage_Index_Model_Mysql4_Event_Collection
  • Mage_Index_Model_Mysql4_Process
  • Mage_Index_Model_Mysql4_Process_Collection
  • Mage_Index_Model_Mysql4_Setup
  • Mage_Index_Model_Observer
  • Mage_Index_Model_Process
  • Mage_Index_Model_Resource_Abstract
  • Mage_Index_Model_Resource_Event
  • Mage_Index_Model_Resource_Event_Collection
  • Mage_Index_Model_Resource_Helper_Mysql4
  • Mage_Index_Model_Resource_Process
  • Mage_Index_Model_Resource_Process_Collection
  • Mage_Index_Model_Resource_Setup
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Magento
  4:  *
  5:  * NOTICE OF LICENSE
  6:  *
  7:  * This source file is subject to the Open Software License (OSL 3.0)
  8:  * that is bundled with this package in the file LICENSE.txt.
  9:  * It is also available through the world-wide-web at this URL:
 10:  * http://opensource.org/licenses/osl-3.0.php
 11:  * If you did not receive a copy of the license and are unable to
 12:  * obtain it through the world-wide-web, please send an email
 13:  * to license@magentocommerce.com so we can send you a copy immediately.
 14:  *
 15:  * DISCLAIMER
 16:  *
 17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
 18:  * versions in the future. If you wish to customize Magento for your
 19:  * needs please refer to http://www.magentocommerce.com for more information.
 20:  *
 21:  * @category    Mage
 22:  * @package     Mage_Index
 23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
 24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 25:  */
 26: 
 27: /**
 28:  * Enter description here ...
 29:  *
 30:  * @method Mage_Index_Model_Resource_Process _getResource()
 31:  * @method Mage_Index_Model_Resource_Process getResource()
 32:  * @method string getIndexerCode()
 33:  * @method Mage_Index_Model_Process setIndexerCode(string $value)
 34:  * @method string getStatus()
 35:  * @method Mage_Index_Model_Process setStatus(string $value)
 36:  * @method string getStartedAt()
 37:  * @method Mage_Index_Model_Process setStartedAt(string $value)
 38:  * @method string getEndedAt()
 39:  * @method Mage_Index_Model_Process setEndedAt(string $value)
 40:  * @method string getMode()
 41:  * @method Mage_Index_Model_Process setMode(string $value)
 42:  *
 43:  * @category    Mage
 44:  * @package     Mage_Index
 45:  * @author      Magento Core Team <core@magentocommerce.com>
 46:  */
 47: class Mage_Index_Model_Process extends Mage_Core_Model_Abstract
 48: {
 49:     const XML_PATH_INDEXER_DATA     = 'global/index/indexer';
 50:     /**
 51:      * Process statuses
 52:      */
 53:     const STATUS_RUNNING            = 'working';
 54:     const STATUS_PENDING            = 'pending';
 55:     const STATUS_REQUIRE_REINDEX    = 'require_reindex';
 56: 
 57:     /**
 58:      * Process event statuses
 59:      */
 60:     const EVENT_STATUS_NEW          = 'new';
 61:     const EVENT_STATUS_DONE         = 'done';
 62:     const EVENT_STATUS_ERROR        = 'error';
 63:     const EVENT_STATUS_WORKING      = 'working';
 64: 
 65:     /**
 66:      * Process modes
 67:      * Process mode allow disable automatic process events processing
 68:      */
 69:     const MODE_MANUAL              = 'manual';
 70:     const MODE_REAL_TIME           = 'real_time';
 71: 
 72:     /**
 73:      * Indexer stategy object
 74:      *
 75:      * @var Mage_Index_Model_Indexer_Abstract
 76:      */
 77:     protected $_indexer = null;
 78: 
 79:     /**
 80:      * Process lock properties
 81:      */
 82:     protected $_isLocked = null;
 83:     protected $_lockFile = null;
 84: 
 85:     /**
 86:      * Whether table changes are allowed
 87:      *
 88:      * @deprecated after 1.6.1.0
 89:      * @var bool
 90:      */
 91:     protected $_allowTableChanges = true;
 92: 
 93:     /**
 94:      * Initialize resource
 95:      */
 96:     protected function _construct()
 97:     {
 98:         $this->_init('index/process');
 99:     }
100: 
101:     /**
102:      * Set indexer class name as data namespace for event object
103:      *
104:      * @param   Mage_Index_Model_Event $event
105:      * @return  Mage_Index_Model_Process
106:      */
107:     protected function _setEventNamespace(Mage_Index_Model_Event $event)
108:     {
109:         $namespace = get_class($this->getIndexer());
110:         $event->setDataNamespace($namespace);
111:         $event->setProcess($this);
112:         return $this;
113:     }
114: 
115:     /**
116:      * Remove indexer namespace from event
117:      *
118:      * @param Mage_Index_Model_Event $event
119:      * @return Mage_Index_Model_Process
120:      */
121:     protected function _resetEventNamespace($event)
122:     {
123:         $event->setDataNamespace(null);
124:         $event->setProcess(null);
125:         return $this;
126:     }
127: 
128:     /**
129:      * Register data required by process in event object
130:      *
131:      * @param Mage_Index_Model_Event $event
132:      * @return Mage_Index_Model_Process
133:      */
134:     public function register(Mage_Index_Model_Event $event)
135:     {
136:         if ($this->matchEvent($event)) {
137:             $this->_setEventNamespace($event);
138:             $this->getIndexer()->register($event);
139:             $event->addProcessId($this->getId());
140:             $this->_resetEventNamespace($event);
141:             if ($this->getMode() == self::MODE_MANUAL) {
142:                 $this->_getResource()->updateStatus($this, self::STATUS_REQUIRE_REINDEX);
143:             }
144:         }
145:         return $this;
146: 
147:     }
148: 
149:     /**
150:      * Check if event can be matched by process
151:      *
152:      * @param Mage_Index_Model_Event $event
153:      * @return bool
154:      */
155:     public function matchEvent(Mage_Index_Model_Event $event)
156:     {
157:         return $this->getIndexer()->matchEvent($event);
158:     }
159: 
160:     /**
161:      * Check if specific entity and action type is matched
162:      *
163:      * @param   string $entity
164:      * @param   string $type
165:      * @return  bool
166:      */
167:     public function matchEntityAndType($entity, $type)
168:     {
169:         if ($entity !== null && $type !== null) {
170:             return $this->getIndexer()->matchEntityAndType($entity, $type);
171:         }
172:         return true;
173:     }
174: 
175:     /**
176:      * Reindex all data what this process responsible is
177:      *
178:      */
179:     public function reindexAll()
180:     {
181:         if ($this->isLocked()) {
182:             Mage::throwException(Mage::helper('index')->__('%s Index process is working now. Please try run this process later.', $this->getIndexer()->getName()));
183:         }
184: 
185:         $processStatus = $this->getStatus();
186: 
187:         $this->_getResource()->startProcess($this);
188:         $this->lock();
189:         try {
190:             $eventsCollection = $this->getUnprocessedEventsCollection();
191: 
192:             /** @var $eventResource Mage_Index_Model_Resource_Event */
193:             $eventResource = Mage::getResourceSingleton('index/event');
194: 
195:             if ($eventsCollection->count() > 0 && $processStatus == self::STATUS_PENDING
196:                 || $this->getForcePartialReindex()
197:             ) {
198:                 $this->_getResource()->beginTransaction();
199:                 try {
200:                     $this->_processEventsCollection($eventsCollection, false);
201:                     $this->_getResource()->commit();
202:                 } catch (Exception $e) {
203:                     $this->_getResource()->rollBack();
204:                     throw $e;
205:                 }
206:             } else {
207:                 //Update existing events since we'll do reindexAll
208:                 $eventResource->updateProcessEvents($this);
209:                 $this->getIndexer()->reindexAll();
210:             }
211:             $this->unlock();
212: 
213:             $unprocessedEvents = $eventResource->getUnprocessedEvents($this);
214:             if ($this->getMode() == self::MODE_MANUAL && (count($unprocessedEvents) > 0)) {
215:                 $this->_getResource()->updateStatus($this, self::STATUS_REQUIRE_REINDEX);
216:             } else {
217:                 $this->_getResource()->endProcess($this);
218:             }
219:         } catch (Exception $e) {
220:             $this->unlock();
221:             $this->_getResource()->failProcess($this);
222:             throw $e;
223:         }
224:         Mage::dispatchEvent('after_reindex_process_' . $this->getIndexerCode());
225:     }
226: 
227:     /**
228:      * Reindex all data what this process responsible is
229:      * Check and using depends processes
230:      *
231:      * @return Mage_Index_Model_Process
232:      */
233:     public function reindexEverything()
234:     {
235:         if ($this->getData('runed_reindexall')) {
236:             return $this;
237:         }
238: 
239:         /** @var $eventResource Mage_Index_Model_Resource_Event */
240:         $eventResource = Mage::getResourceSingleton('index/event');
241:         $unprocessedEvents = $eventResource->getUnprocessedEvents($this);
242:         $this->setForcePartialReindex(count($unprocessedEvents) > 0 && $this->getStatus() == self::STATUS_PENDING);
243: 
244:         if ($this->getDepends()) {
245:             $indexer = Mage::getSingleton('index/indexer');
246:             foreach ($this->getDepends() as $code) {
247:                 $process = $indexer->getProcessByCode($code);
248:                 if ($process) {
249:                     $process->reindexEverything();
250:                 }
251:             }
252:         }
253: 
254:         $this->setData('runed_reindexall', true);
255:         return $this->reindexAll();
256:     }
257: 
258:     /**
259:      * Process event with assigned indexer object
260:      *
261:      * @param Mage_Index_Model_Event $event
262:      * @return Mage_Index_Model_Process
263:      */
264:     public function processEvent(Mage_Index_Model_Event $event)
265:     {
266:         if (!$this->matchEvent($event)) {
267:             return $this;
268:         }
269:         if ($this->getMode() == self::MODE_MANUAL) {
270:             $this->changeStatus(self::STATUS_REQUIRE_REINDEX);
271:             return $this;
272:         }
273: 
274:         $this->_getResource()->updateProcessStartDate($this);
275:         $this->_setEventNamespace($event);
276:         $isError = false;
277: 
278:         try {
279:             $this->getIndexer()->processEvent($event);
280:         } catch (Exception $e) {
281:             $isError = true;
282:         }
283:         $event->resetData();
284:         $this->_resetEventNamespace($event);
285:         $this->_getResource()->updateProcessEndDate($this);
286:         $event->addProcessId($this->getId(), $isError ? self::EVENT_STATUS_ERROR : self::EVENT_STATUS_DONE);
287: 
288:         return $this;
289:     }
290: 
291:     /**
292:      * Get Indexer strategy object
293:      *
294:      * @return Mage_Index_Model_Indexer_Abstract
295:      */
296:     public function getIndexer()
297:     {
298:         if ($this->_indexer === null) {
299:             $code = $this->_getData('indexer_code');
300:             if (!$code) {
301:                 Mage::throwException(Mage::helper('index')->__('Indexer code is not defined.'));
302:             }
303:             $xmlPath = self::XML_PATH_INDEXER_DATA . '/' . $code;
304:             $config = Mage::getConfig()->getNode($xmlPath);
305:             if (!$config || empty($config->model)) {
306:                 Mage::throwException(Mage::helper('index')->__('Indexer model is not defined.'));
307:             }
308:             $model = Mage::getModel((string)$config->model);
309:             if ($model instanceof Mage_Index_Model_Indexer_Abstract) {
310:                 $this->_indexer = $model;
311:             } else {
312:                 Mage::throwException(Mage::helper('index')->__('Indexer model should extend Mage_Index_Model_Indexer_Abstract.'));
313:             }
314:         }
315:         return $this->_indexer;
316:     }
317: 
318:     /**
319:      * Index pending events addressed to the process
320:      *
321:      * @param   null|string $entity
322:      * @param   null|string $type
323:      * @return  Mage_Index_Model_Process
324:      */
325:     public function indexEvents($entity=null, $type=null)
326:     {
327:         /**
328:          * Check if process indexer can match entity code and action type
329:          */
330:         if ($entity !== null && $type !== null) {
331:             if (!$this->getIndexer()->matchEntityAndType($entity, $type)) {
332:                 return $this;
333:             }
334:         }
335: 
336:         if ($this->getMode() == self::MODE_MANUAL) {
337:             return $this;
338:         }
339: 
340:         if ($this->isLocked()) {
341:             return $this;
342:         }
343: 
344:         $this->lock();
345:         try {
346:             /**
347:              * Prepare events collection
348:              */
349:             $eventsCollection = $this->getUnprocessedEventsCollection();
350:             if ($entity !== null) {
351:                 $eventsCollection->addEntityFilter($entity);
352:             }
353:             if ($type !== null) {
354:                 $eventsCollection->addTypeFilter($type);
355:             }
356: 
357:             $this->_processEventsCollection($eventsCollection);
358:             $this->unlock();
359:         } catch (Exception $e) {
360:             $this->unlock();
361:             throw $e;
362:         }
363:         return $this;
364:     }
365: 
366:     /**
367:      * Process all events of the collection
368:      *
369:      * @param Mage_Index_Model_Resource_Event_Collection $eventsCollection
370:      * @param bool $skipUnmatched
371:      * @return Mage_Index_Model_Process
372:      */
373:     protected function _processEventsCollection(
374:         Mage_Index_Model_Resource_Event_Collection $eventsCollection,
375:         $skipUnmatched = true
376:     ) {
377:         // We can't reload the collection because of transaction
378:         /** @var $event Mage_Index_Model_Event */
379:         while ($event = $eventsCollection->fetchItem()) {
380:             try {
381:                 $this->processEvent($event);
382:                 if (!$skipUnmatched) {
383:                     $eventProcessIds = $event->getProcessIds();
384:                     if (!isset($eventProcessIds[$this->getId()])) {
385:                         $event->addProcessId($this->getId(), null);
386:                     }
387:                 }
388:             } catch (Exception $e) {
389:                 $event->addProcessId($this->getId(), self::EVENT_STATUS_ERROR);
390:             }
391:             $event->save();
392:         }
393:         return $this;
394:     }
395: 
396:     /**
397:      * Update status process/event association
398:      *
399:      * @param   Mage_Index_Model_Event $event
400:      * @param   string $status
401:      * @return  Mage_Index_Model_Process
402:      */
403:     public function updateEventStatus(Mage_Index_Model_Event $event, $status)
404:     {
405:         $this->_getResource()->updateEventStatus($this->getId(), $event->getId(), $status);
406:         return $this;
407:     }
408: 
409:     /**
410:      * Get lock file resource
411:      *
412:      * @return resource
413:      */
414:     protected function _getLockFile()
415:     {
416:         if ($this->_lockFile === null) {
417:             $varDir = Mage::getConfig()->getVarDir('locks');
418:             $file = $varDir . DS . 'index_process_'.$this->getId().'.lock';
419:             if (is_file($file)) {
420:                 $this->_lockFile = fopen($file, 'w');
421:             } else {
422:                 $this->_lockFile = fopen($file, 'x');
423:             }
424:             fwrite($this->_lockFile, date('r'));
425:         }
426:         return $this->_lockFile;
427:     }
428: 
429:     /**
430:      * Lock process without blocking.
431:      * This method allow protect multiple process runing and fast lock validation.
432:      *
433:      * @return Mage_Index_Model_Process
434:      */
435:     public function lock()
436:     {
437:         $this->_isLocked = true;
438:         flock($this->_getLockFile(), LOCK_EX | LOCK_NB);
439:         return $this;
440:     }
441: 
442:     /**
443:      * Lock and block process.
444:      * If new instance of the process will try validate locking state
445:      * script will wait until process will be unlocked
446:      *
447:      * @return Mage_Index_Model_Process
448:      */
449:     public function lockAndBlock()
450:     {
451:         $this->_isLocked = true;
452:         flock($this->_getLockFile(), LOCK_EX);
453:         return $this;
454:     }
455: 
456:     /**
457:      * Unlock process
458:      *
459:      * @return Mage_Index_Model_Process
460:      */
461:     public function unlock()
462:     {
463:         $this->_isLocked = false;
464:         flock($this->_getLockFile(), LOCK_UN);
465:         return $this;
466:     }
467: 
468:     /**
469:      * Check if process is locked
470:      *
471:      * @return bool
472:      */
473:     public function isLocked()
474:     {
475:         if ($this->_isLocked !== null) {
476:             return $this->_isLocked;
477:         } else {
478:             $fp = $this->_getLockFile();
479:             if (flock($fp, LOCK_EX | LOCK_NB)) {
480:                 flock($fp, LOCK_UN);
481:                 return false;
482:             }
483:             return true;
484:         }
485:     }
486: 
487:     /**
488:      * Close file resource if it was opened
489:      */
490:     public function __destruct()
491:     {
492:         if ($this->_lockFile) {
493:             fclose($this->_lockFile);
494:         }
495:     }
496: 
497:     /**
498:      * Change process status
499:      *
500:      * @param string $status
501:      * @return Mage_Index_Model_Process
502:      */
503:     public function changeStatus($status)
504:     {
505:         Mage::dispatchEvent('index_process_change_status', array(
506:             'process' => $this,
507:             'status' => $status
508:         ));
509:         $this->_getResource()->updateStatus($this, $status);
510:         return $this;
511:     }
512: 
513:     /**
514:      * Get list of process mode options
515:      *
516:      * @return array
517:      */
518:     public function getModesOptions()
519:     {
520:         return array(
521:             self::MODE_REAL_TIME => Mage::helper('index')->__('Update on Save'),
522:             self::MODE_MANUAL => Mage::helper('index')->__('Manual Update')
523:         );
524:     }
525: 
526:     /**
527:      * Get list of process status options
528:      *
529:      * @return array
530:      */
531:     public function getStatusesOptions()
532:     {
533:         return array(
534:             self::STATUS_PENDING            => Mage::helper('index')->__('Ready'),
535:             self::STATUS_RUNNING            => Mage::helper('index')->__('Processing'),
536:             self::STATUS_REQUIRE_REINDEX    => Mage::helper('index')->__('Reindex Required'),
537:         );
538:     }
539: 
540:     /**
541:      * Get list of "Update Required" options
542:      *
543:      * @return array
544:      */
545:     public function getUpdateRequiredOptions()
546:     {
547:         return array(
548:             0 => Mage::helper('index')->__('No'),
549:             1 => Mage::helper('index')->__('Yes'),
550:         );
551:     }
552: 
553:     /**
554:      * Retrieve depend indexer codes
555:      *
556:      * @return array
557:      */
558:     public function getDepends()
559:     {
560:         $depends = $this->getData('depends');
561:         if (is_null($depends)) {
562:             $depends = array();
563:             $path = self::XML_PATH_INDEXER_DATA . '/' . $this->getIndexerCode();
564:             $node = Mage::getConfig()->getNode($path);
565:             if ($node) {
566:                 $data = $node->asArray();
567:                 if (isset($data['depends']) && is_array($data['depends'])) {
568:                     $depends = array_keys($data['depends']);
569:                 }
570:             }
571: 
572:             $this->setData('depends', $depends);
573:         }
574: 
575:         return $depends;
576:     }
577: 
578:     /**
579:      * Set whether table changes are allowed
580:      *
581:      * @deprecated after 1.6.1.0
582:      * @param bool $value
583:      * @return Mage_Index_Model_Process
584:      */
585:     public function setAllowTableChanges($value = true)
586:     {
587:         $this->_allowTableChanges = $value;
588:         return $this;
589:     }
590: 
591:     /**
592:      * Disable keys in index table
593:      *
594:      * @return Mage_Index_Model_Process
595:      */
596:     public function disableIndexerKeys()
597:     {
598:         $indexer = $this->getIndexer();
599:         if ($indexer) {
600:             $indexer->disableKeys();
601:         }
602:         return $this;
603:     }
604: 
605:     /**
606:      * Enable keys in index table
607:      *
608:      * @return Mage_Index_Model_Process
609:      */
610:     public function enableIndexerKeys()
611:     {
612:         $indexer = $this->getIndexer();
613:         if ($indexer) {
614:             $indexer->enableKeys();
615:         }
616:         return $this;
617:     }
618: 
619:     /**
620:      * Process event with locks checking
621:      *
622:      * @param Mage_Index_Model_Event $event
623:      * @return Mage_Index_Model_Process
624:      */
625:     public function safeProcessEvent(Mage_Index_Model_Event $event)
626:     {
627:         if ($this->isLocked()) {
628:             return $this;
629:         }
630:         if (!$this->matchEvent($event)) {
631:             return $this;
632:         }
633:         $this->lock();
634:         try {
635:             $this->processEvent($event);
636:             $this->unlock();
637:         } catch (Exception $e) {
638:             $this->unlock();
639:             throw $e;
640:         }
641:         return $this;
642:     }
643: 
644:     /**
645:      * Get unprocessed events collection
646:      *
647:      * @return Mage_Index_Model_Resource_Event_Collection
648:      */
649:     public function getUnprocessedEventsCollection()
650:     {
651:         /** @var $eventsCollection Mage_Index_Model_Resource_Event_Collection */
652:         $eventsCollection = Mage::getResourceModel('index/event_collection');
653:         $eventsCollection->addProcessFilter($this, self::EVENT_STATUS_NEW);
654:         return $eventsCollection;
655:     }
656: }
657: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0