Exemplo n.º 1
0
 /**
  * Runs Codebench on the extending class.
  *
  * @return  array  benchmark output
  */
 public function run()
 {
     // Array of all methods to loop over
     $methods = array_filter(get_class_methods($this), array($this, '_method_filter'));
     // Make sure the benchmark runs at least once,
     // also if no subject data has been provided.
     if (empty($this->subjects)) {
         $this->subjects = array('NULL' => NULL);
     }
     // Initialize benchmark output
     $codebench = array('class' => get_class($this), 'description' => $this->description, 'loops' => array('base' => (int) $this->loops, 'total' => (int) $this->loops * count($this->subjects) * count($methods)), 'subjects' => $this->subjects, 'benchmarks' => array());
     // Benchmark each method
     foreach ($methods as $method) {
         // Initialize benchmark output for this method
         $codebench['benchmarks'][$method] = array('time' => 0, 'memory' => 0);
         // Using Reflection because simply calling $this->$method($subject) in the loop below
         // results in buggy benchmark times correlating to the length of the method name.
         $reflection = new ReflectioNamethod(get_class($this), $method);
         // Benchmark each subject on each method
         foreach ($this->subjects as $subject_key => $subject) {
             // Prerun each method/subject combo before the actual benchmark loop.
             // This way relatively expensive initial processes won't be benchmarked, e.g. autoloading.
             // At the same time we capture the return here so we don't have to do that in the loop anymore.
             $return = $reflection->invoke($this, $subject);
             // Start the timer for one subject
             $token = Profiler::start('codebench', $method . $subject_key);
             // The heavy work
             for ($i = 0; $i < $this->loops; ++$i) {
                 $reflection->invoke($this, $subject);
             }
             // Stop and read the timer
             $benchmark = Profiler::total($token);
             // Benchmark output specific to the current method and subject
             $codebench['benchmarks'][$method]['subjects'][$subject_key] = array('return' => $return, 'time' => $benchmark[0], 'memory' => $benchmark[1]);
             // Update method totals
             $codebench['benchmarks'][$method]['time'] += $benchmark[0];
             $codebench['benchmarks'][$method]['memory'] += $benchmark[1];
         }
     }
     // Initialize the fastest and slowest benchmarks for both methods and subjects, time and memory,
     // these values will be overwritten using min() and max() later on.
     // The 999999999 values look like a hack, I know, but they work,
     // unless your method runs for more than 31 years or consumes over 1GB of memory.
     $fastest_method = $fastest_subject = array('time' => 999999999, 'memory' => 999999999);
     $slowest_method = $slowest_subject = array('time' => 0, 'memory' => 0);
     // Find the fastest and slowest benchmarks, needed for the percentage calculations
     foreach ($methods as $method) {
         // Update the fastest and slowest method benchmarks
         $fastest_method['time'] = min($fastest_method['time'], $codebench['benchmarks'][$method]['time']);
         $fastest_method['memory'] = min($fastest_method['memory'], $codebench['benchmarks'][$method]['memory']);
         $slowest_method['time'] = max($slowest_method['time'], $codebench['benchmarks'][$method]['time']);
         $slowest_method['memory'] = max($slowest_method['memory'], $codebench['benchmarks'][$method]['memory']);
         foreach ($this->subjects as $subject_key => $subject) {
             // Update the fastest and slowest subject benchmarks
             $fastest_subject['time'] = min($fastest_subject['time'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['time']);
             $fastest_subject['memory'] = min($fastest_subject['memory'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['memory']);
             $slowest_subject['time'] = max($slowest_subject['time'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['time']);
             $slowest_subject['memory'] = max($slowest_subject['memory'], $codebench['benchmarks'][$method]['subjects'][$subject_key]['memory']);
         }
     }
     // Percentage calculations for methods
     foreach ($codebench['benchmarks'] as &$method) {
         // Calculate percentage difference relative to fastest and slowest methods
         $method['percent']['fastest']['time'] = $method['time'] / $fastest_method['time'] * 100;
         $method['percent']['fastest']['memory'] = $method['memory'] / $fastest_method['memory'] * 100;
         $method['percent']['slowest']['time'] = $method['time'] / $slowest_method['time'] * 100;
         $method['percent']['slowest']['memory'] = $method['memory'] / $slowest_method['memory'] * 100;
         // Assign a grade for time and memory to each method
         $method['grade']['time'] = $this->_grade($method['percent']['fastest']['time']);
         $method['grade']['memory'] = $this->_grade($method['percent']['fastest']['memory']);
         // Percentage calculations for subjects
         foreach ($method['subjects'] as &$subject) {
             // Calculate percentage difference relative to fastest and slowest subjects for this method
             $subject['percent']['fastest']['time'] = $subject['time'] / $fastest_subject['time'] * 100;
             $subject['percent']['fastest']['memory'] = $subject['memory'] / $fastest_subject['memory'] * 100;
             $subject['percent']['slowest']['time'] = $subject['time'] / $slowest_subject['time'] * 100;
             $subject['percent']['slowest']['memory'] = $subject['memory'] / $slowest_subject['memory'] * 100;
             // Assign a grade letter for time and memory to each subject
             $subject['grade']['time'] = $this->_grade($subject['percent']['fastest']['time']);
             $subject['grade']['memory'] = $this->_grade($subject['percent']['fastest']['memory']);
         }
     }
     return $codebench;
 }
Exemplo n.º 2
0
 /**
  * Executes all validation filters, rules, and callbacks. This should
  * typically be called within an if/else block.
  *
  *     if ($validation->check())
  *     {
  *          // The data is valid, do something here
  *     }
  *
  * @return  boolean
  */
 public function check()
 {
     if (Kohana::$profiling === TRUE) {
         // Start a new benchmark
         $benchmark = Profiler::start('Validation', __FUNCTION__);
     }
     // New data set
     $data = $this->_errors = array();
     // Assume nothing has been submitted
     $submitted = FALSE;
     // Get a list of the expected fields
     $expected = array_keys($this->_labels);
     // Import the filters, rules, and callbacks locally
     $filters = $this->_filters;
     $rules = $this->_rules;
     $callbacks = $this->_callbacks;
     foreach ($expected as $field) {
         if (isset($this[$field])) {
             // Some data has been submitted, continue validation
             $submitted = TRUE;
             // Use the submitted value
             $data[$field] = $this[$field];
         } else {
             // No data exists for this field
             $data[$field] = NULL;
         }
         if (isset($filters[TRUE])) {
             if (!isset($filters[$field])) {
                 // Initialize the filters for this field
                 $filters[$field] = array();
             }
             // Append the filters
             $filters[$field] += $filters[TRUE];
         }
         if (isset($rules[TRUE])) {
             if (!isset($rules[$field])) {
                 // Initialize the rules for this field
                 $rules[$field] = array();
             }
             // Append the rules
             $rules[$field] += $rules[TRUE];
         }
         if (isset($callbacks[TRUE])) {
             if (!isset($callbacks[$field])) {
                 // Initialize the callbacks for this field
                 $callbacks[$field] = array();
             }
             // Append the callbacks
             $callbacks[$field] += $callbacks[TRUE];
         }
     }
     // Overload the current array with the new one
     $this->exchangeArray($data);
     if ($submitted === FALSE) {
         // Because no data was submitted, validation will not be forced
         return FALSE;
     }
     // Remove the filters, rules, and callbacks that apply to every field
     unset($filters[TRUE], $rules[TRUE], $callbacks[TRUE]);
     // Execute the filters
     foreach ($filters as $field => $set) {
         // Get the field value
         $value = $this[$field];
         foreach ($set as $filter => $params) {
             // Add the field value to the parameters
             array_unshift($params, $value);
             if (strpos($filter, '::') === FALSE) {
                 // Use a function call
                 $function = new ReflectionFunction($filter);
                 // Call $function($this[$field], $param, ...) with Reflection
                 $value = $function->invokeArgs($params);
             } else {
                 // Split the class and method of the rule
                 list($class, $method) = explode('::', $filter, 2);
                 // Use a static method call
                 $method = new ReflectioNamethod($class, $method);
                 // Call $Class::$method($this[$field], $param, ...) with Reflection
                 $value = $method->invokeArgs(NULL, $params);
             }
         }
         // Set the filtered value
         $this[$field] = $value;
     }
     // Execute the rules
     foreach ($rules as $field => $set) {
         // Get the field value
         $value = $this[$field];
         foreach ($set as $rule => $params) {
             if (!in_array($rule, $this->_empty_rules) and !Validate::not_empty($value)) {
                 // Skip this rule for empty fields
                 continue;
             }
             // Add the field value to the parameters
             array_unshift($params, $value);
             if (method_exists($this, $rule)) {
                 // Use a method in this object
                 $method = new ReflectioNamethod($this, $rule);
                 if ($method->isStatic()) {
                     // Call static::$rule($this[$field], $param, ...) with Reflection
                     $passed = $method->invokeArgs(NULL, $params);
                 } else {
                     // Do not use Reflection here, the method may be protected
                     $passed = call_user_func_array(array($this, $rule), $params);
                 }
             } elseif (strpos($rule, '::') === FALSE) {
                 // Use a function call
                 $function = new ReflectionFunction($rule);
                 // Call $function($this[$field], $param, ...) with Reflection
                 $passed = $function->invokeArgs($params);
             } else {
                 // Split the class and method of the rule
                 list($class, $method) = explode('::', $rule, 2);
                 // Use a static method call
                 $method = new ReflectioNamethod($class, $method);
                 // Call $Class::$method($this[$field], $param, ...) with Reflection
                 $passed = $method->invokeArgs(NULL, $params);
             }
             if ($passed === FALSE) {
                 // Remove the field name from the parameters
                 array_shift($params);
                 // Add the rule to the errors
                 $this->error($field, $rule, $params);
                 // This field has an error, stop executing rules
                 break;
             }
         }
     }
     // Execute the callbacks
     foreach ($callbacks as $field => $set) {
         if (isset($this->_errors[$field])) {
             // Skip any field that already has an error
             continue;
         }
         foreach ($set as $callback) {
             if (is_string($callback) and strpos($callback, '::') !== FALSE) {
                 // Make the static callback into an array
                 $callback = explode('::', $callback, 2);
             }
             if (is_array($callback)) {
                 // Separate the object and method
                 list($object, $method) = $callback;
                 // Use a method in the given object
                 $method = new ReflectioNamethod($object, $method);
                 if (!is_object($object)) {
                     // The object must be NULL for static calls
                     $object = NULL;
                 }
                 // Call $object->$method($this, $field, $errors) with Reflection
                 $method->invoke($object, $this, $field);
             } else {
                 // Use a function call
                 $function = new ReflectionFunction($callback);
                 // Call $function($this, $field, $errors) with Reflection
                 $function->invoke($this, $field);
             }
             if (isset($this->_errors[$field])) {
                 // An error was added, stop processing callbacks
                 break;
             }
         }
     }
     if (isset($benchmark)) {
         // Stop benchmarking
         Profiler::stop($benchmark);
     }
     return empty($this->_errors);
 }