/** {@inheritdoc} */ public function showFront(Curry_Twig_Template $template = null) { if (is_array($this->languages) && count($this->languages)) { // allowed languages $allowedLanguages = array(); foreach ($this->languages as $lang) { $allowedLanguages[$lang['code']] = $lang; } // find preferred language reset($this->languages); $language = current($this->languages); foreach ($this->getLanguage() as $lang => $quality) { if (array_key_exists($lang, $allowedLanguages)) { $language = $allowedLanguages[$lang]; break; } } $page = PageQuery::create()->findPk($language['page_id']); if ($page) { url($page->getUrl(), $_GET)->redirect(); } else { Curry_Core::log('Redirect page not found', Zend_Log::WARN); } } else { Curry_Core::log('No languages found', Zend_Log::WARN); } return ''; }
/** {@inheritdoc} */ public function toTwig() { $r = $this->getRequest(); $luceneIndex = Curry_Core::getSearchIndex(); $vars = array(); $vars['Total'] = $luceneIndex->numDocs(); if (isset($r->get['query'])) { $query = trim($r->get['query']); $hits = $luceneIndex->find($query); if ($this->alwaysWildcard && count($hits) === 0) { $hits = $luceneIndex->find($query . '*'); } $tmp = array(); if ($this->onlyThisLanguage) { foreach ($hits as $hit) { try { if ($hit->locale == Curry_Language::getLangCode()) { $tmp[] = $hit; } } catch (Zend_Search_Lucene_Exception $e) { $tmp[] = $hit; } } $hits = $tmp; } $vars['Query'] = $query; $vars['NumHits'] = count($hits); $vars['hits'] = new Curry_Twig_CollectionWrapper($hits, array($this, 'getHitProperties')); } return $vars; }
public static function setUpBeforeClass() { parent::setUpBeforeClass(); self::$fixturesDirectory = realpath(dirname(dirname(__DIR__)) . '/fixtures'); \Curry_Core::init(array('curry' => array('name' => 'Curry Unit Tests', 'adminEmail' => '*****@*****.**', 'autoBackup' => false, 'projectPath' => self::$fixturesDirectory, 'migrationVersion' => \Curry_Core::MIGRATION_VERSION, 'template' => array('root' => self::$fixturesDirectory . '/templates', 'options' => array('cache' => false)), 'propel' => array('conf' => self::$fixturesDirectory . '/propel/build/conf/curry-conf.php', 'projectClassPath' => self::$fixturesDirectory . '/propel/build/classes')))); // Empty database $con = \Propel::getConnection(); $con->beginTransaction(); try { foreach (\Curry_Propel::getModels(false) as $model) { \PropelQuery::from($model)->deleteAll(); } $con->commit(); } catch (Exception $e) { $con->rollBack(); throw $e; } $setup = new \Curry_Backend_Setup(); $setup->saveConfiguration(array('template' => 'empty', 'admin' => array('username' => 'admin', 'password' => 'admin'), 'user' => array('username' => 'user', 'password' => 'user'))); }
/** * Migrate curry to newer version. */ public function showUpgrade() { $this->addMainMenu(); $releases = self::getReleases(); if ($releases === null) { $this->addMessage('Unable to check for new releases', self::MSG_WARNING); } else { $latest = count($releases) ? array_pop($releases) : null; if ($latest) { $this->addMessage('Installed version: ' . Curry_Core::VERSION); $this->addMessage('Latest version: ' . $latest->version); if (version_compare($latest->version, Curry_Core::VERSION, '>')) { $this->addMessage('New release found: ' . $latest->name); } else { $this->addMessage('You already have the latest version.', self::MSG_SUCCESS); } } else { $this->addMessage('No releases could be found.', self::MSG_WARNING); } } if (!Curry_Core::requireMigration()) { return; } $form = self::getButtonForm('migrate', 'Migrate'); if (isPost() && $form->isValid($_POST) && $form->migrate->isChecked()) { $currentVersion = Curry_Core::$config->curry->migrationVersion; while ($currentVersion < Curry_Core::MIGRATION_VERSION) { $nextVersion = $currentVersion + 1; $migrateMethod = 'doMigrate' . $nextVersion; if (method_exists($this, $migrateMethod)) { try { if ($this->{$migrateMethod}()) { // update configuration migrateVersion number $config = new Zend_Config(require Curry_Core::$config->curry->configPath, true); $config->curry->migrateVersion = $nextVersion; $writer = new Zend_Config_Writer_Array(); $writer->write(Curry_Core::$config->curry->configPath, $config); $currentVersion = $nextVersion; $this->addMessage('Migration to version ' . $nextVersion . ' was successful!', self::MSG_SUCCESS); } else { $this->addMessage("Migrating to version {$nextVersion} returned failure.", self::MSG_ERROR); break; } } catch (Exception $e) { $this->addMessage("Unable to migrate to version {$nextVersion}: " . $e->getMessage(), self::MSG_ERROR); break; } } else { $this->addMessage("Unable to find migration method '{$migrateMethod}'.", self::MSG_ERROR); break; } } } else { $backupUrl = url('', array('module', 'view' => 'Bundle')); $this->addMessage('Curry CMS has been updated and you need to migrate your project before you can continue using the backend. You should <a href="' . $backupUrl . '">backup</a> your data and click the migrate button when you\'re ready!', Curry_Backend::MSG_WARNING, false); $this->addMainContent($form); } }
/** * This is the main function called by Curry_Admin. * * This will call the show{X}() function, where X is specified * by the GET-variable 'view'. It will then render the backend using * the render() function, and return the content. * * @return string */ public function show() { try { $this->preShow(); $view = empty($_GET['view']) ? 'Main' : $_GET['view']; $func = 'show' . $view; if (method_exists($this, $func)) { $this->{$func}(); } elseif (isset($this->proxyViews[$view])) { $callback = $this->proxyViews[$view]['callback']; call_user_func($callback); } else { throw new Exception('Invalid view'); } $this->postShow(); } catch (Exception $e) { if (!headers_sent()) { header("HTTP/1.0 500 Internal server error: " . str_replace("\n", " ", $e->getMessage())); } Curry_Core::log($e->getMessage()); $this->addMessage($e->getMessage(), self::MSG_ERROR); if (Curry_Core::$config->curry->developmentMode) { $this->addMainContent("<pre>" . htmlspecialchars($e->getTraceAsString()) . "</pre>"); } } return $this->render(); }
/** * Function to execute after generating page. */ protected function postGeneration() { if (Curry_Core::$config->curry->developmentMode) { $totalTime = 0; foreach ($this->moduleDebugInfo as $mdi) { $totalTime += $mdi[5]; } $labels = array('Name', 'Class', 'Template', 'Target', 'Cached', 'Time (ms)', 'Cpu (ms)', 'Memory Delta', 'Memory Peak', 'Queries'); Curry_Core::log(array("Modules(" . count($this->moduleDebugInfo) . "): " . round($totalTime / 1000.0, 3) . "s", array_merge(array($labels), $this->moduleDebugInfo)), Curry_Core::LOG_TABLE); } }
/** * Render the specified page revision. * * @param PageRevision $pageRevision * @param Curry_Request $request * @param array $vars * @param array $options */ protected function render(PageRevision $pageRevision, Curry_Request $request, array $vars, array $options) { Curry_Core::log('Showing page ' . $pageRevision->getPage()->getName() . ' (PageRevisionId: ' . $pageRevision->getPageRevisionId() . ')', Zend_Log::NOTICE); $time = microtime(true); $queries = Curry_Propel::getQueryCount(); $cacheName = __CLASS__ . '_Page_' . md5($request->getUri()); $cacheLifetime = $pageRevision->getPage()->getCacheLifetime(); $doCache = $request->getMethod() === 'GET' && $cacheLifetime !== 0; if ($doCache) { ob_start(); } $generator = self::createPageGenerator($pageRevision, $request); $generator->display($vars, $options); if ($doCache) { $cache = array('page_id' => $pageRevision->getPageId(), 'page_revision_id' => $pageRevision->getPageRevisionId(), 'headers' => headers_list(), 'content' => ob_get_flush()); Curry_Core::$cache->save($cache, $cacheName, array(), $cacheLifetime < 0 ? false : $cacheLifetime); } if (Curry_Core::$config->curry->updateTranslationStrings) { Curry_Language::updateLanguageStrings(); } $time = microtime(true) - $time; $queries = $queries !== null ? Curry_Propel::getQueryCount() - $queries : null; Curry_Core::triggerHook('Curry_Application::render', $pageRevision->getPageId(), $pageRevision->getPageRevisionId(), $time, $queries); }
/** * Open the lucene search index and return it. * * @param bool $forceCreation * @return Zend_Search_Lucene_Interface */ public static function getSearchIndex($forceCreation = false) { if (!self::$index || $forceCreation) { if (self::$index) { self::$index->commit(); self::$index = null; } Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()); Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding(self::$config->curry->internalEncoding); $path = Curry_Util::path(self::$config->curry->projectPath, 'data', 'searchindex'); self::$index = $forceCreation ? Zend_Search_Lucene::create($path) : Zend_Search_Lucene::open($path); } return self::$index; }
/** * Restore database from file. * * @todo Fix $maxExecutionTime. * * @param string|resource $file * @param array|null $tables * @param float $maxExecutionTime * @param int $continueLine * @param Curry_Backend|null $backend * @return bool True on success, false otherwise. */ public static function restoreFromFile($file, $tables = null, $maxExecutionTime = 0, $continueLine = 0, Curry_Backend $backend = null) { global $CURRY_DATABASE_RESTORE; $CURRY_DATABASE_RESTORE = true; $fp = is_string($file) ? fopen($file, "r") : $file; $t = microtime(true); $total = 0; $skipped = 0; $failed = 0; $session = new Zend_Session_Namespace(__CLASS__); $con = Propel::getConnection(); $con->beginTransaction(); $adapter = Propel::getDB(); if ($adapter instanceof DBMySQL) { $con->exec("SET foreign_key_checks = 0"); } // Read header $firstline = stream_get_line($fp, self::MAX_LINE_LENGTH, "\n"); $header = json_decode($firstline, true); if (is_array($header) && isset($header['header'])) { $header = $header['header']; // Check header version $version = isset($header['version']) ? (int) $header['version'] : 0; if ($version > self::VERSION) { throw new Exception('Unsupported database version. The file you are trying to restore from is from a newer version of currycms.'); } // Check page version $pageVersion = isset($header['page-version']) ? (int) $header['page-version'] : 0; if ($pageVersion > Page::VERSION) { throw new Exception('Unsupported page version. The file you are trying to restore from is from a newer version of currycms.'); } if ($backend) { $backend->addMessage("Restoring from " . $header['date']); } if ($pageVersion !== Page::VERSION) { if ($backend) { $backend->addMessage("Migrating data from version {$pageVersion} to " . Page::VERSION, Curry_Backend::MSG_WARNING); } Page::preMigrate($pageVersion); } } else { throw new Exception('Invalid header'); } // Empty tables if ($continueLine == 0) { foreach (Curry_Propel::getModels() as $classes) { foreach ($classes as $table) { try { if (is_array($tables) && !in_array($table, $tables)) { continue; } if (!method_exists($table, 'delete')) { if ($backend) { $backend->addMessage("Skipping read-only table: {$table}", Curry_Backend::MSG_WARNING); } continue; } $tableName = PropelQuery::from($table)->getTableMap()->getName(); // use basePeer to avoid foreign key emulation in Normal peer class BasePeer::doDeleteAll($tableName, $con); } catch (Exception $e) { throw new Exception('Unable to empty table ' . $table . ': ' . $e->getMessage()); } } } if ($backend) { $backend->addMessage("Cleared tables in " . round(microtime(true) - $t, 2) . "s"); } $t = microtime(true); } else { $total = $session->total; $skipped = $session->skipped; $failed = $session->failed; if ($backend) { $backend->addMessage("Continuing from line {$continueLine}."); } for ($i = 0; $i < $continueLine; ++$i) { stream_get_line($fp, self::MAX_LINE_LENGTH, "\n"); } } $currentTable = null; $buffer = array(); while (!feof($fp)) { // Read line $data = json_decode(stream_get_line($fp, self::MAX_LINE_LENGTH, "\n"), true); ++$total; if (is_array($data) && isset($data['table'])) { if (is_array($tables) && !in_array($data['table'], $tables) || !method_exists($data['table'], 'delete')) { ++$skipped; continue; } // Verify columns for new table if ($data['table'] !== $currentTable && $currentTable !== null && $backend) { $backend->addMessage('Restoring rows for table ' . $data['table']); $columns = Curry_Array::objectsToArray(PropelQuery::from($data['table'])->getTableMap()->getColumns(), null, 'getPhpName'); $added = array_diff($columns, array_keys($data['values'])); $removed = array_diff(array_keys($data['values']), $columns); if (count($added)) { $backend->addMessage('New column(s): ' . join(', ', $added), Curry_Backend::MSG_WARNING); } if (count($removed)) { $backend->addMessage('Removed column(s): ' . join(', ', $removed), Curry_Backend::MSG_WARNING); } } // Flush buffer when changing tables if ($data['table'] !== $currentTable || count($buffer) >= self::MULTIINSERT_MAXBUFFER) { if ($currentTable !== null && count($buffer)) { Curry_Propel::doMultiInsert($currentTable, $buffer); } $currentTable = $data['table']; $buffer = array(); } // Migrate data if ($pageVersion !== Page::VERSION) { if (!Page::migrateData($data['table'], $data['values'], $pageVersion)) { continue; } } $buffer[] = $data['values']; } else { if ($backend) { $backend->addMessage('Unable to read data on line ' . $total, Curry_Backend::MSG_ERROR); } ++$failed; } // check execution time if ($maxExecutionTime && Curry_Core::getExecutionTime() > $maxExecutionTime) { if ($currentTable !== null && count($buffer)) { Curry_Propel::doMultiInsert($currentTable, $buffer); } $session->total = $total; $session->skipped = $skipped; $session->failed = $failed; $params = array('module' => 'Curry_Backend_Database', 'view' => 'ContinueRestore', 'file' => $file, 'tables' => $tables, 'line' => $total, 'max_execution_time' => $maxExecutionTime); url('', $params)->redirect(302, true); } } // Flush buffer if ($currentTable !== null && count($buffer)) { Curry_Propel::doMultiInsert($currentTable, $buffer); } if ($pageVersion !== Page::VERSION) { Page::postMigrate($pageVersion); } if ($adapter instanceof DBMySQL) { $con->exec("SET foreign_key_checks = 1"); } $con->commit(); $CURRY_DATABASE_RESTORE = false; if ($backend) { if ($skipped) { $backend->addMessage("Skipped {$skipped} rows"); } if ($failed) { $backend->addMessage("Failed to add {$failed} rows", Curry_Backend::MSG_ERROR); } $backend->addMessage("Added " . ($total - $skipped - $failed) . " / {$total} rows in " . round(microtime(true) - $t, 2) . "s", !$failed ? Curry_Backend::MSG_SUCCESS : Curry_Backend::MSG_ERROR); } if (is_string($file)) { fclose($fp); } return !$failed; }
/** * Main routing function. * * @see parent::show() * * @return string */ public function show() { try { $this->preShow(); $func = 'show' . (isset($_GET['view']) ? $_GET['view'] : 'Main'); if (method_exists($this, $func)) { $this->{$func}(); } else { if (in_array($_GET['view'], $this->modelClasses)) { $this->editModel($_GET['view']); } else { if (in_array(substr($_GET['view'], 0, -1), $this->modelClasses) && substr($_GET['view'], -1) == 's') { $this->showGrid(substr($_GET['view'], 0, -1)); } else { if (in_array(substr($_GET['view'], 0, -4), $this->modelClasses) && substr($_GET['view'], -4) == 'Json') { $this->showGridJson(substr($_GET['view'], 0, -4)); } else { throw new Exception('Invalid view'); } } } } $this->postShow(); } catch (Exception $e) { if (!headers_sent()) { header("HTTP/1.0 500 Internal server error: " . str_replace("\n", " ", $e->getMessage())); } Curry_Core::log($e); $this->addMessage($e->getMessage(), self::MSG_ERROR); $this->addMainContent("<pre>" . htmlspecialchars($e->getTraceAsString()) . "</pre>"); } return $this->render(); }
/** * Show index statistics. */ public function showStatistics() { $this->addMainMenu(); $index = Curry_Core::getSearchIndex(); $this->addMessage('Number of documents: ' . $index->numDocs()); $this->addMessage('Number of deleted documents: ' . ($index->count() - $index->numDocs())); $this->addMessage('Number of terms: ' . count($index->terms())); }
/** * Shows the backend. This is the main method of this class. */ public function show() { $twig = $this->getTwig(); $templateFile = 'main.html'; $backendList = null; // Set content-type with charset (some webservers may otherwise override the charset) $encoding = Curry_Core::$config->curry->outputEncoding; header("Content-type: text/html; charset=" . $encoding); $htmlHead = $this->getHtmlHead(); $htmlHead->addStylesheet('shared/css/icons.css'); $htmlHead->addScript('shared/libs/jquery-ui-1.8.17/js/jquery-1.7.1.min.js'); $htmlHead->addScript('shared/backend/common/js/core.js'); $htmlHead->addScript('shared/backend/common/js/plugins.js'); $htmlHead->addScript('shared/backend/common/js/main.js'); $htmlHead->addScript('shared/backend/common/js/finder.js'); $htmlHead->addScript('shared/js/URI.js'); // Project backend css/js if (file_exists(Curry_Core::$config->curry->wwwPath . '/css/backend.css')) { $htmlHead->addStylesheet('css/backend.css'); } if (file_exists(Curry_Core::$config->curry->wwwPath . '/js/backend.js')) { $htmlHead->addScript('js/backend.js'); } // Set language if (Curry_Core::$config->curry->fallbackLanguage) { Curry_Language::setLanguage(Curry_Core::$config->curry->fallbackLanguage); } // Globals $twig->addGlobal('ProjectName', Curry_Core::$config->curry->name); $twig->addGlobal('Encoding', $encoding); $twig->addGlobal('Version', Curry_Core::VERSION); // Logotype if (Curry_Core::$config->curry->backend->logotype) { $twig->addGlobal('Logotype', Curry_Core::$config->curry->backend->logotype); } // Current module $currentModule = 'Curry_Backend_Page'; if (isset($_GET['module'])) { $currentModule = $_GET['module']; } if (Curry_Core::$config->curry->setup) { if ($currentModule !== 'Curry_Backend_Setup') { url('', array('module' => 'Curry_Backend_Setup'))->redirect(); } if (!class_exists('User')) { eval("class User { public static function getUser(){ return new self; } public function hasAccess() { return true; } public function getName() { return 'Dummy'; } }"); } else { User::dummyAuth(); } $backendList = array('Curry_Backend_Setup' => 'Setup'); } else { if (Curry_Core::$config->curry->backend->noauth) { User::dummyAuth(); } } $user = User::getUser(); if (!$user) { $loginRedirect = ''; if (isset($_POST['login_redirect'])) { $loginRedirect = $_POST['login_redirect']; } else { if (!isset($_GET['logout']) && count($_GET)) { $loginRedirect = (string) url('', $_GET); } } $twig->addGlobal('LoginRedirect', $loginRedirect); $this->addBodyClass('tpl-login'); $templateFile = 'login.html'; } else { $twig->addGlobal('user', array('Name' => $user->getName())); // Current module if ($backendList === null) { $backendList = Curry_Backend::getBackendList(); } if ($currentModule != 'Curry_Backend_Setup') { unset($backendList['Curry_Backend_Setup']); } if (!array_key_exists($currentModule, $backendList)) { throw new Exception('Backend module "' . $currentModule . '" not found'); } // Do we need to upgrade? $systemModules = array('Curry_Backend_System', 'Curry_Backend_Database', 'Curry_Backend_Setup'); if (Curry_Core::requireMigration() && !in_array($currentModule, $systemModules)) { url('', array('module' => 'Curry_Backend_System', 'view' => 'Upgrade'))->redirect(); } // Modules $backendGroups = array('Content' => array(), 'Appearance' => array(), 'Accounts' => array(), 'System' => array()); foreach ($backendList as $module => $moduleName) { if (!$user->hasAccess($module)) { continue; } $group = "Other"; if (method_exists($module, 'getGroup')) { $group = call_user_func(array($module, 'getGroup')); } $name = $moduleName; if (method_exists($module, 'getName')) { $n = call_user_func(array($module, 'getName')); if ($n) { $name = $n; } } $message = ''; if (method_exists($module, 'getMessage')) { $message = call_user_func(array($module, 'getMessage')); } $notifications = ''; if (method_exists($module, 'getNotifications')) { try { $notifications = call_user_func(array($module, 'getNotifications')); if (!isset($backendGroups[$group]['Notifications'])) { $backendGroups[$group]['Notifications'] = 0; } $backendGroups[$group]['Notifications'] += (int) $notifications; } catch (Exception $e) { } } $moduleProperties = array('Module' => $module, 'Active' => $module === $currentModule, 'Url' => url('', array("module" => $module)), 'Name' => $name, 'Title' => $message, 'Notifications' => $notifications); if ($group) { if (!isset($backendGroups[$group])) { $backendGroups[$group] = array(); } if (!isset($backendGroups[$group]['modules'])) { $backendGroups[$group]['modules'] = array(); } $backendGroups[$group]['modules'][$module] = $moduleProperties; $backendGroups[$group]['Name'] = $group; $backendGroups[$group]['Active'] = $module == $currentModule; } if ($module == $currentModule) { $twig->addGlobal('module', $moduleProperties); } } $twig->addGlobal('moduleGroups', $backendGroups); if ($currentModule && class_exists($currentModule)) { if ($user->hasAccess($currentModule)) { $this->backend = new $currentModule($this); if ($this->backend) { if (!in_array($currentModule, $systemModules)) { if (self::isPropelBuildInvalid()) { $this->backend->addMessage('Propel has been upgraded and you need to rebuild your database, use <a href="' . url('', array('module' => 'Curry_Backend_Database', 'view' => 'Propel')) . '">auto rebuild</a>.', Curry_Backend::MSG_WARNING, false); } if (Curry_Core::$config->curry->backend->noauth) { $this->backend->addMessage('Authorization has been disabled for backend. You can re-enable it if you go to <a href="' . url('', array('module' => 'Curry_Backend_System')) . '">System Settings</a>.', Curry_Backend::MSG_WARNING, false); } if (Curry_Core::$config->curry->maintenance->enabled) { $this->backend->addMessage('Site has been disabled for maintenance. You can re-enable it in <a href="' . url('', array('module' => 'Curry_Backend_System')) . '">System Settings</a>.', Curry_Backend::MSG_WARNING, false); } $this->doAutoBackup(); } $twig->addGlobal('content', $this->backend->show()); } } else { header('HTTP/1.1 403 Forbidden'); header('Status: 403 Forbidden'); $twig->addGlobal('content', 'Access denied'); } } } // Finalize HtmlHead and add global $htmlHead->addInlineScript('$.registerLibrary(' . Zend_Json::encode($this->libraries, false, array('enableJsonExprFinder' => true)) . ');'); $twig->addGlobal('HtmlHead', $htmlHead->getContent()); $twig->addGlobal('BodyClass', $this->getBodyClass()); // Render template $template = $twig->loadTemplate($templateFile); $template->display(array()); }