5); // Function specific log levels var $function_log_level = array(); // Force the module to log at LEAST at this level var $min_log_level; // Force logging of nothing higher than this level var $max_log_level; // REVISIT : 20090730 // Why is this constructor crashing? // Clearly it's in some sort of infinite // loop, but it seems the correct way // to have a constructor call the parent... /* function __construct() { */ /* parent::__construct(); */ /* $this->prClassLevel(5, 'Model'); */ /* } */ /************************************************************************** ************************************************************************** ************************************************************************** * function: pr * - Prints out debug information, if the log level allows */ function prClassLevel($level, $class = null) { $trace = debug_backtrace(false); $caller = array_shift($trace); $caller = array_shift($trace); if (empty($class)) $class = $caller['class']; $this->class_log_level[$class] = $level; } function prFunctionLevel($level, $function = null, $class = null) { $trace = debug_backtrace(false); $caller = array_shift($trace); $caller = array_shift($trace); if (empty($class)) $class = $caller['class']; if (empty($function)) $function = $caller['function']; $this->function_log_level["{$class}-{$function}"] = $level; } function _pr($level, $mixed, $checkpoint = null) { if (Configure::read() <= 0) return; $log_level = $this->default_log_level; $trace = debug_backtrace(false); // Get rid of pr/prEnter/prReturn $caller = array_shift($trace); // The next entry shows where pr was called from, but it // shows _what_ was called, which is pr/prEntry/prReturn. $caller = array_shift($trace); $file = $caller['file']; $line = $caller['line']; // So, this caller holds the calling function name $caller = $trace[0]; $function = $caller['function']; $class = $caller['class']; //$class = $this->name; // Use class or function specific log level if available if (isset($this->class_log_level[$class])) $log_level = $this->class_log_level[$class]; if (isset($this->function_log_level["{$class}-{$function}"])) $log_level = $this->function_log_level["{$class}-{$function}"]; // Establish log level minimums $min_log_level = $this->min_log_level; if (is_array($this->min_log_level)) { $min_show_level = $min_log_level['show']; $min_log_level = $min_log_level['log']; } // Establish log level maximums $max_log_level = $this->max_log_level; if (is_array($this->max_log_level)) { $max_show_level = $max_log_level['show']; $max_log_level = $max_log_level['log']; } // Determine the applicable log and show levels if (is_array($log_level)) { $show_level = $log_level['show']; $log_level = $log_level['log']; } // Adjust log level up/down to min/max if (isset($min_log_level)) $log_level = max($log_level, $min_log_level); if (isset($max_log_level)) $log_level = min($log_level, $max_log_level); // Adjust show level up/down to min/max if (isset($min_show_level)) $show_level = max($show_level, $min_show_level); if (isset($max_show_level)) $show_level = min($show_level, $max_show_level); // If the level is insufficient, bail out if ($level > $log_level) return; if (!empty($checkpoint)) { $chk = array("checkpoint" => $checkpoint); if (is_array($mixed)) $mixed = $chk + $mixed; else $mixed = $chk + array($mixed); } static $pr_unique_number = 0; $pr_id = 'pr-section-class-' . $class . '-print-' . (++$pr_unique_number); $pr_trace_id = $pr_id . '-trace'; $pr_output_id = $pr_id . '-output'; $pr_entire_base_class = "pr-section"; $pr_entire_class_class = $pr_entire_base_class . '-class-' . $class; $pr_entire_function_class = $pr_entire_class_class . '-function-' . $function; $pr_entire_class = "$pr_entire_base_class $pr_entire_class_class $pr_entire_function_class"; $pr_header_class = "pr-caller"; $pr_trace_class = "pr-trace"; $pr_output_base_class = 'pr-output'; $pr_output_class_class = $pr_output_base_class . '-class-' . $class; $pr_output_function_class = $pr_output_class_class . '-function-' . $function; $pr_output_class = "$pr_output_base_class $pr_output_class_class $pr_output_function_class"; echo '
'."\n"; echo '
'."\n"; echo '' . "\n"; // End pr_trace_class $file = str_replace(ROOT.DS, '', $file); $file = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $file); echo "$file:$line ($class::$function)" . ";\n"; /* $log_show_level = isset($show_level) ? $show_level : '?'; */ /* echo ' L' . $level . "({$log_level}/{$log_show_level})" . ";\n"; */ echo ' L' . $level . ";\n"; echo ' stack'.";\n"; echo " this "; echo 't'."/"; echo 'n'.";\n"; echo " $class "; echo 's'."/"; echo 'h'."/"; echo 'n'.";\n"; echo " $function "; echo 's'."/"; echo 'h'."/"; echo 'n'.";\n"; echo " all "; echo 's'."/"; echo 'h'."/"; echo 'n'."\n"; echo '
' . "\n"; // End pr_header_class if (isset($show_level) && $level > $show_level) $display = 'none'; else $display = 'block'; echo '
'."\n"; pr($mixed, false, false); echo '
' . "\n"; // End pr_output_class echo '
' . "\n"; // End pr_entire_class } function pr($level, $mixed, $checkpoint = null) { $this->_pr($level, $mixed, $checkpoint); } function prEnter($args, $level = 15) { $this->_pr($level, $args, 'Function Entry'); } function prReturn($retval, $level = 16) { $this->_pr($level, $retval, 'Function Return'); return $retval; } /************************************************************************** ************************************************************************** ************************************************************************** * function: queryInit * - Initializes the query fields */ function prDump($all = false) { $vars = get_object_vars($this); foreach (array_keys($vars) AS $name) { if (preg_match("/^[A-Z]/", $name)) unset($vars[$name]); if (preg_match("/^_/", $name) && !$all) unset($vars[$name]); } pr($vars); } /** * Get Enum Values * Snippet v0.1.3 * http://cakeforge.org/snippet/detail.php?type=snippet&id=112 * * Gets the enum values for MySQL 4 and 5 to use in selectTag() */ function getEnumValues($columnName=null, $tableName=null) { if ($columnName==null) { return array(); } //no field specified if (!isset($tableName)) { //Get the name of the table $db =& ConnectionManager::getDataSource($this->useDbConfig); $tableName = $db->fullTableName($this, false); } //Get the values for the specified column (database and version specific, needs testing) $result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'"); //figure out where in the result our Types are (this varies between mysql versions) $types = null; if ( isset( $result[0]['COLUMNS']['Type'] ) ) { //MySQL 5 $types = $result[0]['COLUMNS']['Type']; $default = $result[0]['COLUMNS']['Default']; } elseif ( isset( $result[0][0]['Type'] ) ) { //MySQL 4 $types = $result[0][0]['Type']; $default = $result[0][0]['Default']; } else { //types return not accounted for return array(); } //Get the values return array_flip(array_merge(array(''), // MySQL sets 0 to be the empty string explode("','", strtoupper(preg_replace("/(enum)\('(.+?)'\)/","\\2", $types))) )); } //end getEnumValues /************************************************************************** ************************************************************************** ************************************************************************** * function: queryInit * - Initializes the query fields */ function queryInit(&$query, $link = true) { if (!isset($query)) $query = array(); if (!isset($query['conditions'])) $query['conditions'] = array(); if (!isset($query['group'])) $query['group'] = null; if (!isset($query['fields'])) $query['fields'] = null; if ($link && !isset($query['link'])) $query['link'] = array(); if (!$link && !isset($query['contain'])) $query['contain'] = array(); // In case caller expects query to come back return $query; } /************************************************************************** ************************************************************************** ************************************************************************** * function: nameToID * - Returns the ID of the named item */ function nameToID($name) { $this->cacheQueries = true; $item = $this->find('first', array ('recursive' => -1, 'conditions' => compact('name'), )); $this->cacheQueries = false; if ($item) { $item = current($item); return $item['id']; } return null; } /************************************************************************** ************************************************************************** ************************************************************************** * function: statMerge * - Merges summary data from $b into $a */ function statsMerge (&$a, $b) { if (!isset($b)) return; if (!isset($a)) { $a = $b; } elseif (!is_array($a) && !is_array($b)) { $a += $b; } elseif (is_array($a) && is_array($b)) { foreach (array_intersect_key($a, $b) AS $k => $v) { if (preg_match("/^sp\./", $k)) $a[$k] .= '; ' . $b[$k]; else $this->statsMerge($a[$k], $b[$k]); } $a = array_merge($a, array_diff_key($b, $a)); } else { die ("Can't yet merge array and non-array stats"); } } function recursive_array_replace($find, $replace, &$data) { if (!isset($data)) return; if (is_array($data)) { foreach ($data as $key => &$value) { $this->recursive_array_replace($find, $replace, $value); } return; } if (isset($replace)) $data = preg_replace($find, $replace, $data); elseif (preg_match($find, $data)) $data = null; } function beforeSave() { /* pr(array('class' => $this->name, */ /* 'alias' => $this->alias, */ /* 'function' => 'AppModel::beforeSave')); */ // Replace all empty strings with NULL. // If a particular model doesn't like this, they'll have to // override the behavior, or set useNullForEmpty to false. if ($this->useNullForEmpty) $this->recursive_array_replace("/^\s*$/", null, $this->data); if ($this->formatDateFields) { $alias = $this->alias; foreach ($this->_schema AS $field => $info) { if ($info['type'] == 'date' || $info['type'] == 'timestamp') { if (isset($this->data[$alias][$field])) { /* pr("Fix Date for '$alias'.'$field'; current value = " . */ /* "'{$this->data[$alias][$field]}'"); */ if ($this->data[$alias][$field] === 'CURRENT_TIMESTAMP') // Seems CakePHP is broken for the default timestamp. // It tries to automagically set the value to CURRENT_TIMESTAMP // which is wholly rejected by MySQL. Just put it back to NULL // and let the SQL engine deal with the defaults... it's not // Cake's place to do this anyway :-/ $this->data[$alias][$field] = null; else $this->data[$alias][$field] = $this->dateFormatBeforeSave($this->data[$alias][$field]); } } } } return true; } /************************************************************************** ************************************************************************** ************************************************************************** * function: dateFormatBeforeSave * - convert dates to database format */ function dateFormatBeforeSave($dateString) { /* $time = ''; */ /* if (preg_match('/(\d+(:\d+))/', $dateString, $match)) */ /* $time = ' '.$match[1]; */ /* $dateString = preg_replace('/(\d+(:\d+))/', '', $dateString); */ /* return date('Y-m-d', strtotime($dateString)) . $time; */ if (preg_match('/:/', $dateString)) return date('Y-m-d H:i:s', strtotime($dateString)); else return date('Y-m-d', strtotime($dateString)); } }