Xataface 2.0
Xataface Application Framework
Dataface/ResultController.php
Go to the documentation of this file.
00001 <?php
00002 /*-------------------------------------------------------------------------------
00003  * Xataface Web Application Framework
00004  * Copyright (C) 2005-2008 Web Lite Solutions Corp (shannah@sfu.ca)
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program 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
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  *-------------------------------------------------------------------------------
00020  */
00021 /*******************************************************************************
00022 * File:         Dataface/ResultController.php
00023 * Author: Steve Hannah <shannah@sfu.ca>
00024 * Description:
00025 *       Allows for database controlling .  Forward back, etc.. functionality
00026 *       
00027 ******************************************************************************/
00028 
00029 import( 'Dataface/QueryBuilder.php');
00030 import( 'Dataface/Table.php');
00031 import( 'Dataface/LinkTool.php');
00032 
00033 $GLOBALS['Dataface_ResultController_limit'] = 20;
00034 $GLOBALS['Dataface_ResultController_skip'] = 0;
00035 
00036 
00037 class Dataface_ResultController {
00038    
00039    var $_baseUrl;
00040    var $_prevLink;
00041    var $_nextLink;
00042    var $_tablename;
00043    var $_queryBuilder;
00044    var $_fields;
00045    var $_table;
00046    var $_db;
00047    var $_records;
00048    var $_pos;
00049    var $_totalRecords;
00050    var $_query;
00051    var $_resultSet;
00052    var $type;
00053    
00054    
00058    var $_displayedRecords;
00059    
00060    
00064    var $_titleColumn;
00065    
00066    var $_contentsList;
00067    
00068    
00069    function Dataface_ResultController($tablename, $db='', $baseUrl='', $query=''){
00070            $this->_tablename = $tablename;
00071            $this->_db = $db;
00072            $this->_baseUrl =  $baseUrl ? $baseUrl : $_SERVER['PHP_SELF'];
00073            $app =& Dataface_Application::getInstance();
00074            
00075            $this->_table =& Dataface_Table::loadTable($this->_tablename);
00076            $this->_fields =& $this->_table->fields();
00077            
00078            if ( !$query ){
00079                         $this->_query =& $app->getQuery();
00080                         $query =& $this->_query;
00081                         $this->_queryBuilder = new Dataface_QueryBuilder($this->_query['-table'], $query);
00082                         $this->_resultSet =& $app->getResultSet();
00083 
00084            } else {
00085            
00086                    if ( !is_array($query) ){
00087                                 $query = array("-mode"=>$app->_conf['default_mode']);
00088                         }
00089                         
00090                         $this->_resultSet =& Dataface_QueryTool::loadResult($tablename, $db, $query);
00091                         
00092                    
00093                   
00094                    
00095                    if ( !isset( $query['-limit']) ){
00096                            $query['-limit'] = $GLOBALS['Dataface_ResultController_limit'];
00097                    }
00098                    if ( !isset( $query['-skip']) ){
00099                            $query['-skip'] = $GLOBALS['Dataface_ResultController_skip'];
00100                    }
00101                    if ( !isset( $query['-cursor'] ) ){
00102                            $query['-cursor'] = $query['-skip'];
00103                    }
00104                    if ( !isset( $query['-mode'] ) ){
00105                            $query['-mode'] = $app->_conf['default_mode'];
00106                    }
00107                    
00108                         $this->_queryBuilder = new Dataface_QueryBuilder($this->_tablename, $query);
00109                         $this->_query =& $this->_queryBuilder->_query;
00110                 }
00111             
00112             // set the title column
00113             foreach ($this->_fields as $field){
00114                 if ( preg_match('/char/i', $field['Type']) ){
00115                         $this->_titleColumn = $field['name'];
00116                         break;
00117                 }
00118             }
00119             
00120             if ( !isset($this->_titleColumn) ){
00121                 reset($this->_fields);
00122                 $field = current($this->_fields);
00123                 $this->_titleColumn  = $field['name'];
00124             }
00125             
00126             // set the position
00127             $this->_pos = $query['-cursor'];
00128             
00129             
00130             $this->_displayedRecords = $query['-limit'];
00131             
00132            
00133    }
00134    
00135    
00136    function &getRecords(){
00137            if ( !isset( $this->_records) ){
00138                    $this->_records = array();
00139                    
00140                    $sql = $this->_queryBuilder->select();
00141 
00142                    $sqlStats = $this->_queryBuilder->select_num_rows();
00143                    $db =& Dataface_DB::getInstance();
00144                    $res = $db->query($sqlStats, $this->_table->db, null, true);
00145                    //if ( !$res and !is_array($res) ){
00146                    $this->_totalRecords = $res[0]['num'];
00147                    //list($this->_totalRecords) = mysql_fetch_row( mysql_query( $sqlStats, $this->_db ) );
00148                   
00149                    
00150                    //$res = mysql_query($sql, $this->_db);
00151                    $res = $db->query($sql, $this->_table->db, null, true);
00152                    
00153                    if ( !$res and !is_array($res) ){
00154                            throw new Exception("An error occurred attempting to retrieve records from the database.: ".mysql_error($this->db), E_USER_ERROR);
00155                    }
00156                    $this->_displayedRecords = count($res);
00157                    
00158                    //while ( $row = mysql_fetch_array($res) ){
00159                    foreach ($res as $row){
00160                            $this->_records[] = $row;
00161                    }
00162                    
00163            }
00164            
00165            return $this->_records;
00166            
00167    }
00168    
00169    
00170    function getCurrentPosition(){
00171    
00172                 return $this->_pos;
00173    }
00174    
00175         function setBaseUrl( $url ){
00176                 $this->_baseUrl = $url;
00177         }
00178         
00179         function getBaseUrl(){
00180                 if ( !isset($this->_basUrl) ){
00181                         $this->_baseUrl = $_SERVER['PHP_SELF'];
00182                 }
00183                 
00184                 return $this->_baseUrl;
00185         
00186         }
00187    
00188    // Gets the number of records in this found set.
00189    function getTotalRecords(){
00190                 if (!isset( $this->_totalRecords) ){
00191                         $db =& Dataface_DB::getInstance();
00192                         $res = $db->query($this->_queryBuilder->select_num_rows(), $this->_table->db, null, true);
00193                         $this->_totalRecords = $res[0]['num'];
00194                         //list($this->_totalRecords) = mysql_fetch_row( mysql_query( $this->_queryBuilder->select_num_rows() ) );
00195                         
00196                 }
00197                 
00198                 return $this->_totalRecords;
00199    
00200    }
00201    
00202    
00203    function getDisplayedRecords(){
00204                 return $this->_displayedRecords;
00205         }
00206         
00207         
00211         function getPageIndex(&$selected_url){
00212                 $totalRecords = $this->getTotalRecords();
00213                 $pageNumber = 1;
00214                 $contents = array();
00215                 
00216                 for ( $i=0; $i<$totalRecords; $i+=$this->_query['-limit']){
00217                         $query = /*array_merge($this->_query, */array("-skip"=>$i, "-action"=>"list")/*)*/;
00218                         $link = $this->_buildLink($query);
00219                         $contents[$link] = $pageNumber++;
00220                         
00221                         if ( $this->_resultSet->start() >= $i and $this->_resultSet->start() < ($i+$this->_query['-limit'])){
00222                                 $selected_url = $link;
00223                         }
00224                 }
00225                 
00226                 return $contents;
00227         
00228         }
00229         
00230         
00231         
00235         function getContentsList($selected_url){
00236                 
00237                 if (! isset( $this->_contentsList) ){
00238                         
00239                         $this->_contentsList = array();
00240                         if ( $this->getTotalRecords() > 100 ){
00241                                 // there are over 100 records in this found set.  It is unfeasible
00242                                 // to list them all in the jump menu, so instead we will list ranges
00243                                 // of records
00244                                 //$totalRecords = $this->getTotalRecords();
00245                                 //for ( $i=0; $i<$totalRecords; $i+=$this->_query['-limit']){
00246                                 //      $query = array_merge($this->_query, array("-skip"=>$i, "-action"=>"list"));
00247                                 //      $link = $this->_buildLink($query);
00248                                 //      $this->_contentsList[$link] = ($i+1)." to ".($i+$this->_query['-limit']);
00249                                 //      
00250                                 //      if ( $this->_resultSet->start() >= $i and $this->_resultSet->start() < ($i+$this->_query['-limit'])){
00251                                 //              $selected_url = $link;
00252                                 //      }
00253                                 //}
00254                                 
00255                         
00256                         } else {
00257                                 // There are less than 100 records.. Just list them individually
00258                                 //$sql = $this->_queryBuilder->select( 
00259                                 //              array($this->_titleColumn), 
00260                                 //              array('-skip'=>null, '-limit'=>null) 
00261                                 //      );
00262                                 
00263                                 //$res = mysql_query( 
00264                                 //      $sql, 
00265                                 //      $this->_db 
00266                                 //);
00267                                 $titles = $this->_resultSet->getTitles(false, true,false);
00268                                 $index = 0;
00269                                 //while ( $row = mysql_fetch_array($res) ){
00270                                 $len = count($titles);
00271                                 
00272                                 for ($index =0 ; $index < $len; $index++){
00273                                         //$query = array( "-cursor"=>$index++, "-action"=>'browse');
00274                                         $query = array( "-cursor"=>$index, "-action"=>'browse');
00275                                         $query = array_merge( $this->_query, $query);
00276                                         foreach ($query as $key=>$value) {
00277                                                 if ( $value === null ){
00278                                                         unset($query[$key]);
00279                                                 }
00280                                         }
00281                                         $link = $this->_buildSetLink($query) ;
00282                                         
00283                                         //$this->_contentsList[ $link ] = $row[0];
00284                                         $this->_contentsList[ $link ] = $titles[$index];
00285                                         
00286                                         //if ( $index-1 == $this->_query['-cursor'] ){
00287                                         if ( $index == $this->_query['-cursor'] ){
00288                                                 $selected_url = $link;
00289                                         }
00290                                 }
00291                         }
00292                 }
00293                  
00294                         
00295                 
00296                 return $this->_contentsList;
00297                         
00298         
00299         }
00300         
00301         
00302         function _buildSetLink($query=array()){
00303                 return Dataface_LinkTool::buildSetLink($query);
00304         }       
00305         
00310         function _buildLink($query=array()){
00311                 
00312                 return Dataface_LinkTool::buildLink($query);
00313         }
00314         
00315         function jumpMenu(){
00316                 $contents = $this->getContentsList($selected_url);
00317                 if ( $contents ){
00318                         $html = '<select name="controller" class="jumpMenu" onchange="javascript:window.location=this.options[this.selectedIndex].value;">
00319                                 
00320                                 ';
00321                         $selected_url = '';     
00322                         $currentLink = Dataface_LinkTool::buildLink(array());
00323                         $currentLink = preg_replace('/&?-limit=\d+/', '', $currentLink);
00324                                 // link sans limit for use in field to specify number of records to be displayed per page
00325                         
00326                         foreach ($contents as $key=>$value){
00327                                 
00328                                 $selected = $key==$selected_url ? "selected" : '';
00329                                 $html .= '
00330                                                 <option value="'.$key.'" '.$selected.'>'.$value.'</option>';
00331                         }
00332                         $html .= '</select>';
00333                 } else {
00334                         $html = '';
00335                 }
00336                 return $html;
00337         
00338         }
00339         
00340         function limitField($prefix=''){
00341                 $currentLink = Dataface_LinkTool::buildLink(array('-'.$prefix.'limit'=>null));
00342                 if ( !$prefix ) {
00343                         $limitval = $this->_resultSet->limit();
00344                 } else if (isset($_GET['-'.$prefix.'limit'])){
00345                         $limitval = $_GET['-'.$prefix.'limit'];
00346                 } else {
00347                         $limitval = 30;
00348                 }
00349                 return '(Display <input type="text" value="'.$limitval.'" onchange="window.location = \''.$currentLink.'&-'.$prefix.'limit=\'+this.value" size="3"/> Records per page)';
00350         }
00351         
00352         
00353         function toHtml($prefix=''){
00354                 $app =& Dataface_Application::getInstance();
00355                 $query =& $app->getQuery();
00356                 if ( !isset($this->type) ) $this->type = $query['-mode'];
00357                 
00358                 switch ( $this->type ){
00359                         case 'browse':
00360                                 return $this->browseHtml($prefix);
00361                         default:
00362                                 return $this->listHtml($prefix);
00363                 }
00364         
00365         }
00366         
00367         function listHtml($prefix=''){
00368                 $app =& Dataface_Application::getInstance();
00369                 $rs =& $this->_resultSet;
00370                 $pages = array();
00371                 $start = $rs->start();
00372                 $end = $rs->end();
00373                 $limit = max($rs->limit(),1);
00374                 $found = $rs->found();
00375                 
00376                 // we show up to 5 pages on either side of the current position
00377                 $pages_before = ceil(floatval($start)/floatval($limit));
00378                 $pages_after = ceil(floatval($found-$end-1)/floatval($limit));
00379                 $curr_page = $pages_before + 1;
00380                 $total_pages = $pages_before+$pages_after+1;
00381 
00382                 //$i = $curr_page;
00383                 $i_start = $start;
00384                 for ( $i = $curr_page; $i>max(0,$curr_page-5); $i-- ){
00385                         $pages[$i] = $app->url('-'.$prefix.'limit='.$limit.'&-'.$prefix.'skip='.max($i_start,0));
00386                         if ( $this->_baseUrl ) $pages[$i] = $this->_baseUrl.'?'.substr($pages[$i], strpos($pages[$i], '?')+1);
00387                         $i_start -= $limit;
00388                 }
00389                 //$i = $curr_page+1;
00390                 $i_start = $start+$limit;
00391                 for ($i = $curr_page+1; $i<=min($total_pages,$curr_page+5); $i++){
00392                         $pages[$i] = $app->url('-'.$prefix.'limit='.$limit.'&-'.$prefix.'skip='.$i_start);
00393                         if ( $this->_baseUrl ) $pages[$i] = $this->_baseUrl.'?'.substr($pages[$i], strpos($pages[$i], '?')+1);
00394                         $i_start += $limit;
00395                 }
00396                 ksort($pages);
00397                 
00398                 $pages2 = array();
00399                 if ( $curr_page > 1 ){
00400                         $pages2[df_translate('scripts.GLOBAL.LABEL_PREV','Prev')] = $pages[$curr_page-1];
00401                 }
00402                 
00403                 foreach ( $pages as $pageno=>$pageval){
00404                         $pages2[$pageno] = $pageval;
00405                 }
00406                 
00407                 if ( $curr_page < $total_pages ){
00408                 
00409                         $pages2[df_translate('scripts.GLOBAL.LABEL_NEXT','Next')] = $pages[$curr_page+1];
00410                 }
00411                 $out = array('<ul class="resultController">');
00412                 $out[] = '<li class="rs-description">'.df_translate('scripts.GLOBAL.MESSAGE_FOUND','Found '.$found.' records', array('found'=>$found)).' </li>';
00413                 foreach ($pages2 as $pageno=>$link){
00414                         if ( $pageno == $curr_page ) $selected = ' selected';
00415                         else $selected = '';
00416                         $out[] = '<li class="'.$selected.'"><a href="'.htmlspecialchars($link).'">'.$pageno.'</a></li>';
00417                 }
00418                 $appurl = $app->url('');
00419                 $appurl = preg_replace('/[&\?]'.preg_quote('-'.$prefix.'limit=').'[^&]*/', '', $appurl); 
00420                 $urlprefix = ( $this->_baseUrl ? $this->_baseUrl.'?'.substr($appurl,strpos($appurl,'?')+1) : $appurl);
00421                 $out[] = '<li class="results-per-page"> '.df_translate('scripts.GLOBAL.LABEL_SHOWING', 'Showing').' <input type="text" value="'.$limit.'" onchange="window.location = \''.$urlprefix.'&-'.$prefix.'limit=\'+this.value" size="3"/>'.df_translate('scripts.GLOBAL.MESSAGE_RESULTS_PER_PAGE','Results per page');
00422                 $out[] = '</ul>';
00423                 
00424                 return implode("\n",$out);
00425         }
00426         
00427         function browseHtml($prefix){
00428         
00429                 
00430                 
00431                 $html = '
00432                         <div class="resultController">
00433                         
00434                         <div class="container"><div class="controllerJumpMenu">
00435                         <b>Jump: </b>';
00436                 $html .= $this->jumpMenu().'</div>
00437                         
00438                         </div>
00439                         
00440                         
00441                         <table class="forwardBackTable" width="100%" border="0" cellpadding="0" cellspacing="5"><tr><td width="33%" valign="top" align="left" bgcolor="#eaeaea">
00442                         '. $this->getPrevLinkHtml().'
00443                         </td><td width="34%" valign="top" align="center">
00444                         
00445                         '. $this->getCurrentHtml();
00446                         
00447                         if ( $this->_query['-mode'] == 'list' ) {
00448                                 $html .='<br/>'.$this->limitField();
00449                                         
00450                         }
00451                         
00452                         $html .= '
00453                         
00454                         </td><td width="33%" valign="top" align="right" bgcolor="#eaeaea">
00455                         
00456                         '. $this->getNextLinkHtml().'
00457                         </td>
00458                         </tr>
00459                         </table>
00460                         </div>
00461                                 ';
00462                 return $html;
00463         }
00464         
00465         function getLinkHtml($pos, $linkId=null,$imgURL = null, $imgAlt="Go"){
00466         
00467                 if ( $pos<0 ) return '';
00468                 
00469                 $url = $this->_buildSetLink(
00470                         array('-cursor'=>$pos)
00471                 );
00472                 
00473                 if ( $this->_query['-mode'] == 'browse' ){
00474                         //$this->_resultSet->loadSet(array( $this->_titleColumn) );
00475                         //$titles = $this->_resultSet->getTitles(false, true, false);
00476                         //$data =& $this->_resultSet->indexedData();
00477                         //$index = $pos;// - $this->_resultSet->start();
00478                         //if ( $index >= count($titles) ) $title = '';
00479                         
00480                         //$title = $data[$index][$this->_titleColumn];
00481                         //else $title = $titles[$index];
00482                         $title = $pos.'';
00483                         
00484                 } else if ( $this->_query['-mode'] == 'list' ){
00485                         $from = $pos;
00486                         $to = min( $pos + $this->_resultSet->limit(), $this->_resultSet->found() );
00487                         $title = "Records ".($from+1)." to ".($to);
00488                         $url = $this->_buildLink(
00489                                 array('-skip'=>$from)
00490                         );
00491                         
00492                 }
00493                 if ( $linkId !== null ){
00494                         $id = " id=\"$linkId\"";
00495                 } else {
00496                         $id = '';
00497                 }
00498                 if ( isset($imgURL) ){
00499                         return '<a href="'.$url.'"'.$id.' title="'.$title.'"><img src="'.$imgURL.'" alt="'.$imgAlt.'" /></a>';
00500                 } else {
00501                         return '<a href="'.$url.'"'.$id.' title="'.$title.'">'.$imgAlt.'</a>';
00502                 }
00503         }
00504         
00505         function getPrevLinkHtml($img=null){
00506                 if ( !isset($img) ){
00507                         $img = DATAFACE_URL.'/images/go-previous.png';
00508                 }
00509                 if ( $this->_query['-mode']=='browse'){
00510                         if ( $this->_resultSet->cursor()<=0 ) return '';
00511                         return /*"<b>&lt;&lt; Previous: </b>".*/$this->getLinkHtml($this->_resultSet->cursor()-1, 'prevLink', $img, '&lt;&lt;Back');
00512                 } else if ( $this->_query['-mode']=='list') {
00513                         if ( $this->_resultSet->start()<=0 ) return '';
00514                         return /*"<b>&lt;&lt; Previous: </b>".*/$this->getLinkHtml(
00515                                 max( 
00516                                         $this->_resultSet->start()-$this->_resultSet->limit(), 0), 'prevLink', $img, '&lt;&lt;Back' );
00517                 } else {
00518                         return '';
00519                 }
00520         }
00521         
00522         function getNextLinkHtml($img=null){
00523                 if ( !isset($img) ) $img = DATAFACE_URL.'/images/go-next.png';
00524                 if ( $this->_query['-mode']=='browse' && $this->_resultSet->cursor()+1 < $this->_resultSet->found()){
00525                         return /*"<b>Next: </b>".*/$this->getLinkHtml($this->_resultSet->cursor()+1, 'nextLink', $img, 'Next&gt;&gt;')/*."<b> &gt;&gt;</b>"*/;
00526                 } else if ( $this->_query['-mode']=='list' and $this->_resultSet->end()+1 < $this->_resultSet->found() ) {
00527                         return /*"<b>Next: </b>".*/$this->getLinkHtml(
00528                                 $this->_resultSet->end()+1, 'nextLink', $img, 'Next&gt;&gt;'
00529                         )/*."<b> &gt;&gt;</b>"*/;
00530                 } else {
00531                         return '';
00532                 }
00533         }
00534         
00535         function getCurrentHtml(){
00536                 
00537                 if ( $this->_query['-mode'] == 'list' ){
00538                         return "<b>Now Showing:</b> ".$this->getLinkHtml($this->_resultSet->start(), 'currentLink');
00539                 } else if ($this->_query['-mode'] == 'browse' ) {
00540                         
00541                         return "<b>This Record: </b>".$this->getLinkHtml($this->_resultSet->cursor(), 'currentLink');
00542                 } else {
00543                         return '';
00544                 }
00545         }
00546         
00547         function getPageIndexHtml(){
00548                 if ( $this->_query['-mode'] == 'list' ){
00549                         $selected = '';
00550                         $pages = $this->getPageIndex($selected);
00551                         ob_start();
00552                         echo '<ul class="page-index">';
00553                         $count = 0;
00554                         foreach ( $pages as $link=>$title ){
00555                                 if ( $count++ > 8 ){
00556                                         echo '<li>...</li>
00557                                         ';
00558                                         break;
00559                                 } else if ( $link == $selected ){
00560                                         echo '<li class="selected-page">'.$title.'</li>
00561                                         ';
00562                                 } else {
00563                                         echo '<li><a href="'.$link.'">'.$title.'</a></li>
00564                                         ';
00565                                 }
00566                         }
00567                         echo '</ul>';
00568                         $out = ob_get_contents();
00569                         ob_end_clean();
00570                         return $out;
00571                 }
00572                 return '';
00573         }
00574                 
00575         
00576 
00577 }
 All Data Structures Namespaces Files Functions Variables Enumerations