diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php index 6cce90db9de717c53079202ea106bf46ff2056f7..706ca2af74090240affa1502df63923ddfbc63d6 100644 --- a/module/VuFind/config/module.config.php +++ b/module/VuFind/config/module.config.php @@ -73,6 +73,7 @@ $config = array( 'error' => 'VuFind\Controller\ErrorController', 'help' => 'VuFind\Controller\HelpController', 'index' => 'VuFind\Controller\IndexController', + 'install' => 'VuFind\Controller\InstallController', 'my-research' => 'VuFind\Controller\MyResearchController', 'record' => 'VuFind\Controller\RecordController', 'search' => 'VuFind\Controller\SearchController', diff --git a/module/VuFind/src/VuFind/Controller/InstallController.php b/module/VuFind/src/VuFind/Controller/InstallController.php new file mode 100644 index 0000000000000000000000000000000000000000..f3898f6aad8708ef103180166a3f871d01e20556 --- /dev/null +++ b/module/VuFind/src/VuFind/Controller/InstallController.php @@ -0,0 +1,527 @@ +<?php +/** + * Install Controller + * + * PHP version 5 + * + * Copyright (C) Villanova University 2010. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind2 + * @package Controller + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ +namespace VuFind\Controller; +use VuFind\Config\Reader as ConfigReader, Zend\Mvc\MvcEvent; + +/** + * Class controls VuFind auto-configuration. + * + * @category VuFind2 + * @package Controller + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ + +class InstallController extends AbstractBase +{ + /** + * preDispatch -- block access when appropriate. + * + * @param MvcEvent $e Event object + * + * @return void + */ + public function preDispatch(MvcEvent $e) + { + // If auto-configuration is disabled, prevent any other action from being + // accessed: + $config = ConfigReader::getConfig(); + if (!isset($config->System->autoConfigure) + || !$config->System->autoConfigure + ) { + $routeMatch = $e->getRouteMatch(); + $routeMatch->setParam('action', 'disabled'); + } + } + + /** + * Register the default events for this controller + * + * @return void + */ + protected function attachDefaultListeners() + { + parent::attachDefaultListeners(); + $events = $this->getEventManager(); + $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'preDispatch'), 1000); + } + + /** + * Display disabled message. + * + * @return void + */ + public function disabledAction() + { + return $this->createViewModel(); + } + + /** + * Check if basic configuration is taken care of. + * + * @return array + */ + protected function checkBasicConfig() + { + /* TODO + // Assume success by default -- we'll set to failure if necessary: + $status = true; + + // Make sure we have a local configuration file: + $config = LOCAL_OVERRIDE_DIR . '/application/configs/config.ini'; + if (!file_exists($config)) { + if (!copy(APPLICATION_PATH . '/configs/config.ini', $config)) { + $status = false; + } + } + + // See if the URL setting remains at the default (unless we already + // know we've failed): + if ($status) { + $config = VF_Config_Reader::getConfig(); + if (stristr($config->Site->url, 'myuniversity.edu')) { + $status = false; + } + } + + return array( + 'title' => 'Basic Configuration', 'status' => $status, + 'fix' => 'fixbasicconfig' + ); + */ + } + + /** + * Display repair instructions for basic configuration problems. + * + * @return void + */ + public function fixbasicconfigAction() + { + /* TODO + try { + $config = LOCAL_OVERRIDE_DIR . '/application/configs/config.ini'; + if (!file_exists($config)) { + if (!copy(APPLICATION_PATH . '/configs/config.ini', $config)) { + throw new Exception('Cannot copy file into position.'); + } + } + $writer = new VF_Config_Writer($config); + $path = $this->view->url( + array('controller' => 'index', 'action' => 'Home'), + 'default', true, false + ); + $writer->set('Site', 'url', rtrim($this->view->fullUrl($path), '/')); + if (!$writer->save()) { + throw new Exception('Cannot write config to disk.'); + } + } catch (Exception $e) { + $this->view->configDir = dirname($config); + if (function_exists('posix_getpwuid') + && function_exists('posix_geteuid') + ) { + $processUser = posix_getpwuid(posix_geteuid()); + $this->view->runningUser = $processUser['name']; + } + } + */ + } + + /** + * Check if the cache directory is writable. + * + * @return array + */ + protected function checkCache() + { + /* TODO + $cache = new VF_Cache_Manager(); + return array( + 'title' => 'Cache', + 'status' => !$cache->hasDirectoryCreationError(), + 'fix' => 'fixcache' + ); + */ + } + + /** + * Display repair instructions for cache problems. + * + * @return void + */ + public function fixcacheAction() + { + /* TODO + $cache = new VF_Cache_Manager(); + $this->view->cacheDir = $cache->getCacheDir(); + if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) { + $processUser = posix_getpwuid(posix_geteuid()); + $this->view->runningUser = $processUser['name']; + } + */ + } + + /** + * Check if the database is accessible. + * + * @return array + */ + protected function checkDatabase() + { + /* TODO + try { + // Try to read the tags table just to see if we can connect to the DB: + $tags = new VuFind_Model_Db_Tags(); + $test = $tags->getByText('test', false); + $status = true; + } catch (Exception $e) { + $status = false; + } + return array( + 'title' => 'Database', 'status' => $status, 'fix' => 'fixdatabase' + ); + */ + } + + /** + * Check for missing dependencies. + * + * @return array + */ + protected function checkDependencies() + { + /* TODO + $status + = function_exists('mb_substr') && is_callable('imagecreatefromstring'); + return array( + 'title' => 'Dependencies', 'status' => $status, + 'fix' => 'fixdependencies' + ); + */ + } + + /** + * Show how to fix dependency problems. + * + * @return void + */ + public function fixdependenciesAction() + { + /* TODO + $this->view->problems = 0; + + // Is the mbstring library missing? + if (!function_exists('mb_substr')) { + $msg + = "Your PHP installation appears to be missing the mbstring plug-in." + ." For better language support, it is recommended that you add this." + ." For details on how to do this, see " + ."http://vufind.org/wiki/installation " + ."and look at the PHP installation instructions for your platform."; + $this->_helper->flashMessenger->setNamespace('error')->addMessage($msg); + $this->view->problems++; + } + + // Is the GD library missing? + if (!is_callable('imagecreatefromstring')) { + $msg + = "Your PHP installation appears to be missing the GD plug-in. " + . "For better graphics support, it is recommended that you add this." + . " For details on how to do this, see " + . "http://vufind.org/wiki/installation " + . "and look at the PHP installation instructions for your platform."; + $this->_helper->flashMessenger->setNamespace('error')->addMessage($msg); + $this->view->problems++; + } + */ + } + + /** + * Display repair instructions for database problems. + * + * @return void + */ + public function fixdatabaseAction() + { + /* TODO + $this->view->dbname = $this->_request->getParam('dbname', 'vufind'); + $this->view->dbuser = $this->_request->getParam('dbuser', 'vufind'); + $this->view->dbhost = $this->_request->getParam('dbhost', 'localhost'); + $this->view->dbrootuser = $this->_request->getParam('dbrootuser', 'root'); + + if (!preg_match('/^\w*$/', $this->view->dbname)) { + $this->_helper->flashMessenger->setNamespace('error') + ->addMessage('Database name must be alphanumeric.'); + } else if (!preg_match('/^\w*$/', $this->view->dbuser)) { + $this->_helper->flashMessenger->setNamespace('error') + ->addMessage('Database user must be alphanumeric.'); + } else if (strlen($this->_request->getParam('submit', '')) > 0) { + $newpass = $this->_request->getParam('dbpass'); + $newpassConf = $this->_request->getParam('dbpassconfirm'); + if (empty($newpass) || empty($newpassConf)) { + $this->_helper->flashMessenger->setNamespace('error') + ->addMessage('Password fields must not be blank.'); + } else if ($newpass != $newpassConf) { + $this->_helper->flashMessenger->setNamespace('error') + ->addMessage('Password fields must match.'); + } else { + // Connect to database: + $params = array( + 'host' => $this->view->dbhost, + 'username' => $this->view->dbrootuser, + 'password' => $this->_request->getParam('dbrootpass'), + 'dbname' => null + ); + $db = Zend_Db::factory('mysqli', $params); + try { + $connection = $db->getConnection(); + $query = 'CREATE DATABASE ' . $this->view->dbname; + if (!$connection->query($query)) { + throw new Exception($connection->error); + } + $grant = "GRANT SELECT,INSERT,UPDATE,DELETE ON " + . $this->view->dbname + . ".* TO '{$this->view->dbuser}'@'{$this->view->dbhost}' " + . "IDENTIFIED BY '" + . $connection->real_escape_string($newpass) + . "' WITH GRANT OPTION"; + if (!$connection->query($grant)) { + throw new Exception($connection->error); + }; + if (!$connection->query('FLUSH PRIVILEGES')) { + throw new Exception($connection->error); + } + $connection->select_db($this->view->dbname); + $sql = file_get_contents(APPLICATION_PATH . '/sql/mysql.sql'); + $statements = explode(';', $sql); + foreach ($statements as $current) { + // Skip empty sections: + if (strlen(trim($current)) == 0) { + continue; + } + if (!$connection->query($current)) { + throw new Exception($connection->error); + } + } + // If we made it this far, we can update the config file and + // forward back to the home action! + $string = "mysql://{$this->view->dbuser}:{$newpass}@" + . $this->view->dbhost . '/' . $this->view->dbname; + $config = LOCAL_OVERRIDE_DIR . '/application/configs/config.ini'; + $writer = new VF_Config_Writer($config); + $writer->set('Database', 'database', $string); + if (!$writer->save()) { + return $this->_forward('fixbasicconfig'); + } + return $this->_redirect('/Install'); + } catch (Exception $e) { + $this->_helper->flashMessenger->setNamespace('error') + ->addMessage($e->getMessage()); + } + } + } + */ + } + + /** + * Check if ILS configuration is appropriate. + * + * @return array + */ + protected function checkILS() + { + /* TODO + $config = VF_Config_Reader::getConfig(); + if (in_array($config->Catalog->driver, array('Sample', 'Demo'))) { + $status = false; + } else { + try { + $catalog = VF_Connection_Manager::connectToCatalog(); + $status = true; + } catch (Exception $e) { + $status = false; + } + } + return array('title' => 'ILS', 'status' => $status, 'fix' => 'fixils'); + */ + } + + /** + * Display repair instructions for ILS problems. + * + * @return void + */ + public function fixilsAction() + { + /* TODO + // Process incoming parameter -- user may have selected a new driver: + $newDriver = $this->_request->getParam('driver'); + if (!empty($newDriver)) { + $configPath = LOCAL_OVERRIDE_DIR . '/application/configs/config.ini'; + $writer = new VF_Config_Writer($configPath); + $writer->set('Catalog', 'driver', $newDriver); + if (!$writer->save()) { + return $this->_forward('fixbasicconfig'); + } + // Copy configuration, if applicable: + $ilsIni = APPLICATION_PATH . '/configs/' . $newDriver . '.ini'; + if (file_exists($ilsIni)) { + $success = copy( + $ilsIni, + LOCAL_OVERRIDE_DIR . "/application/configs/{$newDriver}.ini" + ); + if (!$success) { + return $this->_forward('fixbasicconfig'); + } + } + return $this->_redirect('/Install'); + } + + // If we got this far, check whether we have an error with a real driver + // or if we need to warn the user that they have selected a fake driver: + $config = VF_Config_Reader::getConfig(); + if (in_array($config->Catalog->driver, array('Sample', 'Demo'))) { + $this->view->demo = true; + // Get a list of available drivers: + $dir = opendir(APPLICATION_PATH . '/../library/VF/ILS/Driver'); + $this->view->drivers = array(); + $blacklist = array('Sample.php', 'Demo.php', 'Interface.php'); + while ($line = readdir($dir)) { + if (stristr($line, '.php') && !in_array($line, $blacklist)) { + $this->view->drivers[] = str_replace('.php', '', $line); + } + } + closedir($dir); + sort($this->view->drivers); + } else { + $this->view->configPath = LOCAL_OVERRIDE_DIR + . "/application/configs/{$config->Catalog->driver}.ini"; + } + */ + } + + /** + * Check if the Solr index is working. + * + * @return array + */ + protected function checkSolr() + { + /* TODO + try { + $solr = VF_Connection_Manager::connectToIndex(); + $results = $solr->search(); + $status = true; + } catch (Exception $e) { + $status = false; + } + return array('title' => 'Solr', 'status' => $status, 'fix' => 'fixsolr'); + */ + } + + /** + * Display repair instructions for Solr problems. + * + * @return void + */ + public function fixsolrAction() + { + /* TODO + // In Windows, localhost may fail -- see if switching to 127.0.0.1 helps: + $config = VF_Config_Reader::getConfig(); + $configFile = LOCAL_OVERRIDE_DIR . '/application/configs/config.ini'; + if (stristr($config->Index->url, 'localhost')) { + $newUrl = str_replace('localhost', '127.0.0.1', $config->Index->url); + try { + $solr = VF_Connection_Manager::connectToIndex(null, null, $newUrl); + $results= $solr->search(); + + // If we got this far, the fix worked. Let's write it to disk! + $writer = new VF_Config_Writer($configFile); + $writer->set('Index', 'url', $newUrl); + if (!$writer->save()) { + return $this->_forward('fixbasicconfig'); + } + return $this->_redirect('/Install'); + } catch (Exception $e) { + // Didn't work! + } + } + + // If we got this far, the automatic fix didn't work, so let's just assign + // some variables to use in offering troubleshooting advice: + $this->view->rawUrl = $config->Index->url; + $this->view->userUrl = str_replace( + array('localhost', '127.0.0.1'), $this->_request->getHttpHost(), + $config->Index->url + ); + $this->view->core = isset($config->Index->default_core) + ? $config->Index->default_core : "biblio"; + $this->view->configFile = $configFile; + */ + } + + /** + * Disable auto-configuration. + * + * @return void + */ + public function doneAction() + { + /* TODO + $configDir = LOCAL_OVERRIDE_DIR . '/application/configs'; + $writer = new VF_Config_Writer($configDir . '/config.ini'); + $writer->set('System', 'autoConfigure', 0); + if (!$writer->save()) { + return $this->_forward('fixbasicconfig'); + } + $this->view->configDir = $configDir; + */ + } + + /** + * Display summary of installation status + * + * @return void + */ + public function homeAction() + { + /* TODO + // Perform all checks (based on naming convention): + $methods = get_class_methods($this); + $this->view->checks = array(); + foreach ($methods as $method) { + if (substr($method, 0, 5) == 'check') { + $this->view->checks[] = $this->$method(); + } + } + */ + } +} +