<?php
#-------------------------------------------------------------------------
# Module: Newsletter Made Simple
#        (c) to 2008 by Paul Lempkepf
#        (c) 2008 and on by Robert Campbell (calguy1000@cmsmadesimple.org)
#
#  An addon module for CMS Made Simple to provide a flexible
#  mailing list solution.
#
#-------------------------------------------------------------------------
# CMSMS - CMS Made Simple is (c) 2005 by Ted Kulp (wishy@cmsmadesimple.org)
# Visit the CMSMS Homepage at: 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
class nms_fielddef implements ArrayAccess
{
  const TYPE_TEXTBOX = 'textbox';
  const TYPE_TEXTAREA = 'textarea';
  const TYPE_CHECKBOX = 'checkbox';
  const TYPE_DROPDOWN = 'dropdown';

  private $_data;
  private static $_all;

  public function OffsetGet($key)
  {
    switch( $key ) {
    case 'id':
    case 'order':
    case 'required':
      if( isset($this->_data[$key]) ) return (int)$this->_data[$key];
      break;

    case 'type':
    case 'name':
    case 'prompt':
    case 'optiontext':
      if( isset($this->_data[$key]) ) return trim($this->_data[$key]);
      break;

    case 'options':
      if( isset($this->_data['optiontext']) ) return nms_utils::text_to_options($this->_data['optiontext']);
      break;

    default:
      throw new CmsException('Invalid key '.$key.' for '.__CLASS__);
    }
  }

  public function OffsetSet($key,$value)
  {
    switch( $key ) {
    case 'id':
    case 'options':
    case 'order':
      throw new CmsException('This value cannot be adjusted in a '.__CLASS__);

    case 'required':
      $tmp = cms_to_bool($value);
      $this->_data[$key] = ($tmp)?1:0;
      break;

    case 'type':
    case 'name':
    case 'prompt':
      $this->_data[$key] = trim($value);
      break;

    case 'optiontext':
      $this->_data[$key] = trim($value);
      break;

    default:
      throw new CmsException('Invalid key '.$key.' for '.__CLASS__);
    }
  }

  public function OffsetExists($key)
  {
    switch( $key ) {
    case 'id':
    case 'order':
    case 'type':
    case 'name':
    case 'prompt':
    case 'optiontext':
    case 'required':
      if( isset($this->_data[$key]) ) return TRUE;
      return FALSE;

    case 'options':
      if( isset($this->_data['optiontext']) ) return TRUE;
      return FALSE;

    default:
      throw new CmsException('Invalid key '.$key.' for '.__CLASS__);
    }
  }

  public function OffsetUnset($key)
  {
    switch( $key ) {
    case 'order':
    case 'id':
      throw new CmsException('Cannot unset '.$key.' for '.__CLASS__);
      break;

    case 'type':
    case 'name':
    case 'prompt':
    case 'optiontext':
    case 'required':
      unset($this->_data[$key]);
      break;

    case 'options':
      unset($this->_data['optiontext']);
      break;

    default:
      throw new CmsException('Invalid key '.$key.' for '.__CLASS__);
    }
  }

  public function load_from_data($data,$prefix = '')
  {
    foreach( $data as $key => $value ) {
      if( $prefix && startswith($key,$prefix) ) $key = substr($key,strlen($prefix));
      switch( $key ) {
      case 'order':
      case 'iorder':
	$this->_data['order'] = (int)$value;
	break;

      case 'id':
	$this->_data[$key] = (int)$value;

      case 'type':
      case 'name':
      case 'prompt':
	$this->_data[$key] = trim($value);
	break;

      case 'extra':
	$tmp = unserialize($value);
	if( is_array($tmp) && count($tmp) ) {
	  foreach( $tmp as $key2 => $val2 ) {
	    $this[$key2] = $val2;
	  }
	}
	break;

      default:
	$this[$key] = $value;
	break;
      }
    }
  }

  private function _insert()
  {
    $db = cmsms()->GetDb();
    $query = 'SELECT COALESCE(MAX(iorder),0)+1 FROM '.NMS_FIELDDEFS_TABLE;
    $this->_data['order'] = $db->GetOne($query);

    $query = 'INSERT INTO '.NMS_FIELDDEFS_TABLE.' (type,name,prompt,iorder,extra) VALUES (?,?,?,?,?)';
    $extra = array('optiontext'=>$this['optiontext'],'required'=>$this['required']);
    $extra = serialize($extra);
    $dbr = $db->Execute($query,array($this['type'],$this['name'],$this['prompt'],$this['order'],$extra));
    if( !$dbr ) throw new CmsException('Problem creating fielddef record '.$db->sql.' -- '.$db->ErrorMsg());
  }

  private function _update()
  {
    $db = cmsms()->GetDb();
    $query = 'UPDATE '.NMS_FIELDDEFS_TABLE.' SET type = ?, name = ?, prompt = ?, iorder = ?, extra = ? WHERE id = ?';
    $extra = array('optiontext'=>$this['optiontext'],'required'=>$this['required']);
    $extra = serialize($extra);
    $dbr = $db->Execute($query,array($this['type'],$this['name'],$this['prompt'],$this['order'],$extra,$this['id']));
    if( !$dbr ) throw new CmsException('Problem updating fielddef record '.$db->sql.' -- '.$db->ErrorMsg());
  }

  public function validate($validate_db = FALSE)
  {
    if( $this['name'] == '' || strlen($this['name']) > 50 ) throw new CmsException('A custom field must have a name (limit 50 chars)');
    if( preg_match('<^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$>', $this['name']) == 0 ) {
      throw new CmsException('Invalid characters in field name (only alphanumeric characters, no whitespace or punctuation');
    }
    if( !$this['prompt'] ) $this['prompt'] = $this['name'];
    if( strlen($this['prompt']) > 50 ) throw new CmsException('Prompt for custom field is too long');
    if( !in_array($this['type'],self::get_types()) ) throw new CmsException('Invalid type for custom field');
    if( $this['type'] == self::TYPE_DROPDOWN && count($this['options']) == 0 ) {
      throw new CmsException('A dropdown field must have options');
    }

    if( $validate_db ) {
      // do database checks(for conflicts)
      $db = cmsms()->GetDb();
      $query = 'SELECT id FROM '.NMS_FIELDDEFS_TABLE.' WHERE name = ?';
      $tmp = $db->GetOne($query,array($this['name']));
      if( $tmp && $tmp != $this['id'] ) throw new CmsException('A field with the name '.$this['name'].' already exists');
    }

    // all good.
  }

  public function save()
  {
    $this->validate(TRUE);
    if( $this['id'] > 0 ) {
      $this->_update();
    }
    else {
      $this->_insert();
    }
  }

  public function delete()
  {
    if( $this['id'] > 0 ) {
      $db = cmsms()->GetDb();
      $query = 'DELETE FROM '.NMS_FIELDDEFS_TABLE.' WHERE id = ?';
      $db->Execute($query,array($this['id']));

      $query = 'UPDATE '.NMS_FIELDDEFS_TABLE.' SET iorder = iorder - 1 WHERE iorder > ?';
      $db->Execute($query,array($this['order']));
    }
    unset($this->_data['id'],$this->_data['order']);
  }

  public static function &load($id)
  {
    $db = cmsms()->GetDb();
    $query = 'SELECT * FROM '.NMS_FIELDDEFS_TABLE.' WHERE id = ?';
    if( (int)$id == 0 ) {
      $id = trim($id);
      $query = 'SELECT * FROM '.NMS_FIELDDEFS_TABLE.' WHERE name = ?';
    }

    $row = $db->GetRow($query,array($id));
    if( !is_array($row) || count($row) == 0 ) throw new CmsException('Could not find fielddef with id/name '.$id);
    $obj = new nms_fielddef;
    $obj->load_from_data($row);
    return $obj;
  }

  public static function load_all($by_id = FALSE)
  {
    if( !is_array(self::$_all) ) {
      $db = cmsms()->GetDb();
      $query = 'SELECT * FROM '.NMS_FIELDDEFS_TABLE.' ORDER BY iorder ASC';

      $data = $db->GetArray($query);
      if( !is_array($data) || count($data) == 0 ) return;
      self::$_all = $data;
    }

    $out = array();
    foreach( self::$_all as $row ) {
      $obj = new nms_fielddef;
      $obj->load_from_data($row);
      if( $by_id ) {
	$out[$obj['id']] = $obj;
      }
      else {
	$out[$obj['name']] = $obj;
      }
    }
    return $out;
  }

  public static function get_types()
  {
    return array(self::TYPE_TEXTBOX,self::TYPE_TEXTAREA,self::TYPE_CHECKBOX,self::TYPE_DROPDOWN);
  }
}

?>