<?php
#BEGIN_LICENSE
#-------------------------------------------------------------------------
# Module: CGClienttickets (c) 2014 by Robert Campbell
#         (calguy1000@cmsmadesimple.org)
#  An addon module for CMS Made Simple to allow interaction with customer
#  or admin created tickets about a specific data item.
#
#-------------------------------------------------------------------------
# CMS - CMS Made Simple is (c) 2005 by Ted Kulp (wishy@cmsmadesimple.org)
# This projects homepage is: http://www.cmsmadesimple.org
#
#-------------------------------------------------------------------------
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# However, as a special exception to the GPL, this software is distributed
# as an addon module to CMS Made Simple.  You may not use this software
# in any Non GPL version of CMS Made simple, or in any version of CMS
# Made simple that does not indicate clearly and obviously in its admin
# section that the site was built with CMS Made simple.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Or read it online: http://www.gnu.org/licenses/licenses.html#GPL
#
#-------------------------------------------------------------------------
#END_LICENSE

namespace CGClientTickets;

class message extends DataObject
{
    static private $_persist_actor;
    static private $_notify_actor;
    private $_data = array('id'=>null,'ticket_id'=>null,'sender'=>null,'dest'=>null,'subject'=>null,'body'=>null,'extra'=>null,'viewed'=>null,'viewed_by'=>null,
                           'admin_viewed'=>null,'sent'=>null,'created'=>null,'modified'=>null);
    private $_dirty;
    private $_attach_queue = array();

    public function __get($key)
    {
        switch( $key ) {
        case 'id':
        case 'ticket_id':
        case 'sender':
        case 'dest':
        case 'subject':
        case 'body':
        case 'sent':
        case 'viewed':
        case 'viewed_by':
        case 'admin_viewed':
        case 'created':
        case 'modified':
            return $this->_data[$key];
            break;

        case 'extra':
            return serialize($this->_data['extra']);

        default:
            throw new \LogicException($key.' is an invalid member of '.__CLASS__);
        }
    }

    public function __set($key,$val)
    {
        switch( $key ) {
        case 'ticket_id':
        case 'sender':
        case 'dest':
            $val = (int) $val;
            $this->_data[$key] = $val;
            $this->_dirty = TRUE;
            break;

        case 'subject':
        case 'body':
            $val = trim($val);
            $this->_data[$key] = $val;
            $this->_dirty = TRUE;
            break;

        case 'extra':
            $this->_data[$key] = unserialize($val);
            $this->_dirty = TRUE;
            break;

        case 'viewed':
        case 'viewed_by':
        case 'admin_viewed':
        case 'sent':
        case 'id':
        case 'created':
        case 'modified':
            throw new \LogicException($key.' cannot be modified in a '.__CLASS__);

        default:
            throw new \LogicException($key.' is an invalid member of '.__CLASS__);
        }
    }

    public function __isset($key)
    {
        switch( $key ) {
        case 'id':
        case 'ticket_id':
        case 'sender':
        case 'dest':
        case 'subject':
        case 'body':
        case 'viewed':
        case 'viewed_by':
        case 'admin_viewed':
        case 'sent':
        case 'created':
        case 'modified':
            return isset($this->_data[$key]);
            break;

        default:
            throw new \LogicException($key.' is an invalid member of '.__CLASS__);
        }
    }

    public function __unset($key)
    {
        switch( $key ) {
        case 'ticket_id':
        case 'sender':
        case 'dest':
        case 'subject':
        case 'body':
            $this->_data[$key] = null;
            $this->_dirty = TRUE;
            break;

        case 'viewed':
        case 'viewed_by':
        case 'admin_viewed':
        case 'sent':
        case 'id':
        case 'created':
        case 'modified':
            throw new \LogicException($key.' cannot be modified in a '.__CLASS__);

        default:
            throw new \LogicException($key.' is an invalid member of '.__CLASS__);
        }
    }

    public function validate()
    {
        if( $this->ticket_id < 1 ) throw new \CmsInvalidDataException('Ticket id must be valid for a '.__CLASS__);
        if( $this->sender == 0 ) throw new \CmsInvalidDataException('Sender id must be valid for a '.__CLASS__);
        if( $this->dest == 0 ) throw new \CmsInvalidDataException('destination id must be valid for a '.__CLASS__);
        if( trim(strip_tags($this->body)) == '' )  throw new \CmsInvalidDataException('Please specify some valid message content');
    }

    //
    // I/O methods
    //

    public static function get_persist_actor()
    {
        return self::$_persist_actor;
    }

    public static function set_persist_actor(Actor\PersistActor $actor)
    {
        self::$_persist_actor = $actor;
    }

    public static function get_notify_actor()
    {
        return self::$_notify_actor;
    }

    public static function set_notify_actor(Actor\NotifyActor $actor)
    {
        self::$_notify_actor = $actor;
    }

    public function set_viewed($uid)
    {
        if( $uid == 0 ) throw new \LogicException('Invalid UID');
        if( $uid < 0 ) {
            $this->_data['admin_viewed'] = time();
        }
        else {
            $this->_data['viewed'] = time();
        }
        $this->_data['viewed_by'] = $uid;
        $this->_dirty = TRUE;
    }

    public static function load_by_id($id)
    {
        $obj = self::get_persist_actor()->load_by_id($id);
        return $obj;
    }

    public function private_fill($data)
    {
        foreach( $data as $key => $val ) {
            if( array_key_exists($key,$this->_data) ) {
                switch( $key ) {
                case 'extra':
                    $val = unserialize($val);
                default:
                    $this->_data[$key] = $val;
                }
            }
        }
    }

    public function save()
    {
        if( !$this->_dirty ) return;
        $this->validate();
        self::get_persist_actor()->save($this);

        $tmp = self::get_persist_actor()->get_saved_id();
        if( $this->id > 0 && $this->id != $tmp ) throw new \RuntimeException('Error: problem with saved object id');
        $this->_data['id'] = $tmp;

        if( is_array($this->_attach_queue) && count($this->_attach_queue) ) {
            foreach( $this->_attach_queue as $attach ) {
                $this->attach_file($attach[0],$attach[1]);
            }
            $this->_attach_queue = array();
        }

        $mod = \cms_utils::get_module(MOD_CGCLIENTTICKETS);
        $mod->SendEvent($mod::EVENT_NEWTICKETMSG,array('message'=>$this));

        $this->_dirty = FALSE;
    }

    public function delete()
    {
        if( $this->id < 1 ) throw new \RuntimeException('Error: Cannot delete a message that has not been saved');

        $mod = \cms_utils::get_module(MOD_CGCLIENTTICKETS);
        $mod->SendEvent($mod::EVENT_DELETETICKETMSG,array('message'=>$this));

        self::get_persist_actor()->delete($this);
        $this->clear_attachments();
        $this->_data['id'] = null;
        $this->_dirty = TRUE;
    }

    //
    // notify methods
    //
    public function send()
    {
        $actor = self::get_notify_actor();
        if( !is_object( $actor ) ) throw new \RuntimeException('No notify actor specified... messages cannot be sent');
        $actor->notify($this);
        $this->_data['sent'] = time();
        $this->_dirty = TRUE;
        $this->save();
    }

    //
    // attachment methods
    //

    /**
     * Get the attachment path.
     *
     * @return string
     */
    public function get_attachment_path()
    {
        if( $this->id < 1 ) throw new \RuntimeException('Cannot associate files with a message that has not been saved');
        $config = cmsms()->GetConfig();
        $mod = \cms_utils::get_module(MOD_CGCLIENTTICKETS);
        $path = cms_join_path($config['uploads_path'],'__'.$mod->GetName(),'__'.$this->id);
        return $path;
    }

    public function has_attachments()
    {
        $tmp = $this->get_attachments();
        if( count($tmp) ) return TRUE;
        return FALSE;
    }

    public function get_attachments()
    {
        $path = $this->get_attachment_path();
        if( !is_dir($path) ) return;
        if( !is_readable($path) ) throw new \RuntimeException('Attachment directory not readable.');

        $out = array();
        $files = glob($path.'/*');
        for( $i = 0; $i < count($files); $i++ ) {
            $bn = basename($files[$i]);
            $out[] = $bn;
        }
        if( count($out) ) return $out;
    }

    public function clear_attachments()
    {
        $path = $this->get_attachment_path();
        if( !is_dir($path) ) return;
        if( !is_writable($path) ) throw new \RuntimeException('Cannot write to attachment directory '.$path);
        \cge_dir::recursive_rmdir($path);
    }

    public function queue_attach($filename,$destname = null)
    {
        if( !$destname ) $destname = basename($filename);
        $destname = basename($destname);

        if( is_array($this->_attach_queue) ) {
            foreach( $this->_attach_queue as &$row )  {
                if( $row[0] == $filename ) {
                    $row[1] = $destname;
                    return; // already in list.
                }
            }
        }

        $this->_attach_queue[] = array($filename,$destname);
    }

    public function attach_file($filename,$destname = null)
    {
        if( !@is_file($filename) || !@is_readable($filename) ) throw new \RuntimeException('Invalid filename specified '.$filename);
        if( !$destname ) $destname = basename($filename);
        $destname = basename($destname);

        $destpath = $this->get_attachment_path();
        if( !is_dir($destpath) ) \cge_dir::mkdirr($destpath);

        $destname = cms_join_path($destpath,basename($destname));
        if( file_exists($destname) ) {
            // its an overwrite
            if( !is_writable($destname) ) throw new \RuntimeException('Cannot overwrite file: '.$destname.' no write permission');
        }

        @rename($filename,$destname);
    }


} // end of class

#
# EOF
#
?>
