/ */ class Generation_IndexController extends Zend_Controller_Action { const BATCH_SIZE = 100; const STATUS_FILE = 'generation.status.file'; public $contexts = array( 'index' => array('partial'), 'status' => array('json') ); /** * Show form and handle generation */ public function indexAction() { $this->acl->check('content', 'manage'); $this->getHelper('layout')->setLayout('manage-layout'); $request = $this->getRequest(); $form = new Generation_Form_Configure(); $view = $this->view; $view->form = $form; $view->headTitle()->set('Content Generation'); if ($request->isPost() && $form->isValid($request->getPost())) { $targetEntryCount = $form->getValue('count'); $view->showStatus = getmypid(); $this->getHelper('layout')->direct()->content = $this->view->render('index/index.phtml'); echo $this->getHelper('layout')->render(); // write the first status update now, so it's available when we disconnect from the browser. $this->_writeStatusFile( array( 'message' => 'Starting to generate content entries.', 'time' => time(), 'done' => false, 'count' => 0, 'total' => $targetEntryCount ) ); // disconnect the browser and continue $this->getHelper('browserDisconnect')->disconnect(); $this->getHelper('layout')->disableLayout(); $this->getHelper('viewRenderer')->setNoRender(true); $adapter = P4Cms_Content::getDefaultAdapter(); $currentEntryCount = 0; $batchEntryCount = 0; $batchCounter = 0; // create entries until we hit the requested amount; submit out batches every BATCH_SIZE entries while ($currentEntryCount < $targetEntryCount) { $currentEntryCount++; $this->_writeStatusFile( array( 'message' => 'Generating content entries.', 'time' => time(), 'done' => false, 'count' => $currentEntryCount, 'total' => $targetEntryCount ) ); if (!$adapter->inBatch()) { $batchCounter++; $adapter->beginBatch( 'Generating ' . $targetEntryCount . ' content entries. ' . 'Batch ' . $batchCounter . ' of ' . ceil($targetEntryCount / static::BATCH_SIZE) . '.' ); } $generator = new Generation_ContentFactory(); $generator->createEntry()->save(); $batchEntryCount++; // end and start a new batch if current one is full if ($batchEntryCount == static::BATCH_SIZE) { $batchEntryCount = 0; // this can take some time with no progress bar update; inform the user $this->_writeStatusFile( array( 'message' => 'Submitting content entries.', 'time' => time(), 'done' => false, 'count' => $currentEntryCount, 'total' => $targetEntryCount ) ); $adapter->commitBatch(); } } // commit or revert open batch if ($adapter->inBatch()) { // Write status to inform user; count is set to 99% of the total count so the user can tell that further // action is happening. $this->_writeStatusFile( array( 'message' => 'Submitting content entries.', 'time' => time(), 'done' => false, 'count' => $currentEntryCount, 'total' => $targetEntryCount ) ); $adapter->commitBatch(); } $this->_writeStatusFile( array( 'message' => 'Content generation completed.', 'time' => time(), 'done' => true ) ); } } /** * Provide a status update in Json format. */ public function statusAction() { // enforce permissions. $this->acl->check('content', 'manage'); // set context $this->contextSwitch->initContext('json'); $processId = $this->getRequest()->getParam('processId'); $statusFile = sys_get_temp_dir() . '/' . static::STATUS_FILE . $processId; if (!file_exists($statusFile) ) { $status = array( 'label' => 'no status', 'message' => 'No current status file.', 'done' => true ); $this->view->status = $status; return; } $this->view->status = $this->_readStatusFile($processId); } /** * Read JSON-encoded information from temporary status file * * @param string $processId The process for which to read the status. * @return mixed The JSON-decoded contents from the status file. */ private function _readStatusFile($processId) { $statusFile = sys_get_temp_dir() . '/' . static::STATUS_FILE . $processId; $status = ''; if (file_exists($statusFile)) { $content = file_get_contents($statusFile); $status = Zend_Json::decode($content); } return $status; } /** * Write status information to the status file. * * @param array $data The status data to report. * @param string $processId The process for which to write the status. If empty, use current process. */ private function _writeStatusFile($data, $processId = null) { $processId = ($processId) ?: getmypid(); $statusFile = sys_get_temp_dir() . '/' . static::STATUS_FILE . $processId; file_put_contents($statusFile, Zend_Json::encode($data)); } }