Xataface HTML Reports Module 0.1
HTML Reports Module for Xataface
classes/XfHtmlReportBuilder.class.php
Go to the documentation of this file.
00001 <?php
00002 /*
00003  * Xataface HTML Reports Module
00004  * Copyright (C) 2011  Steve Hannah <steve@weblite.ca>
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Library General Public
00017  * License along with this library; if not, write to the
00018  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00019  * Boston, MA  02110-1301, USA.
00020  *
00021  */
00022 require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'simple_html_dom.php';
00023 
00028 class XfHtmlReportBuilder {
00029         
00030         const COMPILE_ERROR = 501;
00031         public static $SUMMARY_FUNCTIONS = array('sum','min','max','count');
00032         
00033         private $templateContent = null;
00034         private $records = null;
00035         private $output = '';
00036         
00037         private $context = null;
00038         
00043         protected $strict = false;
00044         
00045         
00051         public static function getFields($el){
00052                 $out = array();
00053                 if ( preg_match_all('/\{\$([^\}]+)\}/', $el->outertext, $matches, PREG_SET_ORDER) ){
00054                         foreach ($matches as $match){
00055                                 $out[] = trim($match[1]);
00056                         }
00057                 }
00058                 $out = array_unique($out);
00059                 return $out;
00060         }
00061         
00067         public static function getSummaryFields($el){
00068                 $out = array();
00069                 if ( preg_match_all('/\{@([a-zA-Z]+\([^\}]+\))\}/', $el->outertext, $matches, PREG_SET_ORDER) ){
00070                         foreach ($matches as $match){
00071                                 $out[] = trim($match[1]);
00072                         }
00073                 }
00074                 $out = array_unique($out);
00075                 return $out;
00076         
00077         }
00078         
00079         
00090         public static function printGroupData(&$groupData, $groupFields, $summaryFields, $groupHeaders, $groupFooters, $template, $asTable){
00091                 $header = $groupHeaders[$groupData['level']];
00092                 $footer = $groupFooters[$groupData['level']];
00093                 $gfields = $groupFields[$groupData['level']];
00094                 $sfields = $summaryFields[$groupData['level']];
00095                 if ( !@$groupData['summaryRecord'] ){
00096                         throw new Exception("No summary record provided.", 2000);
00097                 }
00098                 $headerText = '';
00099                 if ( $header ){
00100                         $headerText = self::fillReportSingle($groupData['summaryRecord'], $header->innertext);
00101                 }
00102                 $bodyText = '';
00103                 if ( isset($groupData['sections']) ){
00104                         foreach ($groupData['sections'] as $key=>$section){
00105                                 $bodyText .= self::printGroupData($groupData['sections'][$key], $groupFields, $summaryFields, $groupHeaders, $groupFooters, $template, $asTable);
00106                                 
00107                         }
00108                 } else if ( isset($groupData['records']) ){
00109                         $bodyText = self::fillReportMultiple($groupData['records'], $template, false /* no headers */, $asTable);
00110                 }
00111                 $footerText = '';
00112                 if ( $footer ){
00113                         $footerText = self::fillReportSingle($groupData['summaryRecord'], $footer->innertext);
00114                 }
00115                 return $headerText.$bodyText.$footerText;
00116         }
00117         
00126         public static function getGroupKey(Dataface_Record $record, $fields){
00127                 $out = array();
00128                 foreach ($fields as $f){
00129                         $out[] = urlencode($f).'='.urlencode($record->val($f));
00130                 }
00131                 return implode('&', $out);
00132         }
00133         
00134         
00145         public static function fillReportTable($records, $template, $headersAndFooters=true){
00146 
00147                 return self::fillReportMultiple($records, $template, $headersAndFooters, true);
00148         }
00149         
00150         
00159         public static function fillReportMultiple($records, $template, $headersAndFooters=true, $asTable=false){
00160                 if ( !is_array($records) ){
00161                         throw new Exception("Records must be an array.", 2000);
00162                 }
00163                 if ( is_string($template) ){
00164                         $el = str_get_html($template);
00165                 } else {
00166                         $el = $template;
00167                 }
00168                 $groupFields = array();
00169                 $summaryFields = array();
00170                 
00171                 $sectionHeaderEls = $el->find('div.xf-htmlreports-section-header');
00172                 $sectionFooterEls = $el->find('div.xf-htmlreports-section-footer');
00173                 $numLevels = max(count($sectionHeaderEls), count($sectionFooterEls));
00174 
00175                 if ( $numLevels > 0 ){
00176                         if ( !$headersAndFooters ){
00177                                 // Caller doesn't want headers and footers.  We clear them out
00178                                 // then process the remainder of the template.
00179                                 foreach ($sectionHeaderEls as $myel){
00180                                         $myel->outertext = '';
00181                                 }
00182                                 foreach ($sectionFooterEls as $myel){
00183                                         $myel->outertext = '';
00184                                 }
00185                                 return self::fillReportMultiple($records, $el->outertext, false, $asTable);
00186                         }
00187                         $groupFooters = array();
00188                         $groupHeaders = array();
00189                         
00190                         
00191                         for ($i=0; $i<$numLevels; $i++){
00192                                 $groupFields[$i] =  $summaryFields[$i] = array();
00193                                 $groupHeaders[$i] = $groupFooters[$i] = null;
00194                         }
00195                         
00196                         for ($i=0; $i<$numLevels; $i++){
00197                         
00198                                 $j = $numLevels-$i-1;
00199                                 
00200                                 if ( isset($sectionHeaderEls[$i]) ){
00201                                         $groupFields[$i] = array_merge($groupFields[$i], self::getFields($sectionHeaderEls[$i]));
00202                                         $summaryFields[$i] = array_merge($summaryFields[$i], self::getSummaryFields($sectionHeaderEls[$i]));
00203                                         $groupHeaders[$i] = $sectionHeaderEls[$i];
00204                                 } 
00205                                 
00206                                 
00207                                 if ( isset($sectionFooterEls[$j]) ){
00208                                         $groupFields[$i] = array_merge($groupFields[$j], self::getFields($sectionFooterEls[$j]));
00209                                         $summaryFields[$i] = array_merge($summaryFields[$j], self::getSummaryFields($sectionFooterEls[$j]));
00210                                         $groupFooters[$i] = $sectionFooterEls[$j];
00211                                 }
00212                                 
00213                         }
00214                         
00215                         for ( $i=0; $i<$numLevels; $i++){
00216                                 $groupFields[$i] = array_unique($groupFields[$i]);
00217                                 $summaryFields[$i] = array_unique($summaryFields[$i]);
00218                                 
00219                         }
00220                         
00221                         
00222                         // Now that we have our groupings and summaries we can proceed to
00223                         // group the records and create summary rows.
00224                         
00225         
00226                         foreach ($records as $record){
00227                                 $node =& $tree;
00228                                 for ( $i=0; $i<$numLevels; $i++){       
00229                                         $groupKey = self::getGroupKey($record, $groupFields[$i]);
00230                                         if ( !isset($node[$groupKey]) ){
00231                                                 $node[$groupKey] = array(
00232                                                         'summaryRecord'=> null,
00233                                                         'level'=>$i
00234                                                 );
00235                                                 if ( $i<$numLevels-1 ){
00236                                                         $node[$groupKey]['sections'] = array();
00237                                                 } else {
00238                                                         $node[$groupKey]['records'] = array();
00239                                                 }
00240                                         }
00241                                         
00242                                         $temp =& $node[$groupKey];
00243                                         unset($node);
00244                                         if ( isset($temp['sections']) ){
00245                                                 $node =& $temp['sections'];
00246                                         } else {
00247                                                 $node =& $temp['records'];
00248                                         }
00249                                         unset($temp);
00250                                         
00251                                 }
00252                                 $node[] = $record;
00253                                 unset($node);
00254                         }
00255                         $out = '';
00256                         foreach (array_keys($tree) as $groupKey){
00257                                 $groupData =& $tree[$groupKey];
00258                                 self::compileGroupData(&$groupData, $groupFields, $summaryFields);
00259                                 $out .= self::printGroupData(&$groupData, $groupFields, $summaryFields, $groupHeaders, $groupFooters, $template, $asTable);
00260                                 
00261                                 
00262                         }
00263                 
00264                 } else {
00265                 
00266                         $out = '';
00267                         
00268                                 
00269                         
00270                         if ( !is_array($records) ){
00271                                 throw new Exception("No array of records provided.", 2000);
00272                         }
00273                         
00274                         
00275                         if ( $asTable ){
00276                                 $fields = self::getFields($el);
00277                                 $rowtemplate = '<tr>';
00278                                 foreach ($fields as $field){
00279                                         $fielddef = $records[0]->table()->getField($field);
00280                                         if ( PEAR::isError($fielddef) ) continue;
00281                                         $rowtemplate .= '<td class="xf-htmlreports-field xf-htmlreports-field-'.str_replace('.','_', $field).'">{$'.$field.'}</td>';
00282                                 } 
00283                                 $rowtemplate .= '</tr>';
00284                                 $template = $rowtemplate;
00285                                 
00286                                 $cols = array();
00287                                 foreach ($fields as $fieldname){
00288                                         $field = $records[0]->table()->getField($fieldname);
00289                                         if ( PEAR::isError($field) ) continue;
00290                                         $label = $field['widget']['label'];
00291                                         if ( @$field['column'] and @$field['column']['label'] ) $label = $field['column']['label'];
00292                                         $cols[] = $label;
00293                                         
00294                                 }
00295                                 
00296                                 $colTemplate = '<tr><th>'.implode('</th><th>', array_map('htmlspecialchars', $cols)).'</th></tr>';
00297                                 $out = '<table><thead>'.$colTemplate.'</thead><tbody>';
00298                         }
00299                         
00300                         foreach ($records as $rec){
00301                                 $out .= self::fillReportSingle($rec, $template);
00302                         }
00303                         if ( $asTable ){
00304                                 $out .= '</tbody></table>';
00305                         }
00306                 }
00307                 return $out;
00308         
00309         }
00310         
00311         
00312         public static function isDelegateField(Dataface_Table $table, $fieldname){
00313                 if ( strpos($fieldname, '.') !== false ){
00314                         list($rel, $fld) = explode('.', $fieldname);
00315                         $relObj = $table->getRelationship($rel);
00316                         if ( PEAR::isError($relObj) ) throw new Exception($relObj->getMessage(), $relObj->getCode());
00317                         $rtable = $relObj->getTable($fld);
00318                         if ( PEAR::isError($rtable) ) throw new Exception($rtable->getMessage(), $rtable->getCode());
00319                         return self::isDelegateField($rtable, $fld);
00320                 } else {
00321                         $flds =& $table->delegateFields(true);
00322                         return isset($flds[$fieldname]);
00323                 }
00324         }
00325         
00332         public static function extractRecordsFromGroupData(&$groupData){
00333         
00334                 $out = array();
00335                 if ( isset($groupData['records']) ){
00336                         return $groupData['records'];
00337                 } else if ( isset($groupData['sections']) ){
00338                         
00339                         foreach ($groupdData['sections'] as $key=>$section){
00340                                 $secRecs = self::extractRecordsFromGroupData($groupData['sections'][$key]);
00341                                 foreach ($secRecs as $rec){
00342                                         $out[] = $rec;
00343                                 }
00344                         }
00345                 }
00346                 return $out;
00347         
00348         }
00349         
00350         
00366         public static function compileGroupData(&$groupData, $groupFields, $summaryFields){
00367                 $gfields = $groupFields[$groupData['level']];
00368                 $sfields = $summaryFields[$groupData['level']];
00369                 
00370                 $records = self::extractRecordsFromGroupData(&$groupData);
00371                 if ( !$records ) return;
00372                 $summaryRecord = new Dataface_Record($records[0]->table()->tablename, array());
00373                 foreach ($gfields as $gf ){
00374                         $summaryRecord->setValue($gf, $records[0]->val($gf));
00375                 }
00376                 
00377                 
00378                 foreach ($sfields as $opt){
00379                         $summaryRecord->pouch['summaries'][$opt] = self::evaluateAggregateExpression($records, $opt);
00380                         
00381                 }
00382                 $groupData['summaryRecord'] = $summaryRecord;
00383                 if ( isset($groupData['sections']) ){
00384                         foreach (array_keys($groupData['sections']) as $secid){
00385                                 $secGroupData =& $groupData['sections'][$secid];
00386                                 self::compileGroupData($secGroupData, $groupFields, $summaryFields);
00387                                 unset($secGroupData);
00388                         }
00389                 }
00390                 
00391                 
00392                 
00393         }
00394         
00404         public static function evaluateAggregateExpression(array $records, $expression){
00405         
00406                 $parsed = self::parseExpression($expression);
00407                 switch ($parsed['opt']){
00408                 
00409                         case 'sum':
00410                                 $total = 0;
00411                                 if ( !$records ) return $total;
00412                                 if ( $records[0]->table()->isInt($parsed['field']) ){
00413                                         foreach ($records as $rec){
00414                                                 $total += intval($rec->val($parsed['field']));
00415                                         }
00416                                 } else {
00417                                         foreach ($records as $rec){
00418                                                 $total += doubleval($rec->val($parsed['field']));
00419                                         }
00420                                 }
00421                                 return $total;
00422                                 
00423                         case 'count':
00424                                 return count($records);
00425                                 
00426                         case 'max':
00427                                 $max = 0;
00428                                 if ( !$records ) return $max;
00429                                 if ( $records[0]->table()->isInt($parsed['field']) ){
00430                                         foreach ($records as $rec){
00431                                                 $max = max($max, intval($rec->val($parsed['field'])));
00432                                         }
00433                                         return $max;
00434                                 } else if ( $records[0]->table()->isFloat($parsed['field']) ){
00435                                         foreach ($records as $rec){
00436                                                 $max = max($max, doubleval($rec->val($parsed['field'])));
00437                                         }
00438                                         return $max;
00439                                         
00440                                 } else if ( $records[0]->table()->isDate($parsed['field'])){
00441                                         foreach ($records as $rec){
00442                                                 $max = max($max, strtotime($record->strval($parsed['field'])));
00443                                         }
00444                                         return date('Y-m-d H:i:s', $max);
00445                                 } else {
00446                                         $max = null;
00447                                         foreach ($records as $rec){
00448                                                 if ( !isset($max) ){
00449                                                         $max = $rec->val($parsed['field']);
00450                                                 } else if ( ($currtest = $rec->val($parsed['field'])) > $max ){
00451                                                         $max = $currtest;
00452                                                 }
00453                                         }
00454                                         return $max;
00455                                 }
00456                                 
00457                                 
00458                         case 'min':
00459                                 $min = null;
00460                                 if ( !$records ) return $min;
00461                                 if ( $records[0]->table()->isInt($parsed['field']) ){
00462                                         foreach ($records as $rec){
00463                                                 if ( !isset($min)  ){
00464                                                         $min = intval($rec->val($parsed['field']));
00465                                                 } else {
00466                                                         $min = min($min, intval($rec->val($parsed['field'])));
00467                                                 }
00468                                         }
00469                                         return $min;
00470                                 } else if ( $records[0]->table()->isFloat($parsed['field']) ){
00471                                         foreach ($records as $rec){
00472                                                 if ( !isset($min) ){
00473                                                         $min = doubleval($rec->val($parsed['field']));
00474                                                 } else {
00475                                                         $min = min($min, doubleval($rec->val($parsed['field'])));
00476                                                 }
00477                                         }
00478                                         return $min;
00479                                         
00480                                 } else if ( $records[0]->table()->isDate($parsed['field'])){
00481                                         foreach ($records as $rec){
00482                                                 if ( !isset($min) ){
00483                                                         $min = strtotime($record->strval($parsed['field']));
00484                                                 } else {
00485                                         
00486                                                         $min = min($min, strtotime($record->strval($parsed['field'])));
00487                                                 }
00488                                         }
00489                                         return date('Y-m-d H:i:s', $min);
00490                                 } else {
00491                                         $min = null;
00492                                         foreach ($records as $rec){
00493                                                 if ( !isset($min) ){
00494                                                         $min = $rec->val($parsed['field']);
00495                                                 } else if ( ($currtest = $rec->val($parsed['field'])) > $min ){
00496                                                         $min = $currtest;
00497                                                 }
00498                                         }
00499                                         return $min;
00500                                 }
00501                         default:
00502                                 throw new Exception("Unrecognized aggregate operator: ".$parsed['opt'], self::COMPILE_ERROR);
00503                         
00504                         
00505                 }
00506         }
00507         
00508         
00520         public static function parseExpression($expression){
00521                 $expression = trim($expression);
00522                 if ( preg_match('/^([a-zA-Z]+)\(([^\)]+)\)$/', $expression, $matches)){
00523                         return array(
00524                                 'opt'=>trim(strtolower($matches[1])),
00525                                 'field'=>trim($matches[2])
00526                         );
00527                 } else {
00528                         throw new Exception("Failed to parse expression '".$expression."'.  It does not match the required pattern.");
00529                         
00530                 }
00531         }
00532         
00541         public static function fillReportSingle(Dataface_Record $record, $template, $strict = false){
00542                 if ( !$record ) throw new Exception("Null record provided.", 2000);
00543                 if ( is_string($template) ){
00544                         $el = str_get_html($template);
00545                 } else {
00546                         $el = $template;
00547                 }
00548                 $builder = new XfHtmlReportBuilder();
00549                 if ( $strict ){
00550                         $builder->strict = true;
00551                 }
00552                 return $builder->fillReport($record, $record, $el, '');
00553         }
00554         
00555         
00565         public static function validateTemplate(Dataface_Table $table, $template){
00566                 $rec = new Dataface_Record($table->tablename, array());
00567                 self::fillReportSingle($rec, $template, true);
00568                 return true;
00569         }
00570         
00571         
00580         public function fillReport($root, $record, $el, $basePath=''){
00581                 $oldContext = $this->context;
00582                 $this->context = new stdClass;
00583                 $this->context->root = $root;
00584                 $this->context->record = $record;
00585                 $this->context->el = $el;
00586                 $this->context->basePath = $basePath;
00587                 $this->context->rrec = null;
00588                 
00589                 //$dom = str_get_html($template);
00590                 $rrec = null;
00591                 if ( is_a($record, 'Dataface_RelatedRecord') ){
00592                         $rrec = $record;
00593                         $record = $rrec->toRecord();
00594                         $this->context->rrec = $rrec;
00595                         $this->context->record = $record;
00596                 }
00597                 $uls = $el->find('ul[relationship]');
00598                 foreach ($uls as $ul){
00599                         $rel = $ul->relationship;
00600                         
00601                         if ( $this->strict ){
00602                         
00603                                 $relationship = $root->table()->getRelationship($rel);
00604                                 if ( PEAR::isError($relationship) ){
00605                                         throw new Exception(sprintf(
00606                                                         'Relationship "%s" does not exist in table "%s" in the ul tag: %s',
00607                                                         $rel,
00608                                                         $root->table()->tablename,
00609                                                         str_replace($ul->innertext,'',$ul->outertext)
00610                                                 ),
00611                                                 self::COMPILE_ERROR
00612                                         );
00613                                 }
00614                         }
00615                         
00616                         $relatedRecords = $root->getRelatedRecordObjects($rel);
00617                         $lis = $ul->find('li');
00618                         
00619                         $newlis = array();
00620                         foreach ($relatedRecords as $rrec){
00621                                 foreach ($lis as $li){
00622                                         $newlis[] = $this->fillReport($root, $rrec, $li, $rel.'.' );
00623                                 }
00624                         }
00625                         
00626                         $ul->innertext = implode("\n", $newlis);
00627                         
00628                 }
00629                 
00630                 $ols = $el->find('ol[relationship]');
00631                 foreach ($ols as $ol){
00632                         $rel = $ol->relationship;
00633                         
00634                         
00635                         if ( $this->strict ){
00636                         
00637                                 $relationship = $root->table()->getRelationship($rel);
00638                                 if ( PEAR::isError($relationship) ){
00639                                         throw new Exception(sprintf(
00640                                                         'Relationship "%s" does not exist in table "%s" in the ol tag: %s',
00641                                                         $rel,
00642                                                         $root->table()->tablename,
00643                                                         str_replace($ol->innertext,'',$ol->outertext)
00644                                                 ),
00645                                                 self::COMPILE_ERROR
00646                                         );
00647                                 }
00648                         }
00649                         
00650                         $relatedRecords = $root->getRelatedRecordObjects($rel);
00651                         $lis = $ol->find('li');
00652                         
00653                         $newlis = array();
00654                         foreach ($relatedRecords as $rrec){
00655                                 foreach ($lis as $li){
00656                                         $newlis[] = $this->fillReport($root, $rrec, $li, $rel.'.' );
00657                                 }
00658                         }
00659                         
00660                         $ol->innertext = implode("\n", $newlis);
00661                         
00662                 }
00663                 
00664                 $tables = $el->find('table[relationship]');
00665                 foreach ($tables as $table){
00666                         $rel = $table->relationship;
00667                         
00668                         if ( $this->strict ){
00669                         
00670                                 $relationship = $root->table()->getRelationship($rel);
00671                                 if ( PEAR::isError($relationship) ){
00672                                         throw new Exception(sprintf(
00673                                                         'Relationship "%s" does not exist in table "%s" in the table tag: %s',
00674                                                         $rel,
00675                                                         $root->table()->tablename,
00676                                                         str_replace($table->innertext,'',$table->outertext)
00677                                                 ),
00678                                                 self::COMPILE_ERROR
00679                                         );
00680                                 }
00681                         }
00682                         
00683                         $tbody = $table->find('tbody');
00684                         $relatedRecords = $root->getRelatedRecordObjects($rel);
00685                         $trs = $tbody[0]->find('tr');
00686                         
00687                         $newtrs = array();
00688                         foreach ($relatedRecords as $rrec){
00689                                 foreach ($trs as $tr){
00690                                         $newtrs[] = $this->fillReport($root, $rrec, $tr, $rel.'.' );
00691                                 }
00692                         }
00693                         
00694                         $tbody[0]->innertext = implode("\n", $newtrs);
00695                         
00696                 }
00697                 
00698                 
00699                 $content = $el->outertext;
00700                 $content = preg_replace_callback('#\{\$([a-zA-Z0-9_\.]+)\}#', array($this, '_replace_fields'), $content);
00701                 
00702                 $content = preg_replace_callback('#\{@([a-zA-Z]+\([a-zA-Z0-9_\.]+\))\}#', array($this, '_replace_summary_fields'), $content);
00703                 
00704                 
00705                 $this->context = $oldContext;
00706                 return $content;
00707                 
00708                 
00709         
00710         }
00711         
00712         
00718         function _replace_fields($matches){
00719                 //print_r($matches);
00720                 if ( $this->strict ){
00721                         
00722                         if ( !$this->context->root->table()->hasField($matches[1]) ){
00723                                 throw new Exception(sprintf(
00724                                                 'Field "%s" does not exist in table "%s" so the macro "%s" cannot be resolved.',
00725                                                 $matches[1],
00726                                                 $this->context->root->table()->tablename,
00727                                                 $matches[0]
00728                                         ),
00729                                         self::COMPILE_ERROR
00730                                 );
00731                         }
00732                 }
00733                 $parts = explode('.', $matches[1]);
00734                 if ( count($parts)>1 and $this->context->rrec ){
00735                         $rel = $parts[0];
00736                         $fld = $parts[1];
00737                         
00738                         if ( isset($this->context->rrec) and $this->context->rrec->_relationshipName == $rel ){
00739                                 return $this->context->rrec->htmlValue($fld);
00740                         } else {
00741                                 //echo "Related record: ".$this->context->rrec->_relationshipName;
00742                         }
00743                 } else {
00744                         //echo "Getting field ".$parts[0].".";
00745                         if ( !$this->context->root ){
00746                                 throw new Exception("NO root record to replace fields from.", 2000);
00747                         }
00748                         return $this->context->root->htmlValue($matches[1]);
00749                 }
00750                 
00751                 return $matches[0];
00752         }
00753         
00754         
00758         function _replace_summary_fields($matches){
00759                 //print_r($matches);
00760                 
00761                 //echo "Getting field ".$parts[0].".";
00762                 if ( !$this->context->root ){
00763                         throw new Exception("NO root record to replace fields from.", 2000);
00764                 }
00765                 if ( isset($this->context->root->pouch['summaries'][$matches[1]]) ){
00766                         $val = $this->context->root->pouch['summaries'][$matches[1]];
00767                         $expr = self::parseExpression($matches[1]);
00768                         $fld = $expr['field'];
00769                         
00770                         if ( $this->strict ){
00771                         
00772                                 if ( !$this->context->root->table()->hasField($fld) ){
00773                                         throw new Exception(sprintf(
00774                                                         'Field "%s" does not exist in table "%s" so the summary macro "%s" cannot be resolved.',
00775                                                         $fld,
00776                                                         $this->context->root->table()->tablename,
00777                                                         $matches[0]
00778                                                 ),
00779                                                 self::COMPILE_ERROR
00780                                         );
00781                                 }
00782                                 
00783                                 if ( !in_array($expr['opt'] , self::$SUMMARY_FUNCTIONS) ){
00784                                         throw new Exception(sprintf(
00785                                                         'Summary function "%s" is not supported.  Currently only %s are supported.  (Found in macro "%s").',
00786                                                         $expr['opt'],
00787                                                         '"'.implode('", "', self::$SUMMARY_FUNCTIONS).'"',
00788                                                         $matches[0]
00789                                                 ),
00790                                                 self::COMPILE_ERROR
00791                                         );
00792                                         
00793                                 }
00794                         }
00795                         if ( self::isDelegateField($this->context->root->table(), $fld) ) return $val;
00796                         
00797                         $old = $this->context->root->val($fld);
00798                         $this->context->root->setValue($fld, $val);
00799                         $out = $this->context->root->htmlValue($fld);
00800                         $this->context->root->setValue($fld, $old);
00801                         return $out;
00802                 }
00803                 //return $this->context->root->htmlValue($parts[0]);
00804         
00805         
00806                 return $matches[0];
00807         }
00808         
00809 }
 All Data Structures Files Functions Variables Enumerations