Location: PHPKode > projects > AModules3 > amodules-3.0.1/lib/Grid.php
<?
class Grid extends CompleteLister {
    protected $columns;
    private $table;
    private $id;
    
	public $last_column;
    public $sortby='0';
    public $sortby_db=null;

    public $displayed_rows=0;

    public $totals_t=null;
    /**
     * Inline related property
     * If true - TAB key submits row and activates next row
     */
    public $tab_moves_down=false;
    /**
     * Inline related property
     * Wether or not to show submit line
     */
    public $show_submit=true;
    private $record_order=null;

    function init(){
        parent::init();
        $this->api->addHook('pre-render',array($this,'precacheTemplate'));

        $this->sortby=$this->learn('sortby',$_GET[$this->name.'_sort']);
        $this->api->addHook('post-submit', array($this,'submitted'), 3);
    }
    function defaultTemplate(){
        return array('grid','grid');
    }
    function addColumn($type,$name=null,$descr=null){
        if($name===null){
            $name=$type;
            $type='text';
        }
        if($descr===null)$descr=$name;
        $this->columns[$name]=array(
                'type'=>$type,
                'descr'=>$descr
                );

        $this->last_column=$name;

        return $this;
    }
    function addButton($label){
        return $this->add('Button',count($this->elements),'grid_buttons')
            ->setLabel($label)->onClick();
    }
    function addQuickSearch($fields,$class='QuickSearch'){
        return $this->add($class,null,'quick_search')
            ->useFields($fields);
    }
    function makeSortable($db_sort=null){
        // Sorting
        $reverse=false;
        if(substr($db_sort,0,1)=='-'){
            $reverse=true;
            $db_sort=substr($db_sort,1);
        }
        if(!$db_sort)$db_sort=$this->last_column;

        if($this->sortby==$this->last_column){
            // we are already sorting by this column
            $info=array('1',$reverse?0:("-".$this->last_column));
            $this->sortby_db=$db_sort;
        }elseif($this->sortby=="-".$this->last_column){
            // We are sorted reverse by this column
            $info=array('2',$reverse?$this->last_column:'0');
            $this->sortby_db="-".$db_sort;
        }else{
            // we are not sorted by this column
            $info=array('0',$reverse?("-".$this->last_column):$this->last_column);
        }
        $this->columns[$this->last_column]['sortable']=$info;

        return $this;
    }
    function format_number($field){
    }
    function format_text($field){
    	$this->current_row[$field] = $this->current_row[$field];
    }
    function format_shorttext($field){
    	$text=$this->current_row[$field];
    	if(strlen($text)>50)$text=substr($text,0,46).' ...';
    	$this->current_row[$field]=$text;
    }
    function format_html($field){
    	$this->current_row[$field] = htmlentities($this->current_row[$field]);
    }
    function format_money($field){
        $m=$this->current_row[$field];
        $this->current_row[$field]=number_format($m,2);
        if($m<0){
            $this->current_row[$field]='<font color=red>'.$this->current_row[$field].'</font>';
        }
    }
    function format_totals_number($field){
        return $this->format_number($field);
    }
    function format_totals_money($field){
        return $this->format_money($field);
    }
	function format_time($field){
		$this->current_row[$field]=format_time($this->current_row[$field]);
	}
    function format_date($field){
    	if(!$this->current_row[$field])$this->current_row[$field]='-'; else
    	$this->current_row[$field]=date('d/m/Y',strtotime($this->current_row[$field]));
    }
    function format_nowrap($field){
    	$this->row_t->set("tdparam_$field", $this->row_t->get("tdparam_$field")." nowrap");
    }
    function format_wrap($field){
    	$this->row_t->set("tdparam_$field", str_replace('nowrap','wrap',$this->row_t->get("tdparam_$field")));
    }
    function format_template($field){
        $this->current_row[$field]=$this->columns[$field]['template']
            ->set($this->current_row)
            ->trySet('_value_',$this->current_row[$field])
            ->render();
    }
    function format_expander($field, $idfield='id'){
        $n=$this->name.'_'.$field.'_'.$this->current_row[$idfield];
        $this->row_t->set('tdparam_'.$field,'id="'.$n.'" nowrap style="cursor: hand" onclick=\''.
                'expander_flip("'.$this->name.'",'.$this->current_row[$idfield].',"'.
                    $field.'","'.
                    $this->api->getDestinationURL($this->api->page.'_'.$field,array('expander'=>$field,
                            'cut_object'=>$this->api->page.'_'.$field, 'expanded'=>$this->name)).'&id=")\'');
        if($this->current_row[$field]){
            $this->current_row[$field]='<font color="blue">'.$this->current_row[$field].'</font>';
        }else{
            $this->current_row[$field]='<font color="blue">['.$this->columns[$field]['descr'].']</font>';
        }
    }
    function format_inline($field, $idfield='id'){
    	/**
    	 * Formats the InlineEdit: field that on click should substitute the text
    	 * in the columns of the row by the edit controls 
    	 * 
    	 * The point is to set an Id for each column of the row. To do this, we should
    	 * set a property showing that id should be added in prerender
    	 */
    	$col_id=$this->name.'_'.$field.'_inline';
    	$show_submit=$this->show_submit?'true':'false';
    	$tab_moves_down=$this->tab_moves_down?'true':'false';
    	//setting text non empty
    	$text=$this->current_row[$field]?$this->current_row[$field]:'null';

    	$this->row_t->set('tdparam_'.$field, 'id="'.$col_id.'_'.$this->current_row[$idfield].
			'" style="cursor: hand"');
    	$this->current_row[$field]='<a href=\'javascript:'.
			'inline_show("'.$this->name.'","'.$col_id.'",'.$this->current_row[$idfield].', "'.
			$this->api->getDestinationURL($this->api->page, array(
			'cut_object'=>$this->api->page, 'submit'=>$this->name)).
			'", '.$tab_moves_down.', '.$show_submit.');\'>'.$text.'</a>';
    }
    function format_nl2br($field) {
    	$this->current_row[$field] = nl2br($this->current_row[$field]);
    }
    function format_order($field, $idfield='id'){
        $n=$this->name.'_'.$field.'_'.$this->current_row[$idfield];
    	$this->row_t->set("tdparam_$field", 'id="'.$n.'" style="cursor: hand"'); 
    	$this->current_row[$field]=$this->record_order->getCell($this->current_row['id']);
    }
    function format_link($field){
    	$this->current_row[$field]='<a href="'.$this->api->getDestinationURL($field).'">'.
    		$this->columns[$field]['descr'].'</a>';
    }
    function addRecordOrder($field){
    	if(!$this->record_order){
    		$this->record_order=$this->add('RecordOrder');
    		$this->record_order->setField($field);
    	}
    	return $this;
    }
    function setSource($table,$db_fields="*"){
        parent::setSource($table,$db_fields);
        if($this->sortby){
            $desc=false;
            $order=$this->sortby_db;
            if(substr($this->sortby_db,0,1)=='-'){
                $desc=true;
                $order=substr($order,1);
            }
            $this->dq->order($order,$desc);
        }
        //we always need to calc rows
        $this->dq->calc_found_rows();
        return $this;
    }
    function setTemplate($template){
        // This allows you to use Template 
        $this->columns[$this->last_column]['template']=$this->add('SMlite')
            ->loadTemplateFromString($template);
        return $this;
    }

	function submitted(){
		if($_GET['submit']==$this->name){
			//return;// false;
			//saving to DB
			if($_GET['action']=='update'){
				$this->update();
			}
			$row=$this->getRowAsCommaString($_GET['row_id']);
			echo $row;
			exit;
		}
	}
	function update(){
		foreach($_GET as $name=>$value){
			if(strpos($value,'%'))$value=urldecode($value);
			if(strpos($name, 'field_')!==false){
				$this->dq->set(substr($name, 6)."='$value'");
			}
		}
		$idfield=$this->dq->args['fields'][0];
		if($idfield=='*')$idfield='id';
		$this->dq->where($idfield, $_GET['row_id']);
		$this->dq->do_update();
	}

	function getRowAsCommaString($id){
		$idfield=$this->dq->args['fields'][0];
		if($idfield=='*'||strpos($idfield,',')!==false)$idfield='id';
		$this->dq->where($idfield."=$id");
		//we should switch off the limit or we won't get any value
		$this->dq->limit(1);
		$row=$this->api->db->getHash($this->dq->select());
		$row_t=$this->template->cloneRegion('row');
		$row_t->del('cols');
        $col = $row_t->cloneRegion('col');

        foreach($this->columns as $name=>$column){
            $col->del('content');
            $col->set('content','<?$'.$name.'?>');

            // some types needs control over the td

            $col->set('tdparam','<?tdparam_'.$name.'?>nowrap<?/?>');
            $row_t->append('cols',$col->render());
        }
        $this->row_t = $this->api->add('SMlite');
        $this->row_t->loadTemplateFromString($row_t->render());

		$row=$this->formatRow($row);
		$result="";
		foreach($this->columns as $name=>$column){
			$result.=$row[$name]."<row_end>";
		}
		return $result;
	}
	function getRowHTML($id){
		$idfield=$this->dq->args['fields'][0];
		if($idfield=='*')$idfield='id';
		$this->dq->where($idfield."=$id");
		//we should switch off the limit or we won't get any value
		$this->dq->limit(1);
		$row=$this->api->db->getHash($this->dq->select());
		$row_t=$this->template->cloneRegion('row');
		$row_t->del('cols');
        $col = $row_t->cloneRegion('col');

        foreach($this->columns as $name=>$column){
            $col->del('content');
            $col->set('content','<?$'.$name.'?>');

            // some types needs control over the td

            $col->set('tdparam','<?tdparam_'.$name.'?>nowrap<?/?>');
            $row_t->append('cols',$col->render());
        }
        $this->row_t = $this->api->add('SMlite');
        $this->row_t->loadTemplateFromString($row_t->render());
		
		$row=$this->formatRow($row);
        $this->row_t->set($row);
        $result=$this->row_t->render();
        $tr_start=strpos($result, '<td');
        $result="\n ".substr($result, $tr_start, strpos($result, '</tr>')-$tr_start);
		return $result;
	}
    function formatRow($row=null){
    	if($row!=null)$this->current_row=$row;
        foreach($this->columns as $tmp=>$column){ // $this->cur_column=>$column){
            $formatters = split(',',$column['type']);
            foreach($formatters as $formatter){
                if(method_exists($this,$m="format_".$formatter)){
                    $this->$m($tmp);
                }else throw new BaseException("Grid does not know how to format type: ".$formatter);
            }
            if($this->current_row[$tmp]=='')$this->current_row[$tmp]='&nbsp;';
        }
        return $this->current_row;
    }
    function formatTotalsRow(){
        foreach($this->columns as $tmp=>$column){
            $formatters = split(',',$column['type']);
            $all_failed=true;
            foreach($formatters as $formatter){
                if(method_exists($this,$m="format_totals_".$formatter)){
                    $all_failed=false;
                    $this->$m($tmp);
                }
            }
            if($all_failed)$this->current_row[$tmp]='-';
        }
    }
    function precacheTemplate(){
        // pre-cache our template for row
        $row = $this->row_t;

        $col = $row->cloneRegion('col');
        $header = $this->template->cloneRegion('header');
        $header_col = $header->cloneRegion('col');
        $header_sort = $header_col->cloneRegion('sort');


        if($t_row = $this->totals_t){
            $t_col = $t_row->cloneRegion('col');
            $t_row->del('cols');
        }

        $row->set('grid_name',$this->name);
        $row->set('row_id','<?$id?>');
        $row->set('odd_even','<?$odd_even?>');
        $row->del('cols');
        $header->del('cols');
        if(count($this->columns )>0)
        foreach($this->columns as $name=>$column){
            $col->del('content');
            $col->set('content','<?$'.$name.'?>');

            if($t_row){
                $t_col->del('content');
                $t_col->set('content','<?$'.$name.'?>');
                $t_row->append('cols',$t_col->render());
            }

            // some types needs control over the td

            $col->set('tdparam','<?tdparam_'.$name.'?>nowrap<?/?>');

            $row->append('cols',$col->render());

            $header_col->set('descr',$column['descr']);
            if(isset($column['sortable'])){
                $s=$column['sortable'];
                // calculate sortlink
                $l = $this->api->getDestinationURL(null,array($this->name.'_sort'=>$s[1]));

                $header_sort->set('order',$column['sortable'][0]);
                $header_sort->set('sortlink',$l);
                $header_col->set('sort',$header_sort->render());
            }else{
                $header_col->del('sort');
            }
            $header->append('cols',$header_col->render());
        }
        $this->row_t = $this->api->add('SMlite');
        $this->row_t->loadTemplateFromString($row->render());

        if($t_row){
            $this->totals_t = $this->api->add('SMlite');
            $this->totals_t->loadTemplateFromString($t_row->render());
        }

        $this->template->set('header',$header->render());
        $this->template->set('grid_name',$this->name);
        //var_dump(htmlspecialchars($this->row_t->tmp_template));
        
    }
    function render(){
    	if($this->dq&&$this->dq->foundRows()==0){
    		$not_found=$this->add('SMlite')->loadTemplate('grid');
    		$not_found=$not_found->get('not_found');
    		//$this->template->del('header');
    		$this->template->del('rows');
    		$this->template->del('totals');
    		$this->template->set('header','<tr class="header">'.$not_found.'</tr>');
    		//return;
    	}
        parent::render();
    }
    
    public function setWidth( $width ){
    	$this->template->set('container_style', 'margin: 0 auto; width:'.$width.((!is_numeric($width))?'':'px'));
    	return $this;
    }
}
Return current item: AModules3