<commit_before><?php

namespace x2ts\db\orm;

use ArrayAccess;
use BadMethodCallException;
use IteratorAggregate;
use JsonSerializable;
use x2ts\Component;
use x2ts\ComponentFactory as X;
use x2ts\db\IDataBase;
use x2ts\db\MySQL;
use x2ts\db\SqlBuilder;
use x2ts\IAssignable;
use x2ts\MethodNotImplementException;
use x2ts\Toolkit;


/**
 * Class Model
 *
 * @package x2ts
 * @property array              $modified
 * @property-read array         $properties
 * @property-read TableSchema   $tableSchema
 * @property-read MySQL         $db
 * @property-read string        $modelName
 * @property-read bool          $isNewRecord
 * @property-read mixed         $oldPK
 * @property-read mixed         $pk
 * @property-read string        $pkName
 * @property-read string        $tableName
 * @property-read array         $relations
 * @property-read SqlBuilder    $builder
 * @property-read IModelManager $modelManager
 */
class Model extends Component implements
    ArrayAccess,
    IteratorAggregate,
    JsonSerializable,
    IAssignable {
    const INSERT_NORMAL = 0;
    const INSERT_IGNORE = 1;
    const INSERT_UPDATE = 2;

    /**
     * @var mixed
     */
    protected $_oldPK;

    /**
     * @var array
     */
    protected $_properties = [];

    /**
     * @var array
     */
    protected $_modified = [];

    /**
     * @var array
     */
    protected $_relationObjects = [];

    /**
     * @var TableSchema
     */
    protected $_tableSchema;

    /**
     * @var string
     */
    protected $_modelName;

    /**
     * @var string
     */
    protected $_tableName;

    /**
     * @var array
     */
    public static $_conf = array(
        'namespace'   => 'model',
        'tablePrefix' => '',
        'dbId'        => 'db',
        'schemaConf'  => [
            'schemaCacheId'       => 'cc',
            'useSchemaCache'      => false,
            'schemaCacheDuration' => 0,
        ],
        'manager'     => [
            'class' => DirectModelManager::class,
            'conf'  => [],
        ],
    );

    /**
     * @var SqlBuilder
     */
    private $_builder;

    public function getSqlBuilder() {
        return $this->_builder;
    }

    public function __sleep() {
        return ['_modelName', '_properties', '_modified', '_oldPK'];
    }

    public function __wakeup() {
        $this->_builder = new SqlBuilder($this->db);
    }

    /**
     * @param array  $args
     * @param array  $conf
     * @param string $confHash
     *
     * @return Model
     */
    public static function getInstance(array $args, array $conf, string $confHash) {
        @list($modelName) = $args;
        $namespace = $conf['namespace'] ?? static::$_conf['namespace'];
        $className = "\\{$namespace}\\" . Toolkit::toCamelCase($modelName, true);
        if (class_exists($className)) {
            /** @var Model $model */
            $model = new $className($modelName);
            $model->saveConf($conf, $confHash);
            $model->init();
        }

        return new Model($modelName);
    }

    /**
     * @var \ReflectionMethod
     */
    protected $_reflectionMMGetter;

    public function getModelManager(): IModelManager {
        if (null === $this->_reflectionMMGetter) {
            $this->_reflectionMMGetter = (new \ReflectionClass($this->conf['manager']['class']))
                ->getMethod('getInstance');
        }
        return $this->_reflectionMMGetter->invoke(null, $this, $this->conf['manager']['conf']);
    }

    /**
     * @param int|string $pk
     *
     * @return null|Model
     */
    public function load($pk) {
        return $this->modelManager->load($pk);
    }

    /**
     * @param int $scenario [optional]
     *<commit_msg>x2ts\db\orm\Model::getInstance call saveConf before return<commit_after><?php

namespace x2ts\db\orm;

use ArrayAccess;
use BadMethodCallException;
use IteratorAggregate;
use JsonSerializable;
use x2ts\Component;
use x2ts\ComponentFactory as X;
use x2ts\db\IDataBase;
use x2ts\db\MySQL;
use x2ts\db\SqlBuilder;
use x2ts\IAssignable;
use x2ts\MethodNotImplementException;
use x2ts\Toolkit;


/**
 * Class Model
 *
 * @package x2ts
 * @property array              $modified
 * @property-read array         $properties
 * @property-read TableSchema   $tableSchema
 * @property-read MySQL         $db
 * @property-read string        $modelName
 * @property-read bool          $isNewRecord
 * @property-read mixed         $oldPK
 * @property-read mixed         $pk
 * @property-read string        $pkName
 * @property-read string        $tableName
 * @property-read array         $relations
 * @property-read SqlBuilder    $builder
 * @property-read IModelManager $modelManager
 */
class Model extends Component implements
    ArrayAccess,
    IteratorAggregate,
    JsonSerializable,
    IAssignable {
    const INSERT_NORMAL = 0;
    const INSERT_IGNORE = 1;
    const INSERT_UPDATE = 2;

    /**
     * @var mixed
     */
    protected $_oldPK;

    /**
     * @var array
     */
    protected $_properties = [];

    /**
     * @var array
     */
    protected $_modified = [];

    /**
     * @var array
     */
    protected $_relationObjects = [];

    /**
     * @var TableSchema
     */
    protected $_tableSchema;

    /**
     * @var string
     */
    protected $_modelName;

    /**
     * @var string
     */
    protected $_tableName;

    /**
     * @var array
     */
    public static $_conf = array(
        'namespace'   => 'model',
        'tablePrefix' => '',
        'dbId'        => 'db',
        'schemaConf'  => [
            'schemaCacheId'       => 'cc',
            'useSchemaCache'      => false,
            'schemaCacheDuration' => 0,
        ],
        'manager'     => [
            'class' => DirectModelManager::class,
            'conf'  => [],
        ],
    );

    /**
     * @var SqlBuilder
     */
    private $_builder;

    public function getSqlBuilder() {
        return $this->_builder;
    }

    public function __sleep() {
        return ['_modelName', '_properties', '_modified', '_oldPK'];
    }

    public function __wakeup() {
        $this->_builder = new SqlBuilder($this->db);
    }

    /**
     * @param array  $args
     * @param array  $conf
     * @param string $confHash
     *
     * @return Model
     */
    public static function getInstance(array $args, array $conf, string $confHash) {
        @list($modelName) = $args;
        $namespace = $conf['namespace'] ?? static::$_conf['namespace'];
        $className = "\\{$namespace}\\" . Toolkit::toCamelCase($modelName, true);
        /** @var Model $model */
        $model = class_exists($className) ? new $className($modelName) : new Model($modelName);
        $model->saveConf($conf, $confHash);
        $model->init();

        return $model;
    }

    /**
     * @var \ReflectionMethod
     */
    protected $_reflectionMMGetter;

    public function getModelManager(): IModelManager {
        if (null === $this->_reflectionMMGetter) {
            $this->_reflectionMMGetter = (new \ReflectionClass($this->conf['manager']['class']))
                ->getMethod('getInstance');
        }
        return $this->_reflectionMMGetter->invoke(null, $this, $this->conf['manager']['conf']);
    }

    /**
     * @param int|string $pk
     *
     * @return null|Model
     */
    public function load($pk) {
        return $this->modelManager->load($pk);
    }

    /**
     * @param int $scenario [optional]
     *
{'fraction_non_alphanumeric': 0.13999731291146042, 'fraction_numerical': 0.003896278382372699, 'mean_word_length': 2.0965058236272878, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 51, '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': '2841399', 'n_tokens_mistral': 2229, 'n_tokens_neox': 2190, 'n_words': 482}