Xataface 2.0
Xataface Application Framework
actions/register.php
Go to the documentation of this file.
00001 <?php
00002 /*-------------------------------------------------------------------------------
00003  * Xataface Web Application Framework
00004  * Copyright (C) 2005-2007  Steve Hannah (shannah@sfu.ca)
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  *-------------------------------------------------------------------------------
00020  */
00032 class dataface_actions_register {
00033 
00038         var $form;
00039         var $params;
00040         var $ontology;
00041         
00042 
00043         function handle(&$params){
00044                 $this->params =& $params['action'];
00045                 unset($params);
00046                 $params =& $this->params;
00047 
00048                 Dataface_PermissionsTool::getInstance()->setDelegate(new dataface_actions_register_permissions_delegate());
00049                 
00050                 
00051                 $app =& Dataface_Application::getInstance();
00052                 $auth =& Dataface_AuthenticationTool::getInstance();
00053 
00054                 
00055                 import('Dataface/Ontology.php');
00056                 Dataface_Ontology::registerType('Person', 'Dataface/Ontology/Person.php', 'Dataface_Ontology_Person');
00057                 $this->ontology =& Dataface_Ontology::newOntology('Person', $app->_conf['_auth']['users_table']);
00058                 
00059                 $atts =& $this->ontology->getAttributes();
00060                 
00061                 $query =& $app->getQuery();
00062                 if ( !is_array(@$app->_conf['_auth']) ){
00063                         return PEAR::raiseError("Cannot register when authentication is not enabled.", DATAFACE_E_ERROR);
00064                 }
00065                 
00066                 if ( isset($app->_conf['_auth']['email_column']) ){
00067                         
00068                         
00069                         $atts['email'] =& $this->ontology->table->getField( $app->_conf['_auth']['email_column'] );
00070                         $this->fieldnames['email'] = $app->_conf['_auth']['email_column'];
00071                 } 
00072                 
00073                         
00074                 if ( $auth->isLoggedIn() ){
00075                         return Dataface_Error::permissionDenied("Sorry you cannot register once you are logged in.  If you want to register, you must first log out.");
00076                 }
00077                 
00078                 
00079                 
00080                 if ( !@$app->_conf['_auth']['allow_register'] ){
00081                         return PEAR::raiseError("Sorry, registration is not allowed.  Please contact the administrator for an account.", DATAFACE_E_ERROR);
00082                 }
00083                 
00084                 
00085                 $pt =& Dataface_PermissionsTool::getInstance();
00086                 
00087                 
00088                 // Create a new record form on the users table
00089                 $this->form =& df_create_new_record_form($app->_conf['_auth']['users_table']);
00090                 
00091                 // add the -action element so that the form will direct us back here.
00092                 $this->form->addElement('hidden','-action');
00093                 $this->form->setDefaults(array('-action'=>$query['-action']));
00094                 
00095                 // Check to make sure that there isn't another user with the same 
00096                 // username already.
00097                 $validationResults = $this->validateRegistrationForm($_POST);
00098                 if ( count($_POST) > 0 and PEAR::isError($validationResults) ){
00099                         $app->addMessage($validationResults->getMessage());
00100                         $this->form->_errors[$app->_conf['_auth']['username_column']] = $validationResults->getMessage();
00101                 }
00102                 if ( !PEAR::isError($validationResults) and $this->form->validate() ){
00103                         // The form input seems OK.  Let's process the form
00104                         
00105                         // Since we will be using our own form processing for this action, 
00106                         // we need to manually push the field inputs into the Dataface_Record
00107                         // object.
00108                         $this->form->push();
00109                         
00110                         // Now we obtain the Dataface_Record object that is to be added.
00111                         $rec =& $this->form->_record;
00112                         $delegate =& $rec->_table->getDelegate();
00113                         
00114                         
00115                         // Give the delegate classes an opportunity to have some fun
00116                         if ( isset($delegate) and method_exists($delegate, 'beforeRegister') ){
00117                                 $res = $delegate->beforeRegister($rec);
00118                                 if ( PEAR::isError($res) ){
00119                                         return $res;
00120                                 }
00121                         }
00122                         
00123                         $appdel = & $app->getDelegate();
00124                         if ( isset($appdel) and method_exists($appdel, 'beforeRegister') ){
00125                                 $res = $appdel->beforeRegister($rec);
00126                                 if ( PEAR::isError($res) ) return $res;
00127                         }
00128                         
00129                         // This is where we actually do the processing.  This passes control
00130                         // to the processRegistrationForm method in this class.
00131                         $res = $this->form->process(array(&$this, 'processRegistrationForm'), true);
00132                         
00133                         // If there was an error in processing mark the error, and show the
00134                         // form again.  Otherwise we just redirect to the next page and
00135                         // let the user know that he was successful.
00136                         if ( PEAR::isError($res) ){
00137                                 $app->addError($res);
00138                                 
00139                         } else {
00140                         
00141                                 // Let the delegate classes perform their victory lap..
00142                                 if ( isset($delegate) and method_exists($delegate, 'afterRegister') ){
00143                                         $res  = $delegate->afterRegister($rec);
00144                                         if ( PEAR::isError($res) ) return $res;
00145                                 }
00146                                 
00147                                 if ( isset($appdel) and method_exists($appdel, 'afterRegister') ){
00148                                         $res = $appdel->afterRegister($rec);
00149                                         if ( PEAR::isError($res) ) return $res;
00150                                 }
00151                         
00152                         
00153                                 // We accept --redirect markers to specify which page to redirect
00154                                 // to after we're done.  This will usually be the page that the
00155                                 // user was on before they went to the login page.
00156                                 if ( isset($_SESSION['--redirect']) ) $url = $_SESSION['--redirect'];
00157                                 else if ( isset($_SESSION['-redirect']) ) $url = $_SESSION['-redirect'];
00158                                 else if ( isset($_REQUEST['--redirect']) ) $url = $_REQUEST['--redirect'];
00159                                 else if ( isset($_REQUEST['-redirect']) ) $url = $_REQUEST['-redirect'];
00160                                 else $url = $app->url('-action='.$app->_conf['default_action']);
00161                                 
00162                                 if ( @$params['email_validation'] ){
00163                                         $individual = $this->ontology->newIndividual($this->form->_record);
00164                                         $msg = df_translate('actions.register.MESSAGE_THANKYOU_PLEASE_VALIDATE', 
00165                                                 'Thank you. An email has been sent to '.$individual->strval('email').' with instructions on how to complete the registration process.',
00166                                                 array('email'=>$individual->strval('email'))
00167                                                 );
00168                                 } else {
00169                                         // To save the user from having to log in after he has just filled
00170                                         // in the registration form, we will just log him in right here.
00171                                         $_SESSION['UserName'] = $this->form->exportValue($app->_conf['_auth']['username_column']);
00172                                         $msg =  df_translate('actions.register.MESSAGE_REGISTRATION_SUCCESSFUL',
00173                                                 "Registration successful.  You are now logged in."
00174                                                 );
00175                                 }
00176                                 // Now we actually forward to the success page along with a success message
00177                                 if ( strpos($url, '?') === false ) $url .= '?';
00178                                 $app->redirect($url.'&--msg='.urlencode($msg));
00179                         }
00180                 }
00181                 
00182                 // We want to display the form, but not yet so we will use an output buffer
00183                 // to store the form HTML in a variable and pass it to our template.
00184                 ob_start();
00185                 $this->form->display();
00186                 $out = ob_get_contents();
00187                 ob_end_clean();
00188                 
00189                 $context = array('registration_form'=>$out);
00190                 
00191                 // We don't want to keep the registration page in history, because we want to
00192                 // be able to redirect the user back to where he came from before registering.
00193                 $app->prefs['no_history'] = true;
00194                 df_display($context, 'Dataface_Registration.html');
00195         
00196         }
00197         
00201         function createRegistrationTable(){
00202                 if ( !Dataface_Table::tableExists('dataface__registrations', false) ){
00203                         $sql = "create table `dataface__registrations` (
00204                                 registration_code varchar(32) not null,
00205                                 registration_date timestamp(11) not null,
00206                                 registration_data longtext not null,
00207                                 primary key (registration_code))";
00208                                 // registration_code stores an md5 code used to identify the registration
00209                                 // registration_date is the date that the registration was made
00210                                 // registration_data is a serialized array of the data from getValues()
00211                                 // on the record.
00212                                 
00213                                 
00214                         $res = mysql_query($sql, df_db());
00215                         if ( !$res ) throw new Exception(mysql_error(df_db()), E_USER_ERROR);
00216                 }
00217                 return true;
00218         
00219         }
00220         
00227         function validateRegistrationForm($values){
00228 
00229                 $app =& Dataface_Application::getInstance();
00230                 $del =& $app->getDelegate();
00231                 if ( $del and method_exists($del,'validateRegistrationForm') ){
00232                         $res = $del->validateRegistrationForm($values);
00233                         if ( PEAR::isError($res) ) return $res;
00234                         else if ( is_int($res) and $res === 2 ) return true;
00235                 }
00236                 $conf =& $app->_conf['_auth'];
00237                 
00238                 // Make sure username is supplied
00239                 if ( !@$values[$conf['username_column']] ) 
00240                         return PEAR::raiseError(
00241                                 df_translate('actions.register.MESSAGE_USERNAME_REQUIRED', 'Please enter a username')
00242                                 );
00243                 
00244                 
00245                 // Check for a duplicate username
00246                 $res = mysql_query("select count(*) from `".$conf['users_table']."` where `".$conf['username_column']."` = '".addslashes($values[$conf['username_column']])."'", df_db());
00247                 if ( !$res ) throw new Exception(mysql_error(df_db()), E_USER_ERROR);
00248                 
00249                 list($num) = mysql_fetch_row($res);
00250                 if ( $num>0 ){
00251                         return PEAR::raiseError(
00252                                 df_translate('actions.register.MESSAGE_USERNAME_ALREADY_TAKEN', 'Sorry, that username is already in use by another user.')
00253                                 );
00254                 }
00255                 
00256                 // Make sure that the user supplied a password
00257                 if ( !@$values[$conf['password_column']] )
00258                         return PEAR::raiseError(
00259                                 df_translate('actions.register.MESSAGE_PASSWORD_REQUIRED', 'Please enter a password')
00260                                 );
00261                                 
00262                 // Make sure that the user supplied an email address - and that the email address is valid
00263                 $emailField = $this->ontology->getFieldname('email');
00264                 if ( !@$values[$emailField] or !$this->ontology->validate('email', @$values[$emailField], false /*No blanks*/))
00265                         return PEAR::raiseError(
00266                                 df_translate('actions.register.MESSAGE_EMAIL_REQUIRED', 'Please enter a valid email address in order to register.  A valid email address is required because an email will be sent to the address with information on how to activate this account.')
00267                                 );
00268                                 
00269                 return true;
00270         }
00271         
00272         
00273         function _fireDelegateMethod($name, &$record, $params=null){
00274                 $app =& Dataface_Application::getInstance();
00275                 $table = & Dataface_Table::loadTable($app->_conf['_auth']['users_table']);
00276                 
00277                 $appdel =& $app->getDelegate();
00278                 $tdel =& $table->getDelegate();
00279                 
00280                 if ( isset($tdel) and method_exists($tdel, $name) ){
00281                         $res = $tdel->$name($record, $params);
00282                         if ( !PEAR::isError($res) or ($res->getCode() != DATAFACE_E_REQUEST_NOT_HANDLED) ){
00283                                 return $res;
00284                         }
00285                 }       
00286                 
00287                 if ( isset($appdel) and method_exists($appdel, $name) ){
00288                         $res = $appdel->$name($record, $params);
00289                         if ( !PEAR::isError($res) or ($res->getCode() != DATAFACE_E_REQUEST_NOT_HANDLED) ){
00290                                 return $res;
00291                         }
00292                 }
00293                 return PEAR::raiseError("No delegate method found named '$name'.", DATAFACE_E_REQUEST_NOT_HANDLED);
00294         }
00295 
00296         
00297         
00298         function processRegistrationForm($values){
00299                 
00300                 $app =& Dataface_Application::getInstance();
00301                 $conf =& $app->_conf['_auth'];
00302                 $appConf =& $app->conf();
00303                 $table =& Dataface_Table::loadTable($conf['users_table']);
00304                 
00305                 if ( @$this->params['email_validation'] ){
00306                         
00307                         // Let's try to create the registration table if it doesn't already
00308                         // exist
00309                         $this->createRegistrationTable();
00310                         
00311                         // Now we will store the registration attempt
00312                         
00313                         // A unique code to be used as an id
00314                         $code = null;
00315                         do {
00316                                 $code = md5(rand());
00317                         } while ( 
00318                                 mysql_num_rows(
00319                                         mysql_query(
00320                                                 "select registration_code 
00321                                                 from dataface__registrations 
00322                                                 where registration_code='".addslashes($code)."'", 
00323                                                 df_db()
00324                                                 )
00325                                         ) 
00326                                 );
00327                         
00328                         // Now that we have a unique id, we can insert the value
00329                         
00330                         $sql = "insert into dataface__registrations 
00331                                         (registration_code, registration_data) values
00332                                         ('".addslashes($code)."',
00333                                         '".addslashes(
00334                                                 serialize(
00335                                                         $this->form->_record->getValues()
00336                                                         )
00337                                                 )."')";
00338                         $res = mysql_query($sql, df_db());
00339                         if ( !$res ) throw new Exception(mysql_error(df_db()), E_USER_ERROR);
00340                         
00341                         $activation_url = $_SERVER['HOST_URI'].DATAFACE_SITE_HREF.'?-action=activate&code='.urlencode($code);
00342                         
00343                         // Now that the registration information has been inserted, we need
00344                         // to send the confirmation email
00345                         // Let's try to send the email if possible.
00346                         $res = $this->_fireDelegateMethod('sendRegistrationActivationEmail', $this->form->_record, $activation_url );
00347                         if ( !PEAR::isError($res) or ( $res->getCode() != DATAFACE_E_REQUEST_NOT_HANDLED) ){
00348                                 return $res;
00349                         }
00350                         
00351                         // If we got this far, that means that we haven't sent the email yet... Rather
00352                         // let's send it outselves.
00353                         // We use the Person Ontology to work with the users table record in a more
00354                         // generic way.
00355                         $registrant =& $this->ontology->newIndividual($this->form->_record);
00356                         // We now have the user's email address
00357                         $email = $registrant->strval('email');
00358                         
00359                         // Let's get the email info. This will return an associative array
00360                         // of the parameters involved in the registration email.  The keys
00361                         // are:
00362                         // 1. subject
00363                         // 2. message
00364                         // 3. headers
00365                         // 4. parameters
00366                         // These are such that they can be passed directly to the mail function
00367                         $info = $this->_fireDelegateMethod('getRegistrationActivationEmailInfo', $this->form->_record, $activation_url);
00368                         if ( PEAR::isError($info) ) $info = array();
00369                         $info['to'] = $email;
00370                         
00371                         // Override specific parts of the message if delegate class wants it.
00372                         $subject = $this->_fireDelegateMethod('getRegistrationActivationEmailSubject', $this->form->_record, $activation_url);
00373                         if ( !PEAR::isError($subject) ) $info['subject'] = $subject;
00374                         
00375                         
00376                         $message = $this->_fireDelegateMethod('getRegistrationActivationEmailMessage', $this->form->_record, $activation_url);
00377                         if ( !PEAR::isError($message) ) $info['message'] = $message;
00378                         
00379                         $parameters = $this->_fireDelegateMethod('getRegistrationActivationEmailParameters', $this->form->_record, $activation_url);
00380                         if ( !PEAR::isError($parameters) ) $info['parameters'] = $parameters;
00381                         
00382                         $headers = $this->_fireDelegateMethod('getRegistrationActivationEmailHeaders', $this->form->_record, $activation_url);
00383                         if ( !PEAR::isError($headers) ) $info['headers'] = $headers;
00384                         
00385                         
00386                         // Now we fill in the missing information with defaults
00387                         if ( !@$info['subject'] ) 
00388                                 $info['subject'] = df_translate(
00389                                         'actions.register.MESSAGE_REGISTRATION_ACTIVATION_EMAIL_SUBJECT',
00390                                         $app->getSiteTitle().': Activate your account',
00391                                         array('site_title'=>$app->getSiteTitle())
00392                                         );
00393                         
00394                         if ( !@$info['message'] ){
00395                                 $site_title = $app->getSiteTitle();
00396                                 if ( isset($appConf['abuse_email']) ){
00397                                         $admin_email = $appConf['abuse_email'];
00398                                 } else if ( isset($appConf['admin_email']) ){
00399                                         $admin_email = $appConf['admin_email'];
00400                                 } else {
00401                                         $admin_email = $_SERVER['SERVER_ADMIN'];
00402                                 }
00403                                 
00404                                 if ( isset( $appConf['application_name'] ) ){
00405                                         $application_name = $appConf['application_name'];
00406                                 } else {
00407                                         $application_name = df_translate('actions.register.LABEL_A_DATAFACE_APPLICATION','a Dataface Application');
00408                                 }
00409                                 
00410                                 if ( file_exists('version.txt') ){
00411                                         $application_version = trim(file_get_contents('version.txt'));
00412                                 } else {
00413                                         $application_version = '0.1';
00414                                 }
00415                                 
00416                                 if ( file_exists(DATAFACE_PATH.'/version.txt') ){
00417                                         $dataface_version = trim(file_get_contents(DATAFACE_PATH.'/version.txt'));
00418                                 } else {
00419                                         $dataface_version = 'unknown';
00420                                 }
00421                                 
00422                                 
00423                                 
00424                                 
00425                                 $msg = <<<END
00426 Thank you for registering for an account on $site_title .  In order to complete your registration,
00427 please visit $activation_url .
00428 
00429 If you have not registered for an account on this web site and believe that you have received
00430 this email eroneously, please report this to $admin_email .
00431 -----------------------------------------------------------
00432 This message was sent by $site_title which is powered by $application_name version $application_version
00433 $application_name built using Dataface version $dataface_version (http://fas.sfu.ca/dataface).
00434 END;
00435 
00436                                 $info['message'] = df_translate(
00437                                         'actions.register.MESSAGE_REGISTRATION_ACTIVATION_EMAIL_MESSAGE',
00438                                         $msg,
00439                                         array(
00440                                                 'site_title'=>$site_title,
00441                                                 'activation_url'=>$activation_url,
00442                                                 'admin_email'=>$admin_email,
00443                                                 'application_name'=>$application_name,
00444                                                 'application_version'=>$application_version,
00445                                                 'dataface_version'=>$dataface_version
00446                                                 )
00447                                         );
00448                         
00449                         
00450                         }
00451                         
00452                         // Now that we have all of the information ready to send.  Let's send
00453                         // the email message.
00454                         
00455                         if ( @$conf['_mail']['func'] ) $func = $conf['_mail']['func'];
00456                         else $func = 'mail';
00457                         $res = $func($info['to'],
00458                                                 $info['subject'],
00459                                                 $info['message'],
00460                                                 @$info['headers'],
00461                                                 @$info['parameters']);
00462                         if ( !$res ){
00463                                 return PEAR::raiseError('Failed to send activation email.  Please try again later.', DATAFACE_E_ERROR);
00464                         } else {
00465                                 return true;
00466                         }
00467                         
00468                 } else {
00469                         // We aren't using email validation.. let's just pass it to the 
00470                         // form's standard processing function.
00471                         return $this->form->process(array(&$this->form, 'save'), true);
00472                 }
00473                 
00474         }
00475 }
00476 
00477 class dataface_actions_register_permissions_delegate {
00478         function filterPermissions(&$obj, &$perms){
00479                 if ( @$perms['register'] ) $perms['new'] = 1;
00480         }
00481 }
00482 
00483 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations