'/*, '?'*/ ), array ( '&' , '"', ''' , '<' , '>'/*, ''' */), $inputstring ); } /** * Validates an email address via a regular expression, and cheking the host's validity (if specified). * Returns 0 on success, 1 on bad email format, and 2 on invalid host lookup (if $checkhost is TRUE) * @param string $email * @param bool $checkhost * @return int */ function validateEmail($email, $checkhost = false) { if(!preg_match('/^[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*?[a-z]+$/is', $email)) { return 1; } if($checkhost == true) { //if checking the host's validity //attempt to look up the host's information list($Username, $Domain) = split("@",$email); if(getmxrr($Domain, $MXHost)) { return 0; } else { //attempt to open a connection to the domain if(@fsockopen($Domain, 25, $errno, $errstr, 30)) { return 0; } else { return 2; //return an "invalid host" error } } } else { //if not checking host, just return zero return 0; } } /** * Returns or echoes an HTML-friendly output from the standard print_r() function * @param mixed $item * @return mixed */ function htmlprint_r($item,$noecho=false) { if($noecho) { return '
'.print_r($item,true).'
'; } else { echo '
'.print_r($item,true).'
'; } return null; } /** * Cut out comments, whitespace, and newlines from a JavaScript or CSS string * @param string $filetext * @param bool $escapehtml * @return string */ function minify($filetext,$escapehtml=false) { $filetextlength = strlen($filetext); if($filetextlength) { $file = explode("\n",$filetext); $lines = count($file); for($i=0;$i<$lines;$i++) { //strip out single-line comments $comm = mb_strpos($file[$i],'//'); //if a single-line comment is found, delete all text after it and trim the line of extra whitespace if($comm !== false) { $file[$i] = mb_substr($file[$i],0,$comm); } $file[$i] = trim($file[$i]); //remove leading and trailing whitespace } //and output the data $pretext = implode("\n",$file); $text = preg_replace(array('#/\*.*?\*/#s','@([\r\n\t])[\s]+@'),array('',''),$pretext); $minified_text = (str_ireplace(array("\n","\r","\t",'; ',' {','} ',' (',' ( ',') ',' ) ',' + ',' - ',' / ',' * ',' || ',' && ',' = ',' == ',' < ',' > ',' <= ',' >= ',' != ', ' === ',' !== ',': ',' :',' : ',' ? ',' % ',' , ',', '),array('','','',';','{','}','(','(',')',')','+','-','/','*','||','&&','=','==','<','>','<=','>=','!=','===','!==',':',':',':','?','%',',',','),$text)); if($escapehtml) { $minified_text = htmlspecialchars($minified_text); } return $minified_text; } } ?> headers = array(); $this->pagefound = false; $this->db = $db; $this->config = $config; $this->domain = $config->site_domain; $this->domain_secure = $config->site_domain_secure; // $this->file = (!empty($_REQUEST['file']) ? $_REQUEST['file'] : '/index.'.$this->config->site_default_ext); //get the requested file from apache mod_rewrite $this->file = (!empty($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '/index.'.$this->config->site_default_ext); //get the requested file from apache mod_rewrite if(!preg_match('/.*(\/*)[^\.]+\.html/i', $this->file, $m)) { $this->file .= ($m[1] ? $m[1] : '/') . 'index.' . $this->config->site_default_ext; $this->file = str_replace('//', '/', $this->file); } $this->page = null; $this->filename = array(); preg_match('/\/(.*?)\.'.$this->config->site_default_ext.'/', $this->file, $this->filename); //if the requested file type matches this app's filetype, create a page object for it $this->LoadPageObjects(); } /** * Finds the path to the class files required for the requested page * All URL Processing occurs here */ private function LoadPageObjects() { $objs = explode('/',$this->file); //module will contain the modules and requested file $file = stristr($objs[1],$this->config->site_default_ext) ? 'siteroot/'.substr($this->file,1) : substr($this->file,1); $this->pageclass = 'page_' .($siteroot ? $siteroot.'_' : ''). str_replace(array('/','.'.$this->config->site_default_ext),array('_',''),$file); $this->pagepath = $this->config->module_path .$siteroot. str_replace(array('.'.$this->config->site_default_ext),array('.php'),$file); //if the required include file is found, load it, otherwise throw a HTTP 500 error $this->pagefound = file_exists($this->pagepath); if($this->pagefound) { require($this->pagepath); //|| $this->headers['status'] = 'HTTP/1.1 500 Internal Server Error'; } else { $this->headers['status'] = 'HTTP/1.1 404 Not Found'; } } /** * Handles HTTP 301 redirects for this page, if any * @param int $redirect_id */ protected function handle_301_redirects($redirect_id) { $redirect_id = (int) $redirect_id; if($redirect_id > 0) { //if there is a redirect set for the current page $mkey = "page:$redirect_id:redir"; //fetch the info for the new page's redirect (if found), and output a HTTP 301 header and go to the new page $sql = 'SELECT secsubdir,pagename FROM site_pages p LEFT JOIN site_sections AS ss ON p.secid=ss.secid WHERE pageid=' . $redirect_id; $redir = $this->db->select($sql,'object',true,$mkey); if($redir->secsubdir) { header('HTTP/1.1 301 Moved Permanently'); header('Location: ' . Config::web_domain . '/' . (isset($redir->secsubdir) ? $redir->secsubdir .'/' : ''). $redir->pagename .'.html'); exit(0); } else { //if the redirect is not found in the pages table, go back to the site's root page trigger_error("Page ID '$redirect_id' not found in database",E_USER_WARNING); header('HTTP/1.1 404 Not Found'); header('Location: ' . Config::web_domain . '/'); exit(0); } } } /** * Sets the page's HTTP headers */ protected function OutputHeaders() { //$this->headers = array(); $lastmodified = gmdate('D, d M Y G:i:s',$this->page->last_modified) . ' GMT'; $etag = '"'.md5($page->pageid . $lastmodified).'"'; //construct the HTTP headers //These headers should take info from the pages $this->headers['etag'] = 'ETag: '.$etag; /*$this->headers['cache_control'] = 'Cache-Control: '.'private,max-age=3600'; $this->headers['expires'] = 'Expires: ' . gmdate('D, d M Y G:i:s', time() + 3600) . ' GMT';*/ $this->headers['last_modified'] = 'Last-Modified: ' . $lastmodified; $this->headers['content_language'] = 'Content-Language: '.$this->page->pagelanguage; //output the page's HTTP headers foreach ($this->headers as $hval) { header($hval); } //if the page's "etag" value is equal to the user's browser value of 'If-None-Matches' for this page, output an HTTP 304 and exit if($this->page->cache304 && $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $lastmodified) { //$_SERVER['HTTP_IF_NONE_MATCH'] == $etag) //googlebot doesn't do etags header('HTTP/1.1 304 Not Modified'); exit(0); } } /** * Loads the page (if found) and executes all its related code */ public function Go() { $this->logger = new logger('log',$this->db); $this->logger->log(); if($this->pagefound) { //initialize the Page & Smarty object $this->page = new $this->pageclass($this->config->site_root,$this->db,$this->filename[1]); $this->smarty = new SmartyNew($this,$this->config->site_root); //create the Smarty object $this->page->smarty = $this->smarty; //if this page redirects to another, handle it here if($this->page->redirect > 0) { $this->handle_301_redirects($this->page->redirect); } session_start(); $this->page->Action_PreHeaders(); $this->OutputHeaders(); $this->page->Action_PreDisplay(); $this->page->LoadContent(); $content_length = strlen($this->page->pagecontent); header('Content-length: '.$content_length); echo $this->page->pagecontent;// . 'mem:' . memory_get_usage(); $this->page->Action_PostDisplay(); //echo memory_get_usage(); } else { //if the page isn't found, output headers and hadnle the error $this->OutputHeaders(); } } } /** * The parent class of all pages on the site */ abstract class Site_Page { public $site,$smarty,$db; public $pagename, $pageid, $pagelanguage, $pagefound, $redirect, $pagecontent; public $contentonly, $robots_index, $robots_follow; //page parameters public $doctype,$title,$head,$css,$javascript,$bodyparams,$body; //the building blocks of the page public $resources,$resources_name, $tplvars; public $http_headers,$last_modified,$content_type,$content_language,$cache304,$etag; //HTTP Header-related variables //------------------------------------------------------------------------------------- /** * @param string $site * @param mysqli $dblink * @param string $name */ public function __construct($site,$dblink,$name) { //initialize variables $this->site = $site; $this->smarty->page = &$this; $this->pagefound = false; $this->pagecontent = ''; $this->contentonly = false; $this->db = $dblink; $this->resources = array(); $this->resources_name = array(); $this->tplvars = array(); $this->pagename = $this->db->real_escape_string($name); //first, look up the page in the pages table to see if it exists $pagesql = 'SELECT p.pageid,contentonly,pagelanguage,redirect,cache304,UNIX_TIMESTAMP(lastmodified) AS lastmodified,robots_index,robots_follow FROM site_pages AS p LEFT JOIN site_sections AS ss ON p.secid=ss.secid WHERE CONCAT(IF(LENGTH(secsubdir) > 0,CONCAT(secsubdir,"/"),""),pagename)="'.$this->pagename.'" GROUP BY pageid'; $pagedata = $this->db->select($pagesql,'object',true,"page:$this->pagename") or die($this->db->error . ' on line '.__LINE__); //now fill the page properties and piece together the content, using default values if this page's properties aren't set if($pagedata) { //if a page with this name is found $this->pagefound = true; } else { //if not, we output an HTTP header and load the "page not found" page //header('Content-type: text/html; charset=UTF-8'); header('HTTP/1.1 404 Not Found'); //output a "page not found" HTTP header $this->pagename = 'pagenotfound'; $pagesql = 'SELECT pageid,contentonly FROM site_pages p LEFT JOIN site_sections AS ss ON p.secid=ss.secid WHERE CONCAT(IF(LENGTH(secsubdir)>0,CONCAT(secsubdir,"/"),""),pagename)="notfound"'; $pagedata = $this->db->select($pagesql) or die($this->db->error); } //set the page's parameters if($this->pagefound) { $this->pageid = $pagedata->pageid; $this->pagelanguage = $pagedata->pagelanguage; $this->contentonly = $pagedata->contentonly; $this->last_modified = $pagedata->lastmodified; $this->cache304 = $pagedata->cache304; $this->robots_index = $pagedata->robots_index; $this->robots_follow = $pagedata->robots_follow; $this->redirect = $pagedata->redirect; } $this->default_resources(); //get the default resources from the database if($this->pagefound) { $this->get_page_resources(); //now, look up all the resources associated with this page } } //------------------------------------------------------------------------------------- /** * Displays the page via Smarty * @return string */ public function LoadContent() { if(count($this->tplvars)) { foreach ($this->tplvars as $name=>$value) { // assign any output variables to smarty; $this->smarty->assign($name,$value); } } $this->pagecontent = $this->smarty->DisplayResources('main', $this); } /** * Add a header to the page's headers array * @param string $hdr * @param string $key */ protected function SetHeader($hdr,$key=null) { $this->http_headers[$key ? $key : null] = $hdr; } /** * Redirect to the page identified by pageid. A page id is * preferred - if a page name is passed it will be looked * up in the database * @param mixed $pageid */ public function RedirectTo($pageid) { if(is_numeric($pageid)) { $this->redirect = (int) $pageid; } else { //otherwise, lookup the page in the database trigger_error('NEED TO CODE THIS FEATURE',E_USER_ERROR); } } /** * Executes relevant PHP code in the page. * Called BEFORE headers are sent */ public function Action_PreHeaders() { } /** * Executes relevant PHP code in the page. * Called BEFORE all page content has been sent to Smarty */ public function Action_PreDisplay() { } /** * Executes relevant PHP code in the page, * Called AFTER all page content has been sent to Smarty */ public function Action_PostDisplay() { } //------------------------------------------------------------------------------------- /** * Gets the current page's resources from the database */ private function get_page_resources() { $mkey = "page:$this->pagename:resources"; $sql = 'SELECT r.rid,rname,rtype,rtimestamp,content FROM site_pages p INNER JOIN resource_page_map rpm ON p.pageid=rpm.pageid INNER JOIN resources r ON rpm.rid=r.rid WHERE p.pageid='.(int)$this->pageid; $res = $this->db->select($sql,'object',false,$mkey) or die($this->db->error); $ct = count($res); if($ct) { for($i=0;$i<$ct;$i++) { $this->resources[$res[$i]->rid] = $res[$i]; $this->resources_name[$res[$i]->rname] = &$this->resources[$res[$i]->rid]; $this->assign_special_resources($res[$i]); } } } //------------------------------------------------------------------------------------- /** * fetches the default resources from the database and loads them into the page's variables */ private function default_resources() { $mkey = 'page:default_resources'; $sql = 'SELECT rid,REPLACE(rname,"default_","") AS rname,rtype,rtimestamp,content FROM resources WHERE rname LIKE "default_%" OR common=true'; $defres = $this->db->select($sql,'object',false,$mkey) or die($this->db->error); $resct = count($defres); for($i=0;$i<$resct;$i++) { $this->resources[$defres[$i]->rid] = $defres[$i]; $this->resources_name[$defres[$i]->rname] = &$this->resources[$defres[$i]->rid]; $this->assign_special_resources($defres[$i]); //assign the special resources } } //------------------------------------------------------------------------------------- /** * assigns the special resources the values from db_resource * @param StdClass db_resource */ private function assign_special_resources($db_resource) { switch($db_resource->rtype) { case 'doctype': //$this->smarty->fetch($db_resource->rid); $this->doctype = &$this->resources[$db_resource->rid]->content; break; case 'title': $this->title = &$this->resources[$db_resource->rid]->content; break; case 'head': $this->head = &$this->resources[$db_resource->rid]->content; break; case 'css': $this->css = &$this->resources[$db_resource->rid]->content; break; case 'javascript': $this->javascript = &$this->resources[$db_resource->rid]->content; break; case 'bodyparams': $this->bodyparams = &$this->resources[$db_resource->rid]->content; break; case 'body': $this->body = &$this->resources[$db_resource->rid]->content; break; } } //------------------------------------------------------------------------------------- } ?> host_read = Config::db_host_read; $this->host_write = Config::db_host_write; $this->dbname = Config::db_database; $this->username = Config::db_user; $this->password = Config::db_password; $this->port = Config::db_port; $this->memcache_prefix = Config::mmc_prefix ? Config::mmc_prefix . ':' : ''; //connect to the read database by default parent::__construct($this->host_read,$this->username,$this->password,$this->dbname,$this->port,$this->socket); $this->logItems = array(); $this->countQuery = $this->countSelects = $this->countInserts = $this->countUpdates = $this->countDeletes = $this->countMemcache = 0; //init the memcache object if(Config::mmc_on) { $this->memcache = new memcache(); $this->using_memcache = @$this->memcache->connect(Config::mmc_host,Config::mmc_port); if($this->using_memcache) { $this->setMemcacheConfig(); //$this->memcache->flush(); } } $this->set_charset(Config::db_charset); } /** * close down memcache, logs, etc */ public function __destruct() { if($this->using_memcache) { //$this->memcache->close(); } if($this->logging) { //$this->logQueries(); } } public function __tostring() { return 'Data Layer Object'; } /** * Insert the local logs into the database */ protected function logQueries() { if($this->logging && count($this->logItems)) { $this->insertExtended(self::logtable,$this->logItems); } } /** * @param string $var * @return mixed */ public function __get($var) { switch($var) { case 'countQuery': return $this->countQuery; case 'countMemcache': return $this->countMemcache; } } /** * Change the database to read or write mode * @param string $db_alias * @return bool */ public function switchDb($db_alias) { switch ($db_alias) { case 'read': return (bool) $this->connect($this->host_read,$this->username,$this->password,$this->dbname,$this->port,$this->socket); case 'write': return (bool) $this->connect($this->host_write,$this->username,$this->password,$this->dbname,$this->port,$this->socket); } return false; } /** * Set various memcache parameters, such as default timeout, * compression, etc * @param hash $params */ public function setMemcacheConfig($params=array()) { $this->memcache_defaults['timeout'] = 600; //key timeout (in seconds) $this->memcache_defaults['compression'] = MEMCACHE_COMPRESSED; } /** * Get the value of a memcache key. * If not found, return NULL * @param string $key * @return mixed */ public function memcache_get($key) { if($this->using_memcache) { $ok = $this->memcache->get($this->memcache_prefix . $key); //log the result if($this->logging) { $this->mmkeylog[] = array('time'=>number_format(microtime(true),4,'.',''),'action'=>"GET '$this->memcache_prefix$key'",'status'=>($ok !== false ? 'Found ' . gettype($ok) : 'Not found')); } return $ok; } return null; } /** * Set a memcache key * @param string $key * @param mixed $data * @param int $timeout - in seconds * @return bool */ public function memcache_set($key,$data,$timeout) { if($this->using_memcache) { $timeout = $timeout ? $timeout : $this->memcache_defaults['timeout']; $ok = $this->memcache->set($this->memcache_prefix . $key,$data,$timeout); //log the result if($this->logging) { $this->mmkeylog[] = array('time'=>number_format(microtime(true),4,'.',''),'action'=>"SET '$this->memcache_prefix$key'",'status'=>($ok === true ? 'Set successfully' : 'Not set')); } return $ok; } return false; } /** * Delete a memcache key & value from the cache * @param string $key * @return bool */ public function memcache_delete($key) { if($this->using_memcache) { $ok = $this->memcache->delete($this->memcache_prefix . $key); //log the result if($this->logging) { $this->mmkeylog[] = array('time'=>number_format(microtime(true),4,'.',''),'action'=>"DELETE '$this->memcache_prefix$key'",'status'=>($ok === false ? 'Not found' : 'Deleted')); } return $ok; } return false; } /** * Get memcached server statistics. See * http://us3.php.net/manual/en/function.Memcache-getExtendedStats.php * for more details on the parameters * @param string $type * @param int $slabid * @param int $limit * @return hash */ public function memcache_stats($type=null,$slabid=null,$limit=null) { if($this->using_memcache) { return $this->memcache->getExtendedStats(); } else { return array('Memcached is either disabled or unavailable'); } } /** * Run a SELECT query on the database, if $memcache_key * is not filled * @param string $query * @param string $mode - result type to return ('object','array'); * @param bool $single_row - whether to return just the first row in the result set * @param string $memcache_key * @param int $memcache_timeout * @return hash */ public function select($query,$mode='object',$single_row=false,$memcache_key=null,$memcache_timeout=null) { $this->countSelects++; $mc = (bool) $memcache_key; $t0 = microtime(true); if($mc) { //if a memcache key is passed, try to fetch the data from memcache and return it /* Choose the function to use to test the memcache results - if $single_row is NOT set, the result will always be an array, otherwise it will be an object or array, depending on the value of $mode*/ $is_a = 'is_' . ($single_row ? $mode == 'object' ? 'object' : 'array' : 'array'); //echo "MEMCACHE:$memcache_key\n"; $memcache_timeout = $memcache_timeout ? $memcache_timeout : $this->memcache_defaults['timeout']; $res = $this->memcache_get($memcache_key); // get the data for the memcache key file_put_contents('err.txt', gettype($res), FILE_APPEND); $tdiff = microtime(true) - $t0; if($is_a($res)) { // if valid data is retrieved from memcache, return it! if($this->logging) { $this->log('',$memcache_key,$memcache_timeout,$tdiff,'memcache',''); } return $res; } } //query the database if no data from memcache $res = $this->runQuery($query,$mode,$single_row); if($mc && count($res)) { //set the memcache data, if a key is present $this->memcache_set($memcache_key,$res,$this->memcache_defaults['compression'],$memcache_timeout); } if($this->logging) { $tdiff = microtime(true) - $t0; $this->log($query,$memcache_key,$memcache_timeout,$tdiff,'query',$this->getError()); } //print_r($res); //echo "QUERY $query
"; return $res; } /** * Insert data into the database, returning the number * of affected rows (1 if inserted or 0 if failed) * @param string $table * @param hash $params - contains fieldname=>value pairs * @param string $memcache_key - to be invalidated * @return mixed - int on query execution, false on query failure */ public function insert($table,$params,$memcache_key=null) { if($this->logging) { $this->countInserts++; $t0 = microtime(true); } //flush the key's data, if present if($memcache_key) { $this->memcache_delete($memcache_key); } //build and run the query $fields = $this->buildQuery($params); $query = "INSERT INTO $table SET $fields"; $ret = $this->query($query); //log results, if logging if($this->logging) { $tdiff = microtime(true) - $t0; $this->log($query,$memcache_key,$memcache_timeout,$tdiff,'query',$this->getError()); } //and return the data return ($this->affected_rows >= 0 ? $this->affected_rows : false); } /** * Inserts multiple rows into $table using MySQL's extended * INSERT syntax (fastest method for multiple rows), * returning the number of rows inserted * @param string $table * @param hash $data * @return int */ public function insertExtended($table,$data,$memcache_key=null) { if($this->logging) { $t0 = microtime(true); } $query = "INSERT INTO $table("; $fields = array_keys($data[0]); $ct = count($fields); for($i=0;$i<$ct;$i++) { $fields[$i] = $this->real_escape_string($fields[$i]); } $query .= implode(',',$fields).') VALUES '; $rowsql = array(); $rowct = count($data); for($row=0;$row<$rowct;$row++) { $r = array_values($data[$row]); $c = count($r); //escape the data for($i=0;$i<$c;$i++) { if($r[$i] === null) { $r[$i] = 'null'; } else { $r[$i] = '"'.$this->real_escape_string($r[$i]).'"'; } } $rowsql[] = '('.implode(',',$r).')'; } $query .= implode(",\n",$rowsql); $res = $this->query($query); //flush the memcache key if($this->affected_rows && $memcache_key) { $this->memcache_delete($memcache_key); } if($this->logging) { $tdiff = microtime(true) - $t0; $this->log($query,$memcache_key,0,$tdiff,'query',$this->getError()); } return ($this->affected_rows >= 0 ? $this->affected_rows : false); } /** * Runs an update query on the database, returning the * number of affected rows * @param string $table * @param hash $params * @param hash $conditions * @return int */ public function update($table,$params,$conditions,$memcache_key=null) { if($this->logging) { $this->countUpdates++; $t0 = microtime(true); } //flush related cache if($memcache_key) { $this->memcache_delete($memcache_key); } //build and run the query $fields = $this->buildQuery($params); $cond = $this->buildConditions($conditions); $query = "UPDATE $table SET $fields WHERE $cond"; $ret = $this->query($query); //log if($this->logging) { $tdiff = microtime(true) - $t0; $this->log($query,$memcache_key,$memcache_timeout,$tdiff,'query',$this->getError()); } return ($this->affected_rows >= 0 ? $this->affected_rows : false); //return the number of rows affected } /** * Runs a delete query on the specified table, returning the * number of affected rows * @param string $table * @param hash $conditions * @param string $memcache_key * @return int */ public function delete($table,$conditions,$memcache_key=null) { if($this->logging) { $this->countDeletes++; $t0 = microtime(true); } //free cache if($memcache_key) { $this->memcache_delete($memcache_key); } //build and run the query $cond = $this->buildConditions($conditions); $query = "DELETE FROM $table WHERE $cond"; $ret = $this->query($query); //log if($this->logging) { $tdiff = microtime(true) - $t0; $this->log($query,$memcache_key,$memcache_timeout,$tdiff,'query',$this->getError()); } return ($this->affected_rows >= 0 ? $this->affected_rows : false); //return the number of rows affected } /** * Parses db errors into a more human-readable format */ public function getError() { return $this->error; } /** * Constructs a name=value data string series from an associative array * @param hash $params * @param bool $strip * @return string */ protected function buildQuery($params,$strip=true) { $sql = array(); foreach($params as $field=>$value) { $sql[] .= $field .'=\'' . ($strip ? $this->real_escape_string($value) : $value) . '\''; } return implode(',',$sql); } /** * Constructs a name=value condition string series from an associative array * @param hash $params * @param bool $strip * @return string */ protected function buildConditions($params,$strip=true,$or=false) { $sql = array(); if($strip) { foreach($params as $field=>$value) { $sql[] .= $field .'=\''. $this->real_escape_string($value) .'\''; } } else { foreach($params as $field=>$value) { $sql[] .= $field .'=\''. $value .'\''; } } return implode(($or ? ' OR ' : ' AND '),$sql); } /** * Runs a db query, returning the data as a hash array * @param string $query * @param string $mode {object,array} * @param bool $singlerow * @return hash */ protected function runQuery($query,$mode,$singlerow) { //the fetch function to use, depending on mode $qry = ''; $fetch_func = $mode == 'object' ? 'fetch_object' : 'fetch_assoc'; $ret = array(); if($singlerow) { $qry .= ' LIMIT 1'; } $qry = $this->query($query); if($qry) { if($singlerow) { $ret = $qry->$fetch_func(); } else { while($result = $qry->$fetch_func()) { $ret[] = $result; } } $qry->close(); } return $ret; } /** * Log a query's parameters and time to a local variable * @param string $query - the query string * @param string $mckey - memcache key, if present * @param int $mcto - memcache key timeout, if present * @param float $te - query time * @param string $type - {query,memcache} * @parem string $error - error message, if any */ protected function log($query,$mckey,$mcto,$te,$type,$error) { $this->logItems[] = array('query'=>$query,'memcache_key'=>$mckey,'memcache_timeout'=>$mcto,'time_elapsed'=>number_format(1000 * $te,2).'ms','type'=>$type); $err = $this->getError(); if($err) { $this->logItems[count($this->logItems)-1]['error'] = $err; } if($type == 'query') { $this->countQuery++; } else if($type == 'memcache') { $this->countMemcache++; } } /** * Output a readable log of all queries since the connection was opened * @param bool $use_html * @param bool $verbose * @return string */ public function outputStats($use_html=false,$verbose=false) { $nl = $use_html ? '
' : "\n"; $ret = $use_html ? '

Data Layer Statistics

' : "Data Layer Statistics$nl$nl"; $ret .= "DB queries:{$nl}SELECTs: $this->countSelects ($this->countMemcache memcache/$this->countQuery database){$nl}INSERTs: $this->countInserts {$nl}UPDATEs: $this->countUpdates {$nl}DELETEs: $this->countDeletes $nl"; $ret .= 'Memcache '.($this->using_memcache ? 'IS' : 'IS NOT') ." being used$nl"; if($verbose) { $ret .= "Raw query output:$nl"; $qrys = print_r($this->logItems,true); $ret .= ($use_html ? "
$qrys
" : $qrys); } $ret .= $use_html ? '
' : $nl; return $ret; } }; ?>