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: ?>