/**
  * N.B.: if the user passed as input is a supporter, the method prefix '1'
  * to the token, making it 41-character long, rather than 40
  *
  * @param PcApiApp $apiApp
  * @param int $userId
  * @return string
  */
 public static function createToken(PcApiApp $apiApp, $userId)
 {
     $apiAppId = $apiApp->getId();
     // if there is already a token entry for the application and the user, we delete it
     $c = new Criteria();
     $c->add(PcApiTokenPeer::API_APP_ID, $apiAppId);
     $c->add(PcApiTokenPeer::USER_ID, $userId);
     PcApiTokenPeer::doDelete($c);
     $apiTokenEntry = new PcApiToken();
     $tokenPrefix = PcUserPeer::retrieveByPK($userId)->isSupporter() ? '1' : '';
     // we want to be extra-sure the token is unique
     $token = '';
     $safetyCounter = 0;
     // to avoid infinite loop under any circumstances
     do {
         $token = $tokenPrefix . PcUtils::generate40CharacterRandomHash();
         $c = new Criteria();
         $c->add(PcApiTokenPeer::TOKEN, $token);
         $alreadyExisting = PcApiTokenPeer::doSelectOne($c);
         $safetyCounter++;
         if ($safetyCounter == 100) {
             throw new Exception("Detected possible infinite loop while creating API token");
         }
     } while (is_object($alreadyExisting));
     $apiTokenEntry->setToken($token)->setApiAppId($apiAppId)->setUserId($userId)->setExpiryTimestamp(time() + sfConfig::get('app_api_tokenValidity') * 3600)->save();
     return $token;
 }
 /**
  * Removes this object from datastore and sets delete attribute.
  *
  * @param      PropelPDO $con
  * @return     void
  * @throws     PropelException
  * @see        BaseObject::setDeleted()
  * @see        BaseObject::isDeleted()
  */
 public function delete(PropelPDO $con = null)
 {
     if ($this->isDeleted()) {
         throw new PropelException("This object has already been deleted.");
     }
     if ($con === null) {
         $con = Propel::getConnection(PcApiTokenPeer::DATABASE_NAME, Propel::CONNECTION_WRITE);
     }
     $con->beginTransaction();
     try {
         $ret = $this->preDelete($con);
         // symfony_behaviors behavior
         foreach (sfMixer::getCallables('BasePcApiToken:delete:pre') as $callable) {
             if (call_user_func($callable, $this, $con)) {
                 $con->commit();
                 return;
             }
         }
         if ($ret) {
             PcApiTokenPeer::doDelete($this, $con);
             $this->postDelete($con);
             // symfony_behaviors behavior
             foreach (sfMixer::getCallables('BasePcApiToken:delete:post') as $callable) {
                 call_user_func($callable, $this, $con);
             }
             $this->setDeleted(true);
             $con->commit();
         } else {
             $con->commit();
         }
     } catch (PropelException $e) {
         $con->rollBack();
         throw $e;
     }
 }