<?php
/**
* json writing thing
*@author bibby
*$Id$

This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software. It may be freely modified and redistributed, even in commercial applications.
** //*/
define('STORE_PATH',($STORE_PATH?$STORE_PATH:WEB_ROOT.'/bbby/json/'));
define('SPECIAL_CLASS','JThing');

class 
JThing
{
    var 
$type// for directory/semantics
    
var $id;
    var 
$bin// collection of stuff
    
    /**
    @param string type of thing to be
    */
    
function JThing($type$id=false$NoAutoSave=false)
    {
        
$this->type=$type;
        
$this->id = (int)$id;
        
$this->bin=array();
        
$this->savelock=false;
        
$this->autoSave=!$NoAutoSave;
        
$this->load();
        
$this->rawdata;
    }
    
    
/*** get ***
    @access public
    @param string
    @return mixed
    */
    
function get($key)
    {
        return 
$this->{$key};
    }
    
    
/**
    magic fn to get from bin
    */
    
public function __get($mem)
    {
        return 
$this->bin[$mem];
    }
    
    
/*** getKeys ***
    @access public
    @return array key names of set stuff
    */
    
function getKeys()
    {
        return 
array_keys($this->bin);
    }
    
    
/*** getAll ***
    @access public
    @return array of set stuff
    */
    
function getAll()
    {
        return 
$this->bin;
    }
    
    
/*** set ***
    @access public
    @param mixed
    @return void
    */
    
function set($stuff,$v=false,$nosave=false)
    {
        if(!
is_array($stuff))
            
$stuff=array($stuff=>$v);
        foreach(
$stuff as $k=>$v)
        {
            if(
is_object($v))
            {
                if(
$v->{SPECIAL_CLASS})
                {
                    
$this->bin[$k] = JFac::getObj($v);
                    continue;
                }
            }
            
            
$this->bin[$k]=$v;
        }
        
        if(
$nosave===false && $this->autoSave)
            
$this->save();
    }
    
    
/*** _unset ***
    @access public
    @param key [, key [, key]]
    @return void
    */
    
function _unset()
    {
        
$args func_get_args();
        foreach(
$args as $k)
        {
            if(
is_array($k))
            {
                
$_k $k;
                foreach(
$_k as $k)
                    
$this->_unset($k);
                return;
            }
            
            if(
$k)
                unset(
$this->bin[$k]);
        }
        
        
$this->save();
    }
    
    
/*** load ***
    @access public
    @return bool success
    */
    
function load($id=false)
    {
        if(
$id)
        {
            
$this->bin=array();
            
$this->id $id;
        }
        else
            
$id=$this->id;
        
        
$p $this->thingPath();
        if(!
$p)
            return 
false;
            
        
$file $p.$id;
        if(!
file_exists($file))
            return 
false;
        
        
$json file_get_contents$file );
        
$this->rawdata $json;
        
$data get_object_varsjson_decode$json ) );
        if(!
is_array($data))
            return 
false;
        foreach(
$data as $k=>$v)
        {
            if(
is_object($v) && $v->{SPECIAL_CLASS} && JFac::$requested[JFac::hash($v)])
            {
                
#var_dump("requesting again ". JFac::hash($v));
            
}
            else
                
$this->set($k,$v,true);
            
        }
        return 
true;
    }
    
    
/*** save ***
    @access public
    @return bool success
    */
    
function save()
    {
        if(
$this->savelock) return;
        
        
$p $this->thingPath();
        
        if(!
$p)
            return 
false;
        
        if(!
$this->id)
            
$id $this->getNextID();
        if(!
$this->id)
            return 
false;
        
        
$file $p.$this->id;
        
        
$this->savelock=true;
        
$f fopen($file,'w');
        
        
$clone $this->encodeClasses();
        
        if(!
$clone
            return 
false;
        
        
$json json_encode$clone->bin );
        
$this->rawdata $json;
        
fwrite($f$json );
        
fclose($f);
        
#chmod($file,0776);
        
$this->savelock=false;
        
        return 
true;
    }
    
    
    
/*** thingPath ***
    @access public
    @return string file path
    */
    
function thingPath()
    {
        if(!
is_dir(STORE_PATH))
            if(!
mkdir(STORE_PATH))
                return 
false;
        
        if(!
is_dir(STORE_PATH.$this->type))
            if(!
mkdir(STORE_PATH.$this->type))
                return 
false;
                
        return 
STORE_PATH.$this->type."/";
    }
    
    
    
/*** getNextID ***
    @access private
    @return int
    */
    
function getNextID()
    {
        
$path $this->thingPath();
        if(!
$path
            return 
false;
        
        
$id=1;
        
$files scandir($path);
        
sort($files);
        foreach(
$files as $f)
        {
            
$f=(int)$f;
            if( 
$f >= $id)
                
$id $f+1;
        }
        
        
$this->id $id;
        return 
$id;
    }
    
    
/*** encodeClasses ***
    @access private
    @param mixed
    @return mixed
    */
    
function encodeClasses($clone=false)
    {
        if(!
$clone)
        {
            
$clone = clone($this);
        }
        
        if(
is_object($clone))
        {
            
$clone->bin $this->encodeClasses($clone->bin);
            
            return 
$clone;
        }
        elseif(
is_array($clone))
        {
            
$a array_keys($clone);
            
            foreach(
$a as $k)
            {
                if(
is_a($clone[$k],get_class($this)))
                {
                    
$clone[$k]->save();
                    
$clone[$k]=array(
                        
SPECIAL_CLASS=>get_class($clone[$k]),
                        
"type"=>$clone[$k]->type,
                        
"id"=>$clone[$k]->id
                    
);
                }
                elseif(!
is_scalar($clone[$k]))
                    
$clone[$k] = $this->encodeClasses($clone[$k]);
            }
            
            return 
$clone;
        }
        
        return 
$clone;
    }
    
    function 
setAutoSave($to)
    {
        
$this->autoSave = !!$to;
    }
    
    
/*** getJSON ***
    @access public
    @return string JSON
    */
    
function getJSON($callback=false)
    {
        if(!
$callback)                               
            return 
$this->rawdata;
        else
            return 
sprintf("%s(%s);",$callback,$this->rawdata);
    }
}
?>