1: <?php
2:
3: namespace Alpha\Controller;
4:
5: use Alpha\Model\Type\Timestamp;
6: use Alpha\Model\Type\Integer;
7: use Alpha\Model\ActiveRecord;
8: use Alpha\Util\Config\ConfigProvider;
9: use Alpha\Util\Security\SecurityUtils;
10: use Alpha\Util\Helper\Validator;
11: use Alpha\Util\Http\Session\SessionProviderFactory;
12: use Alpha\Util\Http\Request;
13: use Alpha\Util\Http\Response;
14: use Alpha\Util\Logging\Logger;
15: use Alpha\Exception\IllegalArguementException;
16: use Alpha\Exception\FailedUnitCommitException;
17: use Alpha\Exception\FailedSaveException;
18: use Alpha\Exception\LockingException;
19: use Alpha\Exception\AlphaException;
20: use Alpha\Exception\NotImplementedException;
21: use Alpha\View\View;
22: use Alpha\View\ViewState;
23: use ReflectionClass;
24: use Exception;
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: 61: 62: 63: 64: 65: 66: 67:
68: abstract class Controller
69: {
70: 71: 72: 73: 74: 75: 76:
77: protected $name;
78:
79: 80: 81: 82: 83: 84: 85: 86:
87: protected $visibility = 'Public';
88:
89: 90: 91: 92: 93: 94: 95:
96: protected $record = null;
97:
98: 99: 100: 101: 102: 103: 104: 105:
106: protected $unitOfWork;
107:
108: 109: 110: 111: 112: 113: 114:
115: protected $unitStartTime;
116:
117: 118: 119: 120: 121: 122: 123:
124: protected $unitEndTime;
125:
126: 127: 128: 129: 130: 131: 132:
133: protected $unitMAXDuration;
134:
135: 136: 137: 138: 139: 140: 141:
142: protected $firstJob;
143:
144: 145: 146: 147: 148: 149: 150:
151: protected $nextJob;
152:
153: 154: 155: 156: 157: 158: 159:
160: protected $previousJob;
161:
162: 163: 164: 165: 166: 167: 168:
169: protected $lastJob;
170:
171: 172: 173: 174: 175: 176: 177: 178:
179: protected $dirtyObjects = array();
180:
181: 182: 183: 184: 185: 186: 187: 188:
189: protected $newObjects = array();
190:
191: 192: 193: 194: 195: 196: 197:
198: protected $title;
199:
200: 201: 202: 203: 204: 205: 206:
207: protected $keywords;
208:
209: 210: 211: 212: 213: 214: 215:
216: protected $description;
217:
218: 219: 220: 221: 222: 223: 224: 225: 226:
227: protected $statusMessage;
228:
229: 230: 231: 232: 233: 234: 235:
236: protected $request;
237:
238: 239: 240: 241: 242: 243: 244:
245: private static $logger = null;
246:
247: 248: 249: 250: 251: 252: 253: 254: 255:
256: public function __construct($visibility = 'Public')
257: {
258: self::$logger = new Logger('Controller');
259: self::$logger->debug('>>__construct(visibility=['.$visibility.'])');
260:
261: $config = ConfigProvider::getInstance();
262:
263:
264: $this->visibility = $visibility;
265:
266: $this->unitStartTime = new Timestamp(date('Y-m-d H:i:s'));
267: $this->unitEndTime = new Timestamp();
268: $this->unitMAXDuration = new Integer();
269:
270:
271: if ($this->name == '') {
272: $this->setName(get_class($this));
273: }
274:
275: $sessionProvider = $config->get('session.provider.name');
276: $session = SessionProviderFactory::getInstance($sessionProvider);
277:
278: if ($session->get('unitOfWork') !== false && is_array($session->get('unitOfWork'))) {
279: $this->setUnitOfWork($session->get('unitOfWork'));
280: }
281:
282: if ($session->get('dirtyObjects') !== false && is_array($session->get('dirtyObjects'))) {
283: $this->dirtyObjects = $session->get('dirtyObjects');
284: }
285:
286: if ($session->get('newObjects') && is_array($session->get('newObjects'))) {
287: $this->newObjects = $session->get('newObjects');
288: }
289:
290: if ($session->get('statusMessage') !== false) {
291: $this->setStatusMessage($session->get('statusMessage'));
292: }
293:
294: self::$logger->debug('<<__construct');
295: }
296:
297: 298: 299: 300: 301: 302: 303:
304: public function getRecord()
305: {
306: self::$logger->debug('>>getRecord()');
307: self::$logger->debug('<<getRecord ['.var_export($this->record, true).']');
308:
309: return $this->record;
310: }
311:
312: 313: 314: 315: 316: 317: 318:
319: public function setRecord($record)
320: {
321: self::$logger->debug('>>setRecord(record=['.var_export($record, true).'])');
322: $this->record = $record;
323:
324:
325: if ($this->record->isTagged()) {
326: $tags = $this->record->getPropObject('tags')->getRelatedObjects();
327:
328: $keywords = '';
329:
330: if (count($tags) > 0) {
331: foreach ($tags as $tag) {
332: $keywords .= ','.$tag->get('content');
333: }
334: }
335:
336: $this->setKeywords(mb_substr($keywords, 1));
337: }
338:
339: self::$logger->debug('<<setRecord');
340: }
341:
342: 343: 344: 345: 346: 347: 348:
349: public function getName()
350: {
351: self::$logger->debug('>>getName()');
352: self::$logger->debug('<<getName ['.$this->name.']');
353:
354: return $this->name;
355: }
356:
357: 358: 359: 360: 361: 362: 363:
364: public function setName($name)
365: {
366: self::$logger->debug('>>setName(name=['.$name.'])');
367: $this->name = $name;
368: self::$logger->debug('<<setName');
369: }
370:
371: 372: 373: 374: 375: 376: 377:
378: public function getVisibility()
379: {
380: self::$logger->debug('>>getVisibility()');
381: self::$logger->debug('<<getVisibility ['.$this->visibility.']');
382:
383: return $this->visibility;
384: }
385:
386: 387: 388: 389: 390: 391: 392:
393: public function setVisibility($visibility)
394: {
395: self::$logger->debug('>>setVisibility(visibility=['.$visibility.'])');
396: $this->visibility = $visibility;
397: self::$logger->debug('<<setVisibility');
398: }
399:
400: 401: 402: 403: 404: 405: 406:
407: public function getFirstJob()
408: {
409: self::$logger->debug('>>getFirstJob()');
410: self::$logger->debug('<<getFirstJob ['.$this->firstJob.']');
411:
412: return $this->firstJob;
413: }
414:
415: 416: 417: 418: 419: 420: 421:
422: public function getNextJob()
423: {
424: self::$logger->debug('>>getNextJob()');
425: self::$logger->debug('<<getNextJob ['.$this->nextJob.']');
426:
427: return $this->nextJob;
428: }
429:
430: 431: 432: 433: 434: 435: 436:
437: public function getPreviousJob()
438: {
439: self::$logger->debug('>>getPreviousJob()');
440: self::$logger->debug('<<getPreviousJob ['.$this->previousJob.']');
441:
442: return $this->previousJob;
443: }
444:
445: 446: 447: 448: 449: 450: 451:
452: public function getLastJob()
453: {
454: self::$logger->debug('>>getLastJob()');
455: self::$logger->debug('<<getLastJob ['.$this->lastJob.']');
456:
457: return $this->lastJob;
458: }
459:
460: 461: 462: 463: 464: 465: 466: 467: 468: 469:
470: public function setUnitOfWork($jobs)
471: {
472: self::$logger->debug('>>setUnitOfWork(jobs=['.var_export($jobs, true).'])');
473:
474: if (method_exists($this, 'before_setUnitOfWork_callback')) {
475: $this->before_setUnitOfWork_callback();
476: }
477:
478: if (!is_array($jobs)) {
479: throw new IllegalArguementException('Bad $jobs array ['.var_export($jobs, true).'] passed to setUnitOfWork method!');
480: self::$logger->debug('<<setUnitOfWork');
481:
482: return;
483: }
484:
485:
486: foreach ($jobs as $job) {
487: if (!Validator::isURL($job) && !class_exists($job)) {
488: throw new IllegalArguementException('The controller name ['.$job.'] provided in the jobs array is not defined anywhere!');
489: }
490: }
491:
492:
493: $config = ConfigProvider::getInstance();
494: $sessionProvider = $config->get('session.provider.name');
495: $session = SessionProviderFactory::getInstance($sessionProvider);
496: $session->delete('unitOfWork');
497: $this->firstJob = null;
498: $this->previousJob = null;
499: $this->nextJob = null;
500: $this->lastJob = null;
501: $this->dirtyObjects = array();
502: $this->newObjects = array();
503:
504: $numOfJobs = count($jobs);
505:
506: for ($i = 0; $i < $numOfJobs; ++$i) {
507:
508: if ($i == 0) {
509: $this->firstJob = $jobs[$i];
510: self::$logger->debug('First job ['.$this->firstJob.']');
511: }
512:
513: if ($this->name == $jobs[$i]) {
514: if (isset($jobs[$i - 1])) {
515:
516: $this->previousJob = $jobs[$i - 1];
517: self::$logger->debug('Previous job ['.$this->previousJob.']');
518: }
519: if (isset($jobs[$i + 1])) {
520:
521: $this->nextJob = $jobs[$i + 1];
522: self::$logger->debug('Next job ['.$this->nextJob.']');
523: }
524: }
525:
526: if ($i == ($numOfJobs - 1)) {
527: $this->lastJob = $jobs[$i];
528: }
529: }
530:
531: if ($this->previousJob == null) {
532: $this->previousJob = $this->firstJob;
533: }
534:
535: if ($this->nextJob == null) {
536: $this->nextJob = $this->lastJob;
537: }
538:
539: $session->set('unitOfWork', $jobs);
540:
541: if (method_exists($this, 'after_setUnitOfWork_callback')) {
542: $this->after_setUnitOfWork_callback();
543: }
544:
545: self::$logger->debug('<<setUnitOfWork');
546: }
547:
548: 549: 550: 551: 552: 553: 554:
555: public function getStartTime()
556: {
557: self::$logger->debug('>>getStartTime()');
558: self::$logger->debug('<<getStartTime ['.$this->unitStartTime.']');
559:
560: return $this->unitStartTime;
561: }
562:
563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574:
575: public function setUnitStartTime($year, $month, $day, $hour, $minute, $second)
576: {
577: self::$logger->debug('>>setUnitStartTime(year=['.$year.'], month=['.$month.'], day=['.$day.'], hour=['.$hour.'], minute=['.$minute.'],
578: second=['.$second.'])');
579:
580: $config = ConfigProvider::getInstance();
581: $sessionProvider = $config->get('session.provider.name');
582: $session = SessionProviderFactory::getInstance($sessionProvider);
583:
584: $this->unitStartTime->setTimestampValue($year, $month, $day, $hour, $minute, $second);
585: $session->set('unitStartTime', $this->unitStartTime->getValue());
586:
587: self::$logger->debug('<<setUnitStartTime');
588: }
589:
590: 591: 592: 593: 594: 595: 596:
597: public function getEndTime()
598: {
599: self::$logger->debug('>>getEndTime()');
600: self::$logger->debug('<<getEndTime ['.$this->unitEndTime.']');
601:
602: return $this->unitEndTime;
603: }
604:
605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616:
617: public function setUnitEndTime($year, $month, $day, $hour, $minute, $second)
618: {
619: self::$logger->debug('>>setUnitEndTime(year=['.$year.'], month=['.$month.'], day=['.$day.'], hour=['.$hour.'], minute=['.$minute.'],
620: second=['.$second.'])');
621:
622: $config = ConfigProvider::getInstance();
623: $sessionProvider = $config->get('session.provider.name');
624: $session = SessionProviderFactory::getInstance($sessionProvider);
625:
626: $this->unitEndTime->setTimestampValue($year, $month, $day, $hour, $minute, $second);
627: $session->set('unitEndTime', $this->unitEndTime->getValue());
628:
629: self::$logger->debug('<<setUnitEndTime');
630: }
631:
632: 633: 634: 635: 636: 637: 638:
639: public function getMAXDuration()
640: {
641: self::$logger->debug('>>getMAXDuration()');
642: self::$logger->debug('<<getMAXDuration ['.$this->unitMAXDuration.']');
643:
644: return $this->unitMAXDuration;
645: }
646:
647: 648: 649: 650: 651: 652: 653:
654: public function setUnitMAXDuration($duration)
655: {
656: self::$logger->debug('>>setUnitMAXDuration(duration=['.$duration.'])');
657: $this->unitMAXDuration->setValue($duration);
658: self::$logger->debug('<<setUnitMAXDuration');
659: }
660:
661: 662: 663: 664: 665: 666: 667:
668: public function getUnitDuration()
669: {
670: self::$logger->debug('>>getUnitDuration()');
671:
672: $intStartTime = mktime(
673: $this->unitStartTime->getHour(),
674: $this->unitStartTime->getMinute(),
675: $this->unitStartTime->getSecond(),
676: $this->unitStartTime->getMonth(),
677: $this->unitStartTime->getDay(),
678: $this->unitStartTime->getYear()
679: );
680:
681: $intEndTime = mktime(
682: $this->unitEndTime->getHour(),
683: $this->unitEndTime->getMinute(),
684: $this->unitEndTime->getSecond(),
685: $this->unitEndTime->getMonth(),
686: $this->unitEndTime->getDay(),
687: $this->unitEndTime->getYear()
688: );
689:
690: self::$logger->debug('<<getUnitDuration ['.$intEndTime - $intStartTime.']');
691:
692: return $intEndTime - $intStartTime;
693: }
694:
695: 696: 697: 698: 699: 700: 701:
702: public function markDirty($object)
703: {
704: self::$logger->debug('>>markDirty(object=['.var_export($object, true).'])');
705:
706: if (method_exists($this, 'before_markDirty_callback')) {
707: $this->before_markDirty_callback();
708: }
709:
710: $this->dirtyObjects[count($this->dirtyObjects)] = $object;
711:
712: $config = ConfigProvider::getInstance();
713: $sessionProvider = $config->get('session.provider.name');
714: $session = SessionProviderFactory::getInstance($sessionProvider);
715:
716: $session->set('dirtyObjects', $this->dirtyObjects);
717:
718: if (method_exists($this, 'after_markDirty_callback')) {
719: $this->after_markDirty_callback();
720: }
721:
722: self::$logger->debug('<<markDirty');
723: }
724:
725: 726: 727: 728: 729: 730: 731:
732: public function getDirtyObjects()
733: {
734: self::$logger->debug('>>getDirtyObjects()');
735: self::$logger->debug('<<getDirtyObjects ['.var_export($this->dirtyObjects, true).']');
736:
737: return $this->dirtyObjects;
738: }
739:
740: 741: 742: 743: 744: 745: 746:
747: public function markNew($object)
748: {
749: self::$logger->debug('>>markNew(object=['.var_export($object, true).'])');
750:
751: if (method_exists($this, 'before_markNew_callback')) {
752: $this->before_markNew_callback();
753: }
754:
755: $this->newObjects[count($this->newObjects)] = $object;
756:
757: $config = ConfigProvider::getInstance();
758: $sessionProvider = $config->get('session.provider.name');
759: $session = SessionProviderFactory::getInstance($sessionProvider);
760:
761: $session->set('newObjects', $this->newObjects);
762:
763: if (method_exists($this, 'after_markNew_callback')) {
764: $this->after_markNew_callback();
765: }
766:
767: self::$logger->debug('<<markNew');
768: }
769:
770: 771: 772: 773: 774: 775: 776:
777: public function getNewObjects()
778: {
779: self::$logger->debug('>>getNewObjects()');
780: self::$logger->debug('<<getNewObjects ['.var_export($this->newObjects, true).']');
781:
782: return $this->newObjects;
783: }
784:
785: 786: 787: 788: 789: 790: 791:
792: public function commit()
793: {
794: self::$logger->debug('>>commit()');
795:
796: if (method_exists($this, 'before_commit_callback')) {
797: $this->before_commit_callback();
798: }
799:
800: ActiveRecord::begin();
801:
802: $newObjects = $this->getNewObjects();
803:
804: $count = count($newObjects);
805:
806: for ($i = 0; $i < $count; ++$i) {
807: try {
808: $newObjects[$i]->save();
809: } catch (FailedSaveException $e) {
810: throw new FailedUnitCommitException($e->getMessage());
811: self::$logger->error('Failed to save new object of type ['.get_class($newObjects[$i]).'], aborting...');
812: $this->abort();
813:
814: return;
815: } catch (LockingException $e) {
816: throw new FailedUnitCommitException($e->getMessage());
817: self::$logger->error('Failed to save new object of type ['.get_class($newObjects[$i]).'], aborting...');
818: $this->abort();
819:
820: return;
821: }
822: }
823:
824: $dirtyObjects = $this->getDirtyObjects();
825:
826: $count = count($dirtyObjects);
827:
828: for ($i = 0; $i < $count; ++$i) {
829: try {
830: $dirtyObjects[$i]->save();
831: } catch (FailedSaveException $e) {
832: throw new FailedUnitCommitException($e->getMessage());
833: self::$logger->error('Failed to save OID ['.$dirtyObjects[$i]->getID().'] of type ['.get_class($dirtyObjects[$i]).'], aborting...');
834: $this->abort();
835:
836: return;
837: } catch (LockingException $e) {
838: throw new FailedUnitCommitException($e->getMessage());
839: self::$logger->error('Failed to save OID ['.$dirtyObjects[$i]->getID().'] of type ['.get_class($dirtyObjects[$i]).'], aborting...');
840: $this->abort();
841:
842: return;
843: }
844: }
845:
846: try {
847: ActiveRecord::commit();
848:
849: $this->clearUnitOfWorkAttributes();
850:
851: if (method_exists($this, 'after_commit_callback')) {
852: $this->after_commit_callback();
853: }
854:
855: self::$logger->debug('<<commit');
856: } catch (FailedSaveException $e) {
857: throw new FailedUnitCommitException('Failed to commit the transaction, error is ['.$e->getMessage().']');
858: self::$logger->debug('<<commit');
859: }
860: }
861:
862: 863: 864: 865: 866: 867: 868:
869: public function abort()
870: {
871: self::$logger->debug('>>abort()');
872:
873: if (method_exists($this, 'before_abort_callback')) {
874: $this->before_abort_callback();
875: }
876:
877: try {
878: ActiveRecord::rollback();
879:
880: $this->clearUnitOfWorkAttributes();
881:
882: if (method_exists($this, 'after_abort_callback')) {
883: $this->after_abort_callback();
884: }
885:
886: self::$logger->debug('<<abort');
887: } catch (AlphaException $e) {
888: throw new AlphaException('Failed to rollback the transaction, error is ['.$e->getMessage().']');
889: self::$logger->debug('<<abort');
890: }
891: }
892:
893: 894: 895: 896: 897:
898: public function clearUnitOfWorkAttributes()
899: {
900: $config = ConfigProvider::getInstance();
901: $sessionProvider = $config->get('session.provider.name');
902: $session = SessionProviderFactory::getInstance($sessionProvider);
903:
904: $session->delete('unitOfWork');
905: $this->unitOfWork = null;
906: $session->delete('dirtyObjects');
907: $this->dirtyObjects = array();
908: $session->delete('newObjects');
909: $this->newObjects = array();
910: }
911:
912: 913: 914: 915: 916: 917: 918:
919: public function getTitle()
920: {
921: self::$logger->debug('>>getTitle()');
922: self::$logger->debug('<<getTitle ['.$this->title.']');
923:
924: return $this->title;
925: }
926:
927: 928: 929: 930: 931: 932: 933:
934: public function setTitle($title)
935: {
936: self::$logger->debug('>>setTitle(title=['.$title.'])');
937: self::$logger->debug('<<setTitle');
938: $this->title = $title;
939: }
940:
941: 942: 943: 944: 945: 946: 947:
948: public function getDescription()
949: {
950: self::$logger->debug('>>getDescription()');
951: self::$logger->debug('<<getDescription ['.$this->description.']');
952:
953: return $this->description;
954: }
955:
956: 957: 958: 959: 960: 961: 962:
963: public function setDescription($description)
964: {
965: self::$logger->debug('>>setDescription(description=['.$description.'])');
966: self::$logger->debug('<<setDescription');
967: $this->description = $description;
968: }
969:
970: 971: 972: 973: 974: 975: 976:
977: public function getKeywords()
978: {
979: self::$logger->debug('>>getKeywords()');
980: self::$logger->debug('<<getKeywords ['.$this->keywords.']');
981:
982: return $this->keywords;
983: }
984:
985: 986: 987: 988: 989: 990: 991:
992: public function setKeywords($keywords)
993: {
994: self::$logger->debug('>>setKeywords(keywords=['.$keywords.'])');
995: self::$logger->debug('<<setKeywords');
996: $this->keywords = $keywords;
997: }
998:
999: 1000: 1001: 1002: 1003: 1004: 1005:
1006: public function accessError()
1007: {
1008: self::$logger->debug('>>accessError()');
1009:
1010: if (method_exists($this, 'before_accessError_callback')) {
1011: $this->before_accessError_callback();
1012: }
1013:
1014: $config = ConfigProvider::getInstance();
1015:
1016: $sessionProvider = $config->get('session.provider.name');
1017: $session = SessionProviderFactory::getInstance($sessionProvider);
1018:
1019: if ($session->get('currentUser') !== false) {
1020: self::$logger->warn('The user ['.$session->get('currentUser')->get('email').'] attempted to access the resource ['.$this->request->getURI().'] but was denied due to insufficient rights');
1021: } else {
1022: self::$logger->warn('An unknown user attempted to access the resource ['.$this->request->getURI().'] but was denied due to insufficient rights');
1023: }
1024:
1025: $response = new Response(403);
1026: $response->setBody(View::renderErrorPage(403, 'You do not have the correct access rights to view this page. If you have not logged in yet, try going back to the home page and logging in from there.'));
1027:
1028: if (method_exists($this, 'after_accessError_callback')) {
1029: $this->after_accessError_callback();
1030: }
1031:
1032: self::$logger->debug('<<accessError');
1033:
1034: return $response;
1035: }
1036:
1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045:
1046: public function checkRights()
1047: {
1048: self::$logger->debug('>>checkRights()');
1049:
1050: $config = ConfigProvider::getInstance();
1051:
1052: $sessionProvider = $config->get('session.provider.name');
1053: $session = SessionProviderFactory::getInstance($sessionProvider);
1054:
1055: if (method_exists($this, 'before_checkRights_callback')) {
1056: $this->before_checkRights_callback();
1057: }
1058:
1059:
1060: if ($this->getVisibility() == 'Public') {
1061: if (method_exists($this, 'after_checkRights_callback')) {
1062: $this->after_checkRights_callback();
1063: }
1064:
1065: self::$logger->debug('<<checkRights [true]');
1066:
1067: return true;
1068: } else {
1069:
1070: if ($session->get('currentUser') !== false) {
1071:
1072:
1073: if ($this->getVisibility() == 'Session') {
1074: if (method_exists($this, 'after_checkRights_callback')) {
1075: $this->after_checkRights_callback();
1076: }
1077:
1078: self::$logger->debug('<<checkRights [true]');
1079:
1080: return true;
1081: }
1082:
1083:
1084: if ($session->get('currentUser')->inGroup('Admin')) {
1085: if (method_exists($this, 'after_checkRights_callback')) {
1086: $this->after_checkRights_callback();
1087: }
1088:
1089: self::$logger->debug('<<checkRights [true]');
1090:
1091: return true;
1092: } elseif ($session->get('currentUser')->inGroup($this->getVisibility())) {
1093: if (method_exists($this, 'after_checkRights_callback')) {
1094: $this->after_checkRights_callback();
1095: }
1096:
1097: self::$logger->debug('<<checkRights [true]');
1098:
1099: return true;
1100:
1101: } elseif (get_class($this->record) == 'Alpha\Model\Person' && $session->get('currentUser')->getDisplayName() == $this->record->getDisplayName()) {
1102: if (method_exists($this, 'after_checkRights_callback')) {
1103: $this->after_checkRights_callback();
1104: }
1105:
1106: self::$logger->debug('<<checkRights [true]');
1107:
1108: return true;
1109: } else {
1110: self::$logger->debug('<<checkRights [false]');
1111:
1112: return false;
1113: }
1114: } else {
1115: self::$logger->debug('<<checkRights [false]');
1116:
1117: return false;
1118: }
1119: }
1120: }
1121:
1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130:
1131: public function checkSecurityFields()
1132: {
1133: self::$logger->debug('>>checkSecurityFields()');
1134:
1135: $host = $this->request->getHost();
1136: $ip = $this->request->getIP();
1137:
1138:
1139: $var1 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($host.date('Ymd'))), '+/', '-_'), '=');
1140:
1141: $var2 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($ip.$var1)), '+/', '-_'), '=');
1142:
1143: if ($this->request->getParam('var1') === null || $this->request->getParam('var2') === null) {
1144: self::$logger->warn('The required var1/var2 params where not provided on the HTTP request');
1145: self::$logger->debug('<<checkSecurityFields [false]');
1146:
1147: return false;
1148: }
1149:
1150: if ($var1 == $this->request->getParam('var1') && $var2 == $this->request->getParam('var2')) {
1151: self::$logger->debug('<<checkSecurityFields [true]');
1152:
1153: return true;
1154: } else {
1155: 1156: 1157: 1158: 1159:
1160:
1161:
1162: $var1 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($host.date('Ymd', (time() - 3600)))), '+/', '-_'), '=');
1163:
1164: $var2 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($ip.$var1)), '+/', '-_'), '=');
1165:
1166: if ($var1 == $this->request->getParam('var1') && $var2 == $this->request->getParam('var2')) {
1167: self::$logger->debug('<<checkSecurityFields [true]');
1168:
1169: return true;
1170: } else {
1171: self::$logger->warn('The var1/var2 params provided are invalid, values: var1=['.$this->request->getParam('var1').'] var2=['.$this->request->getParam('var2').']');
1172: self::$logger->debug('<<checkSecurityFields [false]');
1173:
1174: return false;
1175: }
1176: }
1177: }
1178:
1179: 1180: 1181: 1182: 1183: 1184: 1185:
1186: public static function generateSecurityFields()
1187: {
1188: if (self::$logger == null) {
1189: self::$logger = new Logger('Controller');
1190: }
1191: self::$logger->debug('>>generateSecurityFields()');
1192:
1193: $request = new Request(array('method' => 'GET'));
1194:
1195: $host = $request->getHost();
1196: $ip = $request->getIP();
1197:
1198:
1199: $var1 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($host.date('Ymd'))), '+/', '-_'), '=');
1200:
1201: $var2 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($ip.$var1)), '+/', '-_'), '=');
1202:
1203: self::$logger->debug('<<generateSecurityFields [array('.$var1.', '.$var2.')]');
1204:
1205: return array($var1, $var2);
1206: }
1207:
1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216:
1217: public static function getCustomControllerName($ActiveRecordType)
1218: {
1219: if (self::$logger == null) {
1220: self::$logger = new Logger('Controller');
1221: }
1222: self::$logger->debug('>>getCustomControllerName(ActiveRecordType=['.$ActiveRecordType.']');
1223:
1224: $config = ConfigProvider::getInstance();
1225:
1226: try {
1227: $class = new ReflectionClass($ActiveRecordType);
1228: $controllerName = $class->getShortname().'Controller';
1229: } catch (Exception $e) {
1230: self::$logger->warn('Bad active record name ['.$ActiveRecordType.'] passed to getCustomControllerName()');
1231:
1232: return;
1233: }
1234:
1235: self::$logger->debug('Custom controller name is ['.$controllerName.']');
1236:
1237: if (file_exists($config->get('app.root').'Controller/'.$controllerName.'.php')) {
1238: $controllerName = 'Controller\\'.$controllerName;
1239: self::$logger->debug('<<getCustomControllerName ['.$controllerName.']');
1240:
1241: return $controllerName;
1242: } elseif (file_exists($config->get('app.root').'Alpha/Controller/'.$controllerName.'.php')) {
1243: $controllerName = 'Alpha\Controller\\'.$controllerName;
1244: self::$logger->debug('<<getCustomControllerName ['.$controllerName.']');
1245:
1246: return $controllerName;
1247: } else {
1248: self::$logger->debug('<<getCustomControllerName');
1249:
1250: return;
1251: }
1252: }
1253:
1254: 1255: 1256: 1257: 1258: 1259: 1260:
1261: public function setStatusMessage($message)
1262: {
1263: $config = ConfigProvider::getInstance();
1264: $sessionProvider = $config->get('session.provider.name');
1265: $session = SessionProviderFactory::getInstance($sessionProvider);
1266:
1267: $this->statusMessage = $message;
1268: $session->set('statusMessage', $message);
1269: }
1270:
1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279:
1280: public function getStatusMessage()
1281: {
1282: $config = ConfigProvider::getInstance();
1283: $sessionProvider = $config->get('session.provider.name');
1284: $session = SessionProviderFactory::getInstance($sessionProvider);
1285:
1286: $session->delete('statusMessage');
1287:
1288: return $this->statusMessage;
1289: }
1290:
1291: 1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301:
1302: public static function checkControllerDefExists($controllerName)
1303: {
1304: if (self::$logger == null) {
1305: self::$logger = new Logger('Controller');
1306: }
1307: self::$logger->debug('>>checkControllerDefExists(controllerName=['.$controllerName.'])');
1308:
1309: $config = ConfigProvider::getInstance();
1310:
1311: $exists = false;
1312:
1313: if ($controllerName == '/') {
1314: $exists = true;
1315: }
1316: if (file_exists($config->get('app.root').'Controller/'.$controllerName.'.php')) {
1317: $exists = true;
1318: }
1319: if (file_exists($config->get('app.root').'Alpha/Controller/'.$controllerName.'.php')) {
1320: $exists = true;
1321: }
1322:
1323: self::$logger->debug('<<checkControllerDefExists ['.$exists.']');
1324:
1325: return $exists;
1326: }
1327:
1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336:
1337: public static function loadControllerDef($controllerName)
1338: {
1339: if (self::$logger == null) {
1340: self::$logger = new Logger('Controller');
1341: }
1342: self::$logger->debug('>>loadControllerDef(controllerName=['.$controllerName.'])');
1343:
1344: $config = ConfigProvider::getInstance();
1345:
1346: if (file_exists($config->get('app.root').'Controller/'.$controllerName.'.php')) {
1347: require_once $config->get('app.root').'Controller/'.$controllerName.'.php';
1348: } elseif (file_exists($config->get('app.root').'Alpha/Controller/'.$controllerName.'.php')) {
1349: require_once $config->get('app.root').'Alpha/Controller/'.$controllerName.'.php';
1350: } else {
1351: throw new IllegalArguementException('The class ['.$controllerName.'] is not defined anywhere!');
1352: }
1353:
1354: self::$logger->debug('<<loadControllerDef');
1355: }
1356:
1357: 1358: 1359: 1360: 1361: 1362: 1363:
1364: public function checkIfAccessingFromSecureURL()
1365: {
1366: if ($this->request->getParam('tk') != null || mb_strpos($this->request->getURI(), '/tk/') !== false) {
1367: return true;
1368: } else {
1369: return false;
1370: }
1371: }
1372:
1373: 1374: 1375: 1376: 1377: 1378: 1379: 1380: 1381:
1382: private function decryptFieldNames($params)
1383: {
1384: $decrypted = array();
1385:
1386: foreach (array_keys($params) as $fieldname) {
1387:
1388:
1389: if (Validator::isBase64($fieldname)) {
1390: $decrypted[SecurityUtils::decrypt(base64_decode($fieldname))] = $params[$fieldname];
1391: }
1392: }
1393:
1394: return $decrypted;
1395: }
1396:
1397: 1398: 1399: 1400: 1401: 1402: 1403: 1404: 1405: 1406: 1407: 1408:
1409: public static function generateURLSlug($URLPart, $seperator = '-', $filter = array(), $crc32Prefix = false)
1410: {
1411: $URLPart = trim($URLPart);
1412:
1413: if (count($filter) > 0) {
1414: $URLPart = str_replace($filter, ' ', $URLPart);
1415: }
1416:
1417: $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $URLPart);
1418: $clean = preg_replace("/[^a-zA-Z0-9\/\._|+ -]/", '', $clean);
1419: $clean = strtolower(trim($clean, '-'));
1420: $clean = preg_replace("/[\.\/_|+ -]+/", $seperator, $clean);
1421:
1422: if ($crc32Prefix) {
1423: $clean = hexdec(hash('crc32b', $URLPart)).$seperator.$clean;
1424: }
1425:
1426: return $clean;
1427: }
1428:
1429: 1430: 1431: 1432: 1433: 1434: 1435:
1436: public function doHEAD($request)
1437: {
1438: throw new NotImplementedException('The HEAD method is not supported by this controller');
1439: }
1440:
1441: 1442: 1443: 1444: 1445: 1446: 1447:
1448: public function doGET($request)
1449: {
1450: throw new NotImplementedException('The GET method is not supported by this controller');
1451: }
1452:
1453: 1454: 1455: 1456: 1457: 1458: 1459:
1460: public function doPOST($request)
1461: {
1462: throw new NotImplementedException('The POST method is not supported by this controller');
1463: }
1464:
1465: 1466: 1467: 1468: 1469: 1470: 1471:
1472: public function doPUT($request)
1473: {
1474: throw new NotImplementedException('The PUT method is not supported by this controller');
1475: }
1476:
1477: 1478: 1479: 1480: 1481: 1482: 1483:
1484: public function doPATCH($request)
1485: {
1486: throw new NotImplementedException('The PATCH method is not supported by this controller');
1487: }
1488:
1489: 1490: 1491: 1492: 1493: 1494: 1495:
1496: public function doDELETE($request)
1497: {
1498: throw new NotImplementedException('The DELETE method is not supported by this controller');
1499: }
1500:
1501: 1502: 1503: 1504: 1505:
1506: public function doOPTIONS($request)
1507: {
1508: $HTTPMethods = array('HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS');
1509: $supported = array();
1510:
1511: foreach ($HTTPMethods as $HTTPMethod) {
1512: $reflector = new \ReflectionMethod($this, 'do'.$HTTPMethod);
1513: $isOverridden = ($reflector->getDeclaringClass()->getName() === get_class($this));
1514:
1515: if ($isOverridden) {
1516: $supported[] = $HTTPMethod;
1517: }
1518: }
1519:
1520: $supported = implode(',', $supported);
1521:
1522: $response = new Response(200);
1523: $response->setHeader('Allow', $supported);
1524:
1525: return $response;
1526: }
1527:
1528: 1529: 1530: 1531: 1532:
1533: public function doTRACE($request)
1534: {
1535: $HTTPMethods = array('HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS');
1536: $supported = array();
1537:
1538: foreach ($HTTPMethods as $HTTPMethod) {
1539: $reflector = new \ReflectionMethod($this, 'do'.$HTTPMethod);
1540: $isOverridden = ($reflector->getDeclaringClass()->getName() === get_class($this));
1541:
1542: if ($isOverridden) {
1543: $supported[] = $HTTPMethod;
1544: }
1545: }
1546:
1547: $supported = implode(',', $supported);
1548:
1549: $response = new Response(405);
1550: $response->setHeader('Allow', $supported);
1551:
1552: return $response;
1553: }
1554:
1555: 1556: 1557: 1558: 1559: 1560: 1561: 1562: 1563: 1564:
1565: public function process($request)
1566: {
1567: if (!$request instanceof Request) {
1568: throw new IllegalArguementException('The request passed to process is not a valid Request object');
1569: }
1570:
1571: $config = ConfigProvider::getInstance();
1572:
1573: $method = $request->getMethod();
1574:
1575: if (in_array($method, array('POST', 'PUT', 'PATCH'))) {
1576: if ($config->get('security.encrypt.http.fieldnames')) {
1577: $decryptedParams = $this->decryptFieldNames($request->getParams());
1578: $request->addParams($decryptedParams);
1579:
1580: if ($request->getParam('_METHOD') != null) {
1581: $request->setMethod($request->getParam('_METHOD'));
1582: $method = $request->getMethod();
1583: }
1584: }
1585: }
1586:
1587: $ProviderClassName = $config->get('app.renderer.provider.name');
1588:
1589: if ($ProviderClassName == 'auto' && $request->getAccept() != null) {
1590: View::setProvider('auto', $request->getAccept());
1591: }
1592:
1593: $this->request = $request;
1594:
1595:
1596: if (!$this->checkRights()) {
1597: return $this->accessError();
1598: }
1599:
1600: switch ($method) {
1601: case 'HEAD':
1602: $response = $this->doHEAD($request);
1603: break;
1604: case 'GET':
1605: $response = $this->doGET($request);
1606: break;
1607: case 'POST':
1608: $response = $this->doPOST($request);
1609: break;
1610: case 'PUT':
1611: $response = $this->doPUT($request);
1612: break;
1613: case 'PATCH':
1614: $response = $this->doPATCH($request);
1615: break;
1616: case 'DELETE':
1617: $response = $this->doDELETE($request);
1618: break;
1619: case 'OPTIONS':
1620: $response = $this->doOPTIONS($request);
1621: break;
1622: case 'TRACE':
1623: $response = $this->doTRACE($request);
1624: break;
1625: }
1626:
1627: return $response;
1628: }
1629:
1630: 1631: 1632: 1633: 1634: 1635: 1636:
1637: public function getRequest()
1638: {
1639: return $this->request;
1640: }
1641:
1642: 1643: 1644: 1645: 1646: 1647: 1648:
1649: public function setRequest($request)
1650: {
1651: if ($request instanceof Request) {
1652: $this->request = $request;
1653: } else {
1654: throw new IllegalArguementException('Invalid request object ['.print_r($request, true).'] passed');
1655: }
1656: }
1657:
1658: 1659: 1660: 1661: 1662: 1663: 1664:
1665: public function after_displayPageHead_callback()
1666: {
1667: $accept = $this->request->getAccept();
1668:
1669: if ($accept != 'application/json' && $this->checkIfAccessingFromSecureURL()) {
1670: $viewState = ViewState::getInstance();
1671: if ($viewState->get('renderAdminMenu') === true) {
1672:
1673: $config = ConfigProvider::getInstance();
1674:
1675: $sessionProvider = $config->get('session.provider.name');
1676: $session = SessionProviderFactory::getInstance($sessionProvider);
1677:
1678: if ($session->get('currentUser') !== false) {
1679: $passwordResetRequired = SecurityUtils::checkAdminPasswordIsDefault($session->get('currentUser')->get('password'));
1680: $menu = View::loadTemplateFragment('html', 'adminmenu.phtml', array('passwordResetRequired' => $passwordResetRequired));
1681: } else {
1682: $menu = '';
1683: }
1684:
1685: return $menu;
1686: }
1687: } else {
1688: return '';
1689: }
1690: }
1691: }
1692: