1: <?php
2:
3: namespace Alpha\Model;
4:
5: use Alpha\Model\Type\String;
6: use Alpha\Model\Type\DEnum;
7: use Alpha\Model\Type\Text;
8: use Alpha\Model\Type\Boolean;
9: use Alpha\Model\Type\Relation;
10: use Alpha\Util\Logging\Logger;
11: use Alpha\Util\Config\Configprovider;
12: use Alpha\Util\Http\Session\SessionProviderFactory;
13: use Alpha\Exception\ValidationException;
14: use Alpha\Exception\FileNotFoundException;
15: use Alpha\Exception\AlphaException;
16: use Alpha\Controller\Front\FrontController;
17:
18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59:
60: class Article extends ActiveRecord
61: {
62: 63: 64: 65: 66: 67: 68:
69: protected $title;
70:
71: 72: 73: 74: 75: 76: 77:
78: protected $section;
79:
80: 81: 82: 83: 84: 85: 86:
87: protected $description;
88:
89: 90: 91: 92: 93: 94: 95:
96: protected $bodyOnload;
97:
98: 99: 100: 101: 102: 103: 104:
105: protected ;
106:
107: 108: 109: 110: 111: 112: 113:
114: protected $content;
115:
116: 117: 118: 119: 120: 121: 122:
123: protected $author;
124:
125: 126: 127: 128: 129: 130: 131:
132: protected $published;
133:
134: 135: 136: 137: 138: 139: 140:
141: protected ;
142:
143: 144: 145: 146: 147: 148: 149:
150: protected $votes;
151:
152: 153: 154: 155: 156: 157: 158:
159: protected $tags;
160:
161: 162: 163: 164: 165: 166: 167:
168: protected $taggedAttributes = array('title', 'description', 'content');
169:
170: 171: 172: 173: 174: 175: 176:
177: private $filePath;
178:
179: 180: 181: 182: 183: 184: 185:
186: protected $dataLabels = array('OID' => 'Article ID#', 'title' => 'Title', 'section' => 'Site Section', 'description' => 'Description', 'bodyOnload' => 'Body onload Javascript', 'content' => 'Content', 'headerContent' => 'HTML Header Content', 'author' => 'Author', 'created_ts' => 'Date Added', 'updated_ts' => 'Date of last Update', 'published' => 'Published', 'URL' => 'URL', 'printURL' => 'Printer version URL', 'comments' => 'Comments', 'votes' => 'Votes', 'tags' => 'Tags');
187:
188: 189: 190: 191: 192: 193: 194:
195: const TABLE_NAME = 'Article';
196:
197: 198: 199: 200: 201: 202: 203:
204: protected $URL;
205:
206: 207: 208: 209: 210: 211: 212:
213: protected $printURL;
214:
215: 216: 217: 218: 219: 220: 221:
222: private static $logger = null;
223:
224: 225: 226: 227: 228:
229: public function __construct()
230: {
231: self::$logger = new Logger('Article');
232:
233:
234: parent::__construct();
235:
236: $this->title = new String();
237: $this->title->setHelper('Please provide a title for the article.');
238: $this->title->setSize(100);
239: $this->title->setRule("/\w+/");
240:
241: $this->section = new DEnum('Alpha\Model\Article::section');
242:
243: $this->description = new String();
244: $this->description->setHelper('Please provide a brief description of the article.');
245: $this->description->setSize(200);
246: $this->description->setRule("/\w+/");
247: $this->bodyOnload = new String();
248: $this->content = new Text();
249: $this->headerContent = new Text();
250: $this->author = new String();
251: $this->author->setHelper('Please state the name of the author of this article');
252: $this->author->setSize(70);
253: $this->author->setRule("/\w+/");
254: $this->published = new Boolean(0);
255:
256: $this->comments = new Relation();
257: $this->markTransient('comments');
258:
259: $this->votes = new Relation();
260: $this->markTransient('votes');
261:
262: $this->tags = new Relation();
263: $this->markTransient('tags');
264:
265: $this->URL = '';
266: $this->printURL = '';
267:
268: $this->markTransient('URL');
269: $this->markTransient('printURL');
270:
271:
272: $this->markUnique('title');
273:
274: $this->markTransient('filePath');
275: $this->markTransient('taggedAttributes');
276:
277: $this->setupRels();
278: }
279:
280: 281: 282: 283: 284: 285:
286: protected function after_save_callback()
287: {
288: if ($this->getVersion() == 1 && $this->tags instanceof \Alpha\Model\Type\Relation) {
289:
290: $this->tags->setValue($this->OID);
291:
292: foreach ($this->taggedAttributes as $tagged) {
293: $tags = Tag::tokenize($this->get($tagged), 'Alpha\Model\Article', $this->getOID());
294: foreach ($tags as $tag) {
295: try {
296: $tag->save();
297: } catch (ValidationException $e) {
298: 299: 300: 301:
302: }
303: }
304: }
305: }
306:
307: $this->setupRels();
308: }
309:
310: 311: 312: 313: 314:
315: protected function after_loadByAttribute_callback()
316: {
317: $this->after_load_callback();
318: }
319:
320: 321: 322: 323: 324:
325: protected function after_load_callback()
326: {
327: $config = ConfigProvider::getInstance();
328:
329: $this->URL = $config->get('app.url').'/a/'.str_replace(' ', $config->get('cms.url.title.separator'), $this->title->getValue());
330:
331: $this->printURL = $config->get('app.url').'/a/'.str_replace(' ', $config->get('cms.url.title.separator'), $this->title->getValue()).'/print';
332:
333: $this->setupRels();
334: }
335:
336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348:
349: public function loadRecentWithLimit($limit, $excludeID = '')
350: {
351: if ($excludeID != '') {
352: $denum = new DEnum('Alpha\Model\Article::section');
353: $excludeID = $denum->getOptionID($excludeID);
354: }
355:
356: $sqlQuery = 'SELECT OID FROM '.$this->getTableName()." WHERE published='1' AND section!='$excludeID' ORDER BY created_ts DESC LIMIT 0, $limit;";
357:
358: $result = $this->query($sqlQuery);
359:
360: $OIDs = array();
361:
362: foreach ($result as $row) {
363: array_push($OIDs, $row['OID']);
364: }
365:
366: return $OIDs;
367: }
368:
369: 370: 371: 372: 373: 374: 375:
376: public function getAttachmentsLocation()
377: {
378: $config = ConfigProvider::getInstance();
379:
380: return $config->get('app.file.store.dir').'attachments/article_'.$this->getID();
381: }
382:
383: 384: 385: 386: 387: 388: 389:
390: public function getAttachmentsURL()
391: {
392: $config = ConfigProvider::getInstance();
393:
394: return $config->get('app.url').'/attachments/article_'.$this->getID();
395: }
396:
397: 398: 399: 400: 401: 402: 403:
404: public function getAttachmentSecureURL($filename)
405: {
406: $config = ConfigProvider::getInstance();
407:
408: return FrontController::generateSecureURL('act=Alpha\\Controller\\AttachmentController&articleOID='.$this->getOID().'&filename='.$filename);
409: }
410:
411: 412: 413: 414: 415: 416: 417:
418: public function createAttachmentsFolder()
419: {
420:
421: try {
422: mkdir($this->getAttachmentsLocation());
423: } catch (\Exception $e) {
424: throw new AlphaException('Unable to create the folder ['.$this->getAttachmentsLocation().'] for the article.');
425: }
426:
427:
428: try {
429: chmod($this->getAttachmentsLocation(), 0777);
430: } catch (\Exception $e) {
431: throw new AlphaException('Unable to set write permissions on the folder ['.$this->getAttachmentsLocation().'].');
432: }
433: }
434:
435: 436: 437: 438: 439: 440: 441:
442: public function getArticleScore()
443: {
444: $votes = $this->getArticleVotes();
445:
446: $score = 0;
447: $total_score = 0;
448: $vote_count = count($votes);
449:
450: for ($i = 0; $i < $vote_count; ++$i) {
451: $total_score += $votes[$i]->get('score');
452: }
453:
454: if ($vote_count > 0) {
455: $score = $total_score / $vote_count;
456: }
457:
458: return sprintf('%01.2f', $score);
459: }
460:
461: 462: 463: 464: 465: 466: 467:
468: public function getArticleVotes()
469: {
470: $votes = $this->votes->getRelatedObjects();
471:
472: return $votes;
473: }
474:
475: 476: 477: 478: 479: 480: 481: 482: 483:
484: public function checkUserVoted()
485: {
486: $config = ConfigProvider::getInstance();
487: $sessionProvider = $config->get('session.provider.name');
488: $session = SessionProviderFactory::getInstance($sessionProvider);
489:
490: if ($session->get('currentUser') == null) {
491: return true;
492: }
493:
494: $userID = $session->get('currentUser')->getID();
495:
496: $vote = new ArticleVote();
497:
498: $sqlQuery = 'SELECT COUNT(*) AS usersVote FROM '.$vote->getTableName()." WHERE articleOID='".$this->OID."' AND personOID='".$userID."';";
499:
500: $result = $this->query($sqlQuery);
501:
502: if (!isset($result[0])) {
503: throw new AlphaException('Failed to check if the current user voted for the article ['.$this->OID.'], query ['.$sqlQuery.']');
504:
505: return false;
506: }
507:
508: $row = $result[0];
509:
510: if ($row['usersVote'] == '0') {
511: return false;
512: } else {
513: return true;
514: }
515: }
516:
517: 518: 519: 520: 521: 522: 523:
524: public function getArticleComments()
525: {
526: $comments = $this->comments->getRelatedObjects();
527:
528: return $comments;
529: }
530:
531: 532: 533: 534: 535: 536: 537: 538: 539:
540: public function loadContentFromFile($filePath)
541: {
542: try {
543: $this->content->setValue(file_get_contents($filePath));
544: $this->filePath = $filePath;
545: } catch (\Exception $e) {
546: throw new FileNotFoundException($e->getMessage());
547: }
548: }
549:
550: 551: 552: 553: 554: 555: 556:
557: public function isLoadedFromFile()
558: {
559: return $this->filePath == '' ? false : true;
560: }
561:
562: 563: 564: 565: 566: 567: 568: 569: 570: 571:
572: public function getContentFileDate()
573: {
574: if ($this->filePath != '') {
575: try {
576: return date('Y-m-d H:i:s', filemtime($this->filePath));
577: } catch (\Exception $e) {
578: throw new FileNotFoundException($e->getMessage());
579: }
580: } else {
581: throw new FileNotFoundException('Error trying to access an article content file when none is set!');
582: }
583: }
584:
585: 586: 587: 588: 589:
590: protected function setupRels()
591: {
592: $this->comments->setValue($this->OID);
593: $this->comments->setRelatedClass('Alpha\Model\ArticleComment');
594: $this->comments->setRelatedClassField('articleOID');
595: $this->comments->setRelatedClassDisplayField('content');
596: $this->comments->setRelationType('ONE-TO-MANY');
597:
598: $this->votes->setValue($this->OID);
599: $this->votes->setRelatedClass('Alpha\Model\ArticleVote');
600: $this->votes->setRelatedClassField('articleOID');
601: $this->votes->setRelatedClassDisplayField('score');
602: $this->votes->setRelationType('ONE-TO-MANY');
603:
604: $this->tags->setRelatedClass('Alpha\Model\Tag');
605: $this->tags->setRelatedClassField('taggedOID');
606: $this->tags->setRelatedClassDisplayField('content');
607: $this->tags->setRelationType('ONE-TO-MANY');
608: $this->tags->setTaggedClass(get_class($this));
609: $this->tags->setValue($this->OID);
610: }
611: }
612: