<?php

class Core_Doctrine_Template_Versionable extends Doctrine_Template_Versionable
{
    /**
     * Update record and its version
     *
     * @return void
     */
    public function update()
    {
        $record = $this->getInvoker();

        $oldAuditLogValue = $this->getAuditLog()->getOption('auditLog');

        // Disable audit log, save, reinstate audit log value
        $this->getAuditLog()->setOption('auditLog', false);

        $record->save();

        $this->getAuditLog()->setOption('auditLog', $oldAuditLogValue);

        if ($this->getAuditLog()->getOption('auditLog')) {
            // If we're using audit log, update version
            $this->updateVersion();
        }
    }

    /**
     * Update selected version
     *
     * @param int $versionNumber Number of version we're updating, or null if
     * we're updating current version (will take the version out of the record)
     * @throws Doctrine_Record_Exception
     */
    public function updateVersion($versionNumber = null)
    {
        if (!$this->getAuditLog()->getOption('auditLog')) {
            throw new Doctrine_Record_Exception('Unable to update version, audit log is not enabled');
        }

        $record = $this->getInvoker();

        // Version number not set, get from the record (update current version)
        if ($versionNumber === null) {
            $versionOption  = $this->getAuditLog()->getOption('version');
            $versionField   = $versionOption['alias'] === null ? $versionOption['name'] : $versionOption['alias'];
            $versionNumber  = $record->get($versionField);
        }

        $version = $this->getAuditLog()->getVersion($record, $versionNumber, Doctrine_Core::HYDRATE_RECORD, false);

        if (!$version) {
            throw new Doctrine_Record_Exception('Unable to update version, version ' . $versionNumber . ' does not exist!');
        }

        $version->merge($record->toArray(), false);
        $version->save();
    }

    /**
     * Delete selected version
     *
     * @param int $versionNumber
     *
     * @throws Doctrine_Record_Exception
     */
    public function deleteVersion($versionNumber = null)
    {
        if (!$this->getAuditLog()->getOption('auditLog')) {
            throw new Doctrine_Record_Exception('Unable to delete version, audit log is not enabled');
        }

        $record     = $this->getInvoker();
        $version    = $this->getAuditLog()->getVersion($record, $versionNumber, Doctrine_Core::HYDRATE_RECORD, false);

        if (!$version) {
            throw new Doctrine_Record_Exception('Unable to delete version, version ' . $versionNumber . ' does not exist!');
        }

        $version->delete();
    }

    /**
     * Create version with next possible version number
     *
     * @return Doctrine_Record
     * @throws Doctrine_Record_Exception
     */
    public function createVersion()
    {
        if (!$this->getAuditLog()->getOption('auditLog')) {
            throw new Doctrine_Record_Exception('Unable to create version, audit log is not enabled');
        }

        $class      = $this->getAuditLog()->getOption('className');

        $record     = $this->getInvoker();

        $versionOption  = $this->getAuditLog()->getOption('version');
        $versionField   = $versionOption['alias'] === null ? $versionOption['name'] : $versionOption['alias'];

        // Create version out of this record, but with next possible version
        $version = new $class();
        $version->merge($record->toArray(), false);
        $version->set($versionField, $this->getAuditLog()->getMaxVersion($record) + 1);
        $version->save();

        return $version;
    }
}
