<?php
/**
 * Install Controller
 *
 * PHP version 5
 *
 * @category Controller
 * @package  Croogo
 * @version  1.0
 * @author   Fahad Ibnay Heylaal <contact@fahad19.com>
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 * @link     http://www.croogo.org
 */
class InstallController extends InstallAppController {
/**
 * Controller name
 *
 * @var string
 * @access public
 */
	var $name = 'Install';
/**
 * No models required
 *
 * @var array
 * @access public
 */
    var $uses = null;
/**
 * No components required
 *
 * @var array
 * @access public
 */
    var $components = null;
/**
 * beforeFilter
 *
 * @return void
 */
    function beforeFilter() {
        parent::beforeFilter();

        $this->layout = 'install';
        App::import('Component', 'Session');
        $this->Session = new SessionComponent;

    }
/**
 * Step 0: welcome
 *
 * A simple welcome message for the installer.
 *
 * @return void
 */
    function index() {

	// file/dir check
	$error = array();
	$permissions = array(
		array(
			'path' => APP.'config', 
			'type' => 'dir',
		),
		array(
			'path' => TMP, 
			'type' => 'dir',
		),
		array(
			'path' => WWW_ROOT. 'media', 
			'type' => 'dir',
		),
		array(
			'path' => WWW_ROOT. 'media'. DS. 'transfer', 
			'type' => 'dir',
		),
		array(
			'path' => WWW_ROOT. 'media'. DS. 'filter', 
			'type' => 'dir',
		),
		array(
			'path' => APP. 'views'. DS. 'themed', 
			'type' => 'dir',
		),
	);

	// check file_exists
	if (!file_exists(APP.'config'.DS.'database.php.install') || !is_readable(APP.'config'.DS.'database.php.install')) {
		$error['nofile'][] = APP.'config'.DS.'database.php.install';
	} else {
		$permissions[] = array(
			'path' => APP.'config'.DS.'database.php.install', 
			'type' => 'file',
		);
	}
	if (!file_exists(APP.'config'.DS.'core.php') || !is_readable(APP.'config'.DS.'core.php')) {
		$error['nofile'][] = APP.'config'.DS.'core.php';
	} else {
		$permissions[] = array(
			'path' => APP.'config'.DS.'core.php',
			'type' => 'file',
		);
	}

	// check permission
	foreach ($permissions as $k => $v) {
		$allowed = array();
		if ($v['type'] == 'dir') {
			$allowed = array('0777', '0707');
		} elseif ($v['type'] == 'file') {
			$allowed = array('0777', '0707', '0666', '0606');
		} 

		if (!in_array(substr(sprintf('%o', fileperms($v['path'])), -4), $allowed)) {
			$error['permission'][] = $v['path'];
		}
	}
	$this->set('error', $error);

	echo ' ';
        $this->set('title_for_layout', __('Installation: Welcome', true));
    }
/**
 * Step 1: database
 *
 * @return void
 */
    function database() {
        $this->set('title_for_layout', __('Step 1: Database', true));
        if (!empty($this->data)) {
            // test database connection
            if (mysql_connect($this->data['Install']['host'], $this->data['Install']['login'], $this->data['Install']['password']) &&
                mysql_select_db($this->data['Install']['database'])) {
                // rename database.php.install
                $result = @rename(APP.'config'.DS.'database.php.install', APP.'config'.DS.'database.php');
		if ($result === false) {
			$this->Session->setFlash(__('Could not make database.php file.', true));
		} else {

			// open database.php file
			App::import('Core', 'File');
			$file = new File(APP.'config'.DS.'database.php', true);
			$content = $file->read();

			// write database.php file
			$content = str_replace('{default_host}', $this->data['Install']['host'], $content);
			$content = str_replace('{default_login}', $this->data['Install']['login'], $content);
			$content = str_replace('{default_password}', $this->data['Install']['password'], $content);
			$content = str_replace('{default_database}', $this->data['Install']['database'], $content);
			// The database import script does not support prefixes at this point
			$content = str_replace('{default_prefix}', $this->data['Install']['prefix'], $content);
			
			if($file->write($content) ) {
				$this->redirect(array('action' => 'data'));
			} else {
				$this->Session->setFlash(__('Could not write database.php file.', true));
				@rename(APP.'config'.DS.'database.php', APP.'config'.DS.'database.php.install');
			}
		}
            } else {
                $this->Session->setFlash(__('Could not connect to database.', true));
            }
	echo ' ';

        }
    }
/**
 * Step 2: insert required data
 *
 * @return void
 */
    function data() {
        $this->set('title_for_layout', __('Step 2: Run SQL', true));
        //App::import('Core', 'Model');
        //$Model = new Model;

        if (isset($this->params['named']['run'])) {
            App::import('Core', 'File');
            App::import('Model', 'ConnectionManager');
            $db = ConnectionManager::getDataSource('default');

            if(!$db->isConnected()) {
                $this->Session->setFlash(__('Could not connect to database.', true));
            } else {
//                $this->__executeSQLScript($db, CONFIGS.'sql'.DS.'dump.sql');
                $this->__executeSQLScript($db, CONFIGS.'sql'.DS.'install'.DS.'create_table.sql');
                $this->__executeSQLScript($db, CONFIGS.'sql'.DS.'install'.DS.'insert_data.sql');

		// set new salt and cipherSeed value
		$File =& new File(CONFIGS . 'core.php');
		if (!class_exists('Security')) {
		    require LIBS . 'security.php';
		}
		$salt = Security::generateAuthKey();
		$seed = null;
		for ($i=0;$i<30;$i++) {
			$seed .= rand(0, 9);
		}
		$contents = $File->read();
		$contents = preg_replace('/(?<=Configure::write\(\'Security.salt\', \')([^\' ]+)(?=\'\))/', $salt, $contents);
		$contents = preg_replace('/(?<=Configure::write\(\'Security.cipherSeed\', \')(\d+)(?=\'\))/', $seed, $contents);

		if (!$File->write($contents)) {
			$this->Session->setFlash(__('Could not set Security.saltor Security.cipherSeed of "app/config/core.php" files. PLEASE edit them  manually.', true));
		}

		// core.phpのバックアップ
		@copy(CONFIGS . 'core.php', CONFIGS . 'core.php.bk_'.time());

		$this->redirect(array('plugin' => 'install', 'controller' => 'install', 'action' => 'regist'));
            }
        }
    }
/**
 * Step 3: regist
 *
 * Regist Administrator Account and come informations of the site.
 *
 * @return void
 */
    function regist() {
        $this->set('title_for_layout', __('Initial registration for the Site.', true));

	if (!empty($this->data)) {

		$this->User = CorePlus::set_model('User');
		$this->User->set($this->data);
		if ($this->User->validates()) {

			// SiteConfig
			$this->SiteConfig = CorePlus::set_model('SiteConfig');

			$siteConfig['SiteConfig'][] = array(
				'key_name' => 'Site.siteName',
				'value' => $this->data['SiteConfig']['siteName']
			);
			$siteConfig['SiteConfig'][] = array(
				'key_name' => 'Site.adminAddress',
				'value' => $this->data['User']['pcmail']
			);
			unset($this->data['SiteConfig']['siteName']);

			$this->SiteConfig->saveAll($siteConfig['SiteConfig'], array('fieldList' => $this->SiteConfig->fields['add']));


			// Set Administrator
			$this->data['User']['group_id'] = Configure::read('Group.admin');

			App::import('Component', 'Auth');
			$this->Auth = new AuthComponent;
			$this->data['User']['password'] = $this->Auth->password($this->data['User']['password1']);

			// Crypt
			App::import('Component', 'Crypt');
			$this->Crypt = new CryptComponent;
			$this->data['User']['pcmail'] = $this->Crypt->crypt($this->data['User']['pcmail']);

			if ($this->User->save($this->data, array('fieldList' => array_merge($this->User->fields['add'], array('pcmail')), 'validate' => false))) {
				$this->redirect(array('plugin' => 'install', 'controller' => 'install', 'action' => 'finish'));
			} else {
				$this->Session->setFlash(__('Initial registrations could not be saves.', true));
			}
		}
	}

	$this->set('idLength', Configure::read('User.UserId.Length'));
	$this->set('passwordLength', Configure::read('User.Password.Length'));

    }
/**
 * Step 4: finish
 *
 * Remind the user to delete 'install' plugin.
 *
 * @return void
 */
    function finish() {
        $this->set('title_for_layout', __('Installation completed successfully', true));

/* Delete method killed (because it depending on Permission)
        if (isset($this->params['named']['delete'])) {
            App::import('Core', 'Folder');
            $this->folder = new Folder;
            if ($this->folder->delete(APP.'plugins'.DS.'install')) {
                $this->Session->setFlash(__('Installataion files deleted successfully.', true));
                $this->redirect('/');
                exit();
            } else {
                $this->Session->setFlash(__('Could not delete installation files.', true));
            }
        }
*/
    }
/**
 * Execute SQL file
 *
 * @link http://cakebaker.42dh.com/2007/04/16/writing-an-installer-for-your-cakephp-application/
 * @param object $db Database
 * @param string $fileName sql file
 * @return void
 */
    function __executeSQLScript($db, $fileName) {
        $statements = file_get_contents($fileName);
        $statements = explode(';', $statements);

	$prefix = $db->config["prefix"];

        foreach ($statements as $statement) {
            if (trim($statement) != '') {

		// table prefix
		if (!empty($prefix)) {
			$pattern = array(
				'/(DROP TABLE IF EXISTS `)([a-z_]+)(`)/i', // DROP TABLE
				'/(CREATE TABLE `)([a-z_]+)(`)/i', // CREATE TABLE
				'/(FOREIGN KEY \(`[a-z_]+`\) REFERENCES `)([a-z_]+)(`)/i', // FOREIGN KEY
				'/(LOCK TABLES `)([a-z_]+)(`)/i', // TABLE LOCK
				'/(INSERT INTO `)([a-z_]+)(` VALUES)/i', // INSERT
				'/(ALTER TABLE `)([a-z_]+)(`)/i', // ALTER TABLE
			);

			$statement = preg_replace($pattern, '$1'.$prefix.'$2$3', $statement);
		}

                $db->query($statement);
            }
        }
    }

}
