<commit_before><?php

namespace Respect\Relational\Schemas;

use PDOStatement;
use Respect\Relational\Schemable;

class Reflected implements Schemable
{
    
}

/**
 * LICENSE
 *
 * Copyright (c) 2009-2011, <NAME>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright notice,<commit_msg>Incomplete draft for Reflected schema<commit_after><?php

namespace Respect\Relational\Schemas;

use ReflectionClass;
use PDOStatement;
use Respect\Relational\Schemable;

class Reflected implements Schemable
{

    protected $namespace;

    public function __construct($namespace)
    {
        throw new \Exception('Not working yet');
        $this->namespace = $namespace;
    }

    public function extractColumns($entity, $name)
    {
        $cols = array();
        $reflection = new ReflectionClass($entity);
        $properties = $reflection->getProperties();
        foreach ($properties as $prop) {
            $propValue = $prop->getValue($entity);
            if (is_object($propValue)) {
                $subName = $this->findTableName($propValue);
                $subCols = $this->extractColumns($propValue, $subName);
                $subPk = $this->findPrimaryKey($subName);
                $propValue = $subCols[$subPk];
            }
            $cols[$prop->getName()] = $propValue;
        }
        return $cols;
    }

    public function fetchHydrated(Finder $finder, PDOStatement $statement)
    {
        
    }

    public function findPrimaryKey($entityName)
    {
        //TODO composite pks
        $reflection = new ReflectionClass("{$this->namespace}{$entityName}");
        $params = $reflection->getConstructor()->getParameters();
        return $params[0]->getName();
    }

    public function findTableName($entity)
    {
        $parts = explode('\\', get_class($entity));
        return end($parts);
    }

    public function generateQuery(Finder $finder)
    {
        $finders = iterator_to_array(FinderIterator::recursive($finder), true);
        $sql = new Sql;

        $this->buildSelectStatement($sql, $finders);
        $this->buildTables($sql, $finders);

        return $sql;
    }

    protected function buildSelectStatement(Sql $sql, $finders)
    {
        $selectTable = array_keys($finders);
        foreach ($selectTable as &$ts)
            $ts = "$ts.*";

        return $sql->select($selectTable);
    }

    protected function buildTables(Sql $sql, $finders)
    {
        $conditions = $aliases = array();

        foreach ($finders as $alias => $finder)
            $this->parseFinder($sql, $finder, $alias, $aliases, $conditions);

        return $sql->where($conditions);
    }

    protected function parseConditions(&$conditions, $finder, $alias)
    {
        $entity = $finder->getName();
        $originalConditions = $finder->getCondition();
        $parsedConditions = array();
        $aliasedPk = "$alias." . $this->findPrimaryKey($entity);

        if (is_scalar($originalConditions))
            $parsedConditions = array($aliasedPk => $originalConditions);
        elseif (is_array($originalConditions))
            foreach ($originalConditions as $column => $value)
                if (is_numeric($column))
                    $parsedConditions[$column] = preg_replace(
                        "/{$entity}[.](\w+)/", "$alias.$1", $value
                    );
                else
                    $parsedConditions["$alias.$column"] = $value;

        return $parsedConditions;
    }

    protected function parseFinder(Sql $sql, Finder $finder, $alias, &$aliases,
                                   &$conditions)
    {
        $entity = $finder->getName();
        $parent = $finder->getParentName();
        $next = $finder->getNextName();

        $parentAlias = $parent ? $aliases[$parent] : null;
        $aliases[$entity] = $alias;
        $parsedConditions = $this->parseConditions($conditions, $finder, $alias);

        if (!empty($parsedConditions))
            $conditions[] = $parsedConditions;

        if (is_null($parentAlias))
            return $sql->from($entity);
        elseif ($finder->isRequired())
            $sql->innerJoin($entity);
        else
            $sql->leftJoin($entity);

        if ($alias !== $entity)
            $sql->as($alias);

        $aliasedPk = "$alias." . $this->findPrimaryKey($entity);
        $aliasedParentPk = "$parentAlias." . $this->findPrimaryKey($parent);

        if ($entity === "{$parent}_{$next}")
            return $sql->on(array("{$alias}.{$parent}_id" => $aliasedParentPk));
        else
            return $sql->on(array("{$parentAlias}.{$entity}_id" => $aliasedPk));
    }

}

/**
 * LICENSE
 *
 * Copyright (c) 2009-2011, <NAME>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright notice,
{'fraction_non_alphanumeric': 0.13306302985624768, 'fraction_numerical': 0.003317360855141909, 'mean_word_length': 2.549378678875082, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3218967', 'n_tokens_mistral': 1500, 'n_tokens_neox': 1461, 'n_words': 359}