Overview

Namespaces

  • Alpha
    • Controller
      • Front
    • Exception
    • Model
      • Type
    • Task
    • Util
      • Backup
      • Cache
      • Code
        • Highlight
        • Metric
      • Config
      • Convertor
      • Email
      • Extension
      • Feed
      • File
      • Graph
      • Helper
      • Http
        • Filter
        • Session
      • Image
      • Logging
      • Search
      • Security
    • View
      • Renderer
        • Html
        • Json
      • Widget

Classes

  • ActiveRecordController
  • ArticleController
  • AttachmentController
  • CacheController
  • Controller
  • DEnumController
  • ExcelController
  • FeedController
  • GenSecureQueryStringController
  • ImageController
  • IndexController
  • InstallController
  • ListActiveRecordsController
  • LogController
  • LoginController
  • LogoutController
  • MetricController
  • PhpinfoController
  • RecordSelectorController
  • SearchController
  • SequenceController
  • TagController

Interfaces

  • ControllerInterface
  • Overview
  • Namespace
  • Class
  • Tree
   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:  * The master controller class for the Alpha Framework.
  28:  *
  29:  * @since 1.0
  30:  *
  31:  * @author John Collins <dev@alphaframework.org>
  32:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
  33:  * @copyright Copyright (c) 2016, John Collins (founder of Alpha Framework).
  34:  * All rights reserved.
  35:  *
  36:  * <pre>
  37:  * Redistribution and use in source and binary forms, with or
  38:  * without modification, are permitted provided that the
  39:  * following conditions are met:
  40:  *
  41:  * * Redistributions of source code must retain the above
  42:  *   copyright notice, this list of conditions and the
  43:  *   following disclaimer.
  44:  * * Redistributions in binary form must reproduce the above
  45:  *   copyright notice, this list of conditions and the
  46:  *   following disclaimer in the documentation and/or other
  47:  *   materials provided with the distribution.
  48:  * * Neither the name of the Alpha Framework nor the names
  49:  *   of its contributors may be used to endorse or promote
  50:  *   products derived from this software without specific
  51:  *   prior written permission.
  52:  *
  53:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  54:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  55:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  56:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  57:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  58:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  59:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  60:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  61:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  63:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  64:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  65:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  66:  * </pre>
  67:  */
  68: abstract class Controller
  69: {
  70:     /**
  71:      * The name of the controller.
  72:      *
  73:      * @var string
  74:      *
  75:      * @since 1.0
  76:      */
  77:     protected $name;
  78: 
  79:     /**
  80:      * Used to set access privileages for the controller to the name of the rights group
  81:      * allowed to access it.  'Public' by default.
  82:      *
  83:      * @var string
  84:      *
  85:      * @since 1.0
  86:      */
  87:     protected $visibility = 'Public';
  88: 
  89:     /**
  90:      * Optionally, the main record object that this controller is currently working with.
  91:      *
  92:      * @var Alpha\Model\ActiveRecord
  93:      *
  94:      * @since 1.0
  95:      */
  96:     protected $record = null;
  97: 
  98:     /**
  99:      * Used to determine if the controller is part of a unit of work sequence
 100:      * (either empty or the name of the unit).
 101:      *
 102:      * @var string
 103:      *
 104:      * @since 1.0
 105:      */
 106:     protected $unitOfWork;
 107: 
 108:     /**
 109:      * Stores the start time of a unit of work transaction.
 110:      *
 111:      * @var Alpha\Model\Type\Timestamp
 112:      *
 113:      * @since 1.0
 114:      */
 115:     protected $unitStartTime;
 116: 
 117:     /**
 118:      * Stores the end time of a unit of work transaction.
 119:      *
 120:      * @var Alpha\Model\Type\Timestamp
 121:      *
 122:      * @since 1.0
 123:      */
 124:     protected $unitEndTime;
 125: 
 126:     /**
 127:      * Stores the maximum allowed time duration (in seconds) of the unit of work.
 128:      *
 129:      * @var Alpha\Model\Type\Integer
 130:      *
 131:      * @since 1.0
 132:      */
 133:     protected $unitMAXDuration;
 134: 
 135:     /**
 136:      * The name of the first controller that is used in this unit of work.
 137:      *
 138:      * @var string
 139:      *
 140:      * @since 1.0
 141:      */
 142:     protected $firstJob;
 143: 
 144:     /**
 145:      * The name of the next controller that is used in this unit of work.
 146:      *
 147:      * @var string
 148:      *
 149:      * @since 1.0
 150:      */
 151:     protected $nextJob;
 152: 
 153:     /**
 154:      * The name of the previous controller that is used in this unit of work.
 155:      *
 156:      * @var string
 157:      *
 158:      * @since 1.0
 159:      */
 160:     protected $previousJob;
 161: 
 162:     /**
 163:      * The name of the last controller that is used in this unit of work.
 164:      *
 165:      * @var string
 166:      *
 167:      * @since 1.0
 168:      */
 169:     protected $lastJob;
 170: 
 171:     /**
 172:      * An array for storing dirty record objects in a session (i.e. persistent business
 173:      * objects that have not been updated in the database yet).
 174:      *
 175:      * @var array
 176:      *
 177:      * @since 1.0
 178:      */
 179:     protected $dirtyObjects = array();
 180: 
 181:     /**
 182:      * An array for storing new reord objects in a session (transient business objects that
 183:      * have no OID yet).
 184:      *
 185:      * @var array
 186:      *
 187:      * @since 1.0
 188:      */
 189:     protected $newObjects = array();
 190: 
 191:     /**
 192:      * The title to be displayed on the controller page.
 193:      *
 194:      * @var string
 195:      *
 196:      * @since 1.0
 197:      */
 198:     protected $title;
 199: 
 200:     /**
 201:      * Meta keywords for the controller page, generally populated from tags.
 202:      *
 203:      * @var string
 204:      *
 205:      * @since 1.0
 206:      */
 207:     protected $keywords;
 208: 
 209:     /**
 210:      * Meta description for the controller page.
 211:      *
 212:      * @var string
 213:      *
 214:      * @since 1.0
 215:      */
 216:     protected $description;
 217: 
 218:     /**
 219:      * Used to set status update messages to display to the user (messages stored between requests
 220:      * in session).  Useful for when you want to display a message to a user after POSTing a request,
 221:      * or when moving from one page to the next.
 222:      *
 223:      * @var string
 224:      *
 225:      * @since 1.0
 226:      */
 227:     protected $statusMessage;
 228: 
 229:     /**
 230:      * The request that has been passed to this controller for processing.
 231:      *
 232:      * @var Alpha\Util\Http\Request
 233:      *
 234:      * @since 2.0
 235:      */
 236:     protected $request;
 237: 
 238:     /**
 239:      * Trace logger.
 240:      *
 241:      * @var Alpha\Util\Logging\Logger
 242:      *
 243:      * @since 1.0
 244:      */
 245:     private static $logger = null;
 246: 
 247:     /**
 248:      * Constructor for the Controller that starts a new session if required, and handles
 249:      * the population of new/dirty objects from the session when available.  Accepts the name
 250:      * of the rights group that has access to this controller, 'Public' by default.
 251:      *
 252:      * @param string $visibility The name of the rights group that can access this controller.
 253:      *
 254:      * @since 1.0
 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:         // set the access rights to the group name indicated
 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:         // uses controller class name as the job name
 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:      * Get the record for this controller (if any).
 299:      *
 300:      * @return mixed
 301:      *
 302:      * @since 1.0
 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:      * Setter for the record for this controller.
 314:      *
 315:      * @param Alpha\Model\ActiveRecord $record
 316:      *
 317:      * @since 1.0
 318:      */
 319:     public function setRecord($record)
 320:     {
 321:         self::$logger->debug('>>setRecord(record=['.var_export($record, true).'])');
 322:         $this->record = $record;
 323: 
 324:         // if the record has tags, use these as the meta keywords for this controller
 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:      * Get the name of the unit of work job.
 344:      *
 345:      * @return string
 346:      *
 347:      * @since 1.0
 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:      * Setter for the unit of work job name.
 359:      *
 360:      * @param string $name The fully-qualified controller class name, or an absolute URL.
 361:      *
 362:      * @since 1.0
 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:      * Get the name of the rights group that has access to this controller.
 373:      *
 374:      * @return string
 375:      *
 376:      * @since 1.0
 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:      * Setter for the name of the rights group that has access to this controller.
 388:      *
 389:      * @param string $visibility
 390:      *
 391:      * @since 1.0
 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:      * Gets the name of the first job in this unit of work.
 402:      *
 403:      * @return string The fully-qualified controller class name, or an absolute URL.
 404:      *
 405:      * @since 1.0
 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:      * Gets the name of the next job in this unit of work.
 417:      *
 418:      * @return string The fully-qualified controller class name, or an absolute URL.
 419:      *
 420:      * @since 1.0
 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:      * Gets the name of the previous job in this unit of work.
 432:      *
 433:      * @return string The fully-qualified controller class name, or an absolute URL.
 434:      *
 435:      * @since 1.0
 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:      * Gets the name of the last job in this unit of work.
 447:      *
 448:      * @return string The fully-qualified controller class name, or an absolute URL.
 449:      *
 450:      * @since 1.0
 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:      * Sets the name of the controller job sequence to the values in the supplied
 462:      * array (and stores the array in the session).
 463:      *
 464:      * @param array $jobs The names of the controllers in this unit of work sequence.  Will accept fully-qualified controller class name, or an absolute URL.
 465:      *
 466:      * @throws Alpha\Exception\IllegalArguementException
 467:      *
 468:      * @since 1.0
 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:         // validate that each controller name in the array actually exists
 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:         // clear out any previous unit of work from the session
 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:             // the first job in the sequence
 508:             if ($i == 0) {
 509:                 $this->firstJob = $jobs[$i];
 510:                 self::$logger->debug('First job ['.$this->firstJob.']');
 511:             }
 512:             // found the current job
 513:             if ($this->name == $jobs[$i]) {
 514:                 if (isset($jobs[$i - 1])) {
 515:                     // set the previous job if it exists
 516:                     $this->previousJob = $jobs[$i - 1];
 517:                     self::$logger->debug('Previous job ['.$this->previousJob.']');
 518:                 }
 519:                 if (isset($jobs[$i + 1])) {
 520:                     // set the next job if it exists
 521:                     $this->nextJob = $jobs[$i + 1];
 522:                     self::$logger->debug('Next job ['.$this->nextJob.']');
 523:                 }
 524:             }
 525:             // the last job in the sequence
 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:      * Getter for the unit start time.
 550:      *
 551:      * @return Timestamp
 552:      *
 553:      * @since 1.0
 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:      * Setter for the unit start time (value will be stored in the session as key unitStartTime).
 565:      *
 566:      * @param int $year
 567:      * @param int $month
 568:      * @param int $day
 569:      * @param int $hour
 570:      * @param int $minute
 571:      * @param int $second
 572:      *
 573:      * @since 1.0
 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:      * Getter for the unit end time.
 592:      *
 593:      * @return Alpha\Model\Type\Timestamp
 594:      *
 595:      * @since 1.0
 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:      * Setter for the unit end time (value will be stored in the session as key unitEndTime).
 607:      *
 608:      * @param int $year
 609:      * @param int $month
 610:      * @param int $day
 611:      * @param int $hour
 612:      * @param int $minute
 613:      * @param int $second
 614:      *
 615:      * @since 1.0
 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:      * Getter for the unit of work MAX duration.
 634:      *
 635:      * @return int
 636:      *
 637:      * @since 1.0
 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:      * Setter for the unit MAX duration.
 649:      *
 650:      * @param int $duration The desired duration in seconds.
 651:      *
 652:      * @since 1.0
 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:      * Calculates and returns the unit of work current duration in seconds.
 663:      *
 664:      * @return int
 665:      *
 666:      * @since 1.0
 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:      * Adds the supplied business object to the dirtyObjects array in the session.
 697:      *
 698:      * @param Alpha\Model\ActiveRecord $object
 699:      *
 700:      * @since 1.0
 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:      * Getter for the dirty objects array.
 727:      *
 728:      * @return array
 729:      *
 730:      * @since 1.0
 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:      * Adds a newly created business object to the newObjects array in the session.
 742:      *
 743:      * @param Alpha\Model\ActiveRecord $object
 744:      *
 745:      * @since 1.0
 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:      * Getter for the new objects array.
 772:      *
 773:      * @return array
 774:      *
 775:      * @since 1.0
 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:      * Commits (saves) all of the new and modified (dirty) objects in the unit of work to the database.
 787:      *
 788:      * @throws FailedUnitCommitException
 789:      *
 790:      * @since 1.0
 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:      * Method to clearup a cancelled unit of work.
 864:      *
 865:      * @throws Alpha\Exception\AlphaException
 866:      *
 867:      * @since 1.0
 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:      * Clears the session and object attributes related to unit of work sessions.
 895:      *
 896:      * @since 1.0
 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:      * Getter for the page title.
 914:      *
 915:      * @return string
 916:      *
 917:      * @since 1.0
 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:      * Setter for the page title.
 929:      *
 930:      * @param string $title
 931:      *
 932:      * @since 1.0
 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:      * Getter for the page description.
 943:      *
 944:      * @return string
 945:      *
 946:      * @since 1.0
 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:      * Setter for the page description.
 958:      *
 959:      * @param string $description
 960:      *
 961:      * @since 1.0
 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:      * Getter for the page keywords.
 972:      *
 973:      * @return string
 974:      *
 975:      * @since 1.0
 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:      * Setter for the page keywords, should pass a comma-seperated list as a string.
 987:      *
 988:      * @param string $keywords
 989:      *
 990:      * @since 1.0
 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:      * Method to return an access error for trespassing users.  HTTP response header code will be 403.
1001:      *
1002:      * @return Alpha\Util\Http\Response
1003:      *
1004:      * @since 1.0
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:      * Checks the user rights of the currently logged-in person against the page
1039:      * visibility set for this controller.  Will return false if the user has
1040:      * not got the correct rights.
1041:      *
1042:      * @return bool
1043:      *
1044:      * @since 1.0
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:         // firstly if the page is Public then there is no issue
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:             // the person is logged in?
1070:             if ($session->get('currentUser') !== false) {
1071: 
1072:                 // if the visibility is 'Session', just being logged in enough
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:                 // checking for admins (can access everything)
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:                 // the person is editing their own profile which is allowed
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 { // the person is NOT logged in
1115:                 self::$logger->debug('<<checkRights [false]');
1116: 
1117:                 return false;
1118:             }
1119:         }
1120:     }
1121: 
1122:     /**
1123:      * Method to check the validity of the two hidden form security
1124:      * fields which aim to ensure that a post to the controller is being sent from
1125:      * the same server that is hosting it.
1126:      *
1127:      * @return bool
1128:      *
1129:      * @since 1.0
1130:      */
1131:     public function checkSecurityFields()
1132:     {
1133:         self::$logger->debug('>>checkSecurityFields()');
1134: 
1135:         $host = $this->request->getHost();
1136:         $ip = $this->request->getIP();
1137: 
1138:         // the server hostname + today's date
1139:         $var1 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($host.date('Ymd'))), '+/', '-_'), '=');
1140:         // the server's IP plus $var1
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:              * Here we are implementing a "grace period" of one hour if the time is < 1:00AM, we will accept
1157:              * a match for yesterday's date in the security fields
1158:              *
1159:              */
1160: 
1161:             // the server hostname + today's date less 1 hour (i.e. yesterday where time is < 1:00AM)
1162:             $var1 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($host.date('Ymd', (time() - 3600)))), '+/', '-_'), '=');
1163:             // the server's IP plus $var1
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:      * Generates the two security fields to prevent remote form processing.
1181:      *
1182:      * @return array An array containing the two fields
1183:      *
1184:      * @since 1.0
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:         // the server hostname + today's date
1199:         $var1 = rtrim(strtr(base64_encode(SecurityUtils::encrypt($host.date('Ymd'))), '+/', '-_'), '=');
1200:         // the server's IP plus $var1
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:      * Returns the name of a custom controller if one is found, otherwise returns null.
1210:      *
1211:      * @param string $ActiveRecordType The classname of the active record
1212:      *
1213:      * @return string
1214:      *
1215:      * @since 1.0
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:      * Set the status message in the session to the value provided.
1256:      *
1257:      * @param string $message
1258:      *
1259:      * @since 1.0
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:      * Gets the current status message for this controller.  Note that by getting the current
1273:      * status message, you clear out the value stored in the session so this method can only be used
1274:      * to get the status message once for display purposes.
1275:      *
1276:      * @return string
1277:      *
1278:      * @since 1.0
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:      * Checks that the definition for the controller classname provided exists.  Will also return true
1293:      * if you pass "/" for the root of the web application.
1294:      *
1295:      * @param string $controllerName
1296:      *
1297:      * @return bool
1298:      *
1299:      * @since 1.0
1300:      * @deprecated
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:      * Loads the definition for the controller classname provided.
1330:      *
1331:      * @param string $controllerName
1332:      *
1333:      * @throws Alpha\Exception\IllegalArguementException
1334:      *
1335:      * @since 1.0
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:      * Method for determining if the current request URL is a secure one (has a tk string or not).
1359:      *
1360:      * @return bool True if the current URL contains a tk value, false otherwise
1361:      *
1362:      * @since 1.0
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:      * Descrypts the HTTP param fieldnames in the array provided and returns the plain version.
1375:      *
1376:      * @param $params array
1377:      *
1378:      * @return array
1379:      * 
1380:      * @since 1.2.2
1381:      */
1382:     private function decryptFieldNames($params)
1383:     {
1384:         $decrypted = array();
1385: 
1386:         foreach (array_keys($params) as $fieldname) {
1387: 
1388:             // set request params where fieldnames provided are based64 encoded and encrypted
1389:             if (Validator::isBase64($fieldname)) {
1390:                 $decrypted[SecurityUtils::decrypt(base64_decode($fieldname))] = $params[$fieldname];
1391:             }
1392:         }
1393: 
1394:         return $decrypted;
1395:     }
1396: 
1397:     /**
1398:      * Converts the supplied string to a "slug" that is URL safe and suitable for SEO.
1399:      *
1400:      * @param string $URLPart     The part of the URL to use as the slug
1401:      * @param string $seperator   The URL seperator to use (default is -)
1402:      * @param array  $filter      An optional array of charactors to filter out
1403:      * @param bool   $crc32Prefix Set to true if you want to prefix the slug with the CRC32 hash of the URLPart supplied
1404:      *
1405:      * @return string A URL slug
1406:      *
1407:      * @since 1.2.4
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:      * {@inheritdoc}
1431:      *
1432:      * @since 2.0
1433:      *
1434:      * @throws Alpha\Exception\NotImplementedException
1435:      */
1436:     public function doHEAD($request)
1437:     {
1438:         throw new NotImplementedException('The HEAD method is not supported by this controller');
1439:     }
1440: 
1441:     /**
1442:      * {@inheritdoc}
1443:      *
1444:      * @since 2.0
1445:      *
1446:      * @throws Alpha\Exception\NotImplementedException
1447:      */
1448:     public function doGET($request)
1449:     {
1450:         throw new NotImplementedException('The GET method is not supported by this controller');
1451:     }
1452: 
1453:     /**
1454:      * {@inheritdoc}
1455:      *
1456:      * @since 2.0
1457:      *
1458:      * @throws Alpha\Exception\NotImplementedException
1459:      */
1460:     public function doPOST($request)
1461:     {
1462:         throw new NotImplementedException('The POST method is not supported by this controller');
1463:     }
1464: 
1465:     /**
1466:      * {@inheritdoc}
1467:      *
1468:      * @since 2.0
1469:      *
1470:      * @throws Alpha\Exception\NotImplementedException
1471:      */
1472:     public function doPUT($request)
1473:     {
1474:         throw new NotImplementedException('The PUT method is not supported by this controller');
1475:     }
1476: 
1477:     /**
1478:      * {@inheritdoc}
1479:      *
1480:      * @since 2.0
1481:      *
1482:      * @throws Alpha\Exception\NotImplementedException
1483:      */
1484:     public function doPATCH($request)
1485:     {
1486:         throw new NotImplementedException('The PATCH method is not supported by this controller');
1487:     }
1488: 
1489:     /**
1490:      * {@inheritdoc}
1491:      *
1492:      * @since 2.0
1493:      *
1494:      * @throws Alpha\Exception\NotImplementedException
1495:      */
1496:     public function doDELETE($request)
1497:     {
1498:         throw new NotImplementedException('The DELETE method is not supported by this controller');
1499:     }
1500: 
1501:     /**
1502:      * {@inheritdoc}
1503:      *
1504:      * @since 2.0
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:      * {@inheritdoc}
1530:      *
1531:      * @since 2.0.2
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:      * Maps the supplied request with the appropiate method to run on this controller, for example
1557:      * GET to doGET(), POST to doPOST() etc.  Returns the response generated by the method called.
1558:      *
1559:      * @param Alpha\Util\Http\Request $request
1560:      *
1561:      * @return Alpha\Util\Http\Response
1562:      *
1563:      * @since 2.0
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:         // check the current user's rights on access to the page controller
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:      * Get the request this controller is processing (if any).
1632:      *
1633:      * @return Alpha\Util\Http\Request
1634:      *
1635:      * @since 2.0
1636:      */
1637:     public function getRequest()
1638:     {
1639:         return $this->request;
1640:     }
1641: 
1642:     /**
1643:      * Set the request this controller is processing.
1644:      *
1645:      * @param Alpha\Util\Http\Request $request
1646:      *
1647:      * @since 2.0
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:      * Use this callback to inject in the admin menu template fragment.
1660:      *
1661:      * @return string
1662:      *
1663:      * @since 1.2
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: 
Alpha Framework 2.0.4 API Documentation API documentation generated by ApiGen 2.8.0