      1: <?php
      2:
      3: /**
      4:  *
      5:  * The master rendering view class for the Alpha Framework.
      6:  *
      7:  * @package alpha::view
      8:  * @since 1.0
      9:  * @author John Collins <dev@alphaframework.org>
     10:  * @version $Id: AlphaView.inc 1664 2013-09-03 22:07:49Z alphadevx $
     11:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
     12:  * @copyright Copyright (c) 2013, John Collins (founder of Alpha Framework).
     13:  * All rights reserved.
     14:  *
     15:  * <pre>
     16:  * Redistribution and use in source and binary forms, with or
     17:  * without modification, are permitted provided that the
     18:  * following conditions are met:
     19:  *
     20:  * * Redistributions of source code must retain the above
     21:  *   copyright notice, this list of conditions and the
     22:  *   following disclaimer.
     23:  * * Redistributions in binary form must reproduce the above
     24:  *   copyright notice, this list of conditions and the
     25:  *   following disclaimer in the documentation and/or other
     26:  *   materials provided with the distribution.
     27:  * * Neither the name of the Alpha Framework nor the names
     28:  *   of its contributors may be used to endorse or promote
     29:  *   products derived from this software without specific
     30:  *   prior written permission.
     31:  *
     32:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     33:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     34:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     35:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     36:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     37:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     38:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     39:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     40:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     41:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     42:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     43:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     44:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     45:  * </pre>
     46:  *
     47:  */
     48: class AlphaView {
     49:     /**
     50:      * The business object that will be rendered
     51:      *
     52:      * @var AlphaDAO
     53:      * @since 1.0
     54:      */
     55:     protected $BO;
     56:
     57:         /**
     58:          * The rendering provider that will be used to render the business object
     59:          *
     60:          * @var AlphaRendererProviderInterface
     61:          * @since 1.2
     62:          */
     63:     protected $provider;
     64:
     65:     /**
     66:      * Trace logger
     67:      *
     68:      * @var Logger
     69:      * @since 1.0
     70:      */
     71:     private static $logger = null;
     72:
     73:     /**
     74:      * Constructor for the AlphaView.  As this is protected, use the AlphaView::getInstance method from a public scope.
     75:      *
     76:      * @param AlphaDAO $BO
     77:      * @throws IllegalArguementException
     78:      * @since 1.0
     79:      */
     80:     protected function __construct($BO) {
     81:         self::$logger = new Logger('AlphaView');
     82:         self::$logger->debug('>>__construct(BO=['.var_export($BO, true).'])');
     83:
     84:         global $config;
     85:
     86:         if(AlphaDAO::checkClassDefExists(get_class($BO)))
     87:             $this->BO = $BO;
     88:         else
     89:             throw new IllegalArguementException('The BO provided ['.get_class($BO).'] is not defined anywhere!');
     90:
     91:         $this->provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), $this->BO);
     92:
     93:         self::$logger->debug('<<__construct');
     94:     }
     95:
     96:     /**
     97:      * Static method which returns a AlphaView object or a custom child view for the BO specified
     98:      * if one exists
     99:      *
    100:      * @param AlphaDAO $BO The main business object that this view is going to render
    101:      * @param boolean $returnParent Flag to enforce the return of this object instead of a child (defaults to false)
    102:      * @return AlphaView Returns a AlphaView object, or a child view object from the /view directory if one exists for this BO
    103:      * @since 1.0
    104:      */
    105:     public static function getInstance($BO, $returnParent=false) {
    106:         if(self::$logger == null)
    107:             self::$logger = new Logger('AlphaView');
    108:         self::$logger->debug('>>getInstance(BO=['.var_export($BO, true).'], returnParent=['.$returnParent.'])');
    109:
    110:         global $config;
    111:
    112:         $filename = get_class($BO);
    113:         // remove the Object part
    114:         $filename = str_replace('Object', '', $filename);
    115:         // replace _ with space, then uppercase words
    116:         $filename = str_replace('_', ' ', $filename);
    117:         $filename = ucwords($filename).'View';
    118:         // finally, remove spaces
    119:         $filename = str_replace(' ', '', $filename);
    120:
    121:         // Check to see if a custom view exists for this BO, and if it does return that view instead
    122:         if (!$returnParent) {
    123:             if (file_exists($config->get('app.root').'view/'.$filename.'.inc')) {
    124:                 require_once $config->get('app.root').'view/'.$filename.'.inc';
    125:
    126:                 self::$logger->debug('<<getInstance [new '.$filename.'('.get_class($BO).')]');
    127:                 return new $filename($BO);
    128:             }elseif (file_exists($config->get('app.root').'alpha/view/'.$filename.'.inc')) {
    129:                 require_once $config->get('app.root').'alpha/view/'.$filename.'.inc';
    130:
    131:                 self::$logger->debug('<<getInstance [new '.$filename.'('.get_class($BO).')]');
    132:                 return new $filename($BO);
    133:             }else{
    134:                 self::$logger->debug('<<getInstance [new AlphaView('.get_class($BO).', true)]');
    135:                 return new AlphaView($BO, true);
    136:             }
    137:         }else{
    138:             self::$logger->debug('<<getInstance [new AlphaView('.get_class($BO).', true)]');
    139:             return new AlphaView($BO, true);
    140:         }
    141:     }
    142:
    143:     /**
    144:      * Simple setter for the view business object
    145:      *
    146:      * @param AlphaDAO $BO
    147:      * @throws IllegalArguementException
    148:      * @since 1.0
    149:      */
    150:     public function setBO($BO) {
    151:         self::$logger->debug('>>setBO(BO=['.var_export($BO, true).'])');
    152:
    153:         if(AlphaDAO::checkClassDefExists(get_class($BO)))
    154:             $this->BO = $BO;
    155:         else
    156:             throw new IllegalArguementException('The BO provided ['.get_class($BO).'] is not defined anywhere!');
    157:
    158:         self::$logger->debug('<<setBO');
    159:     }
    160:
    161:     /**
    162:      * Gets the BO attached to this view (if any)
    163:      *
    164:      * @return AlphaDAO
    165:      * @since 1.0
    166:      */
    167:     public function getBO() {
    168:         return $this->BO;
    169:     }
    170:
    171:     /**
    172:      * Renders the default create view to standard output
    173:      *
    174:      * @param array $fields Hash array of fields to pass to the template
    175:      * @since 1.0
    176:      */
    177:     public function createView($fields=array()) {
    178:         self::$logger->debug('>>createView(fields=['.var_export($fields, true).'])');
    179:
    180:         if(method_exists($this, 'before_createView_callback'))
    181:             $this->before_createView_callback();
    182:
    183:         global $config;
    184:
    185:         $body = $this->provider->createView($fields);
    186:
    187:         echo $body;
    188:
    189:         if(method_exists($this, 'after_createView_callback'))
    190:             $this->after_createView_callback();
    191:
    192:         self::$logger->debug('<<createView');
    193:     }
    194:
    195:     /**
    196:      * Renders a form to enable object editing to standard output
    197:      *
    198:      * @param array $fields Hash array of fields to pass to the template
    199:      * @since 1.0
    200:      */
    201:     public function editView($fields=array()) {
    202:         self::$logger->debug('>>editView(fields=['.var_export($fields, true).'])');
    203:
    204:         if(method_exists($this, 'before_editView_callback'))
    205:             $this->before_editView_callback();
    206:
    207:         global $config;
    208:
    209:         $body = $this->provider->editView($fields);
    210:
    211:         echo $body;
    212:
    213:         if(method_exists($this, 'after_editView_callback'))
    214:             $this->after_editView_callback();
    215:
    216:         self::$logger->debug('<<editView');
    217:     }
    218:
    219:     /**
    220:      * Renders the list view to standard output
    221:      *
    222:      * @param array $fields Hash array of fields to pass to the template
    223:      * @since 1.0
    224:      */
    225:     public function listView($fields=array()) {
    226:         self::$logger->debug('>>listView(fields=['.var_export($fields, true).'])');
    227:
    228:         if(method_exists($this, 'before_listView_callback'))
    229:             $this->before_listView_callback();
    230:
    231:         global $config;
    232:
    233:         $body = $this->provider->listView($fields);
    234:
    235:         echo $body;
    236:
    237:         if(method_exists($this, 'after_listView_callback'))
    238:             $this->after_listView_callback();
    239:
    240:         self::$logger->debug('<<listView');
    241:     }
    242:
    243:     /**
    244:      * Displays a detailed view of the object (read-only) to standard output
    245:      *
    246:      * @param array $fields Hash array of fields to pass to the template
    247:      * @since 1.0
    248:      */
    249:     public function detailedView($fields=array()) {
    250:         self::$logger->debug('>>detailedView(fields=['.var_export($fields, true).'])');
    251:
    252:         if(method_exists($this, 'before_detailedView_callback'))
    253:             $this->before_detailedView_callback();
    254:
    255:         global $config;
    256:
    257:         $body = $this->provider->detailedView($fields);
    258:
    259:         echo $body;
    260:
    261:         if(method_exists($this, 'after_detailedView_callback'))
    262:             $this->after_detailedView_callback();
    263:
    264:         self::$logger->debug('<<detailedView');
    265:     }
    266:
    267:     /**
    268:      * Renders the admin view for the business object screen to standard output
    269:      *
    270:      * @param array $fields Hash array of fields to pass to the template
    271:      * @since 1.0
    272:      */
    273:     public function adminView($fields=array()) {
    274:         self::$logger->debug('>>adminView(fields=['.var_export($fields, true).'])');
    275:
    276:         if(method_exists($this, 'before_adminView_callback'))
    277:             $this->before_adminView_callback();
    278:
    279:         global $config;
    280:
    281:         $body = $this->provider->adminView($fields);
    282:
    283:         echo $body;
    284:
    285:         if(method_exists($this, 'after_adminView_callback'))
    286:             $this->after_adminView_callback();
    287:
    288:         self::$logger->debug('<<adminView');
    289:     }
    290:
    291:     /**
    292:      * Method to render the page header content
    293:      *
    294:      * @param AlphaController $controller
    295:      * @return string
    296:      * @throws IllegalArguementException
    297:      * @since 1.0
    298:      */
    299:     public static function displayPageHead($controller) {
    300:         if(self::$logger == null)
    301:             self::$logger = new Logger('AlphaView');
    302:         self::$logger->debug('>>displayPageHead(controller=['.var_export($controller, true).'])');
    303:
    304:         if(method_exists($controller, 'before_displayPageHead_callback'))
    305:             $controller->before_displayPageHead_callback();
    306:
    307:         global $config;
    308:
    309:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    310:         eval('$header = '.get_class($provider).'::displayPageHead($controller);');
    311:
    312:         if(method_exists($controller, 'after_displayPageHead_callback'))
    313:             $header.= $controller->after_displayPageHead_callback();
    314:
    315:         self::$logger->debug('<<displayPageHead ['.$header.']');
    316:         return $header;
    317:     }
    318:
    319:     /**
    320:      * Method to render the page footer content
    321:      *
    322:      * @param AlphaController $controller
    323:      * @return string
    324:      * @since 1.0
    325:      */
    326:     public static function displayPageFoot($controller) {
    327:         if(self::$logger == null)
    328:             self::$logger = new Logger('AlphaView');
    329:
    330:         self::$logger->debug('>>displayPageFoot(controller=['.get_class($controller).'])');
    331:
    332:         global $config;
    333:
    334:         $footer = '';
    335:
    336:         if(method_exists($controller, 'before_displayPageFoot_callback'))
    337:             $footer .= $controller->before_displayPageFoot_callback();
    338:
    339:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    340:         eval('$footer .= '.get_class($provider).'::displayPageFoot($controller);');
    341:
    342:         if(method_exists($controller, 'after_displayPageFoot_callback'))
    343:             $footer .= $controller->after_displayPageFoot_callback();
    344:
    345:         self::$logger->debug('<<displayPageFoot ['.$footer.']');
    346:         return $footer;
    347:     }
    348:
    349:     /**
    350:      * Renders the content for an update (e.g. successful save) message
    351:      *
    352:      * @param string $message
    353:      * @return string
    354:      * @since 1.0
    355:      */
    356:     public static function displayUpdateMessage($message) {
    357:         if(self::$logger == null)
    358:             self::$logger = new Logger('AlphaView');
    359:         self::$logger->debug('>>displayUpdateMessage(message=['.$message.'])');
    360:
    361:         global $config;
    362:
    363:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    364:         eval('$message = '.get_class($provider).'::displayUpdateMessage($message);');
    365:
    366:         self::$logger->debug('<<displayUpdateMessage ['.$message.']');
    367:         return $message;
    368:     }
    369:
    370:     /**
    371:      * Renders the content for an error (e.g. save failed) message
    372:      *
    373:      * @param string $message
    374:      * @return string
    375:      * @since 1.0
    376:      */
    377:     public static function displayErrorMessage($message) {
    378:         if(self::$logger == null)
    379:             self::$logger = new Logger('AlphaView');
    380:         self::$logger->debug('>>displayErrorMessage(message=['.$message.'])');
    381:
    382:         global $config;
    383:
    384:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    385:         eval('$message = '.get_class($provider).'::displayErrorMessage($message);');
    386:
    387:         self::$logger->debug('<<displayErrorMessage ['.$message.']');
    388:         return $message;
    389:     }
    390:
    391:     /**
    392:      * Renders an error page with the supplied error code (typlically a HTTP code) and a message
    393:      *
    394:      * @param string $code
    395:      * @param string $message
    396:      * @return string
    397:      * @since 1.0
    398:      */
    399:     public static function renderErrorPage($code, $message) {
    400:         if(self::$logger == null)
    401:             self::$logger = new Logger('AlphaView');
    402:         self::$logger->debug('>>renderErrorPage(code=['.$code.'],message=['.$message.'])');
    403:
    404:         global $config;
    405:
    406:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    407:         eval('$message = '.get_class($provider).'::renderErrorPage($code, $message);');
    408:
    409:         self::$logger->debug('<<renderErrorPage ['.$message.']');
    410:         return $message;
    411:     }
    412:
    413:     /**
    414:      * Method to render a hidden HTML form for posting the OID of an object to be deleted
    415:      *
    416:      * @return string
    417:      * @since 1.0
    418:      */
    419:     public static function renderDeleteForm() {
    420:         if(self::$logger == null)
    421:             self::$logger = new Logger('AlphaView');
    422:         self::$logger->debug('>>renderDeleteForm()');
    423:
    424:         global $config;
    425:
    426:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    427:         eval('$html = '.get_class($provider).'::renderDeleteForm();');
    428:
    429:         self::$logger->debug('<<renderDeleteForm ['.$html.']');
    430:         return $html;
    431:     }
    432:
    433:     /**
    434:      * Method to render a HTML form with two hidden, hashed (MD5) form fields to be used as
    435:      * a check to ensure that a post to the controller is being sent from the same server
    436:      * as hosting it.
    437:      *
    438:      * @return string
    439:      * @since 1.0
    440:      */
    441:     public static function renderSecurityFields() {
    442:         if(self::$logger == null)
    443:             self::$logger = new Logger('AlphaView');
    444:         self::$logger->debug('>>renderSecurityFields()');
    445:
    446:         global $config;
    447:
    448:         $provider = AlphaRendererProviderFactory::getInstance($config->get('app.renderer.provider.name'), new PersonObject());
    449:         eval('$html = '.get_class($provider).'::renderSecurityFields();');
    450:
    451:         self::$logger->debug('<<renderSecurityFields ['.$html.']');
    452:         return $html;
    453:     }
    454:
    455:     /**
    456:      * Method to render the default Integer HTML
    457:      *
    458:      * @param string $name The field name
    459:      * @param string $label The label to apply to the field
    460:      * @param string $mode The field mode (create/edit/view)
    461:      * @param string $value The field value (optional)
    462:      * @param bool $tableTags Include table tags and label (optional)
    463:      * @return string
    464:      * @since 1.0
    465:      */
    466:     public function renderIntegerField($name, $label, $mode, $value='', $tableTags=true) {
    467:         self::$logger->debug('>>renderIntegerField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    468:
    469:         global $config;
    470:
    471:         $html = $this->provider->renderIntegerField($name, $label, $mode, $value, $tableTags);
    472:
    473:         self::$logger->debug('<<renderIntegerField ['.$html.']');
    474:         return $html;
    475:     }
    476:
    477:     /**
    478:      * Method to render the default Double HTML
    479:      *
    480:      * @param string $name The field name
    481:      * @param string $label The label to apply to the field
    482:      * @param string $mode The field mode (create/edit/view)
    483:      * @param string $value The field value (optional)
    484:      * @param bool $tableTags Include table tags and label (optional)
    485:      * @return string
    486:      * @since 1.0
    487:      */
    488:     public function renderDoubleField($name, $label, $mode, $value='', $tableTags=true) {
    489:         self::$logger->debug('>>renderDoubleField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    490:
    491:         global $config;
    492:
    493:         $html = $this->provider->renderDoubleField($name, $label, $mode, $value, $tableTags);
    494:
    495:         self::$logger->debug('<<renderDoubleField ['.$html.']');
    496:         return $html;
    497:     }
    498:
    499:     /**
    500:      * Method to render the default Boolean HTML
    501:      *
    502:      * @param string $name The field name
    503:      * @param string $label The label to apply to the field
    504:      * @param string $mode The field mode (create/edit/view)
    505:      * @param string $value The field value (optional)
    506:      * @param bool $tableTags Include table tags and label (optional)
    507:      * @return string
    508:      * @since 1.0
    509:      */
    510:     public function renderBooleanField($name, $label, $mode, $value='', $tableTags=true) {
    511:         self::$logger->debug('>>renderBooleanField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    512:
    513:         global $config;
    514:
    515:         $html = $this->provider->renderBooleanField($name, $label, $mode, $value, $tableTags);
    516:
    517:         self::$logger->debug('<<renderBooleanField ['.$html.']');
    518:         return $html;
    519:     }
    520:
    521:     /**
    522:      * Method to render the default Enum HTML
    523:      *
    524:      * @param string $name The field name
    525:      * @param string $label The label to apply to the field
    526:      * @param string $mode The field mode (create/edit/view)
    527:      * @param array $options The Enum options
    528:      * @param string $value The field value (optional)
    529:      * @param bool $tableTags Include table tags and label (optional)
    530:      * @return string
    531:      * @since 1.0
    532:      */
    533:     public function renderEnumField($name, $label, $mode, $options, $value='', $tableTags=true) {
    534:         self::$logger->debug('>>renderEnumField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    535:
    536:         global $config;
    537:
    538:         $html = $this->provider->renderEnumField($name, $label, $mode, $options, $value, $tableTags);
    539:
    540:         self::$logger->debug('<<renderEnumField ['.$html.']');
    541:         return $html;
    542:     }
    543:
    544:     /**
    545:      * Method to render the default DEnum HTML
    546:      *
    547:      * @param string $name The field name
    548:      * @param string $label The label to apply to the field
    549:      * @param string $mode The field mode (create/edit/view)
    550:      * @param array $options The DEnum options
    551:      * @param string $value The field value (optional)
    552:      * @param bool $tableTags Include table tags and label (optional)
    553:      * @return string
    554:      * @since 1.0
    555:      */
    556:     public function renderDEnumField($name, $label, $mode, $options, $value='', $tableTags=true) {
    557:         self::$logger->debug('>>renderDEnumField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    558:
    559:         global $config;
    560:
    561:         $html = $this->provider->renderDEnumField($name, $label, $mode, $options, $value, $tableTags);
    562:
    563:         self::$logger->debug('<<renderDEnumField ['.$html.']');
    564:         return $html;
    565:     }
    566:
    567:     /**
    568:      * Method to render the default field HTML when type is not known
    569:      *
    570:      * @param string $name The field name
    571:      * @param string $label The label to apply to the field
    572:      * @param string $mode The field mode (create/edit/view)
    573:      * @param string $value The field value (optional)
    574:      * @param bool $tableTags Include table tags and label (optional)
    575:      * @return string
    576:      * @since 1.0
    577:      */
    578:     public function renderDefaultField($name, $label, $mode, $value='', $tableTags=true) {
    579:         self::$logger->debug('>>renderDefaultField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    580:
    581:         global $config;
    582:
    583:         $html = $this->provider->renderDefaultField($name, $label, $mode, $value, $tableTags);
    584:
    585:         self::$logger->debug('<<renderDefaultField ['.$html.']');
    586:         return $html;
    587:     }
    588:
    589:     /**
    590:      * render the default Text HTML
    591:      *
    592:      * @param string $name The field name
    593:      * @param string $label The label to apply to the field
    594:      * @param string $mode The field mode (create/edit/view)
    595:      * @param string $value The field value (optional)
    596:      * @param bool $tableTags Include table tags and label (optional)
    597:      * @return string
    598:      * @since 1.0
    599:      */
    600:     public function renderTextField($name, $label, $mode, $value='', $tableTags=true) {
    601:         self::$logger->debug('>>renderTextField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'])');
    602:
    603:         global $config;
    604:
    605:         $html = $this->provider->renderTextField($name, $label, $mode, $value, $tableTags);
    606:
    607:         self::$logger->debug('<<renderTextField ['.$html.']');
    608:         return $html;
    609:     }
    610:
    611:     /**
    612:      * render the default Relation HTML
    613:      *
    614:      * @param string $name The field name
    615:      * @param string $label The label to apply to the field
    616:      * @param string $mode The field mode (create/edit/view)
    617:      * @param string $value The field value (optional)
    618:      * @param bool $tableTags Include table tags and label (optional)
    619:      * @param bool $expanded Render the related fields in expanded format or not (optional)
    620:      * @param bool $buttons Render buttons for expanding/contacting the related fields (optional)
    621:      * @return string
    622:      * @since 1.0
    623:      */
    624:     public function renderRelationField($name, $label, $mode, $value='', $tableTags=true, $expanded=false, $buttons=true) {
    625:         self::$logger->debug('>>renderRelationField(name=['.$name.'], label=['.$label.'], mode=['.$mode.'], value=['.$value.'], tableTags=['.$tableTags.'], expanded=['.$expanded.'], buttons=['.$buttons.'])');
    626:
    627:         global $config;
    628:
    629:         $html = $this->provider->renderRelationField($name, $label, $mode, $value, $tableTags, $expanded, $buttons);
    630:
    631:         self::$logger->debug('<<renderRelationField ['.$html.']');
    632:         return $html;
    633:     }
    634:
    635:     /**
    636:      * Renders all fields for the current BO in edit/create/view mode
    637:      *
    638:      * @param string $mode (view|edit|create)
    639:      * @param array $filterFields Optional list of field names to exclude from rendering
    640:      * @param array $readOnlyFields Optional list of fields to render in a readonly fashion when rendering in create or edit mode
    641:      * @return string
    642:      * @since 1.0
    643:      */
    644:     public function renderAllFields($mode, $filterFields=array(), $readOnlyFields=array()) {
    645:         self::$logger->debug('>>renderAllFields(mode=['.$mode.'], filterFields=['.var_export($filterFields, true).'], readOnlyFields=['.var_export($readOnlyFields, true).'])');
    646:
    647:         global $config;
    648:
    649:         $html = $this->provider->renderAllFields($mode, $filterFields, $readOnlyFields);
    650:
    651:         self::$logger->debug('<<renderAllFields ['.$html.']');
    652:         return $html;
    653:     }
    654:
    655:     /**
    656:      * Loads a template for the BO specified if one exists.  Lower level custom templates
    657:      * take precedence.
    658:      *
    659:      * @param AlphaDAO $BO
    660:      * @param string $mode
    661:      * @param array $fields
    662:      * @since 1.0
    663:      * @throws IllegalArguementException
    664:      */
    665:     public static function loadTemplate($BO, $mode, $fields) {
    666:         self::$logger->debug('>>loadTemplate(BO=['.var_export($BO, true).'], mode=['.$mode.'], fields=['.var_export($fields, true).'])');
    667:
    668:         global $config;
    669:
    670:         // for each BO property, create a local variable holding its value
    671:         $reflection = new ReflectionClass(get_class($BO));
    672:         $properties = $reflection->getProperties();
    673:
    674:         foreach($properties as $propObj) {
    675:             $propName = $propObj->name;
    676:
    677:             if($propName != 'logger' && !$propObj->isPrivate()) {
    678:                 $prop = $BO->getPropObject($propName);
    679:                 if($prop instanceof DEnum) {
    680:                     ${$propName} = $BO->getPropObject($propName)->getDisplayValue();
    681:                 }else{
    682:                     ${$propName} = $BO->get($propName);
    683:                 }
    684:             }
    685:         }
    686:
    687:         // loop over the $fields array and create a local variable for each key value
    688:         foreach (array_keys($fields) as $fieldName)
    689:             ${$fieldName} = $fields[$fieldName];
    690:
    691:         $filename = $mode.'.phtml';
    692:         $classTemplateDir = get_class($BO);
    693:
    694:         $customPath = $config->get('app.root').'view/html/templates/'.$classTemplateDir.'/'.$filename;
    695:         $defaultPath1 = $config->get('app.root').'alpha/view/renderers/html/templates/'.$classTemplateDir.'/'.$filename;
    696:         $defaultPath2 = $config->get('app.root').'alpha/view/renderers/html/templates/'.$filename;
    697:
    698:         // Check to see if a custom template exists for this BO, and if it does load that
    699:         if (file_exists($customPath)) {
    700:             self::$logger->debug('Loading template ['.$customPath.']');
    701:             require $customPath;
    702:         }elseif (file_exists($defaultPath1)) {
    703:             self::$logger->debug('Loading template ['.$defaultPath1.']');
    704:             require $defaultPath1;
    705:         }elseif (file_exists($defaultPath2)) {
    706:             self::$logger->debug('Loading template ['.$defaultPath2.']');
    707:             require $defaultPath2;
    708:         }else{
    709:             throw new IllegalArguementException('No ['.$mode.'] HTML template found for class ['.get_class($BO).']');
    710:         }
    711:
    712:         self::$logger->debug('<<loadTemplate');
    713:     }
    714:
    715:     /**
    716:      * Loads a template fragment from the renderers/[type]/fragments/[filename.ext] location.
    717:      *
    718:      * @param string $type Currently only html supported, later json and xml.
    719:      * @param string $fileName The name of the fragment file
    720:      * @param array $fields A hash array of field values to pass to the template fragment.
    721:      * @since 1.2
    722:      * @throws IllegalArguementException
    723:      */
    724:     public static function loadTemplateFragment($type, $fileName, $fields) {
    725:         if(self::$logger == null)
    726:             self::$logger = new Logger('AlphaView');
    727:         self::$logger->debug('>>loadTemplateFragment(type=['.$type.'], fileName=['.$fileName.'], fields=['.var_export($fields, true).'])');
    728:
    729:         global $config;
    730:
    731:         // loop over the $fields array and create a local variable for each key value
    732:         foreach (array_keys($fields) as $fieldName)
    733:             ${$fieldName} = $fields[$fieldName];
    734:
    735:         $customPath = $config->get('app.root').'view/'.$type.'/fragments/'.$fileName;
    736:         $defaultPath = $config->get('app.root').'alpha/view/renderers/'.$type.'/fragments/'.$fileName;
    737:
    738:         // Check to see if a custom template exists for this BO, and if it does load that
    739:         if (file_exists($customPath)) {
    740:             self::$logger->debug('Loading template ['.$customPath.']');
    741:             require $customPath;
    742:         }elseif (file_exists($defaultPath)) {
    743:             self::$logger->debug('Loading template ['.$defaultPath.']');
    744:             require $defaultPath;
    745:         }else{
    746:             throw new IllegalArguementException('Template fragment not found in ['.$customPath.'] or ['.$defaultPath.']!');
    747:         }
    748:
    749:         self::$logger->debug('<<loadTemplateFragment');
    750:     }
    751:
    752:     /**
    753:      * Enables you to set an explicit type of AlphaRendererProviderInterface implementation to use for rendering the business
    754:      * object attached to this view.  Note that this has no affect on static methods of the AlphaView class, which always instantiate
    755:      * a new AlphaRendererProviderInterface provider each time they're called.
    756:      *
    757:      * @param string $ProviderClassName The name of the AlphaRendererProviderInterface implementation to use in this view object
    758:      * @since 1.2
    759:      * @throws IllegalArguementException
    760:      */
    761:     public function setProvider($ProviderClassName) {
    762:         $this->provider = AlphaRendererProviderFactory::getInstance($ProviderClassName, $this->BO);
    763:     }
    764: }
    765:
    766: ?>