<commit_before><?php

namespace Pheasant;
use \Pheasant;
use \Pheasant\PropertyReference;

/**
 * An object which represents an entity in the problem domain.
 */
class DomainObject implements \ArrayAccess
{
    private $_data = array();
    private $_changed = array();
    private $_saved = false;
    private $_overriden = array();
    private $_events;

    /**
     * The final constructer which initializes the object. Subclasses
     * can implement {@link construct()} instead
     */
    final public function __construct()
    {
        $pheasant = Pheasant::instance();
        $pheasant->initialize($this);

        // pull default values from schema
        $this->_data = $pheasant->schema($this)->defaults();

        // call user-defined constructor
        $constructor = method_exists($this,'construct')
            ? 'construct'
            : '_defaultConstruct'
            ;

        call_user_func_array(array($this,$constructor), func_get_args());
    }

    /**
     * Default method called without a constructor
     */
    protected function _defaultConstruct()
    {
        foreach(func_get_args() as $arg)
            if(is_array($arg)) $this->load($arg);
    }

    /**
     * Template function for configuring a domain object. Looks for either
     * a tableName() method or a mapper() method, a properties() method and a
     * relationships() method.
     */
    public static function initialize($builder, $pheasant)
    {
        $class = get_called_class();
        $instance = $class::fromArray(array());

        // register mappers and finders
        $pheasant->register($class, $instance->mapper());

        $builder
            ->properties($instance->properties())
            ->relationships($instance->relationships())
            ;
    }

    /**
     * Returns an Identity object for the domain object
     * @return Identity
     */
    public function identity()
    {
        return $this->schema()->identity($this);
    }

    /**
     * Returns whether the object has been saved
     * @return bool
     */
    public function isSaved()
    {
        return $this->_saved;
    }

    /**
     * Saves the domain object via the associated mapper
     * @chainable
     */
    public function save()
    {
        $event = $this->isSaved() ? 'Update' : 'Create';
        $mapper = Pheasant::instance()->mapperFor($this);

        $self = $this;
        $closure = function () use ($event, $mapper, $self) {
            $self->events()->wrap(array($event, 'Save'), $self,
                function ($obj) use ($mapper) {
                    $mapper->save($obj);

                    // ensure we clear the changes before after events fire
                    $obj->markSaved(true)->clearChanges();
                }
            );
        };

        \Pheasant::transaction($closure);

        return $this;
    }

    /**
     * Change the objects saved state
     * @chainable
     */
    public function markSaved($value=true)
    {
        $this->_saved = $value;

        return $this;
    }

    /**
     * Returns a key=>val array of properties that have changed since the last save
     * @return array
     */
    public function changes()
    {
        $changes = array();
        foreach(array_unique($this->_changed) as $key)
            $changes[$key] = $this->get($key, false);

        return $changes;
    }

    /**
     * Clears the changes array<commit_msg>Fire hydrate after create<commit_after><?php

namespace Pheasant;
use \Pheasant;
use \Pheasant\PropertyReference;

/**
 * An object which represents an entity in the problem domain.
 */
class DomainObject implements \ArrayAccess
{
    private $_data = array();
    private $_changed = array();
    private $_saved = false;
    private $_overriden = array();
    private $_events;

    /**
     * The final constructer which initializes the object. Subclasses
     * can implement {@link construct()} instead
     */
    final public function __construct()
    {
        $pheasant = Pheasant::instance();
        $pheasant->initialize($this);

        // pull default values from schema
        $this->_data = $pheasant->schema($this)->defaults();

        // call user-defined constructor
        $constructor = method_exists($this,'construct')
            ? 'construct'
            : '_defaultConstruct'
            ;

        call_user_func_array(array($this,$constructor), func_get_args());
    }

    /**
     * Default method called without a constructor
     */
    protected function _defaultConstruct()
    {
        foreach(func_get_args() as $arg)
            if(is_array($arg)) $this->load($arg);
    }

    /**
     * Template function for configuring a domain object. Looks for either
     * a tableName() method or a mapper() method, a properties() method and a
     * relationships() method.
     */
    public static function initialize($builder, $pheasant)
    {
        $class = get_called_class();
        $instance = $class::fromArray(array());

        // register mappers and finders
        $pheasant->register($class, $instance->mapper());

        $builder
            ->properties($instance->properties())
            ->relationships($instance->relationships())
            ;
    }

    /**
     * Returns an Identity object for the domain object
     * @return Identity
     */
    public function identity()
    {
        return $this->schema()->identity($this);
    }

    /**
     * Returns whether the object has been saved
     * @return bool
     */
    public function isSaved()
    {
        return $this->_saved;
    }

    /**
     * Saves the domain object via the associated mapper
     * @chainable
     */
    public function save()
    {
        $event = $this->isSaved() ? 'Update' : 'Create';
        $mapper = Pheasant::instance()->mapperFor($this);
        $wasCreate = !$this->isSaved();

        $self = $this;
        $closure = function () use ($event, $mapper, $self) {
            $self->events()->wrap(array($event, 'Save'), $self,
                function ($obj) use ($mapper) {
                    $mapper->save($obj);

                    // ensure we clear the changes before after events fire
                    $obj->markSaved(true)->clearChanges();
                }
            );
        };

        \Pheasant::transaction($closure);

        # Simulate a hydrate event on creation
        if($wasCreate) $this->events()->trigger('afterHydrate', $this);

        return $this;
    }

    /**
     * Change the objects saved state
     * @chainable
     */
    public function markSaved($value=true)
    {
        $this->_saved = $value;

        return $this;
    }

    /**
     * Returns a key=>val array of properties that have changed since the last save
     * @return array
     */
    public function changes()
    {
        $changes = array();
        foreach(array_unique($this->_changed) as $key)
            $changes[$key] = $this->get($key, false);

        return $changes;
    }

    /**
     * Clears the changes array
{'fraction_non_alphanumeric': 0.12863247863247862, 'fraction_numerical': 0.0, 'mean_word_length': 2.0646006110868615, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 56, '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': '790830', 'n_tokens_mistral': 1911, 'n_tokens_neox': 1846, 'n_words': 509}