      1: <?php
      2:
      3: /**
      4:  *
      5:  * The main person/user class for the site
      6:  *
      7:  * @package alpha::model
      8:  * @since 1.0
      9:  * @author John Collins <dev@alphaframework.org>
     10:  * @version $Id: PersonObject.inc 1548 2012-07-29 17:07:07Z alphadevx $
     11:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
     12:  * @copyright Copyright (c) 2012, John Collins (founder of Alpha Framework).
     13:  * All rights reserved.
     14:  *
     15:  * <pre>
     16:  * Redistribution and use in source and binary forms, with or
     17:  * without modification, are permitted provided that the
     18:  * following conditions are met:
     19:  *
     20:  * * Redistributions of source code must retain the above
     21:  *   copyright notice, this list of conditions and the
     22:  *   following disclaimer.
     23:  * * Redistributions in binary form must reproduce the above
     24:  *   copyright notice, this list of conditions and the
     25:  *   following disclaimer in the documentation and/or other
     26:  *   materials provided with the distribution.
     27:  * * Neither the name of the Alpha Framework nor the names
     28:  *   of its contributors may be used to endorse or promote
     29:  *   products derived from this software without specific
     30:  *   prior written permission.
     31:  *
     32:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     33:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     34:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     35:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     36:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     37:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     38:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     39:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     40:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     41:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     42:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     43:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     44:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     45:  * </pre>
     46:  *
     47:  */
     48: class PersonObject extends AlphaDAO {
     49:     /**
     50:      * The forum display name of the person
     51:      *
     52:      * @var String
     53:      * @since 1.0
     54:      */
     55:     protected $displayName;
     56:
     57:     /**
     58:      * The email address for the person
     59:      *
     60:      * @var String
     61:      * @since 1.0
     62:      */
     63:     protected $email;
     64:
     65:     /**
     66:      * The password for the person
     67:      *
     68:      * @var String
     69:      * @since 1.0
     70:      */
     71:     protected $password;
     72:
     73:     /**
     74:      * A Relation containing all of the rights groups that this person belongs to
     75:      *
     76:      * @var Relation
     77:      * @since 1.0
     78:      */
     79:     protected $rights;
     80:
     81:     /**
     82:      * An array of data display labels for the class properties
     83:      *
     84:      * @var array
     85:      * @since 1.0
     86:      */
     87:     protected $dataLabels = array("OID"=>"Member ID#",
     88:                                     "displayName"=>"Display Name",
     89:                                     "email"=>"E-mail Address",
     90:                                     "password"=>"Password",
     91:                                     "state"=>"Account state",
     92:                                     "URL"=>"Your site address",
     93:                                     "rights"=>"Rights Group Membership");
     94:
     95:     /**
     96:      * The name of the database table for the class
     97:      *
     98:      * @var string
     99:      * @since 1.0
    100:      */
    101:     const TABLE_NAME = 'Person';
    102:
    103:     /**
    104:      * The state of the person (account status)
    105:      *
    106:      * @var Enum
    107:      * @since 1.0
    108:      */
    109:     protected $state;
    110:
    111:     /**
    112:      * The website URL of the person
    113:      *
    114:      * @var String
    115:      * @since 1.0
    116:      */
    117:     protected $URL;
    118:
    119:     /**
    120:      * Trace logger
    121:      *
    122:      * @var Logger
    123:      * @since 1.0
    124:      */
    125:     private static $logger = null;
    126:
    127:     /**
    128:      * Constructor for the class that populates all of the complex types with default values
    129:      *
    130:      * @since 1.0
    131:      */
    132:     public function __construct() {
    133:         self::$logger = new Logger('PersonObject');
    134:         self::$logger->debug('>>__construct()');
    135:
    136:         // ensure to call the parent constructor
    137:         parent::__construct();
    138:         $this->displayName = new String();
    139:         $this->displayName->setRule(AlphaValidator::REQUIRED_USERNAME);
    140:         $this->displayName->setSize(70);
    141:         $this->displayName->setHelper('Please provide a name for display on the website (only letters, numbers, and .-_ characters are allowed!).');
    142:         $this->email = new String();
    143:         $this->email->setRule(AlphaValidator::REQUIRED_EMAIL);
    144:         $this->email->setSize(70);
    145:         $this->email->setHelper('Please provide a valid e-mail address as your username.');
    146:         $this->password = new String();
    147:         $this->password->setSize(70);
    148:         $this->password->setHelper('Please provide a password for logging in.');
    149:         $this->password->isPassword(true);
    150:         $this->state = new Enum(array(
    151:                                     'Active',
    152:                                     'Disabled'));
    153:         $this->state->setValue('Active');
    154:         $this->URL = new String();
    155:         $this->URL->setRule(AlphaValidator::OPTIONAL_HTTP_URL);
    156:         $this->URL->setHelper('URLs must be in the format http://some_domain/ or left blank!');
    157:         // add unique keys to displayName and email (which is effectively the username in Alpha)
    158:         $this->markUnique('displayName');
    159:         $this->markUnique('email');
    160:
    161:         $this->rights = new Relation();
    162:         $this->markTransient('rights');
    163:         $this->setupRels();
    164:
    165:         self::$logger->debug('<<__construct');
    166:     }
    167:
    168:     /**
    169:      * Set up the transient attributes for the rights group after it has loaded
    170:      *
    171:      * @since 1.0
    172:      */
    173:     protected function after_load_callback() {
    174:         $this->setupRels();
    175:     }
    176:
    177:     /**
    178:      * Set up the transient attributes for the site after it has loaded
    179:      *
    180:      * @since 1.0
    181:      */
    182:     protected function after_loadByAttribute_callback() {
    183:         $this->setupRels();
    184:     }
    185:
    186:     /**
    187:      * Looks up the OID for the Standard rights group, then relates the new person
    188:      * to that group if they are not in it already.  If that group does not exist it
    189:      * will be recreated!
    190:      *
    191:      * @since 1.0
    192:      */
    193:     protected function after_save_callback() {
    194:         if($this->getVersionNumber()->getValue() == 1) {
    195:             $standardGroup = new RightsObject();
    196:
    197:             $this->setupRels();
    198:
    199:             if(!$this->inGroup('Standard')) {
    200:                 try {
    201:                     $standardGroup->loadByAttribute('name', 'Standard');
    202:                 }catch (BONotFoundException $e) {
    203:                     $standardGroup->set('name', 'Standard');
    204:                     $standardGroup->save();
    205:                 }
    206:
    207:                 $lookup = $this->rights->getLookup();
    208:                 $lookup->setValue(array($this->getID(), $standardGroup->getID()));
    209:                 $lookup->save();
    210:             }
    211:         }
    212:     }
    213:
    214:     /**
    215:      * Encrypts any fields called 'password' posted for the PersonObject
    216:      *
    217:      * @since 1.0
    218:      */
    219:     protected function before_populateFromPost_callback() {
    220:         if(isset($_POST['password']) && preg_match(AlphaValidator::REQUIRED_STRING, $_POST['password']))
    221:             $_POST['password'] = crypt($_POST['password']);
    222:     }
    223:
    224:     /**
    225:      * Sets up the Relation definitions on this BO
    226:      *
    227:      * @since 1.0
    228:      */
    229:     protected function setupRels() {
    230:         // set up MANY-TO-MANY relation person2rights
    231:         if(isset($this->rights)) {
    232:             $this->rights->setRelatedClass('PersonObject', 'left');
    233:             $this->rights->setRelatedClassDisplayField('email', 'left');
    234:             $this->rights->setRelatedClass('RightsObject', 'right');
    235:             $this->rights->setRelatedClassDisplayField('name', 'right');
    236:             $this->rights->setRelationType('MANY-TO-MANY');
    237:             $this->rights->setValue($this->getID());
    238:         }
    239:     }
    240:
    241:     /**
    242:      * Setter for displayName
    243:      *
    244:      * @param string $displayName
    245:      * @since 1.0
    246:      */
    247:     public function setDisplayName($displayName) {
    248:         $this->displayName->setValue($displayName);
    249:     }
    250:
    251:     /**
    252:      * Getter for displayName
    253:      *
    254:      * @return String
    255:      * @since 1.0
    256:      */
    257:     public function getDisplayName() {
    258:         return $this->displayName;
    259:     }
    260:
    261:     /**
    262:      * Checks to see if the person is in the rights group specified
    263:      *
    264:      * @param string $groupName
    265:      * @return bool
    266:      * @since 1.0
    267:      */
    268:     public function inGroup($groupName) {
    269:         if(self::$logger == null)
    270:             self::$logger = new Logger('PersonObject');
    271:         self::$logger->debug('>>inGroup(groupName=['.$groupName.'])');
    272:
    273:         $group = new RightsObject();
    274:
    275:         try {
    276:             $group->loadByAttribute('name', $groupName);
    277:         }catch (BONotFoundException $e) {
    278:             self::$logger->error('Unable to load the group named ['.$groupName.']');
    279:             self::$logger->debug('<<inGroup [false]');
    280:             return false;
    281:         }
    282:
    283:         $rel = $group->getMembers();
    284:
    285:         try {
    286:             // load all person2rights RelationLookup objects for this person
    287:             $lookUps = $rel->getLookup()->loadAllByAttribute('leftID', $this->getID());
    288:             foreach($lookUps as $lookUp) {
    289:                 // the rightID (i.e. RightsObject OID) will be on the right side of the value array
    290:                 $ids = $lookUp->getValue();
    291:                 // if we have found a match, return true right away
    292:                 if($ids[1] == $group->getID()) {
    293:                     self::$logger->debug('<<inGroup [true]');
    294:                     return true;
    295:                 }
    296:             }
    297:         }catch (BONotFoundException $e) {
    298:             self::$logger->debug('<<inGroup [false]');
    299:             return false;
    300:         }
    301:
    302:         self::$logger->debug('<<inGroup [false]');
    303:         return false;
    304:     }
    305:
    306:     /**
    307:      * A generic method for mailing a person
    308:      *
    309:      * @param string $message
    310:      * @param string $subject
    311:      * @since 1.0
    312:      * @throws MailNotSentException
    313:      */
    314:     public function sendMail($message, $subject) {
    315:         global $config;
    316:
    317:         $body = '<html><head></head><body><p>Dear '.$this->getDisplayName().',</p>';
    318:
    319:         $body .= $message;
    320:
    321:         $body .= '</body></html>';
    322:
    323:         $headers = 'MIME-Version: 1.0'."\n";
    324:         $headers .= 'Content-type: text/html; charset=iso-8859-1'."\n";
    325:         $headers .= "From: ".$config->get('email.reply.to')."\n";
    326:
    327:         try {
    328:             mail($this->get('email'), $subject, $body, $headers);
    329:         }catch (PHPException $e) {
    330:             throw new MailNotSentException('Error sending a mail to ['.$this->get('email').']');
    331:         }
    332:     }
    333:
    334:     /**
    335:      * Generates a random password for the user
    336:      *
    337:      * @return string
    338:      * @since 1.0
    339:      */
    340:     public function generatePassword() {
    341:         $alphabet = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
    342:         // the password will be 7 random characters and 2 numbers
    343:         $newPassword = '';
    344:         for ($i = 0; $i < 7; $i++) {
    345:             $newPassword.= $alphabet[rand(0,25)];
    346:         }
    347:         $newPassword.= rand(0,100);
    348:         $newPassword.= rand(0,100);
    349:
    350:         return $newPassword;
    351:     }
    352:
    353:     /**
    354:      * Method for getting a count of the amount of article comments posted by the user
    355:      *
    356:      * @return integer
    357:      * @since 1.0
    358:      * @throws AlphaException
    359:      */
    360:     public function getCommentCount() {
    361:         $temp = new ArticleCommentObject();
    362:
    363:         $sqlQuery = "SELECT COUNT(OID) AS post_count FROM ".$temp->getTableName()." WHERE created_by='".$this->OID."';";
    364:
    365:         $result = $this->query($sqlQuery);
    366:
    367:         if(!isset($result[0])) {
    368:             throw new AlphaException('Failed to get the count of the comments posted for the person ['.$this->getDisplayName().'], query is ['.$sqlQuery.']');
    369:             return 0;
    370:         }
    371:
    372:         $row = $result[0];
    373:
    374:         if(isset($row['post_count']))
    375:             return $row['post_count'];
    376:         else
    377:             return 0;
    378:     }
    379: }
    380:
    381: ?>