<commit_before><?php

namespace ActiveCollab\DatabaseObject;

use ActiveCollab\DatabaseConnection\ConnectionInterface;
use InvalidArgumentException;
use ReflectionClass;

/**
 * @package ActiveCollab\DatabaseObject
 */
class Pool implements PoolInterface
{
    /**
     * @var ConnectionInterface
     */
    private $connection;

    /**
     * @var ObjectInterface[]
     */
    private $objects_pool = [];

    /**
     * @param ConnectionInterface $connection
     */
    public function __construct(ConnectionInterface $connection)
    {
        $this->connection = $connection;
    }

    /**
     * Produce new instance of $type
     *
     * @param  string          $type
     * @param  array|null      $attributes
     * @param  boolean         $save
     * @return ObjectInterface
     */
    public function produce($type, array $attributes = null, $save = true)
    {
        if ($registered_type = $this->getRegisteredType($type)) {

            /** @var Object $object */
            $object = new $type($this, $this->connection);

            if ($attributes) {
                foreach ($attributes as $k => $v) {
                    if ($object->fieldExists($k)) {
                        $object->setFieldValue($k, $v);
                    } else {
                        $object->setAttribute($k, $v);
                    }
                }
            }

            if ($save) {
                $object->save();

                $this->objects_pool[$registered_type][$object->getId()] = $object;
            }

            return $object;
        }

        throw new InvalidArgumentException("Can't produce an instance of '$type'");
    }

    /**
     * Return object from object pool by the given type and ID
     *
     * @param  string                   $type
     * @param  integer                  $id
     * @param  boolean                  $use_cache
     * @return Object
     * @throws InvalidArgumentException
     */
    public function &getById($type, $id, $use_cache = true)
    {
        if ($registered_type = $this->getRegisteredType($type)) {
            $id = (integer) $id;

            if ($id < 1) {
                throw new InvalidArgumentException('ID is expected to be a number larger than 0');
            }

            if (isset($this->objects_pool[$registered_type][$id]) && $use_cache) {
                return $this->objects_pool[$registered_type][$id];
            } else {
                $type_fields = $this->getTypeFields($registered_type);

                if ($row = $this->connection->executeFirstRow($this->getSelectOneByType($registered_type), [$id])) {
                    $object_class = in_array('type', $type_fields) ? $row['type'] : $type;

                    /** @var ObjectInterface $object */
                    $object = new $object_class($this, $this->connection);
                    $object->loadFromRow($row);

                    $this->addToObjectPool($registered_type, $object);

                    return $object;
                } else {
                    return null;
                }
            }
        }

        throw new InvalidArgumentException("Type '$type' is not registered");
    }

    /**
     * Reload an object of the give type with the given ID
     *
     * @param  string  $type
     * @param  integer $id
     * @return Object
     */
    public function &reload($type, $id)
    {
        return $this->getById($type, $id, false);
    }

    /**
     * Check if object #ID of $type is in the pool
     *
     * @param  string  $type
     * @param  integer $id
     * @return boolean
     */
    public function isInPool($type, $id)
    {
        if ($registered_type = $this->getRegisteredType($type)) {
            $id = (integer)$id;

            if ($id < 1) {
                throw new InvalidArgumentException('ID is expected to be a number larger than 0');
            }

            return isset($this->objects_pool[$type][$id]);
        } else {
            throw new InvalidArgumentException("Type '$type' is not registered");
        }
    }

    /**
     * Add object to the object pool
     *
     * @param string          $registered_type
     * @param ObjectInterface $object
     */
    private function addToObjectPool($registered_type, ObjectInterface &$object)
    {
        if (empty($this->objects_pool[$registered_type])) {
            $this->objects_pool[$registered_type] = [];
        }

        $this->objects_pool[$registered_type][$object->getId()] = $object;
    }

    /**
     * Add object to the pool
     *
     * @param ObjectInterface $object<commit_msg>Pool should save NULL when object with the given ID is not found<commit_after><?php

namespace ActiveCollab\DatabaseObject;

use ActiveCollab\DatabaseConnection\ConnectionInterface;
use InvalidArgumentException;
use ReflectionClass;

/**
 * @package ActiveCollab\DatabaseObject
 */
class Pool implements PoolInterface
{
    /**
     * @var ConnectionInterface
     */
    private $connection;

    /**
     * @var ObjectInterface[]
     */
    private $objects_pool = [];

    /**
     * @param ConnectionInterface $connection
     */
    public function __construct(ConnectionInterface $connection)
    {
        $this->connection = $connection;
    }

    /**
     * Produce new instance of $type
     *
     * @param  string          $type
     * @param  array|null      $attributes
     * @param  boolean         $save
     * @return ObjectInterface
     */
    public function produce($type, array $attributes = null, $save = true)
    {
        if ($registered_type = $this->getRegisteredType($type)) {

            /** @var Object $object */
            $object = new $type($this, $this->connection);

            if ($attributes) {
                foreach ($attributes as $k => $v) {
                    if ($object->fieldExists($k)) {
                        $object->setFieldValue($k, $v);
                    } else {
                        $object->setAttribute($k, $v);
                    }
                }
            }

            if ($save) {
                $object->save();

                $this->objects_pool[$registered_type][$object->getId()] = $object;
            }

            return $object;
        }

        throw new InvalidArgumentException("Can't produce an instance of '$type'");
    }

    /**
     * Return object from object pool by the given type and ID
     *
     * @param  string                   $type
     * @param  integer                  $id
     * @param  boolean                  $use_cache
     * @return Object
     * @throws InvalidArgumentException
     */
    public function &getById($type, $id, $use_cache = true)
    {
        if ($registered_type = $this->getRegisteredType($type)) {
            $id = (integer) $id;

            if ($id < 1) {
                throw new InvalidArgumentException('ID is expected to be a number larger than 0');
            }

            if (isset($this->objects_pool[$registered_type][$id]) && $use_cache) {
                return $this->objects_pool[$registered_type][$id];
            } else {
                $type_fields = $this->getTypeFields($registered_type);

                if ($row = $this->connection->executeFirstRow($this->getSelectOneByType($registered_type), [$id])) {
                    $object_class = in_array('type', $type_fields) ? $row['type'] : $type;

                    /** @var ObjectInterface $object */
                    $object = new $object_class($this, $this->connection);
                    $object->loadFromRow($row);

                    return $this->addToObjectPool($registered_type, $object);
                } else {
                    $object = null;

                    return $this->addToObjectPool($registered_type, $object);
                }
            }
        }

        throw new InvalidArgumentException("Type '$type' is not registered");
    }

    /**
     * Reload an object of the give type with the given ID
     *
     * @param  string  $type
     * @param  integer $id
     * @return Object
     */
    public function &reload($type, $id)
    {
        return $this->getById($type, $id, false);
    }

    /**
     * Check if object #ID of $type is in the pool
     *
     * @param  string  $type
     * @param  integer $id
     * @return boolean
     */
    public function isInPool($type, $id)
    {
        if ($registered_type = $this->getRegisteredType($type)) {
            $id = (integer)$id;

            if ($id < 1) {
                throw new InvalidArgumentException('ID is expected to be a number larger than 0');
            }

            return isset($this->objects_pool[$type][$id]);
        } else {
            throw new InvalidArgumentException("Type '$type' is not registered");
        }
    }

    /**
     * Add object to the object pool
     *
     * @param  string               $registered_type
     * @param  ObjectInterface|null $object
     * @return ObjectInterface
     */
    private function &addToObjectPool($registered_type, ObjectInterface &$object = null)
    {
        if (empty($this->objects_pool[$registered_type])) {
            $this->objects_pool[$registered_type] = [];
        }

        $this->objects_pool[$registered_type][$object->getId()] = $object;

        return $this->objects_pool[$registered_type][$object->getId()];
    }

    /**
     * Add object to the pool
     *
     * @param ObjectInterface $object
{'fraction_non_alphanumeric': 0.12331529236973363, 'fraction_numerical': 0.0008489865223389578, 'mean_word_length': 1.7612071491356578, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1590992', 'n_tokens_mistral': 2581, 'n_tokens_neox': 2438, 'n_words': 606}