[pLog-svn] r5990 - plog/branches/lifetype-1.2
reto at devel.lifetype.net
reto at devel.lifetype.net
Fri Oct 19 16:49:08 EDT 2007
Author: reto
Date: 2007-10-19 16:49:07 -0400 (Fri, 19 Oct 2007)
New Revision: 5990
Added:
plog/branches/lifetype-1.2/wizard.php
Log:
hmmm, somehow the wizard lost its file extension (php).
strange...
Copied: plog/branches/lifetype-1.2/wizard.php (from rev 5989, plog/branches/lifetype-1.2/wizard)
===================================================================
--- plog/branches/lifetype-1.2/wizard.php (rev 0)
+++ plog/branches/lifetype-1.2/wizard.php 2007-10-19 20:49:07 UTC (rev 5990)
@@ -0,0 +1,2367 @@
+|<?php
+
+ if (!defined( "PLOG_CLASS_PATH" )) {
+ define( "PLOG_CLASS_PATH", dirname(__FILE__)."/");
+ }
+
+ set_time_limit (5 * 3600);
+
+ //
+ // enable this for debugging purposes
+ //
+ define( "DB_WIZARD_DEBUG", false );
+
+ //
+ // in case you're having problems with time outs while upgrading (probably too
+ // many records) lower this figure
+ //
+ define( "WIZARD_MAX_RECORDS_PER_STEP", 75 );
+
+ //
+ // minimum php version required
+ //
+ define( "MIN_PHP_VERSION", "4.2.0" );
+
+ //
+ // whether data transformers should fail on error by default
+ // It might be convenient to set this to 'false' if we're running
+ // the wizard on top of an already updated installation
+ //
+ define( "DATABASE_DATA_TRANSFORMER_FAIL_ON_ERROR_DEFAULT", true );
+
+ // many hosts don't have this enabled and we, for the time being, need it...
+ ini_set("arg_seperator.output", "&");
+
+ include_once( PLOG_CLASS_PATH."class/bootstrap.php" );
+ lt_include( PLOG_CLASS_PATH."class/controller/controller.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/template/templateservice.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/action/action.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/database/db.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/template/template.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/view/view.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/validator/usernamevalidator.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/validator/stringvalidator.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/validator/integervalidator.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/validator/emailvalidator.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/validator/passwordvalidator.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/timestamp.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/net/http/httpvars.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/misc/version.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/file/file.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/file/finder/filefinder.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/gallery/resizers/gddetector.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/config/configfilestorage.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/data/textfilter.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/locale/locales.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/locale/localefinder.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/template/templatesets/templatesets.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/bloginfo.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/users.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/blogs.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/articlecategories.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/articles.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/mylinkscategories.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/userpermissions.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/blogcategories.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/globalarticlecategories.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/gallery/dao/galleryalbums.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/permissions.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/userpermissions.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/permission.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/userpermission.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/dao/userinfo.class.php" );
+ lt_include( PLOG_CLASS_PATH."class/misc/integritychecker.class.php" );
+
+ // table schemas
+ include( PLOG_CLASS_PATH."install/dbschemas.properties.php" );
+ // default configuration values for 1.1
+ include( PLOG_CLASS_PATH."install/defaultconfig.properties.php" );
+
+ define( "TEMP_FOLDER", "./tmp" );
+
+ // maps used to map requests with actions
+ $_actionMap["Checks"] = "WizardChecks";
+ $_actionMap["Default"] = "WizardChecks";
+ $_actionMap["Intro"] = "WizardIntro";
+ $_actionMap["Step1"] = "WizardStepOne";
+ $_actionMap["Step2"] = "WizardStepTwo";
+ $_actionMap["Step3"] = "WizardStepThree";
+ $_actionMap["Step4"] = "WizardStepFour";
+ $_actionMap["Step5"] = "WizardStepFive";
+ $_actionMap["Update1"] = "UpdateStepOne";
+ $_actionMap["Update2"] = "UpdateStepTwo";
+ $_actionMap["Update3"] = "UpdateStepThree";
+ $_actionMap["Fix120"] = "Fix120StepOne";
+
+
+ /**
+ * Open a connection to the database
+ */
+ function connectDb( $ignoreError = false , $selectDatabase = true )
+ {
+ $config = new ConfigFileStorage();
+ // open a connection to the database
+ //$db = NewADOConnection('mysql');
+ $db = PDb::getDriver('mysql');
+
+ if ( $selectDatabase ) {
+ $res = $db->Connect($config->getValue( "db_host" ), $config->getValue( "db_username" ), $config->getValue( "db_password" ), $config->getValue( "db_database" ), $config->getValue( "db_character_set" ));
+ } else {
+ $res = $db->Connect($config->getValue( "db_host" ), $config->getValue( "db_username" ), $config->getValue( "db_password" ), null, $config->getValue( "db_character_set" ));
+ }
+
+ if( DB_WIZARD_DEBUG )
+ $db->debug = true;
+
+ // return error
+ if( $ignoreError )
+ return $db;
+
+ if( !$res )
+ return false;
+
+ return $db;
+ }
+
+ /**
+ * Returns the database prefix
+ */
+ function getDbPrefix()
+ {
+ $config = new ConfigFileStorage();
+ return $config->getValue( "db_prefix" );
+ }
+
+ /**
+ * some useful little functions
+ */
+ class WizardTools
+ {
+ /**
+ * returns true if plog has already been installed before or
+ * false otherwise
+ */
+ function isNewInstallation()
+ {
+ $configFile = new ConfigFileStorage();
+ // if plog hasn't been installed, this file will have empty settings
+ if( $configFile->getValue( "db_host") == "" && $configFile->getValue( "db_username") == "" &&
+ $configFile->getValue( "db_database") == "" && $configFile->getValue( "db_prefix" ) == "" &&
+ $configFile->getValue( "db_password" ) == "" )
+ $isNew = true;
+ else
+ $isNew = false;
+
+ return( $isNew );
+ }
+
+ /**
+ * Clean up the default temporary folder
+ */
+ function cleanTmpFolder()
+ {
+ // remove the files recursively, but only files, do not do anything to directories
+ File::deleteDir( TEMP_FOLDER, true, true, array(".svn", ".htaccess") );
+ }
+ }
+
+ /**
+ * Renders a template file.
+ */
+ class WizardView extends View
+ {
+
+ var $_templateName;
+
+ function WizardView( $templateName )
+ {
+ $this->View();
+ $this->_templateName = $templateName;
+ }
+
+ function render()
+ {
+ // build the file name
+ $templateFileName = "wizard/".$this->_templateName.".template";
+
+ //$t = new Template( $templateFileName, "" );
+ $t = new Smarty();
+ $v = new Version();
+ $this->_params->setValue( "version", $v->getVersion());
+ $this->_params->setValue( "projectPage", $v->getProjectPage());
+ $this->_params->setValue( "safeMode", ini_get("safe_mode"));
+ $t->assign( $this->_params->getAsArray());
+ $t->template_dir = "./templates";
+ $t->compile_dir = TEMP_FOLDER;
+ $t->cache_dir = TEMP_FOLDER;
+ $t->use_sub_dirs = false;
+ $t->caching = false;
+
+ print $t->fetch( $templateFileName );
+ }
+ }
+
+ class WizardAction extends Action
+ {
+ function WizardAction( $actionInfo, $request )
+ {
+ $this->Action( $actionInfo, $request );
+ }
+ }
+
+ class WizardValidator
+ {
+ var $_desc;
+ var $_critical;
+ var $_valid;
+ var $_solution;
+
+ function WizardValidator( $desc = "", $solution = "", $critical = true )
+ {
+ $this->_desc = $desc;
+ $this->_critical = $critical;
+ $this->_valid = false;
+ $this->_solution = $solution;
+ }
+
+ function isCritical()
+ {
+ return( $this->_critical );
+ }
+
+ function getDesc()
+ {
+ return( $this->_desc );
+ }
+
+ function isValid()
+ {
+ return( $this->_valid );
+ }
+
+ function getSolution()
+ {
+ return( $this->_solution );
+ }
+
+ function validate()
+ {
+ return( $this->_valid );
+ }
+ }
+
+ class WizardPhpVersionValidator extends WizardValidator
+ {
+ function WizardPhpVersionValidator( $minVersion = MIN_PHP_VERSION )
+ {
+ $this->WizardValidator( "Checking if the installed <b>PHP</b> version is at least $minVersion",
+ "Please upgrade your version of PHP to $minVersion or newer",
+ true );
+ $this->_minVersion = $minVersion;
+ }
+
+ function validate()
+ {
+ $this->_valid = version_compare( phpversion(), $this->_minVersion ) >= 0;
+ return( parent::validate());
+ }
+ }
+
+ class WizardWritableFileValidator extends WizardValidator
+ {
+ var $_file;
+
+ function WizardWritableFileValidator( $file )
+ {
+ $this->WizardValidator( "Checking if file/folder <b>$file</b> is writable",
+ "Please make sure that the file is writable by the web server",
+ true );
+ $this->_file = $file;
+ }
+
+ function validate()
+ {
+ $this->_valid = File::isWritable( $this->_file );
+ return( parent::validate());
+ }
+ }
+
+ class WizardSessionFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardSessionFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>session</b> functions are available",
+ "LifeType requires support for sessions to be part of your PHP installation",
+ true );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "session_start" ) &&
+ function_exists( "session_destroy" ) &&
+ function_exists( "session_cache_limiter" ) &&
+ function_exists( "session_name" ) &&
+ function_exists( "session_set_cookie_params" ) &&
+ function_exists( "session_save_path" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardSessionSettingsValidator extends WizardValidator
+ {
+ function WizardSessionSettingsValidator()
+ {
+ $this->WizardValidator( "Checking if <b>session.auto_start</b> is disabled",
+ "LifeType can only run when session.auto_start is disabled.",
+ true );
+ }
+
+ function validate()
+ {
+ $this->_valid = (ini_get( "session.auto_start" ) == "0");
+ return( parent::validate());
+ }
+ }
+
+ class WizardMySQLFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardMySQLFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>MySQL</b> functions are available",
+ "LifeType requires support for MySQL to be part of your PHP installation",
+ true );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "mysql_select_db" ) &&
+ function_exists( "mysql_query" ) &&
+ function_exists( "mysql_connect" ) &&
+ function_exists( "mysql_fetch_assoc" ) &&
+ function_exists( "mysql_num_rows" ) &&
+ function_exists( "mysql_free_result" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardXmlFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardXmlFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>XML</b> functions are available",
+ "LifeType requires support for XML to be part of your PHP installation",
+ true );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "xml_set_object" ) &&
+ function_exists( "xml_set_element_handler" ) &&
+ function_exists( "xml_parser_create" ) &&
+ function_exists( "xml_parser_set_option" ) &&
+ function_exists( "xml_parse" ) &&
+ function_exists( "xml_parser_free" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardSafeModeValidator extends WizardValidator
+ {
+ function WizardSafeModeValidator()
+ {
+ $this->WizardValidator( "Checking if <b>safe mode</b> is disabled",
+ "LifeType can run when PHP's safe mode is enabled, but it may cause some problems.",
+ false );
+ }
+
+ function validate()
+ {
+ $this->_valid = (ini_get( "safe_mode" ) == "");
+ return( parent::validate());
+ }
+ }
+
+ class WizardIconvFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardIconvFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>iconv</b> functions are available",
+ "LifeType requires support for some resource metadata conversion and some LifeType plugins requires support for multi-byte language encoding/decoding.",
+ false );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "iconv" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardMbstringFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardMbstringFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>mbstring</b> functions are available",
+ "Some LifeType plugins requires support for multi-byte language encoding/decoding.",
+ false );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "mb_convert_encoding" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardGdFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardGdFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>gd</b> or <b>gd2</b> functions are available",
+ "LifeType requires support for generating image thumbnail.",
+ false );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "imagecopyresampled" ) &&
+ function_exists( "imagecopyresized" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardFileUploadsValidator extends WizardValidator
+ {
+ function WizardFileUploadsValidator()
+ {
+ $this->WizardValidator( "Checking if <b>file_uploads</b> is enabled",
+ "LifeType requires support for uploading resources.",
+ true );
+ }
+
+ function validate()
+ {
+ $this->_valid = (ini_get( "file_uploads" ) == 1);
+ return( parent::validate());
+ }
+ }
+
+ class WizardFileIntegrityValidator extends WizardValidator
+ {
+ function WizardFileIntegrityValidator()
+ {
+ $this->WizardValidator( "Checking that all files have been correctly uploaded",
+ "will be set later on...",
+ false );
+ }
+
+ function validate()
+ {
+ include( PLOG_CLASS_PATH."install/files.properties.php");
+
+ $result = IntegrityChecker::checkIntegrity(
+ $data
+ );
+
+
+ $this->_valid = ( count( $result ) == 0 );
+ if( !$this->_valid ) {
+ /* let's modify a private attribute... */
+ $fileList = implode( "<br/>", array_keys( $result ));
+ $this->_solution = "The current version of the following is not the expected one. Installation can proceed but please make sure that all files were uploaded correctly:"."<br/>".$fileList;
+ }
+
+ return( parent::validate());
+ }
+ }
+
+ class WizardCtypeFunctionsAvailableValidator extends WizardValidator
+ {
+ function WizardCtypeFunctionsAvailableValidator()
+ {
+ $this->WizardValidator( "Checking if <b>ctype</b> functions are available",
+ "Some LifeType plugins requires support for variable type validation.",
+ false );
+ }
+
+ function validate()
+ {
+ $this->_valid = function_exists( "ctype_digit" );
+ return( parent::validate());
+ }
+ }
+
+ class WizardChecks extends WizardAction
+ {
+ function perform()
+ {
+ // build the array with checks
+ $checkGroups['File checks'] = Array(
+ "writeConfigFile" => new WizardWritableFileValidator( "config/config.properties.php" ),
+ "writeTmpFolder" => new WizardWritableFileValidator( "tmp" ),
+ "writeGalleryFolder" => new WizardWritableFileValidator( "gallery" ),
+ "fileVersionCheck" => new WizardFileIntegrityValidator()
+ );
+
+ $checkGroups['PHP version checking'] = Array(
+ "php" => new WizardPhpVersionValidator()
+ );
+
+ $checkGroups['PHP configuration checking'] = Array(
+ "sessionSettings" => new WizardSessionSettingsValidator(),
+ "safemode" => new WizardSafeModeValidator(),
+ "fileUploads" => new WizardFileUploadsValidator()
+ );
+
+ $checkGroups['PHP functions availability checking'] = Array(
+ "sessions" => new WizardSessionFunctionsAvailableValidator(),
+ "mysql" => new WizardMySQLFunctionsAvailableValidator(),
+ "xml" => new WizardXmlFunctionsAvailableValidator(),
+ "iconv" => new WizardIconvFunctionsAvailableValidator(),
+ "mbstring" => new WizardMbstringFunctionsAvailableValidator(),
+ "gd" => new WizardGdFunctionsAvailableValidator(),
+ "ctype" => new WizardCtypeFunctionsAvailableValidator()
+ );
+
+ // run the checks
+ $ok = true;
+ foreach( $checkGroups as $checkGroup => $checks ) {
+ foreach( $checks as $id => $check ) {
+ $valid = $checkGroups[$checkGroup][$id]->validate();
+ // if it doesn't validate but it's not critical, then we can proced too
+ if( !$checkGroups[$checkGroup][$id]->isCritical())
+ $valid = true;
+ $ok = ($ok && $valid);
+ }
+ }
+
+ // create the view and pass the results
+ $this->_view = new WizardView( "checks" );
+ $this->_view->setValue( "ok", $ok );
+ $this->_view->setValue( "checkGroups", $checkGroups );
+
+ if( WizardTools::isNewInstallation())
+ $this->_view->setValue( "mode", "install" );
+ else
+ $this->_view->setValue( "mode", "update" );
+
+ return true;
+ }
+ }
+
+ class WizardPagedAction extends WizardAction
+ {
+ var $willRefresh;
+
+ function WizardPagedAction( $actionInfo, $request )
+ {
+ $this->WizardAction( $actionInfo, $request );
+
+ $this->willRefresh = false;
+ }
+
+ /**
+ * @private
+ */
+ function getPageFromRequest()
+ {
+ lt_include( PLOG_CLASS_PATH."class/data/validator/integervalidator.class.php");
+ // get the value from the request
+ $page = HttpVars::getRequestValue( "page" );
+ // but first of all, validate it
+ $val = new IntegerValidator();
+ if( !$val->validate( $page ))
+ $page = 1;
+
+ return $page;
+ }
+
+ /**
+ * @private
+ */
+ function willRefresh()
+ {
+ return( $this->willRefresh );
+ }
+ }
+
+ /**
+ * Gets the information about the database from the user.
+ */
+ class WizardIntro extends WizardAction
+ {
+ function WizardIntro( $actionInfo, $request )
+ {
+ $this->WizardAction( $actionInfo, $request );
+ }
+
+ function perform()
+ {
+ // we can detect whether plog is already installed or not and direct users to the right
+ // place
+ if( WizardTools::isNewInstallation())
+ $this->_view = new WizardView( "intro" );
+ else {
+ Controller::setForwardAction( "Update1" );
+ return false;
+ }
+
+ $this->setCommonData();
+ return true;
+ }
+ }
+
+ /**
+ *
+ * Saves data to the configuration file
+ *
+ */
+ class WizardStepOne extends WizardAction
+ {
+
+ var $_dbServer;
+ var $_dbUser;
+ var $_dbPassword;
+ var $_dbName;
+ var $_dbPrefix;
+ var $_connection;
+
+ function WizardStepOne( $actionInfo, $request )
+ {
+ $this->WizardAction( $actionInfo, $request );
+
+ // data validation
+ $this->registerFieldValidator( "dbServer", new StringValidator());
+ $this->registerFieldValidator( "dbUser", new StringValidator());
+ $this->registerFieldValidator( "dbPassword", new StringValidator(), true );
+ $this->registerFieldValidator( "dbName", new StringValidator());
+ $this->registerFieldValidator( "dbPrefix", new StringValidator(), true );
+ $errorView = new WizardView( "intro" );
+ $errorView->setErrorMessage( "Some data was incorrect or missing." );
+ $this->setValidationErrorView( $errorView );
+ }
+
+ function perform()
+ {
+ // fetch the data needed from the request
+ $this->_dbServer = $this->_request->getValue( "dbServer" );
+ $this->_dbUser = $this->_request->getValue( "dbUser" );
+ $this->_dbPassword = $this->_request->getValue( "dbPassword" );
+ $this->_dbName = $this->_request->getValue( "dbName" );
+ $this->_skipThis = $this->_request->getValue( "skipDbInfo" );
+ $this->_dbPrefix = $this->_request->getValue( "dbPrefix", DEFAULT_DB_PREFIX );
+
+ // we should now save the data to the configuration file, just before
+ // we read it
+ $configFile = new ConfigFileStorage();
+
+ // we expect everything to be fine
+ $errors = false;
+
+ // before doing anything, we should check of the configuration file is
+ // writable by this script, or else, throw an error and bail out gracefully
+ $configFileName = $configFile->getConfigFileName();
+ if( !File::exists( $configFileName )) {
+ if (! File::touch( $configFileName ) ) {
+ $this->_view = new WizardView( "intro" );
+ $message = "Could not create the LifeType configuration file $configFileName. Please make sure
+ that the file can be created by the user running the webserver. It is needed to
+ store the database configuration settings.";
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ } else {
+ ConfigFileStorage::createConfigFile( $configFileName );
+ }
+ }
+ if( File::exists( $configFileName ) && !File::isWritable( $configFileName )) {
+ $this->_view = new WizardView( "intro" );
+ $message = "Please make sure that the file $configFileName can be written by this script during
+ the installation process. It is needed to store the database configuration settings. Once the
+ installation is complete, please revert the permissions to no writing possible.";
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ }
+
+ // continue if everything went fine
+ if( !$configFile->saveValue( "db_username", $this->_dbUser ) ||
+ !$configFile->saveValue( "db_password", $this->_dbPassword ) ||
+ !$configFile->saveValue( "db_host", $this->_dbServer ) ||
+ !$configFile->saveValue( "db_database", $this->_dbName ) ||
+ !$configFile->saveValue( "db_prefix", $this->_dbPrefix )) {
+ $errors = true;
+ }
+
+ if( $errors ) {
+ $message = "Could not save values to the configuration file. Please make sure it is available and
+ that has write permissions for the user under your web server is running.";
+ $this->_view = new WizardView( "intro" );
+ $this->_view->setErrorMessage( $message );
+
+ return( false );
+ }
+ else {
+ $connectionEsablished = false;
+
+ $this->_connection = @mysql_connect( $this->_dbServer, $this->_dbUser, $this->_dbPassword );
+ if( $this->_connection ) {
+ $connectionEsablished = true;
+ } else {
+ $connectionEsablished = false;
+ $message = "There was an error connecting to the database. Please check your settings.";
+ }
+
+ if ( !$connectionEsablished ) {
+ $this->_view = new WizardView( "step1" );
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ } else {
+ $this->_view = new WizardView( "step1" );
+ $availableCharacterSets = $this->getAvailableCharacterSets();
+ $defaultCharacterSet = $this->getDatabaseCharacterSet();
+ $createDatabase = false;
+ if( empty( $defaultCharacterSet ) )
+ {
+ $defaultCharacterSet = $this->getServerCharacterSet();
+ $createDatabase = true;
+ }
+ $this->_view->setValue( "availableCharacterSets", $availableCharacterSets );
+ $this->_view->setValue( "defaultCharacterSet", $defaultCharacterSet );
+ $this->_view->setValue( "createDatabase", $createDatabase );
+ // now we better read the information from the config file to make sure that
+ // it has been correctly saved
+ $this->setCommonData( true );
+ return true;
+ }
+ }
+ }
+
+ function getAvailableCharacterSets()
+ {
+ // check mysql version first. Version lower than 4.1 doesn't support utf8
+ $serverVersion = mysql_get_server_info( $this->_connection );
+ $version = explode( '.', $serverVersion );
+ if ( $version[0] < 4 ) return false;
+ if ( ( $version[0] == 4 ) && ( $version[1] == 0 ) ) return false;
+
+ // check if utf8 support was compiled in
+ $result = mysql_query( "SHOW CHARACTER SET", $this->_connection );
+ if( $result )
+ {
+ if( mysql_num_rows($result) > 0 ) {
+ // iterate through resultset
+ $availableCharacterSets = array();
+ while( $row = mysql_fetch_array( $result, MYSQL_ASSOC ) )
+ {
+ array_push( $availableCharacterSets, $row['Charset'] );
+ }
+ return $availableCharacterSets;
+ }
+ }
+ return false;
+ }
+
+ function getDatabaseCharacterSet()
+ {
+ if( !@mysql_select_db( $this->_dbName, $this->_connection ) ) {
+ return false;
+ }
+
+ // We use a SHOW CREATE DATABASE command to show the original
+ // SQL character set when DB was created.
+ $result = mysql_query( "SHOW CREATE DATABASE `".$this->_dbName."`", $this->_connection );
+ if( $result )
+ {
+ if( mysql_num_rows( $result ) < 0 ) {
+ // The specified db name is wrong!
+ return false;
+ }
+ $dbInfo = mysql_fetch_row( $result );
+ $pattern = '/40100 DEFAULT CHARACTER SET (\w+) /';
+ if( ( preg_match( $pattern, $dbInfo[1], $match ) > 0 ) ) {
+ return $match[1];
+ }
+ }
+ return false;
+ }
+
+ function getServerCharacterSet(){
+ // We use a SHOW CREATE DATABASE command to show the original
+ // SQL character set when DB was created.
+ $result = mysql_query( "SHOW VARIABLES LIKE 'character_set_server'", $this->_connection );
+ if( $result )
+ {
+ if( mysql_num_rows( $result ) > 0 ) {
+ $row = mysql_fetch_array( $result, MYSQL_ASSOC );
+ return $row['Value'];
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ *
+ * Second step where we connect to the database and create the tables.
+ *
+ */
+ class WizardStepTwo extends WizardAction
+ {
+
+ var $_db;
+ var $_database;
+ var $_dbCharacterSet;
+ var $_createDatabase;
+
+ function setDbConfigValues( &$view )
+ {
+ $configFile = new ConfigFileStorage();
+ $configFile->reload();
+ $view->setValue( "dbUser", $configFile->getValue( "db_username" ));
+ $view->setValue( "dbPassword", $configFile->getValue( "db_password" ));
+ $view->setValue( "dbServer", $configFile->getValue( "db_host" ));
+ $view->setValue( "dbName", $configFile->getValue( "db_database" ));
+ $view->setValue( "dbPrefix", $configFile->getValue( "db_prefix" ));
+ $view->setValue( "dbCharacterSet", $configFile->getValue( "db_character_set" ));
+ return true;
+ }
+
+ function perform()
+ {
+ global $Tables;
+ global $Inserts;
+
+ $this->_dbCharacterSet = $this->_request->getValue( "dbCharacterSet" );
+ $configFile = new ConfigFileStorage();
+ $configFileName = $configFile->getConfigFileName();
+
+ if( File::exists( $configFileName ) && !File::isWritable( $configFileName )) {
+ $this->_view = new WizardView( "step1" );
+ $message = "Please make sure that the file $configFileName can be written by this script during
+ the installation process. It is needed to store the database configuration settings. Once the
+ installation is complete, please revert the permissions to no writing possible.";
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ }
+
+ // continue if everything went fine
+ if( !$configFile->saveValue( "db_character_set", $this->_dbCharacterSet ) ) {
+ $message = "Could not save values to the configuration file. Please make sure it is available and
+ that has write permissions for the user under your web server is running.";
+ $this->_view = new WizardView( "step1" );
+ $this->_view->setErrorMessage( $message );
+
+ return false;
+ }
+
+ $createDb = $this->_request->getValue( "createDatabase" );
+ $message = '';
+
+ // only check for errors in case the database table should already exist!
+ if( !$createDb ) {
+ $connectionEsablished = false;
+
+ // Lets check the 'everything is fine' case first..
+ $this->_db = connectDb();
+ if( $this->_db ) {
+ $connectionEsablished = true;
+ } else {
+ $connectionEsablished = false;
+ $message = "There was an error selecting the database. Please verify the database was already created or check the 'Create database' checkbox.";
+ }
+
+ // We were unable to connect to the db and select the right db.. lets try
+ // just to connect.. maybe the database needs to be created (even though the
+ // user did not check the appropriate box).
+ if ( !$connectionEsablished ) {
+ $this->_db = connectDb( true, false );
+ if( !$this->_db ) {
+ $message = "There was an error connecting to the database. Please check your settings.";
+ }
+ }
+
+ if ( !$connectionEsablished ) {
+ $this->_view = new WizardView( "step1" );
+ $this->setDbConfigValues( $this->_view );
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ }
+ }
+
+ $config = new ConfigFileStorage();
+ $this->_database = $config->getValue( "db_database" );
+ $this->_dbPrefix = $config->getValue( "db_prefix" );
+
+ // create the database
+ if( $createDb ) {
+ $this->_db = connectDb( false, false );
+ if( !$this->_db ) {
+ $this->_view = new WizardView( "step1" );
+ $this->setDbConfigValues( $this->_view );
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ }
+ if( !$this->_db->Execute( "CREATE DATABASE ".$this->_database )) {
+ $message = "Error creating the database: ".$this->_db->ErrorMsg();
+ $message .= "<br/><br/>If the database already exists, go back to Step 2 and use a new database name.";
+ $this->_view = new WizardView( "step1" );
+ $this->setDbConfigValues( $this->_view );
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData( true );
+ return false;
+ } else {
+ $message = "Database created successfully.<br/>";
+ }
+ }
+
+ // reconnect using the new database.
+ $config = new ConfigFileStorage();
+ $this->_db->Connect( $config->getValue( "db_host" ),
+ $config->getValue( "db_username" ),
+ $config->getValue( "db_password" ),
+ $config->getValue( "db_database" ));
+
+ // create a data dictionary to give us the right sql code needed to create the tables
+ $dict = NewPDbDataDictionary( $this->_db );
+
+ // create the tables
+ $errors = false;
+
+ foreach( $Tables as $name => $table ) {
+ $upperName = $dict->upperName;
+ $tableSchema = $table["schema"];
+ if ( isset( $table["options"] ) )
+ {
+ $tableOptions = $table["options"];
+ $options = array ( $upperName => $tableOptions );
+ } else {
+ $options = array ();
+ }
+ $sqlarray = $dict->CreateTableSQL( $this->_dbPrefix.$name, $tableSchema, $options );
+
+ // each table may need more than one sql query because of indexes, triggers, etc...
+ $ok = true;
+ foreach( $sqlarray as $sql ) {
+ $ok = ( $ok && $this->_db->Execute( $sql ));
+ }
+
+ if( $ok )
+ $message .= "Table <strong>$name</strong> created successfully.<br/>";
+ else {
+ $message .= "Error creating table $name: ".$this->_db->ErrorMsg()."<br/>";
+ $errors = true;
+ }
+ }
+
+ if( $errors ) {
+ $message = "There was an error creating the tables in the database. Please make sure that the user chosen to connect to the database has enough permissions to create tables.<br/><br/>$message";
+ $this->_view = new WizardView( "step1" );
+ $this->_view->setErrorMessage( $message );
+ $this->setDbConfigValues( $this->_view );
+ $this->setCommonData();
+ return false;
+ }
+
+ // try to guess the url where plog is running
+ $httpProtocol = (array_key_exists("HTTPS", $_SERVER) && $_SERVER["HTTPS"] == "on") ? "https://" : "http://";
+ $httpHost = $_SERVER["HTTP_HOST"];
+ $requestUrl = $_SERVER["REQUEST_URI"];
+ $requestUrl = str_replace( "/wizard.php", "", $requestUrl );
+ $plogUrl = $httpProtocol.$httpHost.$requestUrl;
+
+ // Find some of the tools we are going to need (last one is for os x, with fink installed)
+ // TBD: support for Windows specific directories
+ $folders = Array( "/bin/", "/usr/bin/", "/usr/local/bin/", "/sw/bin/" );
+ $finder = new FileFinder();
+ $pathToUnzip = $finder->findBinary( "unzip", $folders );
+ $pathToTar = $finder->findBinary( "tar", $folders);
+ $pathToGzip = $finder->findBinary( "gzip", $folders);
+ $pathToBzip2 = $finder->findBinary( "bzip2", $folders);
+ $pathToConvert = $finder->findBinary( "convert", $folders);
+
+ // and execute some insert's
+ foreach( $Inserts as $insert ) {
+ $query = str_replace( "{dbprefix}", $this->_dbPrefix, $insert );
+ $query = str_replace( "{plog_base_url}", $plogUrl, $query );
+ // replace also the placeholders for the paths to the tools
+ $query = str_replace( "{path_to_tar}", $pathToTar, $query );
+ $query = str_replace( "{path_to_unzip}", $pathToUnzip, $query );
+ $query = str_replace( "{path_to_bz2}", $pathToBzip2, $query );
+ $query = str_replace( "{path_to_gzip}", $pathToGzip, $query );
+ $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+ $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+ if( !$this->_db->Execute( $query )) {
+ $message .= "Error executing code: ".$this->_db->ErrorMsg()."<br/>";
+ $errors = true;
+ }
+ }
+
+ //
+ // show some information regarding the helper tools we're going to need
+ // and wether they were found or not
+ //
+ $message .= "<br/><b>-- Helper tools --</b><br/>";
+ if( $pathToTar == "" )
+ $message .= "The helper tool 'tar' was not found<br/>";
+ else
+ $message .= "The helper tool 'tar' was found in $pathToTar<br/>";
+ if( $pathToGzip == "" )
+ $message .= "The helper tool 'gzip' was not found<br/>";
+ else
+ $message .= "The helper tool 'gzip' was found in $pathToGzip<br/>";
+ if( $pathToUnzip == "" )
+ $message .= "The helper tool 'unzip' was not found<br/>";
+ else
+ $message .= "The helper tool 'unzip' was found in $pathToUnzip<br/>";
+ if( $pathToBzip2 == "" )
+ $message .= "The helper tool 'bzip2' was not found<br/>";
+ else
+ $message .= "The helper tool 'bzip2' was found in $pathToTar<br/>";
+ if( $pathToConvert == "" )
+ $message .= "The helper tool 'convert' (from the ImageMagick package) was not found<br/>";
+ else
+ $message .= "The helper tool 'convert' (from the ImageMagick package) was found in $pathToConvert<br/>";
+
+ // Scan for locales
+ $locales = new Locales();
+ // find all the new locales that we have not yet stored
+ $f = new LocaleFinder();
+ $newLocaleCodes = $f->find();
+
+ foreach( $newLocaleCodes as $newLocaleCode ) {
+ $res = $locales->addLocale( $newLocaleCode );
+ }
+
+ // load the core permissions
+ include( PLOG_CLASS_PATH."install/corepermissions.properties.php" );
+
+ // process permissions
+ $total = 0;
+ foreach( $permissions as $perm ) {
+ // check if it already exists
+ $query = "SELECT * FROM ".Db::getPrefix()."permissions WHERE permission = '".$perm[0]."'";
+ $result = $this->_db->Execute( $query );
+ if( !$result || $result->RowCount() < 1 ) {
+ // permission needs to be added
+ $corePerm = ( $perm[2] == true ? 1 : 0 );
+ $adminOnly = ( $perm[3] == true ? 1 : 0 );
+
+ $query = "INSERT INTO ".Db::getPrefix()."permissions (permission,description,core_perm,admin_only) ".
+ "VALUES ('".$perm[0]."','".$perm[1]."','".$corePerm."','".$adminOnly."')";
+
+ $this->_db->Execute( $query );
+ $total++;
+ }
+ }
+
+ // show some feedback
+ if( $errors ) {
+ $this->_view = new WizardView( "step1" );
+ $this->setDbConfigValues( $this->_view );
+ $message = "There was an error initializing some of the tables. Please make sure that the user chosen to connect to the database has enough permissions to add records to the database.<br/><br/>$message";
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData();
+ }
+ else {
+ $this->_view = new WizardView( "step2" );
+ $this->_view->setValue( "message", $message );
+ }
+ }
+ }
+
+ /**
+ *
+ * this action only shows some feedback
+ *
+ */
+ class WizardStepThree extends WizardAction
+ {
+ function perform()
+ {
+ $this->_view = new WizardView( "step3" );
+ $this->setCommonData();
+ }
+ }
+
+ /**
+ *
+ * Create the first user in the database
+ *
+ */
+ class WizardStepFour extends WizardAction
+ {
+
+ var $_userName;
+ var $_userPassword;
+ var $_confirmPassword;
+ var $_userEmail;
+ var $_userFullName;
+
+ function WizardStepFour( $actionInfo, $request )
+ {
+ $this->WizardAction( $actionInfo, $request );
+
+ $this->registerFieldValidator( "userName", new UsernameValidator());
+ $this->registerFieldValidator( "userPassword", new PasswordValidator());
+ $this->registerFieldValidator( "userPasswordCheck", new PasswordValidator());
+ $this->registerFieldValidator( "userEmail", new EmailValidator());
+ $this->registerField( "userFullName" );
+ $view = new WizardView( "step3" );
+ $view->setErrorMessage( "Some data is missing or incorrect" );
+ $this->setValidationErrorView( $view );
+ }
+
+ // creates the user
+ function perform()
+ {
+ $this->_userName = $this->_request->getValue( "userName" );
+ $this->_userPassword = $this->_request->getValue( "userPassword" );
+ $this->_confirmPassword = $this->_request->getValue( "userPasswordCheck" );
+ $this->_userEmail = $this->_request->getValue( "userEmail" );
+ $this->_userFullName = $this->_request->getValue( "userFullName" );
+
+ $db = connectDb();
+
+ if( !$db ) {
+ $this->_view = new WizardView( "step3" );
+ $this->_view->setErrorMessage( "There was an error connecting to the database. Please check your settings." );
+ $this->setCommonData();
+ return false;
+ }
+
+ if( $this->_confirmPassword != $this->_userPassword ) {
+ $this->_view = new WizardView( "step3" );
+ $this->_form->setFieldValidationStatus( "userPasswordCheck", false );
+ $this->setCommonData( true );
+ return false;
+ }
+
+ $dbPrefix = Db::getPrefix();
+
+ $users = new Users();
+ $user = new UserInfo( $this->_userName,
+ $this->_userPassword,
+ $this->_userEmail,
+ "",
+ $this->_userFullName);
+ // set the user as an administrator
+ $user->setSiteAdmin( true );
+ // and add this record to the db
+ $userId = $users->addUser( $user );
+ if( !$userId ) {
+ $this->_view = new WizardView( "step3" );
+ $db =& Db::getDb();
+ $message = "There was an error adding the user. Make sure that the user does not already exist in the database (".$db->ErrorMsg().")";
+ $this->_view->setErrorMessage( $message );
+ $this->setCommonData();
+ return false;
+ }
+
+ // since this user is an administrator, he must be granted all the administrator
+ // permissions available
+ $perms = new Permissions();
+ $userPerms = new UserPermissions();
+ foreach( $perms->getAllPermissions() as $perm ) {
+ if( $perm->isAdminOnlyPermission()) {
+ // if it's an admin permission, add it
+ $p = new UserPermission( $userId, 0, $perm->getId());
+ $userPerms->grantPermission( $p );
+ //print("granting permission: ".$perm->getName()."<br/>");
+ }
+ }
+
+ $this->_view = new Wizardview( "step4" );
+ $this->_view->setValue( "ownerid", $userId );
+ $this->_view->setValue( "siteLocales", Locales::getLocales());
+ $this->_view->setValue( "defaultLocale", Locales::getDefaultLocale());
+ $ts = new TemplateSets();
+ $this->_view->setValue( "siteTemplates", $ts->getGlobalTemplateSets());
+ $this->setCommonData();
+ return true;
+ }
+
+ }
+
+ class WizardStepFive extends WizardAction
+ {
+
+ var $_blogName;
+ var $_ownerId;
+ var $_blogProperties;
+
+ function WizardStepFive( $actionInfo, $request )
+ {
+ $this->WizardAction( $actionInfo, $request );
+
+ $this->registerFieldValidator( "blogName", new StringValidator());
+ $this->registerFieldValidator( "ownerid", new IntegerValidator());
+ $this->registerFieldValidator( "blogTemplate", new StringValidator());
+ $this->registerFieldValidator( "blogLocale", new StringValidator());
+ $view = new WizardView( "step4" );
+ $view->setErrorMessage( "Some data is missing or incorrect" );
+ $view->setValue( "siteLocales", Locales::getLocales());
+ $view->setValue( "defaultLocale", Locales::getDefaultLocale());
+ $ts = new TemplateSets();
+ $view->setValue( "siteTemplates", $ts->getGlobalTemplateSets());
+ $this->setValidationErrorView( $view );
+ }
+
+ function perform()
+ {
+ // Before we add a new blog, we need to add blog category and global article category first
+ // add blog category
+ $blogCategories = new BlogCategories();
+ $blogCategory = new BlogCategory( "General", "General" );
+ $blogCategoryId = $blogCategories->addBlogCategory( $blogCategory );
+
+ // add global article category
+ $globalArticleCategories = new GlobalArticleCategories();
+ $globalArticleCategory = new GlobalArticleCategory( "General", "General" );
+ $globalArticleCategoryId = $globalArticleCategories->addGlobalArticleCategory( $globalArticleCategory );
+
+ // retrieve the values from the view
+ $this->_blogName = $this->_request->getValue( "blogName" );
+ $this->_ownerId = $this->_request->getValue( "ownerid" );
+ $this->_blogProperties = $this->_request->getValue( "properties" );
+ $this->_blogTemplate = $this->_request->getValue( "blogTemplate" );
+ $this->_blogLocale = $this->_request->getValue( "blogLocale" );
+
+ // configure the blog
+ $blogs = new Blogs();
+ $blog = new BlogInfo( $this->_blogName, $this->_ownerId, "", "" );
+ // set the default BlogCategory id to blog
+ $blog->setBlogCategoryId( $blogCategoryId );
+ $blog->setProperties( $this->_blogProperties );
+ $blog->setStatus( BLOG_STATUS_ACTIVE );
+ $blogSettings = $blog->getSettings();
+ $blogSettings->setValue( "locale", $this->_blogLocale );
+ $blogSettings->setValue( "template", $this->_blogTemplate );
+ $blog->setSettings( $blogSettings );
+
+ // and now save it to the database
+ $newblogId = $blogs->addBlog( $blog );
+ if( !$newblogId ) {
+ $this->_view = new WizardView( "step4" );
+ $this->_view->setValue( "siteLocales", Locales::getLocales());
+ $ts = new TemplateSets();
+ $this->_view->setValue( "siteTemplates", $ts->getGlobalTemplateSets());
+ $this->_view->setErrorMessage( "There was an error creating the new blog" );
+ $this->setCommonData( true );
+ return false;
+ }
+
+ // if the blog was created, we can add some basic information
+ // add a category
+ $articleCategories = new ArticleCategories();
+ $articleCategory = new ArticleCategory( "General", "General", $newblogId, true );
+ $catId = $articleCategories->addArticleCategory( $articleCategory );
+
+ // load the right locale
+ $locale =& Locales::getLocale( $this->_blogLocale );
+ // and load the right text
+ $articleTopic = $locale->tr( "register_default_article_topic" );
+ $articleText = $locale->tr( "register_default_article_text" );
+ $article = new Article( $articleTopic, $articleText, Array( $catId ), $this->_ownerId, $newblogId, POST_STATUS_PUBLISHED, 0, Array(), "welcome" );
+ // set the default ArticleGlobalCategory id to article
+ $article->setGlobalCategoryId( $globalArticleCategoryId );
+ // set the current time to article
+ $t = new Timestamp();
+ $article->setDateObject( $t );
+ $articles = new Articles();
+ $articles->addArticle( $article );
+
+ // add a new first album so that users can start uploading stuff right away
+ $t = new Timestamp();
+ $album = new GalleryAlbum( $newblogId,
+ "General",
+ "General",
+ GALLERY_RESOURCE_PREVIEW_AVAILABLE,
+ 0,
+ $t->getTimestamp(),
+ Array(),
+ true );
+ $albums = new GalleryAlbums();
+ $albums->addAlbum( $album );
+
+ // add a new default mylinkscategory
+ $linksCategory = new MyLinksCategory( "General", $newblogId );
+ $linksCategories = new MyLinksCategories();
+ $linksCategories->addMyLinksCategory( $linksCategory );
+
+ // save a few things in the default configuration
+ $config =& Config::getConfig();
+ // default blog id
+ $config->saveValue( "default_blog_id", (int)$newblogId );
+ // default locale
+ $config->saveValue( "default_locale", $this->_blogLocale );
+ // and finally, the default template
+ $config->saveValue( "default_template", $this->_blogTemplate );
+
+ //
+ // detect wether we have GD available and set the blog to use it
+ //
+ if( GdDetector::detectGd()) {
+ $config->saveValue( "thumbnail_method", "gd" );
+ $message = "GD has been detected and set as the backend for dealing with images.";
+ }
+ else {
+ $pathToConvert = $config->getValue( "path_to_convert" );
+ if( $pathToConvert ) {
+ $config->saveValue( "thumbnail_method", "imagemagick" );
+ $message = "ImageMagick has been detected and set as the backend for dealing with images.";
+ }
+ else {
+ // nothing was found, so we'll have to do away with the 'null' resizer...
+ $config->saveValue( "thumbnail_method", "null" );
+ $message = "Neither GD nor ImageMagick have been detected in this host so it will not be possible to generate thumbnails from images.";
+ }
+ }
+
+ // clean the data cache to avoid problems when we're done
+ lt_include( PLOG_CLASS_PATH."class/cache/cachemanager.class.php" );
+ $cache =& CacheManager::getCache();
+ $cache->clearCache();
+
+ WizardTools::cleanTmpFolder();
+
+ $this->_view = new WizardView( "step5" );
+ $this->_view->setValue( "message", $message );
+ return true;
+ }
+ }
+
+ class UpdateStepOne extends WizardAction
+ {
+
+ function perform()
+ {
+ $this->_view = new WizardView( "update1" );
+ WizardStepTwo::setDbConfigValues( $this->_view );
+ $this->setCommonData();
+ }
+ }
+
+ class UpdateStepTwo extends WizardAction
+ {
+ function perform()
+ {
+ lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+ $config =& Config::getConfig();
+ $resourcesNamingRule = $config->getValue( "resources_naming_rule", "original_file_name" );
+
+ $this->_view = new WizardView( "update2" );
+ $this->_view->setValue( "resourcesNamingRule", $resourcesNamingRule );
+ $this->setCommonData();
+ }
+ }
+
+ /**
+ * Generic class that performs data updates on the database
+ */
+ class DatabaseDataTransformer extends Model
+ {
+ /**
+ * @public
+ * Public fields, may be accessed by other classes
+ */
+ var $updatedRecords;
+ var $message;
+ var $errorRecords;
+ var $notModifiedRecords;
+ var $failOnError;
+ var $page;
+ var $itemsPerPage;
+ var $dbPrefix;
+
+ function DatabaseDataTransformer( $page = -1, $itemsPerPage = WIZARD_MAX_RECORDS_PER_STEP )
+ {
+ $this->Model();
+
+ $this->updatedRecords = 0;
+ $this->errorRecords = 0;
+ $this->notModifiedRecords = 0;
+ $this->addedRecords = 0;
+ $this->deletedRecords = 0;
+ $this->failOnError = DATABASE_DATA_TRANSFORMER_FAIL_ON_ERROR_DEFAULT;
+ $this->message = "";
+
+ $this->page = $page;
+ $this->itemsPerPage = $itemsPerPage;
+
+ $this->dbPrefix = $this->getPrefix();
+ }
+
+ /**
+ * Rerforms the transformation. Returns true if the step was successful or false otherwise.
+ * Upon finalization, please check the $message string to get more information. Use the $updatedRecords,
+ * $errorRecords, $notModifiedRecords, $addedRecords and $deletedRecords for some figures regarding the
+ * previous step
+ */
+ function perform()
+ {
+ // must be implemented by child classes
+ return true;
+ }
+
+ /**
+ * Returns true if there is no more data for this transformer to upgrade, or false otherwise
+ *
+ * @return True if ready or false if not
+ */
+ function isComplete()
+ {
+ return( $this->getNumSteps() <= $this->page );
+ }
+
+ /**
+ * returns the number of steps needed to process this data
+ */
+ function getNumSteps( $table = "" )
+ {
+ // if there is a table name, we can take a shortcut or else we expect child
+ // classes to reimplement this method
+ if( $table ) {
+ $numItems = $this->getNumItems( $this->getPrefix().$table );
+
+ $numSteps = ceil( $numItems / $this->itemsPerPage );
+ }
+ else {
+ $numSteps = 0;
+ }
+
+ return( $numSteps );
+ }
+
+ /**
+ * returns the total number of records processed so far based on the current page and the
+ * number of items per page
+ */
+ function getTotalProcessedRecords()
+ {
+ return( $this->page * $this->itemsPerPage );
+ }
+
+ /**
+ * returns an approximate percentage of records processed so far
+ */
+ function getPercentProcessed()
+ {
+ $processed = $this->getTotalProcessedRecords();
+ return((int)($processed / ( $this->getNumSteps() * $this->itemsPerPage ) * 100 ));
+ }
+ }
+
+ /**
+ * This step takes care of transforming the database schema, one
+ * table at a time.
+ */
+ class DatabaseSchemaDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ global $Tables;
+ return( count( $Tables ) - 1);
+ }
+
+ function perform()
+ {
+ global $Tables;
+
+ $tablesArray = array_keys( $Tables );
+ $curTable = $tablesArray[$this->page-1];
+
+ $db =& Db::getDb();
+ $dict = NewPDbDataDictionary( $db );
+ $errors = false;
+
+ $this->message = "Performing changes to the dabase schema, please wait (step %s of %s)<br/>";
+
+ $errorMessage = "";
+ $table_errors = false;
+ $upperName = $dict->upperName;
+ $tableSchema = $Tables[$curTable]["schema"];
+ if ( isset( $Tables[$curTable]["options"] )) {
+ $tableOptions = $Tables[$curTable]["options"];
+ $options = array ( $upperName => $tableOptions );
+ }
+ else {
+ $options = array ();
+ }
+
+ // generate the code with the changes for the table
+ $sqlarray = $dict->ChangeTableSQL( $this->getPrefix().$curTable, $tableSchema, $options );
+
+ foreach( $sqlarray as $sql ) {
+ // and run the query
+ //print( "sql: ".$sql."<br/>" );
+ if( !$this->Execute( $sql )) {
+ $table_errors = true;
+ $errors = true;
+ $errorMessage .= $this->_db->ErrorMsg()."<br/>";
+ }
+ }
+
+ if( !$table_errors ) {
+ $this->message .= "Changes to table <strong>$curTable</strong> executed successfully.<br/>";
+ $result = true;
+ }
+ else {
+ $this->message .= "Error modifying table $curTable: ".$errorMessage;
+ $result = false;
+ }
+
+ return( $result );
+ }
+ }
+
+ /**
+ * Processes all users and grants the appropriate permissions
+ */
+ class UserPermissionsDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( parent::getNumSteps( "tmp_users_permissions" ));
+ }
+
+ function perform()
+ {
+ $this->message = "Updating user permissions (step %s of %s)<br/>";
+
+ $query3 = "SELECT * FROM ".Db::getPrefix()."tmp_users_permissions";
+ $res3 = $this->Execute( $query3, $this->page, $this->itemsPerPage );
+ if( $res3->RecordCount() == 0 ) {
+ $this->message .= "No more records to process";
+ return( true );
+ }
+
+ $permissions = new Permissions();
+ $userPermissions = new UserPermissions();
+ $allPerms = $permissions->getAllPermissions();
+ $blogOwnerOnlyPerms = Array( "update_blog",
+ "add_blog_user",
+ "update_blog_user",
+ "view_blog_users",
+ "view_blog_stats",
+ "add_blog_template",
+ "view_blog_templates",
+ "view_blog_stats" );
+
+ while( $row = $res3->FetchRow()) {
+ // grant all the non-admin permissions so that users can still access the blogs to where they still had permissions
+ if( $row["permission_id"] != 3) {
+ foreach( $allPerms as $perm ) {
+ if( !$perm->isAdminOnlyPermission() && !in_array( $perm->getName(), $blogOwnerOnlyPerms )) {
+ //print( "granting perm: ".$perm->getName()." - user: ".$row["user_id"]." - blog id: ".$row["blog_id"]."<br/>");
+ $perm = new UserPermission( $row["user_id"], $row["blog_id"], $perm->getId());
+ $userPermissions->grantPermission( $perm );
+ }
+ }
+ }
+ }
+
+ $this->message .= "{$this->updatedRecords} users updated (".$this->getPercentProcessed()."%%)<br/>";
+
+ $this->Execute("DROP TABLE ".Db::getPrefix()."tmp_users_permissions");
+
+ return true;
+ }
+ }
+
+ class PermissionLoader extends DatabaseDataTransformer
+ {
+
+ //
+ // load the new list of permissions
+ //
+ function getNumSteps()
+ {
+ return( 0 );
+ }
+
+ function perform()
+ {
+ // initial message, no errors yet
+ $this->message = "Loading new permissions (step %s of %s)<br/>";
+ $errors = false;
+
+ // load the core permissions
+ include( PLOG_CLASS_PATH."install/corepermissions.properties.php" );
+
+ // process permissions
+ $total = 0;
+ foreach( $permissions as $perm ) {
+ // check if it already exists
+ $query = "SELECT * FROM ".$this->dbPrefix."permissions WHERE permission = '".$perm[0]."'";
+ $result = $this->Execute( $query );
+ if( !$result || $result->RowCount() < 1 ) {
+ // permission needs to be added
+ $corePerm = ( $perm[2] == true ? 1 : 0 );
+ $adminOnly = ( $perm[3] == true ? 1 : 0 );
+ $query = "INSERT INTO ".$this->dbPrefix."permissions (permission,description,core_perm,admin_only) ".
+ "VALUES ('".$perm[0]."','".$perm[1]."','".$corePerm."','".$adminOnly."')";
+ $this->_db->Execute( $query );
+ $total++;
+ }
+ }
+
+ //
+ // prepare the users_permissions table for the next step
+ //
+
+ // make sure we are starting with an empty table
+ $this->Execute("DELETE FROM ".Db::getPrefix()."tmp_users_permissions");
+
+ if( !$this->Execute( "INSERT INTO ".$this->dbPrefix."tmp_users_permissions SELECT * FROM ".$this->dbPrefix."users_permissions WHERE blog_id != 0 AND permission_id != 1" )) {
+ $this->message .= "Error preparing the users_permissions table for transformation";
+ $errors = true;
+ }
+ else {
+ $this->Execute( "DELETE FROM ".$this->dbPrefix."users_permissions" );
+ $this->message .= count($permissions)." permissions successfully loaded";
+ $errors = false;
+ }
+
+ return( !$errors );
+ }
+ }
+
+ class ConfigDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( 0 );
+ }
+
+ function perform()
+ {
+ global $Inserts;
+
+ $this->message = "Adding new configuration parameters (step %s of %s)<br/>";
+ $errors = false;
+
+ // Find some of the tools we are going to need (last one is for os x, with fink installed), this will be needed later on
+ $folders = Array( "/bin/", "/usr/bin/", "/usr/local/bin/", "/sw/bin/" );
+ $finder = new FileFinder();
+ $pathToUnzip = $finder->findBinary( "unzip", $folders );
+ $pathToTar = $finder->findBinary( "tar", $folders);
+ $pathToGzip = $finder->findBinary( "gzip", $folders);
+ $pathToBzip2 = $finder->findBinary( "bzip2", $folders);
+ $pathToConvert = $finder->findBinary( "convert", $folders);
+
+ // check the configuration and add the new configuration settings that were added for 1.2
+ foreach( $Inserts as $key => $insert ) {
+ $checkKeyQuery = "SELECT * FROM ".$this->dbPrefix."config WHERE config_key ='".$key."';";
+ $result = $this->Execute($checkKeyQuery);
+ if(!$result){
+ $this->message .= "Error executing code: ".$this->_db->ErrorMsg()."<br/>";
+ $errors = true;
+ }
+ else{
+ if ($result->RecordCount() == 0) {
+ // replace the prefix
+ $query = str_replace( "{dbprefix}", $this->dbPrefix, $insert );
+ // replace also the placeholders for the paths to the tools
+ $query = str_replace( "{path_to_tar}", $pathToTar, $query );
+ $query = str_replace( "{path_to_unzip}", $pathToUnzip, $query );
+ $query = str_replace( "{path_to_bz2}", $pathToBzip2, $query );
+ $query = str_replace( "{path_to_gzip}", $pathToGzip, $query );
+ $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+ $query = str_replace( "{path_to_convert}", $pathToConvert, $query );
+ if( !$this->Execute( $query )) {
+ $this->message .= "Error executing code: ".$this->_db->ErrorMsg()."<br/>";
+ $errors = true;
+ }
+ }
+ $result->Close();
+ }
+ }
+ // check to see if we need to remove duplicates and the id index
+ $query = "SELECT id FROM ".$this->dbPrefix."config LIMIT 1";
+ $result = $this->Execute($query);
+ // if $result is false, id column has already been removed
+ if($result){
+ $result->Close();
+ // remove all duplicates in plog_config table
+
+ // first create temp table without the duplicates
+ $query = "CREATE TEMPORARY TABLE tmptable ".
+ "SELECT * FROM ".$this->dbPrefix."config WHERE 1 GROUP BY config_key";
+ $result = $this->Execute($query);
+ if($result){
+ //$result->Close();
+ // Now delete the old table
+ $query = "DELETE FROM ".$this->dbPrefix."config";
+ $result = $this->Execute($query);
+ if($result) {
+ //$result->Close();
+ // Insert the unique rows into the old table
+ $query = "INSERT INTO ".$this->dbPrefix."config SELECT * FROM tmptable";
+ $result = $this->Execute($query);
+ }
+ }
+ /*if(!$result){
+ $this->message .= "Error removing duplicates in config table<br/>";
+ $errors = true;
+ }*/
+
+ if($result){
+
+ // remove index id field, we don't need it any more!
+ $query = "ALTER TABLE ".$this->dbPrefix."config DROP COLUMN id";
+ $result = $this->Execute($query);
+ if(!$result){
+ $this->message .= "Error removing old id column from config table: ".$this->_db->ErrorMsg()."<br/>";
+ $errors = true;
+ }
+ }
+ }
+
+ if( !$errors ) {
+ $this->message .= "Configuration settings updated successfully";
+ }
+
+ return( !$errors );
+ }
+ }
+
+ /**
+ * Processes all admin users and grants the appropriate permissions
+ */
+ class AdminUserPermissionsDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( parent::getNumSteps( "users" ));
+ }
+
+ function perform()
+ {
+ $this->message = "Updating admin user permissions (step %s of %s)<br/>";
+
+ // load each one of the categories and update them
+ // list of categories
+ /*$query3 = "SELECT id, site_admin FROM ".$this->dbPrefix."users";
+ $res3 = $this->Execute( $query3, $this->page, $this->itemsPerPage );
+ if( $res3->RecordCount() == 0 ) {
+ $this->message .= "No more records to process";
+ return( true );
+ }*/
+
+ $users = new Users();
+ $allUsers = $users->getAllUsers( USER_STATUS_ALL, "", "", $this->page, $this->itemsPerPage );
+
+ $permissions = new Permissions();
+ $userPermissions = new UserPermissions();
+ $loginPerm = $permissions->getPermissionByName( "login_perm" );
+ $allPerms = $permissions->getAllPermissions();
+
+ //while( $row = $res3->FetchRow()) {
+ foreach( $allUsers as $user ) {
+ //print("Processing user: ".$user->getUsername()."<br/>");
+ //if( $row["site_admin"] > 0 ) {
+ if( $user->isSiteAdmin()) {
+ // it's an admin, let's grant all the appropriate permissions
+ foreach( $allPerms as $perm ) {
+ if( $perm->isAdminOnlyPermission() && $perm->getName() != "login_perm" ) {
+ //$userPerm = new UserPermission( $row["id"], 0, $perm->getId());
+ $userPerm = new UserPermission( $user->getId(), 0, $perm->getId());
+ $userPermissions->grantPermission( $userPerm );
+ }
+ }
+ }
+ // grant the login_perm permission or else users won't be able to log in
+ $newPerm = new UserPermission( $user->getId(), 0, $loginPerm->getId());
+ $userPermissions->grantPermission( $newPerm );
+
+ $this->updatedRecords++;
+ }
+
+ $this->message .= "{$this->updatedRecords} users updated (".$this->getPercentProcessed()."%%)<br/>";
+ return true;
+ }
+ }
+
+ /**
+ * processes all resource files and renames the files to their "real" names
+ */
+ class ResourcesOriginalFileNameDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( parent::getNumSteps( "gallery_resources" ));
+ }
+
+ function perform()
+ {
+ $this->message = "Updating resource files with original file naming rule (step %s of %s)<br/>";
+
+ $query1 = "SELECT id, owner_id, file_name, resource_type, thumbnail_format FROM ".$this->dbPrefix."gallery_resources";
+
+ $config =& Config::getConfig();
+ $galleryFolder = $config->getValue( "resources_folder" );
+
+ // total number of comments
+ $res1 = $this->Execute( $query1, $this->page, $this->itemsPerPage );
+ if( !$res1 ) {
+ $this->message .= "Error performing loading resource data";
+ return false;
+ }
+ if( $res1->RecordCount() == 0 ) {
+ $this->message .= "No more records to process";
+ return( true );
+ }
+ $numComments = Array();
+ while( $row = $res1->FetchRow()) {
+ //
+ // process each one of the rows and rename the main file
+ //
+
+ // get the file extension
+ if(( $extPos = strrpos( $row["file_name"], "." )) !== false ) {
+ $fileExt = substr( $row["file_name"], $extPos+1, strlen( $row["file_name"] ));
+ }
+ else {
+ $fileExt = "";
+ }
+
+ $fileName = $galleryFolder.$row["owner_id"]."/".$row["owner_id"]."-".$row["id"].".".$fileExt;
+ $destFileName = $galleryFolder.$row["owner_id"]."/".$row["file_name"];
+
+ //print( "Renaming file: $fileName --- $destFileName<br/>" );
+
+ // skip the rename if we already did it
+ if( File::exists( $fileName )) {
+ if( !File::exists( $destFileName)) {
+ if( !File::rename( $fileName, $destFileName )) {
+ $this->message .= "Error updating resource file with id ".$row["id"].", while attempting to rename file from $fileName to $destFileName<br/>";
+ }
+ }
+ }
+
+ // if it's an image, we also need to process the previews
+ if( $row["resource_type"] == "1" ) {
+ // calculate the extension of the preview file, depending on how it was saved
+ if( $row["thumbnail_format"] == "same" ) {
+ $previewExt = strtolower( $fileExt );
+ $destFileName = $row["file_name"];
+ }
+ else {
+ $previewExt = $row["thumbnail_format"];
+ // remove the old extension and put the new one in place
+ //print("file name = ".$row["file_name"]." - file ext = $fileExt - previewExt = $previewExt" );
+ $destFileName = str_replace( $fileExt, $previewExt, $row["file_name"] );
+ }
+
+ // file names for the preview and medium preview
+ $previewFileName = $galleryFolder.$row["owner_id"]."/previews/".$row["owner_id"]."-".$row["id"].".".$previewExt;
+ $medPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$row["owner_id"]."-".$row["id"].".".$previewExt;
+ // destination file names for the preview and medium preview
+ $destPreviewFileName = $galleryFolder.$row["owner_id"]."/previews/".$destFileName;
+ $destMedPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$destFileName;
+
+ //print(" -- renaming preview: $previewFileName -- $destPreviewFileName<br/>");
+ //print(" -- renaming medium preview: $medPreviewFileName -- $destMedPreviewFileName<br/>");
+
+ if( File::exists( $previewFileName )) {
+ if( !File::exists( $destPreviewFileName)) {
+ File::rename( $previewFileName, $destPreviewFileName );
+ }
+ }
+ if( File::exists( $medPreviewFileName )) {
+ if( !File::exists( $destMedPreviewFileName)) {
+ File::rename( $medPreviewFileName, $destMedPreviewFileName );
+ }
+ }
+ }
+
+ $this->updatedRecords++;
+ }
+ $res1->Close();
+ $this->message .= "{$this->updatedRecords} resource files updated, ".$this->getTotalProcessedRecords()." processed so far (".$this->getPercentProcessed()."%%)<br/>";
+ return true;
+ }
+ }
+
+ /**
+ * processes all resource files and renames the files to their "encoded" names
+ */
+ class ResourcesEncodedFileNameDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( parent::getNumSteps( "gallery_resources" ));
+ }
+
+ function perform()
+ {
+ $this->message = "Updating resource files with encoded file naming rule (step %s of %s)<br/>";
+
+ $query1 = "SELECT id, owner_id, file_name, resource_type, thumbnail_format FROM ".$this->dbPrefix."gallery_resources";
+
+ $config =& Config::getConfig();
+ $galleryFolder = $config->getValue( "resources_folder" );
+
+ // total number of comments
+ $res1 = $this->Execute( $query1, $this->page, $this->itemsPerPage );
+ if( !$res1 ) {
+ $this->message .= "Error performing loading resource data";
+ return false;
+ }
+ if( $res1->RecordCount() == 0 ) {
+ $this->message .= "No more records to process";
+ return( true );
+ }
+ $numComments = Array();
+ while( $row = $res1->FetchRow()) {
+ //
+ // process each one of the rows and rename the main file
+ //
+
+ // get the file extension
+ if(( $extPos = strrpos( $row["file_name"], "." )) !== false ) {
+ $fileExt = substr( $row["file_name"], $extPos+1, strlen( $row["file_name"] ));
+ }
+ else {
+ $fileExt = "";
+ }
+
+ $fileName = $galleryFolder.$row["owner_id"]."/".$row["owner_id"]."-".$row["id"].".".$fileExt;
+ $destFileName = $galleryFolder.$row["owner_id"]."/".$row["owner_id"]."-".$row["id"].".".strtolower($fileExt);
+
+ if( $fileName != $destFileName ) {
+ if( File::exists( $fileName )) {
+ if( !File::exists( $destFileName)) {
+ if( !File::rename( $fileName, $destFileName )) {
+ $this->message .= "Error updating resource file with id ".$row["id"].", while attempting to rename file from $fileName to $destFileName<br/>";
+ }
+ }
+ }
+ }
+
+ $this->updatedRecords++;
+ }
+ $res1->Close();
+ $this->message .= "{$this->updatedRecords} resource files updated, ".$this->getTotalProcessedRecords()." processed so far (".$this->getPercentProcessed()."%%)<br/>";
+ return true;
+ }
+ }
+
+ /**
+ * processes all resource files that we did not convert correctly in 1.2.0
+ */
+ class ResourcesFix120FileNameDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( parent::getNumSteps( "gallery_resources" ));
+ }
+
+ function perform()
+ {
+ $this->message = "Fixing resource files with original file naming rule (step %s of %s)<br/>";
+
+ $query1 = "SELECT id, owner_id, file_name, resource_type, thumbnail_format FROM ".$this->dbPrefix."gallery_resources";
+
+ $config =& Config::getConfig();
+ $galleryFolder = $config->getValue( "resources_folder" );
+
+ // total number of comments
+ $res1 = $this->Execute( $query1, $this->page, $this->itemsPerPage );
+ if( !$res1 ) {
+ $this->message .= "Error performing loading resource data";
+ return false;
+ }
+ if( $res1->RecordCount() == 0 ) {
+ $this->message .= "No more records to process";
+ return( true );
+ }
+ $numComments = Array();
+ while( $row = $res1->FetchRow()) {
+ //
+ // process each one of the rows and rename the main file
+ //
+
+ // get the file extension
+ if(( $extPos = strrpos( $row["file_name"], "." )) !== false ) {
+ $fileExt = substr( $row["file_name"], $extPos+1, strlen( $row["file_name"] ));
+ }
+ else {
+ $fileExt = "";
+ }
+
+ // Only convert the preview file name if the file extension does not lower case
+ if( strtolower( $fileExt ) != $fileExt ) {
+ // if it's an image, we also need to process the previews
+ if( $row["resource_type"] == "1" ) {
+ // calculate the extension of the preview file, depending on how it was saved
+ if( $row["thumbnail_format"] == "same" ) {
+ $previewExt = strtolower( $fileExt );
+ $destFileName = $row["file_name"];
+ }
+ else {
+ $previewExt = $row["thumbnail_format"];
+ // remove the old extension and put the new one in place
+ //print("file name = ".$row["file_name"]." - file ext = $fileExt - previewExt = $previewExt" );
+ $destFileName = str_replace( $fileExt, $previewExt, $row["file_name"] );
+ }
+
+ // file names for the preview and medium preview
+ $previewFileName = $galleryFolder.$row["owner_id"]."/previews/".$row["owner_id"]."-".$row["id"].".".$previewExt;
+ $medPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$row["owner_id"]."-".$row["id"].".".$previewExt;
+ // destination file names for the preview and medium preview
+ $destPreviewFileName = $galleryFolder.$row["owner_id"]."/previews/".$destFileName;
+ $destMedPreviewFileName = $galleryFolder.$row["owner_id"]."/previews-med/".$destFileName;
+
+ //print(" -- renaming preview: $previewFileName -- $destPreviewFileName<br/>");
+ //print(" -- renaming medium preview: $medPreviewFileName -- $destMedPreviewFileName<br/>");
+
+ if( File::exists( $previewFileName )) {
+ if( !File::exists( $destPreviewFileName)) {
+ File::rename( $previewFileName, $destPreviewFileName );
+ }
+ }
+ if( File::exists( $medPreviewFileName )) {
+ if( !File::exists( $destMedPreviewFileName)) {
+ File::rename( $medPreviewFileName, $destMedPreviewFileName );
+ }
+ }
+ }
+ }
+
+ $this->updatedRecords++;
+ }
+ $res1->Close();
+ $this->message .= "{$this->updatedRecords} resource files updated, ".$this->getTotalProcessedRecords()." processed so far (".$this->getPercentProcessed()."%%)<br/>";
+ return true;
+ }
+ }
+
+ // Dummy Transformer
+ class DummyDataTransformer extends DatabaseDataTransformer
+ {
+ function getNumSteps()
+ {
+ return( 0 );
+ }
+
+ function perform()
+ {
+ return true;
+ }
+ }
+
+ /**
+ * This class is basically now a "data transformer runner", because now it works
+ * like class that executes data transformers, collects their results and refreshes
+ * the page to execute the next step of the transformer. If the current transformer
+ * reported that its processing is complete, this class will continue with the next
+ * transformer unless there are no more transformer to run.
+ *
+ * In order to coordinate the current step and the current transformer, two parameters
+ * are needed in each request:
+ *
+ * - page
+ * - transformerId
+ *
+ * The 'page' parameter holds the current page, while 'transformerId' is the index of
+ * the current transformer in the $this->transformers array.
+ *
+ * In order to add new transformers, follow these steps:
+ *
+ * - Create your own transfomer class by extending DatabaseDataTransformer and implementing
+ * the methods DatabaseDataTransformer::perform() and DatabaseDataTransformer::getNumSteps(). The
+ * first does the data processing while the second one returns the number of needed steps to the
+ * class running the transformer.
+ * - Add the name of the transformer class to the the UpdateStepThree::transformers array,
+ * and the class will take care of everything else.
+ */
+ class UpdateStepThree extends WizardPagedAction
+ {
+ var $resourcesNamingRule;
+ var $message;
+ var $currentTransformerId;
+ var $totalTransformers;
+
+ function UpdateStepThree( $actionInfo, $httpRequest )
+ {
+ $this->WizardPagedAction( $actionInfo, $httpRequest );
+ // data validation
+ $this->registerFieldValidator( "resourcesNamingRule", new StringValidator());
+ $errorView = new WizardView( "update2" );
+ $errorView->setErrorMessage( "Some data was incorrect or missing." );
+ $this->setValidationErrorView( $errorView );
+
+ /**
+ * array with the data transformers that will be run
+ */
+ $this->resourcesNamingRule = $this->_request->getValue( "resourcesNamingRule" );
+ if( $this->resourcesNamingRule == 'encoded_file_name' ) {
+ $this->transformers = Array(
+ "DatabaseSchemaDataTransformer",
+ "PermissionLoader",
+ "AdminUserPermissionsDataTransformer",
+ "UserPermissionsDataTransformer",
+ "ConfigDataTransformer",
+ "ResourcesEncodedFileNameDataTransformer",
+ "DummyDataTransformer"
+ );
+ }
+ else {
+ $this->transformers = Array(
+ "DatabaseSchemaDataTransformer",
+ "PermissionLoader",
+ "AdminUserPermissionsDataTransformer",
+ "UserPermissionsDataTransformer",
+ "ConfigDataTransformer",
+ "ResourcesOriginalFileNameDataTransformer",
+ "DummyDataTransformer"
+ );
+ }
+
+ $this->currentTransformerId = $this->getTransformerIdFromRequest();
+ $this->totalTransformers = count( $this->transformers ) - 1;
+ }
+
+ /**
+ * gets the id of the transformer from the request. If it is not available, it
+ * will return the id of the first transformer available (which is '0')
+ *
+ * @private
+ */
+ function getTransformerIdFromRequest()
+ {
+ $id = HttpVars::getRequestValue( "transformerId" );
+ $val = new IntegerValidator();
+ if( !$val->validate( $id ))
+ $id = 0;
+
+ return $id;
+ }
+
+ function perform()
+ {
+ $step = $this->getPageFromRequest();
+
+ // get the current transformer class so that we can continue where we left
+ $transformerClass = $this->transformers[$this->currentTransformerId];
+ $transformer = new $transformerClass( $step );
+ $result = $transformer->perform();
+ $complete = $transformer->isComplete();
+ $message = $transformer->message;
+ $message = sprintf( $message, $this->currentTransformerId + 1, $this->totalTransformers );
+
+ //print("transformer = $transformerClass<br/>");
+
+ // error during processing and the processor is configured
+ // to fail on error
+ if( !$result && $transformer->failOnError ) {
+ //print("Error in step = $step<br/>");
+ $this->_view = new WizardView( "update3" );
+ $this->_view->setValue( "resourcesNamingRule", $this->resourcesNamingRule );
+ // current and next step
+ $this->_view->setValue( "currentStep", $step );
+ $this->_view->setValue( "nextStep", $step+1 );
+ // whether this transformer is ready
+ $this->_view->setValue( "complete", $complete );
+ // transformer id
+ $this->_view->setValue( "transformerId", $this->currentTransformerId );
+ $this->_view->setValue( "error", true );
+ if( $transformer->DbError() != "" ) {
+ $message .= "<br/>The database error message was: ".$transformer->DbError()."<br/>";
+ }
+
+ $this->_view->setErrorMessage( $message );
+ }
+ else {
+ if( !$complete ) {
+ //print("it's not complete! step = $step<br/>");
+ $this->_view = new WizardView( "update3" );
+ $this->_view->setValue( "resourcesNamingRule", $this->resourcesNamingRule );
+ // current and next step
+ $this->_view->setValue( "currentStep", $step );
+ $this->_view->setValue( "nextStep", $step+1 );
+ // whether this transformer is ready
+ $this->_view->setValue( "complete", $complete );
+ // transformer id
+ $this->_view->setValue( "transformerId", $this->currentTransformerId );
+ }
+ else {
+ // have we already been through all transformers?
+ //print("transformer complete! - num transformers = ".count($this->transformers)."<br/>");
+ $moreTransformers = ( $this->currentTransformerId+1 < count( $this->transformers ));
+ if( $moreTransformers ) {
+ //print("Starting new transformer!<br/>");
+ $this->_view = new WizardView( "update3" );
+ $this->_view->setValue( "resourcesNamingRule", $this->resourcesNamingRule );
+ // current and next step
+ $this->_view->setValue( "currentStep", 0 );
+ $this->_view->setValue( "nextStep", 1 );
+ // whether this transformer is ready
+ $this->_view->setValue( "complete", false );
+ // transformer id
+ $this->_view->setValue( "transformerId", $this->currentTransformerId+1 );
+ }
+ else {
+ // no more data to transform, we can finalize the installation!
+ // delete the contents of the temporary folder
+ lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+ $config =& Config::getConfig();
+ $tmpFolder = $config->getValue( "temp_folder", TEMP_FOLDER );
+ WizardTools::cleanTmpFolder();
+
+ // save the resources naming rule to config table
+ $config->saveValue( "resources_naming_rule", $this->resourcesNamingRule );
+
+ $this->_view = new WizardView( "update4" );
+ }
+ }
+ }
+
+ $this->_view->setValue( "message", $message );
+
+ return true;
+ }
+ }
+
+ // Fix those resources that we did not convert correctly in 1.2.0
+ class Fix120StepOne extends WizardPagedAction
+ {
+ var $message;
+ var $currentTransformerId;
+ var $totalTransformers;
+
+ function Fix120StepOne( $actionInfo, $httpRequest )
+ {
+ $this->WizardPagedAction( $actionInfo, $httpRequest );
+
+ /**
+ * array with the data transformers that will be run
+ */
+ $this->transformers = Array(
+ "ResourcesFix120FileNameDataTransformer",
+ "DummyDataTransformer"
+ );
+
+ $this->currentTransformerId = $this->getTransformerIdFromRequest();
+ $this->totalTransformers = count( $this->transformers ) - 1;
+ }
+
+ /**
+ * gets the id of the transformer from the request. If it is not available, it
+ * will return the id of the first transformer available (which is '0')
+ *
+ * @private
+ */
+ function getTransformerIdFromRequest()
+ {
+ $id = HttpVars::getRequestValue( "transformerId" );
+ $val = new IntegerValidator();
+ if( !$val->validate( $id ))
+ $id = 0;
+
+ return $id;
+ }
+
+ function perform()
+ {
+ $step = $this->getPageFromRequest();
+
+ // get the current transformer class so that we can continue where we left
+ $transformerClass = $this->transformers[$this->currentTransformerId];
+ $transformer = new $transformerClass( $step );
+ $result = $transformer->perform();
+ $complete = $transformer->isComplete();
+ $message = $transformer->message;
+ $message = sprintf( $message, $this->currentTransformerId + 1, $this->totalTransformers );
+
+ //print("transformer = $transformerClass<br/>");
+
+ // error during processing and the processor is configured
+ // to fail on error
+ if( !$result && $transformer->failOnError ) {
+ //print("Error in step = $step<br/>");
+ $this->_view = new WizardView( "update3" );
+ // current and next step
+ $this->_view->setValue( "currentStep", $step );
+ $this->_view->setValue( "nextStep", $step+1 );
+ // whether this transformer is ready
+ $this->_view->setValue( "complete", $complete );
+ // transformer id
+ $this->_view->setValue( "transformerId", $this->currentTransformerId );
+ $this->_view->setValue( "error", true );
+ if( $transformer->DbError() != "" ) {
+ $message .= "<br/>The database error message was: ".$transformer->DbError()."<br/>";
+ }
+
+ $this->_view->setErrorMessage( $message );
+ }
+ else {
+ if( !$complete ) {
+ //print("it's not complete! step = $step<br/>");
+ $this->_view = new WizardView( "fix120" );
+ // current and next step
+ $this->_view->setValue( "currentStep", $step );
+ $this->_view->setValue( "nextStep", $step+1 );
+ // whether this transformer is ready
+ $this->_view->setValue( "complete", $complete );
+ // transformer id
+ $this->_view->setValue( "transformerId", $this->currentTransformerId );
+ }
+ else {
+ // have we already been through all transformers?
+ //print("transformer complete! - num transformers = ".count($this->transformers)."<br/>");
+ $moreTransformers = ( $this->currentTransformerId+1 < count( $this->transformers ));
+ if( $moreTransformers ) {
+ //print("Starting new transformer!<br/>");
+ $this->_view = new WizardView( "fix120" );
+ // current and next step
+ $this->_view->setValue( "currentStep", 0 );
+ $this->_view->setValue( "nextStep", 1 );
+ // whether this transformer is ready
+ $this->_view->setValue( "complete", false );
+ // transformer id
+ $this->_view->setValue( "transformerId", $this->currentTransformerId+1 );
+ }
+ else {
+ // no more data to transform, we can finalize the installation!
+ // delete the contents of the temporary folder
+ lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
+ $config =& Config::getConfig();
+ $tmpFolder = $config->getValue( "temp_folder", TEMP_FOLDER );
+ WizardTools::cleanTmpFolder();
+
+ // User upgrade LifeType from 1.1.x to 1.2.0, they have to use "original_file_name",
+ // becasue there is no option for user to choose he want to use encoded file name
+ // or original file name.
+ // save the resources naming rule to config table
+ $config->saveValue( "resources_naming_rule", "original_file_name" );
+
+ $this->_view = new WizardView( "update4" );
+ }
+ }
+ }
+
+ $this->_view->setValue( "message", $message );
+
+ return true;
+ }
+ }
+
+ // check if the "./tmp" folder is writable by us, otherwise
+ // throw an error before the user gets countless errors
+ // from Smarty
+ if( !File::isWritable( TEMP_FOLDER ) || !File::isDir( TEMP_FOLDER )) {
+ print("<span style=\"color:red; font-size: 14px;\">Error</span><br/><br/>This wizard needs the ".TEMP_FOLDER." folder to be writable by the web server user.<br/><br/>Please correct it and try again.");
+ die();
+ }
+
+ //// main part ////
+ $controller = new Controller( $_actionMap, "nextStep" );
+ $controller->process( HttpVars::getRequest());
+?>
More information about the pLog-svn
mailing list