![]() |
Xataface 2.0
Xataface Application Framework
|
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><< Previous: </b>".*/$this->getLinkHtml($this->_resultSet->cursor()-1, 'prevLink', $img, '<<Back'); 00512 } else if ( $this->_query['-mode']=='list') { 00513 if ( $this->_resultSet->start()<=0 ) return ''; 00514 return /*"<b><< Previous: </b>".*/$this->getLinkHtml( 00515 max( 00516 $this->_resultSet->start()-$this->_resultSet->limit(), 0), 'prevLink', $img, '<<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>>')/*."<b> >></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>>' 00529 )/*."<b> >></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 }