/**
  * Performs the work of inserting or updating the row in the database.
  *
  * If the object is new, it inserts it; otherwise an update is performed.
  * All related objects are also updated in this method.
  *
  * @param      PropelPDO $con
  * @return     int The number of rows affected by this insert/update and any referring fk objects' save() operations.
  * @throws     PropelException
  * @see        save()
  */
 protected function doSave(PropelPDO $con)
 {
     $affectedRows = 0;
     // initialize var to track total num of affected rows
     if (!$this->alreadyInSave) {
         $this->alreadyInSave = true;
         // We call the save method on the following object(s) if they
         // were passed to this object by their coresponding set
         // method.  This object relates to these object(s) by a
         // foreign key reference.
         if ($this->aPcUser !== null) {
             if ($this->aPcUser->isModified() || $this->aPcUser->isNew()) {
                 $affectedRows += $this->aPcUser->save($con);
             }
             $this->setPcUser($this->aPcUser);
         }
         // If this object has been modified, then save it to the database.
         if ($this->isModified()) {
             if ($this->isNew()) {
                 $pk = PcSupporterPeer::doInsert($this, $con);
                 $affectedRows += 1;
                 // we are assuming that there is only 1 row per doInsert() which
                 // should always be true here (even though technically
                 // BasePeer::doInsert() can insert multiple rows).
                 $this->setNew(false);
             } else {
                 $affectedRows += PcSupporterPeer::doUpdate($this, $con);
             }
             $this->resetModified();
             // [HL] After being saved an object is no longer 'modified'
         }
         $this->alreadyInSave = false;
     }
     return $affectedRows;
 }
 /**
  * Logins the user (performing the brute force attack check)
  * 
  * @param myUser $userSf
  * @param PcUser $userApp - the user trying to login
  * @param boolean $rememberme - whether the user wanted to remember the login
  * @param boolean $remembermeCookieAlreadySet - in this case, if even
  *    $rememberme is true, the cookie is not set because it is already available
  * @return boolean - false if the account is blocked because of a brute
  *         force attack detection
  */
 public static function login(myUser $userSf, PcUser $userApp, $rememberme = false, $remembermeCookieAlreadySet = false)
 {
     // Check whether the account must be block because of a
     // brute force attack detection
     $c = new Criteria();
     $c->addJoin(PcUserPeer::ID, PcFailedLoginsPeer::USER_ID, Criteria::INNER_JOIN);
     $c->add(PcUserPeer::ID, $userApp->getId(), Criteria::EQUAL);
     $row = PcFailedLoginsPeer::doSelectOne($c);
     if ($row) {
         $maxAttempts = sfConfig::get('app_bruteForceLockout_loginAttemptThreshold');
         $currentAttempts = $row->getTimes();
         $timeout = sfConfig::get('app_bruteForceLockout_lockoutDuration');
         $secondsElapsedFromLastAttempt = time() - strtotime($row->getUpdatedAt());
         if ($secondsElapsedFromLastAttempt > $timeout) {
             // reset the 'failed logins' situation for the user
             $row->delete();
         } else {
             if ($currentAttempts >= $maxAttempts) {
                 PcWatchdog::alert('Brute force attack attempt', 'For the userid ' . $row->getUserId());
                 return false;
             }
         }
     }
     $userApp->setLanguage(PcUtils::getVisitorAcceptLanguage());
     $userApp->setIpAddress(PcUtils::getVisitorIPAddress());
     $userApp->save();
     $userSf->setAuthenticated(true);
     $userSf->setAttribute('userid', $userApp->getId());
     if ($userApp->isAdmin()) {
         $userSf->addCredential('admin');
     }
     if ($userApp->isStaffMember()) {
         $userSf->addCredential('staffMember');
     }
     if ($userApp->isContractor()) {
         $userSf->addCredential('contractor');
     }
     if ($userApp->isEditor()) {
         $userSf->addCredential('editor');
     }
     if ($userApp->isTranslator()) {
         $userSf->addCredential('translator');
     }
     if ($rememberme && !$remembermeCookieAlreadySet) {
         self::setRememberMeCookie($userSf, $userApp);
     } else {
         if (!$rememberme) {
             // the user may login a second time (while still logged in because of forum integration problems), without
             // ticking the rememberme checkbox
             self::resetRememberMeCookie();
         } else {
             // if $rememberme and $remembermeCookieAlreadySet
             // are both true we don't need to do anything
         }
     }
     sfContext::getInstance()->getEventDispatcher()->notify(new sfEvent('CustomAuthLogin', 'custom_auth.login', array('user' => $userApp, 'rememberme' => $rememberme)));
     return true;
 }
 /**
  * Performs the work of inserting or updating the row in the database.
  *
  * If the object is new, it inserts it; otherwise an update is performed.
  * All related objects are also updated in this method.
  *
  * @param      PropelPDO $con
  * @return     int The number of rows affected by this insert/update and any referring fk objects' save() operations.
  * @throws     PropelException
  * @see        save()
  */
 protected function doSave(PropelPDO $con)
 {
     $affectedRows = 0;
     // initialize var to track total num of affected rows
     if (!$this->alreadyInSave) {
         $this->alreadyInSave = true;
         // We call the save method on the following object(s) if they
         // were passed to this object by their coresponding set
         // method.  This object relates to these object(s) by a
         // foreign key reference.
         if ($this->aPcUser !== null) {
             if ($this->aPcUser->isModified() || $this->aPcUser->isNew()) {
                 $affectedRows += $this->aPcUser->save($con);
             }
             $this->setPcUser($this->aPcUser);
         }
         if ($this->isNew()) {
             $this->modifiedColumns[] = PcBlogPostPeer::ID;
         }
         // If this object has been modified, then save it to the database.
         if ($this->isModified()) {
             if ($this->isNew()) {
                 $pk = PcBlogPostPeer::doInsert($this, $con);
                 $affectedRows += 1;
                 // we are assuming that there is only 1 row per doInsert() which
                 // should always be true here (even though technically
                 // BasePeer::doInsert() can insert multiple rows).
                 $this->setId($pk);
                 //[IMV] update autoincrement primary key
                 $this->setNew(false);
             } else {
                 $affectedRows += PcBlogPostPeer::doUpdate($this, $con);
             }
             $this->resetModified();
             // [HL] After being saved an object is no longer 'modified'
         }
         if ($this->collPcBlogCategoriesPostss !== null) {
             foreach ($this->collPcBlogCategoriesPostss as $referrerFK) {
                 if (!$referrerFK->isDeleted()) {
                     $affectedRows += $referrerFK->save($con);
                 }
             }
         }
         if ($this->collPcBlogComments !== null) {
             foreach ($this->collPcBlogComments as $referrerFK) {
                 if (!$referrerFK->isDeleted()) {
                     $affectedRows += $referrerFK->save($con);
                 }
             }
         }
         $this->alreadyInSave = false;
     }
     return $affectedRows;
 }
 /**
  * Register a new user
  *
  * @param string $email - the email address
  * @param string $password - the plain password (no encryption)
  * @param string $lang - if it is null or empty, the language will be detected from the header of the request
  * @param string $preferredLang - this should be a 2-char abbreviation of the lang the user wants,
  *         among the ones in the main app.yml config file
  * @param string $tzLabel - a timezone label as in the PcTimezone db table
  * @param integer $dstOn (1 or 0) - whether or not the dst for the user is on
  * @param boolen $joinNewsletter(=false) - whether the user decided to join our newsletter
  * @param boolen $sendActivationEmail(=true) - whether to send the activation email  
  * @return boolean|PcUser false is a user with that email already exists, the PcUser object otherwise
  */
 public static function registerNewUser($email, $password, $lang, $preferredLang, $tzLabel, $dstOn, $joinNewsletter = false, $sendActivationEmail = true)
 {
     if (self::emailExist($email)) {
         return false;
     }
     $newUser = new PcUser();
     $newUser->setEmail($email);
     $newUser->setPassword($password);
     $newUser->setAwaitingActivation(1);
     if ($joinNewsletter) {
         $newUser->setNewsletter(1);
     }
     $newUser->save();
     // Dealing with timezone
     $newUser->setDstActive($dstOn);
     $c = new Criteria();
     $c->add(PcTimezonePeer::LABEL, $tzLabel, Criteria::EQUAL);
     $timezone = PcTimezonePeer::doSelectOne($c);
     if (!is_object($timezone)) {
         // set to a default one
         $timezone = PcTimezonePeer::retrieveByPK(21);
     }
     $newUser->setTimezoneId($timezone->getId());
     // Dealing with formats
     // _ time format: the countries with the majority of our users are using the
     //   12H format, thus we can leave the default
     // _ for the date format we check whether they are in USA
     // _ for the first day of the week, we check whether they are in USA
     $dateFormatId = 3;
     $weekStart = 1;
     // from Monday
     $tzOffset = $timezone->getOffset();
     if ($tzOffset <= -300 && $tzOffset >= -450) {
         $dateFormatId = 4;
         $weekStart = 0;
         // from Sunday
     }
     $newUser->setDateFormat($dateFormatId);
     $newUser->setWeekStart($weekStart);
     if ($lang != null && $lang !== '') {
         $newUser->setLanguage($lang);
     } else {
         $newUser->setLanguage(PcUtils::getVisitorAcceptLanguage());
     }
     $availableLangs = PcLanguagePeer::getAvailableLanguageAbbreviations();
     if (in_array($preferredLang, $availableLangs)) {
         $newUser->setPreferredLanguage($preferredLang);
     } else {
         $newUser->setPreferredLanguage(SfConfig::get('app_site_defaultLang'));
     }
     $newUser->setIpAddress(PcUtils::getVisitorIPAddress());
     if ($sessionEntryPoint = sfContext::getInstance()->getUser()->getAttribute('session_entry_point')) {
         $newUser->setSessionEntryPoint($sessionEntryPoint);
     }
     if ($sessionReferral = sfContext::getInstance()->getUser()->getAttribute('session_referral')) {
         $newUser->setSessionReferral($sessionReferral);
     }
     $newUser->save();
     // Creating system lists
     $inboxList = new PcList();
     $inboxList->setIsInbox(1)->setTitle(__('ACCOUNT_LISTS_INBOX'))->setCreator($newUser)->save();
     $todoList = new PcList();
     $todoList->setIsTodo(1)->setTitle(__('ACCOUNT_LISTS_TODO'))->setCreator($newUser)->save();
     // Creating default contexts
     $context = new PcUsersContexts();
     $context->setPcUser($newUser)->setContext(__('ACCOUNT_TAGS_DEFAULT_HOME'))->save();
     $context = new PcUsersContexts();
     $context->setPcUser($newUser)->setContext(__('ACCOUNT_TAGS_DEFAULT_ERRANDS'))->save();
     $context = new PcUsersContexts();
     $context->setPcUser($newUser)->setContext(__('ACCOUNT_TAGS_DEFAULT_COMPUTER'))->save();
     // Creating some tasks for the inbox
     $newUser->addToInbox(__('ACCOUNT_MISC_WELCOME_TASK'));
     // creating Plancake email address
     $newUser->generateAndStorePlancakeEmailAddress();
     // I need to use a token for the activation of their account
     $token = '';
     $c = new Criteria();
     $c->add(PcActivationTokenPeer::USER_ID, $newUser->getId(), Criteria::EQUAL);
     $tokenEntry = PcActivationTokenPeer::doSelectOne($c);
     if (is_object($tokenEntry)) {
         $token = $tokenEntry->getToken();
     } else {
         $secret = sfConfig::get('app_registration_secret');
         // token doesn't need to be 32-char long. It is better to keep it short
         // so there will be less chance the email client will break the link into 2 lines
         $token = substr(md5($newUser->getId() . $secret . time()), 0, 14);
         $tokenEntry = new PcActivationToken();
         $tokenEntry->setUserId($newUser->getId());
         $tokenEntry->setToken($token);
         $tokenEntry->save();
     }
     // now we can send the email
     if ($sendActivationEmail) {
         $link = sfContext::getInstance()->getController()->genUrl('@activation?t=' . $token, true);
         $from = sfConfig::get('app_emailAddress_contact');
         $subject = 'Plancake - ' . __('WEBSITE_REGISTRATION_EMAIL_SUBJECT');
         $body = sprintf(__('WEBSITE_REGISTRATION_EMAIL_BODY'), $link);
         PcUtils::sendEmail($email, $subject, $body, $from);
     }
     $newUser->refreshLatestBlogAccess();
     sfContext::getInstance()->getEventDispatcher()->notify(new sfEvent($newUser, 'user.sign_up', array('user' => $newUser, 'plainPassword' => $password)));
     return $newUser;
 }