public function sendContent($includeMaster) { $benchmarkEnabled = Kwf_Benchmark::isEnabled(); if ($benchmarkEnabled) { $startTime = microtime(true); } $process = $this->_getProcessInputComponents($includeMaster); if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint('getProcessInputComponents', microtime(true) - $startTime); } self::_callProcessInput($process); if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('processInput'); } $hasDynamicParts = false; $out = $this->_render($includeMaster, $hasDynamicParts); if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('render'); } header('Content-Type: text/html; charset=utf-8'); if (!$hasDynamicParts) { $lifetime = 60 * 60; header('Cache-Control: public, max-age=' . $lifetime); header('Expires: ' . gmdate("D, d M Y H:i:s \\G\\M\\T", time() + $lifetime)); header('Pragma: public'); } echo $out; self::_callPostProcessInput($process); if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('postProcessInput'); } }
public function renderMaster($component) { static $benchmarkEnabled; if (!isset($benchmarkEnabled)) { $benchmarkEnabled = Kwf_Benchmark::isEnabled(); } $content = false; if ($this->_enableCache) { $content = Kwf_Component_Cache::getInstance()->load($component->componentId, $this->_getRendererName(), 'fullPage'); $this->_minLifetime = null; } Kwf_Benchmark::checkpoint('load fullPage cache'); $statType = null; if (!$content) { if ($benchmarkEnabled) { $startTime = microtime(true); } if (!$this->_enableCache || ($content = Kwf_Component_Cache::getInstance()->load($component, $this->_getRendererName(), 'page')) === null) { $masterHelper = new Kwf_Component_View_Helper_Master(); $masterHelper->setRenderer($this); $content = $masterHelper->master($component); if ($this->_enableCache) { Kwf_Component_Cache::getInstance()->save($component, $content, $this->_getRendererName(), 'page', '', '', null); $statType = 'miss'; } else { $statType = 'noviewcache'; } } else { $statType = 'hit'; } if ($statType) { Kwf_Benchmark::count("rendered {$statType}", $component->componentId . ': page'); } Kwf_Benchmark::countLog('render-' . $statType); if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint($component->componentId . ' page', microtime(true) - $startTime); } Kwf_Benchmark::checkpoint('render page'); $pass1Cacheable = true; $content = $this->_renderPass1($content, $pass1Cacheable); Kwf_Benchmark::checkpoint('render pass 1'); if ($this->_enableCache && $pass1Cacheable) { Kwf_Component_Cache::getInstance()->save($component, $content, $this->_getRendererName(), 'fullPage', '', '', $this->_minLifetime); } Kwf_Benchmark::count("rendered miss", $component->componentId . ': fullPage'); Kwf_Benchmark::countLog('fullpage-miss'); } else { Kwf_Benchmark::count("rendered hit", $component->componentId . ': fullPage'); Kwf_Benchmark::countLog('fullpage-hit'); } $content = $this->_renderPass2($content); Kwf_Benchmark::checkpoint('render pass 2'); Kwf_Component_Cache::getInstance()->writeBuffer(); return $content; }
public function sendContent($includeMaster) { $benchmarkEnabled = Kwf_Benchmark::isEnabled(); if (Kwf_Util_Https::supportsHttps()) { $foundRequestHttps = Kwf_Util_Https::doesComponentRequestHttps($this->_data); if (isset($_SERVER['HTTPS'])) { //we are on https if (!$foundRequestHttps && isset($_COOKIE['kwcAutoHttps']) && !Zend_Session::sessionExists() && !Zend_Session::isStarted()) { //we where auto-redirected to https but don't need https anymore setcookie('kwcAutoHttps', '', 0, '/'); //delete cookie Kwf_Util_Https::ensureHttp(); } } else { //we are on http if ($foundRequestHttps) { setcookie('kwcAutoHttps', '1', 0, '/'); Kwf_Util_Https::ensureHttps(); } } if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('check requestHttps'); } } if ($benchmarkEnabled) { $startTime = microtime(true); } $process = $this->_getProcessInputComponents($includeMaster); if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint('getProcessInputComponents', microtime(true) - $startTime); } self::_callProcessInput($process); if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('processInput'); } $hasDynamicParts = false; $out = $this->_render($includeMaster, $hasDynamicParts); if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('render'); } header('Content-Type: text/html; charset=utf-8'); if (!$hasDynamicParts) { $lifetime = 60 * 60; header('Cache-Control: public, max-age=' . $lifetime); header('Expires: ' . gmdate("D, d M Y H:i:s \\G\\M\\T", time() + $lifetime)); header('Pragma: public'); } echo $out; self::_callPostProcessInput($process); if ($benchmarkEnabled) { Kwf_Benchmark::checkpoint('postProcessInput'); } }
public static function registerAutoload() { if (!class_exists('Kwf_Benchmark', false)) { require KWF_PATH . '/Kwf/Benchmark.php'; } if (Kwf_Benchmark::isEnabled()) { $class = 'Kwf_Loader_Benchmark'; if (!class_exists($class, false)) { require KWF_PATH . '/Kwf/Loader/Benchmark.php'; } } else { //für performance $class = 'Kwf_Loader'; } spl_autoload_register(array($class, 'loadClass')); }
public function renderComponent($component, &$hasDynamicParts = false) { static $benchmarkEnabled; if (!isset($benchmarkEnabled)) { $benchmarkEnabled = Kwf_Benchmark::isEnabled(); } $content = false; if ($this->_enableCache && $component->isPage) { //use fullPage cache only for pages $content = Kwf_Component_Cache::getInstance()->load($component->componentId, $this->_getRendererName(), 'fullPage'); $this->_minLifetime = null; } Kwf_Benchmark::checkpoint('load fullPage cache'); $statType = null; if (!$content) { $helper = new Kwf_Component_View_Helper_Component(); $helper->setRenderer($this); $content = $helper->component($component); $pass1Cacheable = true; $content = $this->_renderPass1($content, $pass1Cacheable); Kwf_Benchmark::checkpoint('render pass 1'); if (strpos($content, '<kwc2 ') === false) { //if there are no components that need second render cycle start HtmlParser now //and cache result in fullPage cache if ($this->_renderFormat == self::RENDER_HTML && $this->_htmlStyles) { $p = new Kwc_Mail_HtmlParser($this->_htmlStyles); $content = $p->parse($content); Kwf_Benchmark::checkpoint('html parser (in fullPage)'); } } if ($this->_enableCache && $pass1Cacheable && $component->isPage) { Kwf_Component_Cache::getInstance()->save($component, $content, $this->_getRendererName(), 'fullPage', '', '', $this->_minLifetime); } } $hasPass2Placeholders = strpos($content, '<kwc2 ') !== false; $content = $this->_renderPass2($content); Kwf_Benchmark::checkpoint('render pass 2'); //if there where components that needed second render cycle the HtmlParser wasn't started yet //do that now (should be avoided as it's slow) if ((!$component->isPage || $hasPass2Placeholders) && $this->_renderFormat == self::RENDER_HTML && $this->_htmlStyles) { $p = new Kwc_Mail_HtmlParser($this->_htmlStyles); $content = $p->parse($content); Kwf_Benchmark::checkpoint('html parser'); } Kwf_Component_Cache::getInstance()->writeBuffer(); return $content; }
public function getDb($db = 'web') { if (!isset($this->_db[$db])) { $dbConfig = $this->getDbConfig($db); $this->_db[$db] = Zend_Db::factory('PDO_MYSQL', $dbConfig); $this->_db[$db]->query('SET names UTF8'); $this->_db[$db]->query('SET SESSION sql_mode=\'\''); if (Kwf_Config::getValue('debug.disableMysqlQueryCache')) { $this->_db[$db]->query('SET SESSION query_cache_type=0'); } /** * lc_time_names wird hier nicht gesetzt weil man für trlKwf * momentan das userModel benötigt und das gibts ohne DB * Verbindung nicht -> Endlosschleifen gefahr. * lc_time_names wurde früher vermutlich im TreeCache noch benötigt * (z.B. bei den News Month), aber das macht jetzt das PHP, dehalb * ist es nicht mehr nötig dies zu setzen. */ // $this->_db[$db]->query("SET lc_time_names = '".trlKwf('en_US')."'"); if (Kwf_Config::getValue('debug.querylog')) { $profiler = new Kwf_Db_Profiler(true); $this->_db[$db]->setProfiler($profiler); } else { if (Kwf_Config::getValue('debug.queryTimeout')) { $profiler = new Kwf_Db_Profiler_Timeout(Kwf_Config::getValue('debug.queryTimeout'), true); $this->_db[$db]->setProfiler($profiler); } else { if (Kwf_Benchmark::isEnabled() || Kwf_Benchmark::isLogEnabled()) { $profiler = new Kwf_Db_Profiler_Count(true); $this->_db[$db]->setProfiler($profiler); } } } } return $this->_db[$db]; }
public function sendAction() { $this->_helper->viewRenderer->setNoRender(true); Kwf_Events_ModelObserver::getInstance()->disable(); $newsletterId = $this->_getParam('newsletterId'); $nlRow = Kwf_Model_Abstract::getInstance('Kwc_Newsletter_Model')->getRow($newsletterId); $mailsPerMinute = $nlRow->getCountOfMailsPerMinute(); // In Schleife senden $queueLogModel = $nlRow->getModel()->getDependentModel('QueueLog'); $count = 0; $countErrors = 0; $countNoUser = 0; $start = microtime(true); do { // Schlafen bis errechnet Zeit if ($nlRow->mails_per_minute != 'unlimited') { $sleep = $start + 60 / $mailsPerMinute * $count - microtime(true); if ($sleep > 0) { usleep($sleep * 1000000); } if ($this->_getParam('debug')) { echo "sleeping {$sleep}s\n"; } } $nlStatus = Kwf_Model_Abstract::getInstance('Kwc_Newsletter_Model')->fetchColumnByPrimaryId('status', $nlRow->id); if ($nlStatus != 'sending') { if ($this->_getParam('debug')) { echo "break sending because newsletter status changed to '{$nlStatus}'\n"; } break; } Kwf_Benchmark::enable(); Kwf_Benchmark::reset(); Kwf_Benchmark::checkpoint('start'); $userStart = microtime(true); // Zeile aus queue holen, falls nichts gefunden, Newsletter fertig $row = $nlRow->getNextQueueRow(getmypid()); Kwf_Benchmark::checkpoint('get next recipient'); if ($row) { $recipient = $row->getRecipient(); if (!$recipient || !$recipient->getMailEmail()) { $countNoUser++; $status = 'usernotfound'; } else { if ($recipient instanceof Kwc_Mail_Recipient_UnsubscribableInterface && $recipient->getMailUnsubscribe()) { $countNoUser++; $status = 'usernotfound'; } else { if ($recipient instanceof Kwf_Model_Row_Abstract && $recipient->hasColumn('activated') && !$recipient->activated) { $countNoUser++; $status = 'usernotfound'; } else { try { $mc = $nlRow->getMailComponent(); $t = microtime(true); $mail = $mc->createMail($recipient); $createTime = microtime(true) - $t; $t = microtime(true); $mail->send(); $sendTime = microtime(true) - $t; Kwf_Benchmark::checkpoint('send mail'); $count++; $status = 'sent'; } catch (Exception $e) { echo 'Exception in Sending Newsletter with id ' . $nlRow->id . ' with recipient ' . $recipient->getMailEmail(); echo $e->__toString(); $countErrors++; $status = 'failed'; } $nlRow->getModel()->getTable()->update(array('count_sent' => new Zend_Db_Expr('count_sent + 1'), 'last_sent_date' => date('Y-m-d H:i:s')), 'id = ' . $nlRow->id); } } } $queueLogModel->createRow(array('newsletter_id' => $row->newsletter_id, 'recipient_model' => $row->recipient_model, 'recipient_id' => $row->recipient_id, 'status' => $status, 'send_date' => date('Y-m-d H:i:s')))->save(); $row->delete(); Kwf_Benchmark::checkpoint('update queue'); if ($this->_getParam('verbose')) { if (Kwf_Benchmark::isEnabled() && $this->_getParam('benchmark')) { echo Kwf_Benchmark::getCheckpointOutput(); } echo "[" . getmypid() . "] {$status} in " . round((microtime(true) - $userStart) * 1000) . "ms ("; echo "create " . round($createTime * 1000) . "ms, "; echo "send " . round($sendTime * 1000) . "ms"; echo ") [" . round(memory_get_usage() / (1024 * 1024)) . "MB] [" . round($count / (microtime(true) - $start), 1) . " mails/s]\n"; } if ($status == 'failed' && $this->_getParam('debug')) { echo "stopping because sending failed in debug mode\n"; break; } if (memory_get_usage() > 100 * 1024 * 1024) { if ($this->_getParam('debug')) { echo "stopping because of >100MB memory usage\n"; } break; } } } while ($row); $stop = microtime(true); // Log schreiben $logModel = $nlRow->getModel()->getDependentModel('Log'); $row = $logModel->createRow(array('newsletter_id' => $nlRow->id, 'start' => date('Y-m-d H:i:s', floor($start)), 'stop' => date('Y-m-d H:i:s', floor($stop)), 'count' => $count, 'countErrors' => $countErrors)); $row->save(); // Debugmeldungen if ($this->_getParam('debug')) { $average = round($count / ($stop - $start) * 60); $info = $nlRow->getInfo(); echo "\n"; echo "{$count} Newsletters sent ({$average}/minute), {$countErrors} errors, {$countNoUser} user not found.\n"; echo $info['text'] . "\n"; } Kwf_Events_ModelObserver::getInstance()->enable(); }
/** * Check if user is logged in (faster than directly calling user model) * * Only asks user model (expensive) when there is something stored in the session * * @return boolean if user is logged in */ public static function hasAuthedUser() { static $benchmarkEnabled; if (!isset($benchmarkEnabled)) { $benchmarkEnabled = Kwf_Benchmark::isEnabled(); } if ($benchmarkEnabled) { $t = microtime(true); } if (!Zend_Session::isStarted() && !Zend_Session::sessionExists() && !Kwf_Config::getValue('autologin')) { if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint('hasAuthedUser: no session', microtime(true) - $t); } return false; } if (!Kwf_Auth::getInstance()->getStorage()->read()) { if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint('hasAuthedUser: storage empty', microtime(true) - $t); } return false; } $m = Kwf_Registry::get('userModel'); if (!$m) { return false; } $ret = $m->hasAuthedUser(); if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint('hasAuthedUser: asked model', microtime(true) - $t); } return $ret; }
/** * Render components (ie. expand <kwc ...>) * * Pass 1 for content that can be stored in fullPage cache, * 2 for everything else. 2 includes 1, so calling just with 2 also works * @param string render content */ protected function _renderPass2($ret, &$hasDynamicParts = false) { //execute all plugins that where added in pass 1 $ret = $this->_findAndExecutePlugins($ret, self::PLUGIN_TYPE_USECACHE, $hasDynamicParts); $ret = $this->_findAndExecutePlugins($ret, self::PLUGIN_TYPE_BEFORE, $hasDynamicParts); $ret = $this->_findAndExecutePlugins($ret, self::PLUGIN_TYPE_REPLACE, $hasDynamicParts); $ret = $this->_findAndExecuteUseCacheDynamic($ret, $hasDynamicParts); static $benchmarkEnabled; if (!isset($benchmarkEnabled)) { $benchmarkEnabled = Kwf_Benchmark::isEnabled(); } $offset = 0; while ($target = $this->_getNextRenderTarget($ret, 2, $offset)) { if ($benchmarkEnabled) { $startTime = microtime(true); } if ($target['type'] == 'dynamic' && $target['config']['class'] == 'Kwf_Component_Dynamic_SessionToken' && !Kwf_Setup::hasAuthedUser()) { $hasDynamicParts = true; //yes, this is cheating, but a very common case that's worth optimizing using this hack $ret = substr($ret, 0, $target['start']) . '' . substr($ret, $target['end'] + 1); continue; } $helper = $this->_getHelper($target['type']); $statType = null; $content = null; if ($this->_enableCache && $target['isCacheable']) { $content = $this->_cacheLoad($target['componentId'], $target['type'], $target['value']); } if (!is_null($content)) { //cache hit $statType = 'hit'; //look for UseViewCache plugin in $content if ($p = $this->_findSinglePlugin(self::PLUGIN_TYPE_USECACHE, $content)) { $hasDynamicParts = true; if (!$p['plugin']->useViewCache($this)) { //re-render, without <pluginC $content = $this->_renderUncached($target['componentId'], $target['type'], $target['config']); } else { //continue with content $content = $p['content']; } } else { //execute replace and before plugin if ($p = $this->_findSinglePlugin(self::PLUGIN_TYPE_REPLACE, $content)) { $hasDynamicParts = true; $r = $p['plugin']->replaceOutput($this); if ($r !== false) { $content = $r; } else { $content = $p['content']; } } $content = $this->_findAndExecutePlugins($content, self::PLUGIN_TYPE_BEFORE, $hasDynamicParts); } $content = $this->_findAndExecuteUseCacheDynamic($content, $hasDynamicParts); } else { if ($this->_enableCache && $target['isCacheable']) { //cache miss $statType = 'miss'; $content = $this->_renderAndCache($target['componentId'], $target['type'], $target['value'], $target['config'], false); } else { $hasDynamicParts = true; //view cache disabled $statType = 'noviewcache'; $content = $this->_renderUncached($target['componentId'], $target['type'], $target['config']); } } $content = $helper->renderCached($content, $target['componentId'], $target['config']); $ret = substr($ret, 0, $target['start']) . $content . substr($ret, $target['end'] + 1); if ($statType) { if ($benchmarkEnabled) { Kwf_Benchmark::count("rendered {$statType}", $target['statId']); } Kwf_Benchmark::countLog('render-' . $statType); } if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint($target['componentId'] . ' ' . $target['type'], microtime(true) - $startTime); } } //execute Render Cached Dynamic, used eg for callback link modifier in componentLink while (($start = strpos($ret, '<rcd ')) !== false) { $hasDynamicParts = true; $startEnd = strpos($ret, '>', $start); $args = explode(' ', substr($ret, $start + 5, $startEnd - $start - 5)); $end = strpos($ret, '</rcd ' . $args[0] . '>'); $content = substr($ret, $startEnd + 1, $end - $startEnd - 1); if ($benchmarkEnabled) { $startTime = microtime(true); } $componentId = $args[0]; $type = $args[1]; $settings = json_decode($args[2], true); $content = $this->_getHelper($type)->renderCachedDynamic($content, $componentId, $settings); if ($benchmarkEnabled) { Kwf_Benchmark::subCheckpoint("renderCachedDynamic {$type} {$componentId}", microtime(true) - $startTime); } $ret = substr($ret, 0, $start) . $content . substr($ret, $end + 7 + strlen($args[0])); } $ret = $this->_findAndExecutePlugins($ret, self::PLUGIN_TYPE_AFTER, $hasDynamicParts); return $ret; }
public function sendContent($includeMaster) { $content = $this->getContent($includeMaster); $content['contents'] = $content['content']; unset($content['content']); if (!isset($content['lifetime'])) { $content['lifetime'] = false; } if (Kwf_Benchmark::isEnabled()) { ob_start(); Kwf_Benchmark::output(); $content['contents'] .= ob_get_contents(); ob_end_clean(); } Kwf_Media_Output::outputWithoutShutdown($content); exit; }