Overview

Packages

  • alpha::controller
  • alpha::controller::front
  • alpha::exceptions
  • alpha::model
  • alpha::model::types
  • alpha::tasks
  • alpha::tests
  • alpha::util
  • alpha::util::cache
  • alpha::util::codehighlight
  • alpha::util::convertors
  • alpha::util::feeds
  • alpha::util::filters
  • alpha::util::graphs
  • alpha::util::helpers
  • alpha::util::metrics
  • alpha::view
  • alpha::view::renderers
  • alpha::view::widgets

Classes

  • AlphaController
  • CacheManager
  • Create
  • CreateArticle
  • Detail
  • Edit
  • EditArticle
  • EditDEnum
  • EditTags
  • GenSecureQueryStrings
  • Install
  • ListAll
  • ListBusinessObjects
  • ListDEnums
  • ListSequences
  • Login
  • Logout
  • PreviewArticle
  • Search
  • TagManager
  • ViewArticle
  • ViewArticleFile
  • ViewArticlePDF
  • ViewArticlePrint
  • ViewArticleTitle
  • ViewAttachment
  • ViewExcel
  • ViewFeed
  • ViewImage
  • ViewLog
  • ViewMetrics
  • ViewRecordSelector
  • ViewTestResults

Interfaces

  • AlphaControllerInterface
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
   1: <?php
   2: 
   3: /**
   4:  *
   5:  * The master controller class for the Alpha Framework.
   6:  *
   7:  * @package alpha::controller
   8:  * @since 1.0
   9:  * @author John Collins <dev@alphaframework.org>
  10:  * @version $Id: AlphaController.inc 1665 2013-09-09 20:22:14Z 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: abstract class AlphaController {
  49:     /**
  50:      * The name of the controller
  51:      *
  52:      * @var string
  53:      * @since 1.0
  54:      */
  55:     protected $name;
  56: 
  57:     /**
  58:      * Used to set access privileages for the controller to the name of the rights group
  59:      * allowed to access it.  'Public' by default.
  60:      *
  61:      * @var string
  62:      * @since 1.0
  63:      */
  64:     protected $visibility = 'Public';
  65: 
  66:     /**
  67:      * Optionally, a BO may be set for the default validation form handling code to load in the displayPageHead()
  68:      * method.  The definition of this BO class will need to be included in the child controller.
  69:      *
  70:      * @var AlphaDAO
  71:      * @since 1.0
  72:      */
  73:     protected $BO = null;
  74: 
  75:     /**
  76:      * Used to determine if the controller is part of a unit of work sequence
  77:      * (either empty or the name of the unit).
  78:      *
  79:      * @var string
  80:      * @since 1.0
  81:      */
  82:     protected $unitOfWork;
  83: 
  84:     /**
  85:      * Stores the start time of a unit of work transaction.
  86:      *
  87:      * @var Timestamp
  88:      * @since 1.0
  89:      */
  90:     protected $unitStartTime;
  91: 
  92:     /**
  93:      * Stores the end time of a unit of work transaction.
  94:      *
  95:      * @var Timestamp.
  96:      * @since 1.0
  97:      */
  98:     protected $unitEndTime;
  99: 
 100:     /**
 101:      * Stores the maximum allowed time duration (in seconds) of the unit of work.
 102:      *
 103:      * @var Integer
 104:      * @since 1.0
 105:      */
 106:     protected $unitMAXDuration;
 107: 
 108:     /**
 109:      * The name of the first controller that is used in this unit of work.
 110:      *
 111:      * @var string
 112:      * @since 1.0
 113:      */
 114:     protected $firstJob;
 115: 
 116:     /**
 117:      * The name of the next controller that is used in this unit of work.
 118:      *
 119:      * @var string
 120:      * @since 1.0
 121:      */
 122:     protected $nextJob;
 123: 
 124:     /**
 125:      * The name of the previous controller that is used in this unit of work.
 126:      *
 127:      * @var string
 128:      * @since 1.0
 129:      */
 130:     protected $previousJob;
 131: 
 132:     /**
 133:      * The name of the last controller that is used in this unit of work.
 134:      *
 135:      * @var string
 136:      * @since 1.0
 137:      */
 138:     protected $lastJob;
 139: 
 140:     /**
 141:      * An array for storing dirty objects in a session (i.e. persistent business
 142:      * objects that have not been updated in the database yet).
 143:      *
 144:      * @var array
 145:      * @since 1.0
 146:      */
 147:     protected $dirtyObjects = array();
 148: 
 149:     /**
 150:      * An array for storing new objects in a session (transient business objects that
 151:      * have no OID yet).
 152:      *
 153:      * @var array
 154:      * @since 1.0
 155:      */
 156:     protected $newObjects = array();
 157: 
 158:     /**
 159:      * The title to be displayed on the controller page
 160:      *
 161:      * @var string
 162:      * @since 1.0
 163:      */
 164:     protected $title;
 165: 
 166:     /**
 167:      * Meta keywords for the controller page, generally populated from tags
 168:      *
 169:      * @var string
 170:      * @since 1.0
 171:      */
 172:     protected $keywords;
 173: 
 174:     /**
 175:      * Meta description for the controller page.
 176:      *
 177:      * @var string
 178:      * @since 1.0
 179:      */
 180:     protected $description;
 181: 
 182:     /**
 183:      * Used to set status update messages to display to the user (messages stored between requests
 184:      * in _SESSION).  Useful for when you want to display a message to a user after POSTing a request,
 185:      * or when moving from one page to the next.
 186:      *
 187:      * @var string
 188:      * @since 1.0
 189:      */
 190:     protected $statusMessage;
 191: 
 192:     /**
 193:      * Trace logger
 194:      *
 195:      * @var Logger
 196:      * @since 1.0
 197:      */
 198:     private static $logger = null;
 199: 
 200:     /**
 201:      * Constructor for the AlphaController that starts a new session if required, and handles
 202:      * the population of new/dirty objects from the session when available.  Accepts the name
 203:      * of the rights group that has access to this controller, 'Public' by default.
 204:      *
 205:      * @param string $visibility The name of the rights group that can access this controller.
 206:      * @since 1.0
 207:      */
 208:     public function __construct($visibility='Public') {
 209:         self::$logger = new Logger('AlphaController');
 210:         self::$logger->debug('>>__construct(visibility=['.$visibility.'])');
 211: 
 212:         global $config;
 213: 
 214:         // kick off new session, or reuse existing one
 215:         if(!isset($_SESSION)) {
 216:             $url = parse_url($config->get('app.url'));
 217:             $hostname = $url['host'];
 218:             session_set_cookie_params(0, '/', $hostname, false, true);
 219:             session_start();
 220:         }
 221: 
 222:         // set the access rights to the group name indicated
 223:         $this->visibility = $visibility;
 224: 
 225:         // check the current user's rights on access to the page controller
 226:         if(!$this->checkRights()) {
 227:             $this->accessError();
 228:             // no more execution should take place
 229:             exit;
 230:         }
 231: 
 232:         // if configured to do so, force redirect to the front controller
 233:         if($config->get('app.force.front.controller') && basename($_SERVER['PHP_SELF']) != 'index.php') {
 234:             // set the correct HTTP header for the response
 235:                 header('HTTP/1.1 301 Moved Permanently');
 236: 
 237:                 if(empty($_SERVER['QUERY_STRING'])) {
 238:                     header('Location: '.$config->get('app.url').'?act='.get_class($this));
 239:                     self::$logger->debug('<<__construct');
 240:                     exit;
 241:                 }else{
 242:                     header('Location: '.$config->get('app.url').'?act='.get_class($this).'&'.$_SERVER['QUERY_STRING']);
 243:                     self::$logger->debug('<<__construct');
 244:                     exit;
 245:                 }
 246: 
 247:                 // we're done here
 248:                 self::$logger->debug('<<__construct');
 249:                 return;
 250:         }
 251: 
 252:         $this->unitStartTime = new Timestamp(date("Y-m-d H:i:s"));
 253:         $this->unitEndTime = new Timestamp();
 254:         $this->unitMAXDuration = new Integer();
 255: 
 256:         // uses controller class name as the job name
 257:         if($this->name == '')
 258:             $this->setName(get_class($this));
 259: 
 260:         if(isset($_SESSION['unitOfWork']) && is_array($_SESSION['unitOfWork']))
 261:             $this->setUnitOfWork($_SESSION['unitOfWork']);
 262: 
 263:         if(isset($_SESSION['dirtyObjects']) && is_array($_SESSION['dirtyObjects']))
 264:             $this->dirtyObjects = $_SESSION['dirtyObjects'];
 265: 
 266:         if(isset($_SESSION['newObjects']) && is_array($_SESSION['newObjects']))
 267:             $this->newObjects = $_SESSION['newObjects'];
 268: 
 269:         if(isset($_SESSION['statusMessage']))
 270:             $this->setStatusMessage($_SESSION['statusMessage']);
 271: 
 272:         if($config->get('security.encrypt.http.fieldnames') && !empty($_POST))
 273:             $this->decryptFieldNames();
 274: 
 275:         self::$logger->debug('<<__construct');
 276:     }
 277: 
 278:     /**
 279:      * Get the BO for this controller (if any).
 280:      *
 281:      * @return mixed
 282:      * @since 1.0
 283:      */
 284:     public function getBO() {
 285:         self::$logger->debug('>>getBO()');
 286:         self::$logger->debug('<<getBO ['.var_export($this->BO, true).']');
 287:         return $this->BO;
 288:     }
 289: 
 290:     /**
 291:      * Setter for the BO for this controller.
 292:      *
 293:      * @param AlphaDAO $BO
 294:      * @since 1.0
 295:      */
 296:     public function setBO($BO) {
 297:         self::$logger->debug('>>setBO(BO=['.var_export($BO, true).'])');
 298:         $this->BO = $BO;
 299: 
 300:         // if the BO has tags, use these as the meta keywords for this controller
 301:         if($this->BO->isTagged()) {
 302:             $tags = $this->BO->getPropObject('tags')->getRelatedObjects();
 303: 
 304:             $keywords = '';
 305: 
 306:             if(count($tags) > 0) {
 307:                 foreach($tags as $tag)
 308:                     $keywords .= ','.$tag->get('content');
 309:             }
 310: 
 311:             $this->setKeywords(substr($keywords, 1));
 312:         }
 313: 
 314:         self::$logger->debug('<<setBO');
 315:     }
 316: 
 317:     /**
 318:      * Get the name of the unit of work job.
 319:      *
 320:      * @return string
 321:      * @since 1.0
 322:      */
 323:     public function getName() {
 324:         self::$logger->debug('>>getName()');
 325:         self::$logger->debug('<<getName ['.$this->name.']');
 326:         return $this->name;
 327:     }
 328: 
 329:     /**
 330:      * Setter for the unit of work job name.
 331:      *
 332:      * @param string $name
 333:      * @since 1.0
 334:      */
 335:     public function setName($name) {
 336:         self::$logger->debug('>>setName(name=['.$name.'])');
 337:         $this->name = $name;
 338:         self::$logger->debug('<<setName');
 339:      }
 340: 
 341:     /**
 342:      * Get the name of the rights group that has access to this controller.
 343:      *
 344:      * @return string
 345:      * @since 1.0
 346:      */
 347:     public function getVisibility() {
 348:         self::$logger->debug('>>getVisibility()');
 349:         self::$logger->debug('<<getVisibility ['.$this->visibility.']');
 350:         return $this->visibility;
 351:     }
 352: 
 353:     /**
 354:      * Setter for the name of the rights group that has access to this controller.
 355:      *
 356:      * @param string $visibility
 357:      * @since 1.0
 358:      */
 359:     public function setVisibility($visibility) {
 360:         self::$logger->debug('>>setVisibility(visibility=['.$visibility.'])');
 361:         $this->visibility = $visibility;
 362:         self::$logger->debug('<<setVisibility');
 363:     }
 364: 
 365:     /**
 366:      * Gets the name of the first job in this unit of work.
 367:      *
 368:      * @return string
 369:      * @since 1.0
 370:      */
 371:     public function getFirstJob() {
 372:         self::$logger->debug('>>getFirstJob()');
 373:         self::$logger->debug('<<getFirstJob ['.$this->firstJob.']');
 374:         return $this->firstJob;
 375:     }
 376: 
 377:     /**
 378:      * Gets the name of the next job in this unit of work
 379:      *
 380:      * @return string
 381:      * @since 1.0
 382:      */
 383:     public function getNextJob() {
 384:         self::$logger->debug('>>getNextJob()');
 385:         self::$logger->debug('<<getNextJob ['.$this->nextJob.']');
 386:         return $this->nextJob;
 387:     }
 388: 
 389:     /**
 390:      * Gets the name of the previous job in this unit of work
 391:      *
 392:      * @return string
 393:      * @since 1.0
 394:      */
 395:     public function getPreviousJob() {
 396:         self::$logger->debug('>>getPreviousJob()');
 397:         self::$logger->debug('<<getPreviousJob ['.$this->previousJob.']');
 398:         return $this->previousJob;
 399:     }
 400: 
 401:     /**
 402:      * Gets the name of the last job in this unit of work.
 403:      *
 404:      * @return string
 405:      * @since 1.0
 406:      */
 407:     public function getLastJob() {
 408:         self::$logger->debug('>>getLastJob()');
 409:         self::$logger->debug('<<getLastJob ['.$this->lastJob.']');
 410:         return $this->lastJob;
 411:     }
 412: 
 413:     /**
 414:      * Sets the name of the controller job sequence to the values in the supplied
 415:      * array (and stores the array in the session).
 416:      *
 417:      * @param array $jobs The names of the controllers in this unit of work sequence.
 418:      * @throws IllegalArguementException
 419:      * @since 1.0
 420:      */
 421:     public function setUnitOfWork($jobs) {
 422:         self::$logger->debug('>>setUnitOfWork(jobs=['.var_export($jobs, true).'])');
 423: 
 424:         if(method_exists($this, 'before_setUnitOfWork_callback'))
 425:             $this->before_setUnitOfWork_callback();
 426: 
 427:         if(!is_array($jobs)) {
 428:             throw new IllegalArguementException('Bad $jobs array ['.var_export($jobs, true).'] passed to setUnitOfWork method!');
 429:             self::$logger->debug('<<setUnitOfWork');
 430:             return;
 431:         }
 432: 
 433:         // validate that each controller name in the array actually exists
 434:         foreach($jobs as $job) {
 435:             if(!AlphaController::checkControllerDefExists($job))
 436:                 throw new IllegalArguementException('The controller name ['.$job.'] provided in the jobs array is not defined anywhere!');
 437:         }
 438: 
 439:         // clear out any previous unit of work from the session
 440:         $_SESSION['unitOfWork'] = null;
 441:         $this->dirtyObjects = array();
 442:         $this->newObjects = array();
 443: 
 444:         $numOfJobs = count($jobs);
 445: 
 446:         for($i=0; $i<$numOfJobs; $i++) {
 447:             // the first job in the sequence
 448:             if($i==0) {
 449:                 $this->firstJob = $jobs[$i];
 450:                 self::$logger->debug('First job ['.$this->firstJob.']');
 451:             }
 452:             // found the current job
 453:             if($this->name == $jobs[$i]) {
 454:                 if(isset($jobs[$i-1])) {
 455:                     // set the previous job if it exists
 456:                     $this->previousJob = $jobs[$i-1];
 457:                     self::$logger->debug('Previous job ['.$this->previousJob.']');
 458:                 }
 459:                 if(isset($jobs[$i+1])) {
 460:                     // set the next job if it exists
 461:                     $this->nextJob = $jobs[$i+1];
 462:                     self::$logger->debug('Next job ['.$this->nextJob.']');
 463:                 }
 464:             }
 465:             // the last job in the sequence
 466:             if($i==($numOfJobs-1)) {
 467:                 $this->lastJob = $jobs[$i];
 468:             }
 469:         }
 470: 
 471:         $_SESSION['unitOfWork'] = $jobs;
 472: 
 473:         if(method_exists($this, 'after_setUnitOfWork_callback'))
 474:             $this->after_setUnitOfWork_callback();
 475: 
 476:         self::$logger->debug('<<setUnitOfWork');
 477:     }
 478: 
 479:     /**
 480:      * Getter for the unit start time.
 481:      *
 482:      * @return Timestamp
 483:      * @since 1.0
 484:      */
 485:     public function getStartTime() {
 486:         self::$logger->debug('>>getStartTime()');
 487:         self::$logger->debug('<<getStartTime ['.$this->unitStartTime.']');
 488:         return $this->unitStartTime;
 489:     }
 490: 
 491:     /**
 492:      * Setter for the unit start time (value will be stored in the session as key unitStartTime).
 493:      *
 494:      * @param integer $year
 495:      * @param integer $month
 496:      * @param integer $day
 497:      * @param integer $hour
 498:      * @param integer $minute
 499:      * @param integer $second
 500:      * @since 1.0
 501:      */
 502:     public function setUnitStartTime($year, $month, $day, $hour, $minute, $second) {
 503:         self::$logger->debug('>>setUnitStartTime(year=['.$year.'], month=['.$month.'], day=['.$day.'], hour=['.$hour.'], minute=['.$minute.'],
 504:             second=['.$second.'])');
 505: 
 506:         $this->unitStartTime->setTimestampValue($year, $month, $day, $hour, $minute, $second);
 507:         $_SESSION['unitStartTime'] = $this->unitStartTime->getValue();
 508: 
 509:         self::$logger->debug('<<setUnitStartTime');
 510:     }
 511: 
 512:     /**
 513:      * Getter for the unit end time.
 514:      *
 515:      * @return Timestamp
 516:      * @since 1.0
 517:      */
 518:     public function getEndTime() {
 519:         self::$logger->debug('>>getEndTime()');
 520:         self::$logger->debug('<<getEndTime ['.$this->unitEndTime.']');
 521:         return $this->unitEndTime;
 522:     }
 523: 
 524:     /**
 525:      * Setter for the unit end time (value will be stored in the session as key unitEndTime).
 526:      *
 527:      * @param integer $year
 528:      * @param integer $month
 529:      * @param integer $day
 530:      * @param integer $hour
 531:      * @param integer $minute
 532:      * @param integer $second
 533:      * @since 1.0
 534:      */
 535:     public function setUnitEndTime($year, $month, $day, $hour, $minute, $second) {
 536:         self::$logger->debug('>>setUnitEndTime(year=['.$year.'], month=['.$month.'], day=['.$day.'], hour=['.$hour.'], minute=['.$minute.'],
 537:          second=['.$second.'])');
 538: 
 539:         $this->unitEndTime->setTimestampValue($year, $month, $day, $hour, $minute, $second);
 540:         $_SESSION['unitEndTime'] = $this->unitEndTime->getValue();
 541: 
 542:         self::$logger->debug('<<setUnitEndTime');
 543:     }
 544: 
 545:     /**
 546:      * Getter for the unit of work MAX duration.
 547:      *
 548:      * @return Integer
 549:      * @since 1.0
 550:      */
 551:     public function getMAXDuration() {
 552:         self::$logger->debug('>>getMAXDuration()');
 553:         self::$logger->debug('<<getMAXDuration ['.$this->unitMAXDuration.']');
 554:         return $this->unitMAXDuration;
 555:     }
 556: 
 557:     /**
 558:      * Setter for the unit MAX duration.
 559:      *
 560:      * @param integer $duration The desired duration in seconds.
 561:      * @since 1.0
 562:      */
 563:     public function setUnitMAXDuration($duration) {
 564:         self::$logger->debug('>>setUnitMAXDuration(duration=['.$duration.'])');
 565:         $this->unitMAXDuration->setValue($duration);
 566:         self::$logger->debug('<<setUnitMAXDuration');
 567:     }
 568: 
 569:     /**
 570:      * Calculates and returns the unit of work current duration in seconds.
 571:      *
 572:      * @return integer
 573:      * @since 1.0
 574:      */
 575:     public function getUnitDuration() {
 576:         self::$logger->debug('>>getUnitDuration()');
 577: 
 578:         $intStartTime = mktime(
 579:             $this->unitStartTime->getHour(),
 580:             $this->unitStartTime->getMinute(),
 581:             $this->unitStartTime->getSecond(),
 582:             $this->unitStartTime->getMonth(),
 583:             $this->unitStartTime->getDay(),
 584:             $this->unitStartTime->getYear()
 585:             );
 586: 
 587:         $intEndTime = mktime(
 588:             $this->unitEndTime->getHour(),
 589:             $this->unitEndTime->getMinute(),
 590:             $this->unitEndTime->getSecond(),
 591:             $this->unitEndTime->getMonth(),
 592:             $this->unitEndTime->getDay(),
 593:             $this->unitEndTime->getYear()
 594:             );
 595: 
 596:         self::$logger->debug('<<getUnitDuration ['.$intEndTime-$intStartTime.']');
 597:         return $intEndTime-$intStartTime;
 598:      }
 599: 
 600:     /**
 601:      * Adds the supplied business object to the dirtyObjects array in the session.
 602:      *
 603:      * @param AlphaDAO $object
 604:      * @since 1.0
 605:      */
 606:     public function markDirty($object) {
 607:         self::$logger->debug('>>markDirty(object=['.var_export($object, true).'])');
 608: 
 609:         if(method_exists($this, 'before_markDirty_callback'))
 610:             $this->before_markDirty_callback();
 611: 
 612:         $this->dirtyObjects[count($this->dirtyObjects)] = $object;
 613: 
 614:         $_SESSION['dirtyObjects'] = $this->dirtyObjects;
 615: 
 616:         if(method_exists($this, 'after_markDirty_callback'))
 617:             $this->after_markDirty_callback();
 618: 
 619:         self::$logger->debug('<<markDirty');
 620:     }
 621: 
 622:     /**
 623:      * Getter for the dirty objects array.
 624:      *
 625:      * @return array
 626:      * @since 1.0
 627:      */
 628:     public function getDirtyObjects() {
 629:         self::$logger->debug('>>getDirtyObjects()');
 630:         self::$logger->debug('<<getDirtyObjects ['.var_export($this->dirtyObjects, true).']');
 631:         return $this->dirtyObjects;
 632:     }
 633: 
 634:     /**
 635:      * Adds a newly created business object to the newObjects array in the session.
 636:      *
 637:      * @param AlphaDAO $object
 638:      * @since 1.0
 639:      */
 640:     public function markNew($object) {
 641:         self::$logger->debug('>>markNew(object=['.var_export($object, true).'])');
 642: 
 643:         if(method_exists($this, 'before_markNew_callback'))
 644:             $this->before_markNew_callback();
 645: 
 646:         $this->newObjects[count($this->newObjects)] = $object;
 647: 
 648:         $_SESSION['newObjects'] = $this->newObjects;
 649: 
 650:         if(method_exists($this, 'after_markNew_callback'))
 651:             $this->after_markNew_callback();
 652: 
 653:         self::$logger->debug('<<markNew');
 654:     }
 655: 
 656:     /**
 657:      * Getter for the new objects array.
 658:      *
 659:      * @return array
 660:      * @since 1.0
 661:      */
 662:     public function getNewObjects() {
 663:         self::$logger->debug('>>getNewObjects()');
 664:         self::$logger->debug('<<getNewObjects ['.var_export($this->newObjects, true).']');
 665:         return $this->newObjects;
 666:     }
 667: 
 668:     /**
 669:      * Commits (saves) all of the new and modified (dirty) objects in the unit of work to the database.
 670:      *
 671:      * @throws FailedUnitCommitException
 672:      * @since 1.0
 673:      */
 674:     public function commit() {
 675:         self::$logger->debug('>>commit()');
 676: 
 677:         if(method_exists($this, 'before_commit_callback'))
 678:             $this->before_commit_callback();
 679: 
 680:         AlphaDAO::begin();
 681: 
 682:         $newObjects = $this->getNewObjects();
 683: 
 684:         $count = count($newObjects);
 685: 
 686:         for ($i = 0; $i < $count; $i++) {
 687:             try {
 688:                 $newObjects[$i]->save();
 689:             }catch (FailedSaveException $e) {
 690:                 throw new FailedUnitCommitException($e->getMessage());
 691:                 self::$logger->error('Failed to save new object of type ['.get_class($newObjects[$i]).'], aborting...');
 692:                 $this->abort();
 693:                 return;
 694:             }catch (LockingException $e) {
 695:                 throw new FailedUnitCommitException($e->getMessage());
 696:                 self::$logger->error('Failed to save new object of type ['.get_class($newObjects[$i]).'], aborting...');
 697:                 $this->abort();
 698:                 return;
 699:             }
 700:         }
 701: 
 702:         $dirtyObjects = $this->getDirtyObjects();
 703: 
 704:         $count = count($dirtyObjects);
 705: 
 706:         for ($i = 0; $i < $count; $i++) {
 707:             try {
 708:                 $dirtyObjects[$i]->save();
 709:             }catch (FailedSaveException $e) {
 710:                 throw new FailedUnitCommitException($e->getMessage());
 711:                 self::$logger->error('Failed to save OID ['.$dirtyObjects[$i]->getID().'] of type ['.get_class($dirtyObjects[$i]).'], aborting...');
 712:                 $this->abort();
 713:                 return;
 714:             }catch (LockingException $e) {
 715:                 throw new FailedUnitCommitException($e->getMessage());
 716:                 self::$logger->error('Failed to save OID ['.$dirtyObjects[$i]->getID().'] of type ['.get_class($dirtyObjects[$i]).'], aborting...');
 717:                 $this->abort();
 718:                 return;
 719:             }
 720:         }
 721: 
 722:         try{
 723:             AlphaDAO::commit();
 724: 
 725:             $this->clearUnitOfWorkAttributes();
 726: 
 727:             if(method_exists($this, 'after_commit_callback'))
 728:                 $this->after_commit_callback();
 729: 
 730:             self::$logger->debug('<<commit');
 731:         }catch(FailedSaveException $e) {
 732:             throw new FailedUnitCommitException('Failed to commit the transaction, error is ['.$e->getMessage().']');
 733:             self::$logger->debug('<<commit');
 734:         }
 735:     }
 736: 
 737:     /**
 738:      * Method to clearup a cancelled unit of work.
 739:      *
 740:      * @throws AlphaException
 741:      * @since 1.0
 742:      */
 743:     public function abort() {
 744:         self::$logger->debug('>>abort()');
 745: 
 746:         if(method_exists($this, 'before_abort_callback'))
 747:             $this->before_abort_callback();
 748: 
 749:         try{
 750:             AlphaDAO::rollback();
 751: 
 752:             $this->clearUnitOfWorkAttributes();
 753: 
 754:             if(method_exists($this, 'after_abort_callback'))
 755:                 $this->after_abort_callback();
 756: 
 757:             self::$logger->debug('<<abort');
 758:         }catch(AlphaException $e) {
 759:             throw new AlphaException('Failed to rollback the transaction, error is ['.$e->getMessage().']');
 760:             self::$logger->debug('<<abort');
 761:         }
 762:     }
 763: 
 764:     /**
 765:      * Clears the session and object attributes related to unit of work sessions
 766:      */
 767:     private function clearUnitOfWorkAttributes() {
 768:         $_SESSION['unitOfWork'] = null;
 769:         $this->unitOfWork = null;
 770:         $_SESSION['dirtyObjects'] = null;
 771:         $this->dirtyObjects = array();
 772:         $_SESSION['newObjects'] = null;
 773:         $this->newObjects = array();
 774:     }
 775: 
 776:     /**
 777:      * Getter for the page title.
 778:      *
 779:      * @return string
 780:      * @since 1.0
 781:      */
 782:     public function getTitle() {
 783:         self::$logger->debug('>>getTitle()');
 784:         self::$logger->debug('<<getTitle ['.$this->title.']');
 785:         return $this->title;
 786:     }
 787: 
 788:     /**
 789:      * Setter for the page title.
 790:      *
 791:      * @param string $title
 792:      * @since 1.0
 793:      */
 794:     public function setTitle($title) {
 795:         self::$logger->debug('>>setTitle(title=['.$title.'])');
 796:         self::$logger->debug('<<setTitle');
 797:         $this->title = $title;
 798:     }
 799: 
 800:     /**
 801:      * Getter for the page description.
 802:      *
 803:      * @return string
 804:      * @since 1.0
 805:      */
 806:     public function getDescription() {
 807:         self::$logger->debug('>>getDescription()');
 808:         self::$logger->debug('<<getDescription ['.$this->description.']');
 809:         return $this->description;
 810:     }
 811: 
 812:     /**
 813:      * Setter for the page description.
 814:      *
 815:      * @param string $description
 816:      * @since 1.0
 817:      */
 818:     public function setDescription($description) {
 819:         self::$logger->debug('>>setDescription(description=['.$description.'])');
 820:         self::$logger->debug('<<setDescription');
 821:         $this->description = $description;
 822:     }
 823: 
 824:     /**
 825:      * Getter for the page keywords.
 826:      *
 827:      * @return string
 828:      * @since 1.0
 829:      */
 830:     public function getKeywords() {
 831:         self::$logger->debug('>>getKeywords()');
 832:         self::$logger->debug('<<getKeywords ['.$this->keywords.']');
 833:         return $this->keywords;
 834:     }
 835: 
 836:     /**
 837:      * Setter for the page keywords, should pass a comma-seperated list as a string.
 838:      *
 839:      * @param string $keywords
 840:      * @since 1.0
 841:      */
 842:     public function setKeywords($keywords) {
 843:         self::$logger->debug('>>setKeywords(keywords=['.$keywords.'])');
 844:         self::$logger->debug('<<setKeywords');
 845:         $this->keywords = $keywords;
 846:     }
 847: 
 848:     /**
 849:      * Method to display an access error for trespassing users.  HTTP response header code will be 403.
 850:      *
 851:      * @since 1.0
 852:      */
 853:     public function accessError() {
 854:         self::$logger->debug('>>accessError()');
 855: 
 856:         if(method_exists($this, 'before_accessError_callback'))
 857:             $this->before_accessError_callback();
 858: 
 859:         global $config;
 860: 
 861:         if(isset($_SESSION['currentUser']))
 862:             self::$logger->warn('The user ['.$_SESSION['currentUser']->get('email').'] attempted to access the resource ['.$_SERVER['REQUEST_URI'].'] but was denied due to insufficient rights');
 863:         else
 864:             self::$logger->warn('An unknown user attempted to access the resource ['.$_SERVER['REQUEST_URI'].'] but was denied due to insufficient rights');
 865: 
 866:         header('HTTP/1.1 403 Forbidden');
 867:         $front = new FrontController();
 868:         echo AlphaView::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.');
 869: 
 870:         if(method_exists($this, 'after_accessError_callback'))
 871:             $this->after_accessError_callback();
 872: 
 873:         self::$logger->debug('<<accessError');
 874:     }
 875: 
 876:     /**
 877:      * Checks the user rights of the currently logged-in person against the page
 878:      * visibility set for this controller.  Will return false if the user has
 879:      * not got the correct rights.
 880:      *
 881:      * @return boolean
 882:      * @since 1.0
 883:      */
 884:     public function checkRights() {
 885:         self::$logger->debug('>>checkRights()');
 886: 
 887:         if(method_exists($this, 'before_checkRights_callback'))
 888:             $this->before_checkRights_callback();
 889: 
 890:         // firstly if the page is Public then there is no issue
 891:         if ($this->getVisibility() == 'Public') {
 892:             if(method_exists($this, 'after_checkRights_callback'))
 893:                 $this->after_checkRights_callback();
 894: 
 895:             self::$logger->debug('<<checkRights [true]');
 896:             return true;
 897:         }else{
 898:             // the person is logged in?
 899:             if (isset($_SESSION['currentUser'])) {
 900:                 // checking for admins (can access everything)
 901:                 if ($_SESSION['currentUser']->inGroup('Admin')) {
 902:                     if(method_exists($this, 'after_checkRights_callback'))
 903:                         $this->after_checkRights_callback();
 904: 
 905:                     self::$logger->debug('<<checkRights [true]');
 906:                     return true;
 907:                 } elseif ($_SESSION['currentUser']->inGroup($this->getVisibility())) {
 908:                     if(method_exists($this, 'after_checkRights_callback'))
 909:                         $this->after_checkRights_callback();
 910: 
 911:                     self::$logger->debug('<<checkRights [true]');
 912:                     return true;
 913:                 // the person is editing their own profile which is allowed
 914:                 } elseif (get_class($this->BO) == 'PersonObject' && $_SESSION['currentUser']->getDisplayName() == $this->BO->getDisplayName()) {
 915:                     if(method_exists($this, 'after_checkRights_callback'))
 916:                         $this->after_checkRights_callback();
 917: 
 918:                     self::$logger->debug('<<checkRights [true]');
 919:                     return true;
 920:                 }else{
 921:                     self::$logger->debug('<<checkRights [false]');
 922:                     return false;
 923:                 }
 924:             }else{ // the person is NOT logged in
 925:                 self::$logger->debug('<<checkRights [false]');
 926:                 return false;
 927:             }
 928:         }
 929:     }
 930: 
 931:     /**
 932:      * Method to check the validity of the two hidden form security
 933:      * fields which aim to ensure that a post to the controller is being sent from
 934:      * the same server that is hosting it.
 935:      *
 936:      * @return boolean
 937:      * @since 1.0
 938:      */
 939:     public static function checkSecurityFields() {
 940:         if(self::$logger == null)
 941:             self::$logger = new Logger('AlphaController');
 942:         self::$logger->debug('>>checkSecurityFields()');
 943: 
 944:         // the server hostname + today's date
 945:         $var1 = base64_encode(AlphaSecurityUtils::encrypt($_SERVER['HTTP_HOST'].date("Ymd")));
 946:         // the server's IP plus $var1
 947:         $var2 = base64_encode(AlphaSecurityUtils::encrypt($_SERVER['REMOTE_ADDR'].$var1));
 948: 
 949:         if(empty($_REQUEST['var1']) || empty($_REQUEST['var2'])) {
 950:             self::$logger->warn('The required var1/var2 params where not provided on the HTTP request');
 951:             self::$logger->debug('<<checkSecurityFields [false]');
 952:             return false;
 953:         }
 954: 
 955:         if ($var1 == $_REQUEST['var1'] && $var2 == $_REQUEST['var2']) {
 956:             self::$logger->debug('<<checkSecurityFields [true]');
 957:             return true;
 958:         }else{
 959:             /*
 960:              * Here we are implementing a "grace period" of one hour if the time is < 1:00AM, we will accept
 961:              * a match for yesterday's date in the security fields
 962:              *
 963:              */
 964: 
 965:             // the server hostname + today's date less 1 hour (i.e. yesterday where time is < 1:00AM)
 966:             $var1 = base64_encode(AlphaSecurityUtils::encrypt($_SERVER['HTTP_HOST'].date("Ymd", (time()-3600))));
 967:             // the server's IP plus $var1
 968:             $var2 = base64_encode(AlphaSecurityUtils::encrypt($_SERVER['REMOTE_ADDR'].$var1));
 969: 
 970:             if ($var1 == $_REQUEST['var1'] && $var2 == $_REQUEST['var2']) {
 971:                 self::$logger->debug('<<checkSecurityFields [true]');
 972:                 return true;
 973:             }else{
 974:                 self::$logger->warn('The var1/var2 params provided are invalid, values: var1=['.$_REQUEST['var1'].'] var2=['.$_REQUEST['var2'].']');
 975:                 self::$logger->debug('<<checkSecurityFields [false]');
 976:                 return false;
 977:             }
 978:         }
 979:     }
 980: 
 981:     /**
 982:      * Generates the two security fields to prevent remote form processing.
 983:      *
 984:      * @return array An array containing the two fields
 985:      * @since 1.0
 986:      */
 987:     public static function generateSecurityFields() {
 988:         if(self::$logger == null)
 989:             self::$logger = new Logger('AlphaController');
 990:         self::$logger->debug('>>generateSecurityFields()');
 991: 
 992:         // the server hostname + today's date
 993:         $var1 = base64_encode(AlphaSecurityUtils::encrypt($_SERVER['HTTP_HOST'].date("Ymd")));
 994:         // the server's IP plus $var1
 995:         $var2 = base64_encode(AlphaSecurityUtils::encrypt($_SERVER['REMOTE_ADDR'].$var1));
 996: 
 997:         self::$logger->debug('<<generateSecurityFields [array('.$var1.', '.$var2.')]');
 998:         return array($var1, $var2);
 999:     }
1000: 
1001:     /**
1002:      * Returns the name of a custom controller if one is found, otherwise returns null.
1003:      *
1004:      * @param string $BOName The classname of the business object
1005:      * @param string $mode The mode of the controller (create, view, edit)
1006:      * @return string
1007:      * @since 1.0
1008:      */
1009:     public static function getCustomControllerName($BOName, $mode) {
1010:         if(self::$logger == null)
1011:             self::$logger = new Logger('AlphaController');
1012:         self::$logger->debug('>>getCustomControllerName(BOName=['.$BOName.'], mode=['.$mode.'])');
1013: 
1014:         global $config;
1015: 
1016:         // strip the Object part from the class name
1017:         $BOName = substr($BOName, 0, strpos($BOName, 'Object'));
1018:         // uppercase the first letter of each word, e.g. create cart becomes Create Cart
1019:         $controllerName = ucwords($mode.' '.$BOName);
1020:         // remove spaces
1021:         $controllerName = str_replace(' ', '', $controllerName);
1022: 
1023:         self::$logger->debug('Custom controller name is ['.$controllerName.']');
1024: 
1025:         if (file_exists($config->get('app.root').'controller/'.$controllerName.'.php')) {
1026:             self::$logger->debug('<<getCustomControllerName');
1027:             return $controllerName;
1028:         }elseif (file_exists($config->get('app.root').'alpha/controller/'.$controllerName.'.php')) {
1029:             self::$logger->debug('<<getCustomControllerName');
1030:             return $controllerName;
1031:         }else{
1032:             self::$logger->debug('<<getCustomControllerName');
1033:             return null;
1034:         }
1035:     }
1036: 
1037:     /**
1038:      * Does a HTTP redirect to a custom controller if one is found.
1039:      *
1040:      * @param string $BOName The classname of the business object
1041:      * @param string $mode The mode of the controller (create, view, edit)
1042:      * @throws FileNotFoundException
1043:      * @since 1.0
1044:      */
1045:     protected function loadCustomController($BOName, $mode) {
1046:         self::$logger->debug('>>loadCustomController(BOName=['.$BOName.'], mode=['.$mode.'])');
1047: 
1048:         global $config;
1049: 
1050:         // strip the Object part from the class name
1051:         $BOName = substr($BOName, 0, strpos($BOName, 'Object'));
1052:         // uppercase the first letter of each word, e.g. create cart becomes Create Cart
1053:         $controllerName = ucwords($mode.' '.$BOName);
1054:         // remove spaces
1055:         $controllerName = str_replace(' ', '', $controllerName);
1056: 
1057:         self::$logger->debug('Custom controller name is ['.$controllerName.']');
1058: 
1059:         // just making sure that we are not already using the custom controller
1060:         if(get_class($this) != $controllerName) {
1061:             if (file_exists($config->get('app.root').'controller/'.$controllerName.'.php')) {
1062:                 self::$logger->debug('Custom controller found, redirecting...');
1063:                 // handle secure URLs
1064:                 if(isset($_GET['tk'])) {
1065:                     $params = FrontController::decodeQueryParams($_GET['tk']);
1066:                     $params = preg_replace('/act=.*\&/', 'act='.$controllerName.'&', $params);
1067:                     self::$logger->debug('Params are ['.$params.']');
1068: 
1069:                     $url = FrontController::generateSecureURL($params);
1070:                     self::$logger->debug('Redirecting to ['.$url.']');
1071:                     header('Location: '.$url);
1072:                     self::$logger->debug('<<loadCustomController');
1073:                     exit;
1074:                 }else{
1075:                     $url = $config->get('app.url').'controller/'.$controllerName.'.php?'.$_SERVER['QUERY_STRING'];
1076:                     self::$logger->debug('Redirecting to ['.$url.']');
1077:                     header('Location: '.$url);
1078:                     self::$logger->debug('<<loadCustomController');
1079:                     exit;
1080:                 }
1081:             }elseif (file_exists($config->get('app.root').'alpha/controller/'.$controllerName.'.php')) {
1082:                 self::$logger->debug('Custom controller found, redirecting...');
1083:                 // handle secure URLs
1084:                 if(self::checkIfAccessingFromSecureURL()) {
1085:                     if(isset($_GET['tk'])) {
1086:                         $params = FrontController::decodeQueryParams($_GET['tk']);
1087:                     }else{
1088:                         $start = strpos($_SERVER['REQUEST_URI'], '/tk/')+3;
1089:                         $end = strlen($_SERVER['REQUEST_URI']);
1090:                         $tk = substr($_SERVER['REQUEST_URI'], $start+1, $end-($start+1));
1091:                         $params = FrontController::decodeQueryParams($tk);
1092:                     }
1093: 
1094:                     $params = preg_replace('/act=.*\&/', 'act='.$controllerName.'&', $params);
1095:                     self::$logger->debug('Params are ['.$params.']');
1096: 
1097:                     $url = FrontController::generateSecureURL($params);
1098:                     self::$logger->debug('Redirecting to ['.$url.']');
1099:                     header('Location: '.$url);
1100:                     self::$logger->debug('<<loadCustomController');
1101:                     exit;
1102:                 }else{
1103:                     $url = $config->get('app.url').'alpha/controller/'.$controllerName.'.php?'.$_SERVER['QUERY_STRING'];
1104:                     self::$logger->debug('Redirecting to ['.$url.']');
1105:                     header('Location: '.$url);
1106:                     self::$logger->debug('<<loadCustomController');
1107:                     exit;
1108:                 }
1109:             }else{
1110:                 // throw an exception if we have gotten this far and no custom controller was found
1111:                 throw new FileNotFoundException('The controller ['.$controllerName.'] could not be loaded as it does not exist');
1112:             }
1113:         }
1114: 
1115:         self::$logger->debug('<<loadCustomController');
1116:     }
1117: 
1118:     /**
1119:      * Set the status message in the _SESSION to the value provided.
1120:      *
1121:      * @param string $message
1122:      * @since 1.0
1123:      */
1124:     public function setStatusMessage($message) {
1125:         $this->statusMessage = $message;
1126:         $_SESSION['statusMessage'] = $message;
1127:     }
1128: 
1129:     /**
1130:      * Gets the current status message for this controller.  Note that by getting the current
1131:      * status message, you clear out the value stored in _SESSION so this method can only be used
1132:      * to get the status message once for display purposes.
1133:      *
1134:      * @return string
1135:      * @since 1.0
1136:      */
1137:     public function getStatusMessage() {
1138:         $_SESSION['statusMessage'] = null;
1139:         return $this->statusMessage;
1140:     }
1141: 
1142:     /**
1143:      * Checks that the definition for the controller classname provided exists.  Will also return true
1144:      * if you pass "/" for the root of the web application.
1145:      *
1146:      * @param string $controllerName
1147:      * @return boolean
1148:      * @since 1.0
1149:      */
1150:     public static function checkControllerDefExists($controllerName) {
1151:         if(self::$logger == null)
1152:             self::$logger = new Logger('AlphaController');
1153:         self::$logger->debug('>>checkControllerDefExists(controllerName=['.$controllerName.'])');
1154: 
1155:         global $config;
1156: 
1157:         $exists = false;
1158: 
1159:         if($controllerName == '/')
1160:             $exists = true;
1161:         if(file_exists($config->get('app.root').'controller/'.$controllerName.'.php'))
1162:             $exists = true;
1163:         if(file_exists($config->get('app.root').'alpha/controller/'.$controllerName.'.php'))
1164:             $exists = true;
1165: 
1166:         self::$logger->debug('<<checkControllerDefExists ['.$exists.']');
1167:         return $exists;
1168:     }
1169: 
1170:     /**
1171:      * Loads the definition for the controller classname provided.
1172:      *
1173:      * @param string $controllerName
1174:      * @throws IllegalArguementException
1175:      * @since 1.0
1176:      */
1177:     public static function loadControllerDef($controllerName) {
1178:         if(self::$logger == null)
1179:             self::$logger = new Logger('AlphaController');
1180:         self::$logger->debug('>>loadControllerDef(controllerName=['.$controllerName.'])');
1181: 
1182:         global $config;
1183: 
1184:         if(file_exists($config->get('app.root').'controller/'.$controllerName.'.php'))
1185:             require_once $config->get('app.root').'controller/'.$controllerName.'.php';
1186:         elseif(file_exists($config->get('app.root').'alpha/controller/'.$controllerName.'.php'))
1187:             require_once $config->get('app.root').'alpha/controller/'.$controllerName.'.php';
1188:         else
1189:             throw new IllegalArguementException('The class ['.$controllerName.'] is not defined anywhere!');
1190: 
1191:         self::$logger->debug('<<loadControllerDef');
1192:     }
1193: 
1194:     /**
1195:      * Static function for determining if the current request URL is a secure one (has a tk string or not)
1196:      *
1197:      * @return boolean True if the current URL contains a tk value, false otherwise
1198:      * @since 1.0
1199:      */
1200:     public static function checkIfAccessingFromSecureURL() {
1201:         if (isset($_GET['tk']) || strpos($_SERVER['REQUEST_URI'], '/tk/') !== false)
1202:             return true;
1203:         else
1204:             return false;
1205:     }
1206: 
1207:     /**
1208:      * Descrypts the POST fieldnames in the global $_REQUEST and $_POST variables
1209:      *
1210:      * @since 1.2.2
1211:      */
1212:     private function decryptFieldNames() {
1213:         foreach(array_keys($_POST) as $fieldname) {
1214: 
1215:             // set request params where fieldnames provided are based64 encoded and encrypted
1216:             if(AlphaValidator::isBase64($fieldname)) {
1217:                 $_REQUEST[trim(AlphaSecurityUtils::decrypt(base64_decode($fieldname)))] = $_POST[$fieldname];
1218:                 $_POST[trim(AlphaSecurityUtils::decrypt(base64_decode($fieldname)))] = $_POST[$fieldname];
1219:             }
1220: 
1221:             // clear non-encrypted fields (we won't accept these when security.encrypt.http.fieldnames = true), and encrypted fieldnames already decrypted above.
1222:             unset($_POST[$fieldname]);
1223:             unset($_REQUEST[$fieldname]);
1224: 
1225:         }
1226:     }
1227: }
1228: 
1229: ?>
Alpha Framework ${alpha.version.new} API Documentation API documentation generated by ApiGen 2.8.0