brokencube/automatorm

View on GitHub
src/Orm/Dump.php

Summary

Maintainability
D
2 days
Test Coverage
<?php

namespace Automatorm\Orm;

/**
 * @codeCoverageIgnore
 */
class Dump
{
    public static $url_prefix = null;
    public static $id_limit = 30;
    
    public static function dump($var)
    {
        // Use specialised function to dump Orm objects
        if (is_object($var)) {
            if ($var instanceof Model) {
                return "<pre>" . static::dumpModel($var) . "</pre>\n";
            }
            
            if ($var instanceof Collection) {
                return "<pre>" . static::dumpCollection($var) . "</pre>\n";
            }
        }
        
        // Fall back to var_dump for everything else
        ob_start();
        var_dump($var);
        return "<pre>" . ob_get_clean() . "</pre>\n";
    }
    
    public static function dumpCollection(Collection $collection)
    {
        if (is_object($collection->first()) and $collection->first() instanceof Model) {
            $output = "<span><strong>Collection of ".get_class($collection->first())." Models</strong></span>\n";
        } else {
            $output = "<span><strong>Collection object:</strong></span>\n";
        }
        
        foreach ($collection as $key => $value) {
            $output .= "  " . \Automatorm\Orm\Dump::format($key, $value);
        }
        return $output;
    }
    
    public static function dumpModel(Model $model)
    {
        $data_access = function ($var) {
            return $this->$var;
        };
        
        $closure = function () use ($data_access) {
            $data = $data_access->bindTo($this->_data, $this->_data);
            $schema = $data('model');
            $seen = [];
            
            $output = "<span><strong>".get_class()."</strong></span>\n";
            $output .= "  <span><strong>id</strong></span> => ".$this->id."\n";
            $output .= "  <span><strong>connection</strong></span> => ".$this->connection->name."\n";
            $output .= "  <span><strong>table</strong></span> => ".$this->table."\n";
                        
            $output .= "  <span><strong>object_properties</strong></span> =>\n";
            foreach (get_object_vars($this) as $key => $value) {
                $output .= "    " . \Automatorm\Orm\Dump::format($key, $value, $seen);
                $seen[$key] = true;
            }
            
            $output .= "  <span><strong>dynamic_properties</strong></span> =>\n";
            foreach (get_class_methods($this) as $method) {
                if (substr($method, 0, 10) == '_property_') {
                    $key = substr($method, 10);
                    try {
                        $value = $this->$method();
                        $output .= "    " . \Automatorm\Orm\Dump::format($key, $value, $seen);
                    } catch (\Throwable $e) {
                        $output .= "    " . \Automatorm\Orm\Dump::format($key, null, $seen, 0, $e);
                    }
                    $seen[$key] = true;
                }
            }

            $output .= "  <span><strong>data_properties</strong></span> =>\n";
            foreach ($data('data') as $key => $value) {
                $output .= "    " . \Automatorm\Orm\Dump::format($key, $value, $seen);
                $seen[$key] = true;
            }
            
            $output .= "  <span><strong>external_tables</strong></span> =>\n";
            $output .= "    <span><strong>1-1</strong></span> =>\n";
            if ($schema['one-to-one']) {
                foreach ($schema['one-to-one'] as $key => $contents) {
                    $value = $this->_data->$key;
                
                    $output .= "      " . \Automatorm\Orm\Dump::format($key, $value, $seen);
                    $seen[$key] = true;
                }
            }

            $output .= "    <span><strong>*-1</strong></span> =>\n";
            if ($schema['many-to-one']) {
                foreach ($schema['many-to-one'] as $key => $contents) {
                    $value = $this->_data->$key;
                
                    $output .= "      " . \Automatorm\Orm\Dump::format($key, $value, $seen);
                    $seen[$key] = true;
                }
            }

            $output .= "    <span><strong>1-*</strong></span> =>\n";
            if ($schema['one-to-many']) {
                foreach ($schema['one-to-many'] as $key => $contents) {
                    $count = $this->_data->joinCount($key, []);
                    if ($count < \Automatorm\Orm\Dump::$id_limit) {
                        $value = $this->{$key};
                    } else {
                        $value = new Collection(
                            Model::factory(
                                [$contents['column_name'] => $this->id],
                                $contents['table'],
                                Schema::getSchemaByName($contents['schema']),
                                ['limit' => 1]
                            )
                        );
                    }
                    
                    $output .= "      " . \Automatorm\Orm\Dump::format($key, $value, $seen, $count);
                    
                    $seen[$key] = true;
                }
            }

            $output .= "    <span><strong>*-*</strong></span> =>\n";
            if ($schema['many-to-many']) {
                foreach ($schema['many-to-many'] as $key => $contents) {
                    $ids = $this->{$key}->id->toArray();
                    $value = $this->_data->join($key, ['id' => array_slice($ids, 0, \Automatorm\Orm\Dump::$id_limit)]);
            
                    $output .= "      " . \Automatorm\Orm\Dump::format($key, $value, $seen, count($ids));
                
                    $seen[$key] = true;
                }
            }
            
            return $output;
        };
        
        $c = $closure->bindTo($model, $model);
        return $c();
    }
    
    public static function format($key, $value, $seen = [], $collectionCount = 0, $exceptionThrown = false)
    {
        switch (true) {
            case $value instanceof Model:
                $namespace = explode('\\', get_class($value));
                $class = array_pop($namespace);
                $table = $value::$tablename;
                $type = 'Model';

                // Show table name if Model is not subclassed
                if (get_class($value) == 'Automatorm\\Orm\\Model') {
                    $display1 = 'tablename:';
                    $display2 = $table;
                } else {
                    $display1 = implode('\\', $namespace) . '\\';
                    $display2 = $class;
                }
                
                if (static::$url_prefix) {
                    $table = $value->_data->getTable();
                    $display3 = " <a href='".static::$url_prefix."/{$table}/{$value->id}'>".$value->id."</a>";
                } else {
                    $display3 = " ".$value->id;
                }
                
                if (method_exists($value, '__toString')) {
                    $display4 = ' (' . \Automatorm\Orm\Dump::safeTruncate($value) . ')';
                }
                break;

            case $value instanceof Collection:
                $ids = [];
                foreach ($value as $obj) {
                    if ($obj instanceof Model && static::$url_prefix) {
                        $table = $obj->_data->getTable();
                        $ids[] = "<a href='".static::$url_prefix."/{$table}/{$obj->id}'>".$obj->id."</a>";
                    } else {
                        $ids[] = $obj->id;
                    }
                }
                
                if ($ids) {
                    $namespace = explode('\\', get_class($obj));
                    $class = array_pop($namespace);
                    
                    if (get_class($obj) == 'Automatorm\\Orm\\Model') {
                        $display1 = 'tablename:';
                        $display2 = $obj->_data->getTable();
                    } else {
                        $display1 = implode('\\', $namespace) . '\\';
                        $display2 = $class;
                    }
                    
                    if ($collectionCount > \Automatorm\Orm\Dump::$id_limit) {
                        $display3 = "";
                        $display4 = " ({$collectionCount} results total)";
                    } else {
                        $display3 = " [".implode(',', $ids)."]";
                        if (method_exists($obj, '__toString')) {
                            foreach ($value as $obj) {
                                $objstrings[] = \Automatorm\Orm\Dump::safeTruncate($obj);
                            }
                            $display4 = implode(',', $objstrings);
                            $display4 = ' (' . $display4 . ')';
                        }
                    }
                } else {
                    $display1 = 'empty';
                    $display3 = " []";
                }
                
                $type = 'Collection';
                break;

            case $value instanceof DateTimeInterface:
                $type = 'DateTime';
                $display3 = $value->format('Y-m-d H:i:s');
                break;
            
            case is_object($value):
                $namespace = explode('\\', get_class($value));
                $class = array_pop($namespace);
                
                $type = 'object';
                $display1 = implode('\\', $namespace) . '\\';
                $display2 = $class;
                if (method_exists($value, '__toString')) {
                    $display4 = ' (' . (string) $value . ')';
                }
                break;
            
            case is_bool($value):
                $type = 'boolean';
                $display3 = $value?'true':'false';
                break;
            
            case is_null($value):
                $type = 'null';
                $display3 = "NULL";
                break;

            case is_string($value):
                $type = 'string';
                $display3 = '"' . $value .'"';
                break;
            
            default:
                $type = gettype($value);
                $display3 = $value;
                break;
        }
        
        if ($exceptionThrown) {
            $display5 = "Exception Thrown";
        }
        
        if (array_key_exists($key, $seen)) {
            return
                "<del style='color: #999999;'><strong>$key</strong> => <small>$type</small> ".
                $display1.
                $display2.
                $display3.
                $display4.
                "</del>\n";
        } else {
            return "<strong>$key</strong> => <small>$type</small> ".
            "<span style='color: #999999;'>$display1</span>".
            "<span style='color: #000077;'>$display2</span>".
            "<span style='color: #cc0000;'>$display3</span>".
            "<span style='color: #007700;'>$display4</span>".
            "<strong style='color: #ff0000;'>$display5</strong>".
            "\n";
        }
    }
    
    public static function safeTruncate($string, $length = 50)
    {
        if (strlen($string) > $length) {
            return htmlspecialchars(substr($string, 0, $length)) . '...';
        }
        return htmlspecialchars($string);
    }
}