/application/libraries/grocery_crud.php
PHP | 4906 lines | 3642 code | 719 blank | 545 comment | 494 complexity | cf270da4489c18f3567ffe13db15cfbe MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * PHP grocery CRUD
- *
- * A Codeigniter library that creates a CRUD automatically with just few lines of code.
- *
- * Copyright (C) 2010 - 2012 John Skoumbourdis.
- *
- * LICENSE
- *
- * Grocery CRUD is released with dual licensing, using the GPL v3 (license-gpl3.txt) and the MIT license (license-mit.txt).
- * You don't have to do anything special to choose one license or the other and you don't have to notify anyone which license you are using.
- * Please see the corresponding license file for details of these licenses.
- * You are free to use, modify and distribute this software, but all copyright information must remain.
- *
- * @package grocery CRUD
- * @copyright Copyright (c) 2010 through 2012, John Skoumbourdis
- * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
- * @version 1.3
- * @author John Skoumbourdis <scoumbourdisj@gmail.com>
- */
- // ------------------------------------------------------------------------
- /**
- * grocery Field Types
- *
- * The types of the fields and the default reactions
- *
- * @package grocery CRUD
- * @author John Skoumbourdis <scoumbourdisj@gmail.com>
- * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
- * @link http://www.grocerycrud.com/documentation
- */
- class grocery_CRUD_Field_Types
- {
- /**
- * Gets the field types of the main table.
- * @return array
- */
- public function get_field_types()
- {
- if($this->field_types !== null)
- return $this->field_types;
-
- $types = array();
- foreach($this->basic_model->get_field_types_basic_table() as $field_info)
- {
- $field_info->required = !empty($this->required_fields) && in_array($field_info->name,$this->required_fields) ? true : false;
-
- $field_info->display_as =
- isset($this->display_as[$field_info->name]) ?
- $this->display_as[$field_info->name] :
- ucfirst(str_replace("_"," ",$field_info->name));
-
- if($this->change_field_type !== null && isset($this->change_field_type[$field_info->name]))
- {
- $field_type = $this->change_field_type[$field_info->name];
-
- $field_info->crud_type = $field_type->type;
- $field_info->extras = $field_type->extras;
-
- $real_type = $field_info->crud_type;
- }
- elseif(isset($this->relation[$field_info->name]))
- {
- $real_type = 'relation';
- $field_info->crud_type = 'relation';
- }
- elseif(isset($this->upload_fields[$field_info->name]))
- {
- $real_type = 'upload_file';
- $field_info->crud_type = 'upload_file';
- }
- else
- {
- $real_type = $this->get_type($field_info);
- $field_info->crud_type = $real_type;
- }
-
- switch ($real_type) {
- case 'text':
- if(!empty($this->unset_texteditor) && in_array($field_info->name,$this->unset_texteditor))
- $field_info->extras = false;
- else
- $field_info->extras = 'text_editor';
- break;
-
- case 'relation':
- $field_info->extras = $this->relation[$field_info->name];
- break;
-
- case 'upload_file':
- $field_info->extras = $this->upload_fields[$field_info->name];
- break;
-
- default:
- if(empty($field_info->extras))
- $field_info->extras = false;
- break;
- }
-
- $types[$field_info->name] = $field_info;
- }
-
- if(!empty($this->relation_n_n))
- {
- foreach($this->relation_n_n as $field_name => $field_extras)
- {
- $field_info = (object)array();
- $field_info->name = $field_name;
- $field_info->crud_type = 'relation_n_n';
- $field_info->extras = $field_extras;
- $field_info->required = !empty($this->required_fields) && in_array($field_name,$this->required_fields) ? true : false;;
- $field_info->display_as =
- isset($this->display_as[$field_name]) ?
- $this->display_as[$field_name] :
- ucfirst(str_replace("_"," ",$field_name));
- $types[$field_name] = $field_info;
- }
- }
-
- if(!empty($this->add_fields))
- foreach($this->add_fields as $field_object)
- {
- $field_name = isset($field_object->field_name) ? $field_object->field_name : $field_object;
-
- if(!isset($types[$field_name]))
- {
- $field_info = (object)array(
- 'name' => $field_name,
- 'crud_type' => $this->change_field_type !== null && isset($this->change_field_type[$field_name]) ?
- $this->change_field_type[$field_name]->type :
- 'string',
- 'display_as' => isset($this->display_as[$field_name]) ?
- $this->display_as[$field_name] :
- ucfirst(str_replace("_"," ",$field_name)),
- 'required' => in_array($field_name,$this->required_fields) ? true : false
- );
-
- $types[$field_name] = $field_info;
- }
- }
-
- if(!empty($this->edit_fields))
- foreach($this->edit_fields as $field_object)
- {
- $field_name = isset($field_object->field_name) ? $field_object->field_name : $field_object;
-
- if(!isset($types[$field_name]))
- {
- $field_info = (object)array(
- 'name' => $field_name,
- 'crud_type' => $this->change_field_type !== null && isset($this->change_field_type[$field_name]) ?
- $this->change_field_type[$field_name]->type :
- 'string',
- 'display_as' => isset($this->display_as[$field_name]) ?
- $this->display_as[$field_name] :
- ucfirst(str_replace("_"," ",$field_name)),
- 'required' => in_array($field_name,$this->required_fields) ? true : false
- );
-
- $types[$field_name] = $field_info;
- }
- }
-
- $this->field_types = $types;
-
- return $this->field_types;
- }
-
- public function get_primary_key()
- {
- return $this->basic_model->get_primary_key();
- }
-
- /**
- * Get the html input for the specific field with the
- * current value
- *
- * @param object $field_info
- * @param string $value
- * @return object
- */
- protected function get_field_input($field_info, $value = null)
- {
- $real_type = $field_info->crud_type;
-
- $types_array = array(
- 'integer',
- 'text',
- 'true_false',
- 'string',
- 'date',
- 'datetime',
- 'enum',
- 'set',
- 'relation',
- 'relation_n_n',
- 'upload_file',
- 'hidden',
- 'password',
- 'readonly',
- 'dropdown',
- 'multiselect'
- );
-
- if (in_array($real_type,$types_array)) {
- /* A quick way to go to an internal method of type $this->get_{type}_input .
- * For example if the real type is integer then we will use the method
- * $this->get_integer_input
- * */
- $field_info->input = $this->{"get_".$real_type."_input"}($field_info,$value);
- }
- else
- {
- $field_info->input = $this->get_string_input($field_info,$value);
- }
-
- return $field_info;
- }
-
- protected function change_list_value($field_info, $value = null)
- {
- $real_type = $field_info->crud_type;
-
- switch ($real_type) {
- case 'hidden':
- case 'invisible':
- case 'integer':
-
- break;
- case 'true_false':
- if(isset($this->default_true_false_text[$value]))
- $value = $this->default_true_false_text[$value];
- break;
- case 'string':
- $value = $this->character_limiter($value,$this->character_limiter,"...");
- break;
- case 'text':
- $value = $this->character_limiter(strip_tags($value),$this->character_limiter,"...");
- break;
- case 'date':
- if(!empty($value) && $value != '0000-00-00' && $value != '1970-01-01')
- {
- list($year,$month,$day) = explode("-",$value);
-
- $value = date($this->php_date_format, mktime (0, 0, 0, (int)$month , (int)$day , (int)$year));
- }
- else
- {
- $value = '';
- }
- break;
- case 'datetime':
- if(!empty($value) && $value != '0000-00-00 00:00:00' && $value != '1970-01-01 00:00:00')
- {
- list($year,$month,$day) = explode("-",$value);
- list($hours,$minutes) = explode(":",substr($value,11));
-
- $value = date($this->php_date_format." - H:i", mktime ((int)$hours , (int)$minutes , 0, (int)$month , (int)$day ,(int)$year));
- }
- else
- {
- $value = '';
- }
- break;
- case 'enum':
- $value = $this->character_limiter($value,$this->character_limiter,"...");
- break;
- case 'multiselect':
- $value_as_array = array();
- foreach(explode(",",$value) as $row_value)
- {
- $value_as_array[] = array_key_exists($row_value,$field_info->extras) ? $field_info->extras[$row_value] : $row_value;
- }
- $value = implode(",",$value_as_array);
- break;
-
- case 'relation_n_n':
- $value = $this->character_limiter(str_replace(',',', ',$value),$this->character_limiter,"...");
- break;
-
- case 'password':
- $value = '******';
- break;
-
- case 'dropdown':
- $value = array_key_exists($value,$field_info->extras) ? $field_info->extras[$value] : $value;
- break;
-
- case 'upload_file':
- if(empty($value))
- {
- $value = "";
- }
- else
- {
- $is_image = !empty($value) &&
- ( substr($value,-4) == '.jpg'
- || substr($value,-4) == '.png'
- || substr($value,-5) == '.jpeg'
- || substr($value,-4) == '.gif'
- || substr($value,-5) == '.tiff')
- ? true : false;
-
- $file_url = base_url().$field_info->extras->upload_path."/$value";
-
- $file_url_anchor = '<a href="'.$file_url.'"';
- if($is_image)
- {
- $file_url_anchor .= ' class="image-thumbnail"><img src="'.$file_url.'" height="50px">';
- }
- else
- {
- $file_url_anchor .= ' target="_blank">'.$this->character_limiter($value,$this->character_limiter,'...',true);
- }
- $file_url_anchor .= '</a>';
-
- $value = $file_url_anchor;
- }
- break;
-
- default:
- $value = $this->character_limiter($value,$this->character_limiter,"...");
- break;
- }
-
- return $value;
- }
- /**
- * Character Limiter of codeigniter (I just don't want to load the helper )
- *
- * Limits the string based on the character count. Preserves complete words
- * so the character count may not be exactly as specified.
- *
- * @access public
- * @param string
- * @param integer
- * @param string the end character. Usually an ellipsis
- * @return string
- */
- function character_limiter($str, $n = 500, $end_char = '…')
- {
- if (strlen($str) < $n)
- {
- return $str;
- }
- // a bit complicated, but faster than preg_replace with \s+
- $str = preg_replace('/ {2,}/', ' ', str_replace(array("\r", "\n", "\t", "\x0B", "\x0C"), ' ', $str));
- if (strlen($str) <= $n)
- {
- return $str;
- }
- $out = '';
- foreach (explode(' ', trim($str)) as $val)
- {
- $out .= $val.' ';
- if (strlen($out) >= $n)
- {
- $out = trim($out);
- return (strlen($out) === strlen($str)) ? $out : $out.$end_char;
- }
- }
- }
-
- protected function get_type($db_type)
- {
- $type = false;
- if(!empty($db_type->type))
- {
- switch ($db_type->type) {
- case '1':
- case '3':
- case 'int':
- case 'tinyint':
- case 'mediumint':
- case 'longint':
- if( $db_type->db_type == 'tinyint' && $db_type->db_max_length == 1)
- $type = 'true_false';
- else
- $type = 'integer';
- break;
- case '254':
- case 'string':
- case 'enum':
- if($db_type->db_type != 'enum')
- $type = 'string';
- else
- $type = 'enum';
- break;
- case 'set':
- if($db_type->db_type != 'set')
- $type = 'string';
- else
- $type = 'set';
- break;
- case '252':
- case 'blob':
- case 'text':
- case 'mediumtext':
- case 'longtext':
- $type = 'text';
- break;
- case '10':
- case 'date':
- $type = 'date';
- break;
- case '12':
- case 'datetime':
- case 'timestamp':
- $type = 'datetime';
- break;
- }
- }
- return $type;
- }
- }
- // ------------------------------------------------------------------------
- /**
- * Grocery Model Driver
- *
- * Drives the model - I'ts so easy like you drive a bicycle :-)
- *
- * @package grocery CRUD
- * @author John Skoumbourdis <scoumbourdisj@gmail.com>
- * @version 1.3
- * @link http://www.grocerycrud.com/documentation
- */
- class grocery_CRUD_Model_Driver extends grocery_CRUD_Field_Types
- {
- /**
- * @var grocery_CRUD_Model
- */
- public $basic_model = null;
-
- protected function set_default_Model()
- {
- $ci = &get_instance();
- $ci->load->model('grocery_CRUD_Model');
-
- $this->basic_model = $ci->grocery_CRUD_Model;
- }
-
- protected function get_total_results()
- {
- if(!empty($this->where))
- foreach($this->where as $where)
- $this->basic_model->where($where[0],$where[1],$where[2]);
- if(!empty($this->or_where))
- foreach($this->or_where as $or_where)
- $this->basic_model->or_where($or_where[0],$or_where[1],$or_where[2]);
- if(!empty($this->like))
- foreach($this->like as $like)
- $this->basic_model->like($like[0],$like[1],$like[2]);
-
- if(!empty($this->or_like))
- foreach($this->or_like as $or_like)
- $this->basic_model->or_like($or_like[0],$or_like[1],$or_like[2]);
- if(!empty($this->having))
- foreach($this->having as $having)
- $this->basic_model->having($having[0],$having[1],$having[2]);
-
- if(!empty($this->or_having))
- foreach($this->or_having as $or_having)
- $this->basic_model->or_having($or_having[0],$or_having[1],$or_having[2]);
-
- if(!empty($this->relation))
- foreach($this->relation as $relation)
- $this->basic_model->join_relation($relation[0],$relation[1],$relation[2]);
-
- if(!empty($this->relation_n_n))
- {
- $columns = $this->get_columns();
- foreach($columns as $column)
- {
- //Use the relation_n_n ONLY if the column is called . The set_relation_n_n are slow and it will make the table slower without any reason as we don't need those queries.
- if(isset($this->relation_n_n[$column->field_name]))
- {
- $this->basic_model->set_relation_n_n_field($this->relation_n_n[$column->field_name]);
- }
- }
-
- }
-
- return $this->basic_model->get_total_results();
- }
-
- public function set_model($model_name)
- {
- $ci = &get_instance();
- $ci->load->model('grocery_CRUD_Model');
-
- $ci->load->model($model_name);
-
- $temp = explode('/',$model_name);
- krsort($temp);
- foreach($temp as $t)
- {
- $real_model_name = $t;
- break;
- }
-
- $this->basic_model = $ci->$real_model_name;
- }
-
- protected function set_ajax_list_queries($state_info = null)
- {
- if(!empty($state_info->per_page))
- {
- if(empty($state_info->page) || !is_numeric($state_info->page) )
- $this->limit($state_info->per_page);
- else
- {
- $limit_page = ( ($state_info->page-1) * $state_info->per_page );
- $this->limit($state_info->per_page, $limit_page);
- }
- }
-
- if(!empty($state_info->order_by))
- {
- $this->order_by($state_info->order_by[0],$state_info->order_by[1]);
- }
-
- if(!empty($state_info->search))
- {
- if(!empty($this->relation))
- foreach($this->relation as $relation_name => $relation_values)
- $temp_relation[$this->_unique_field_name($relation_name)] = $this->_get_field_names_to_search($relation_values);
-
- if($state_info->search->field !== null)
- {
- if(isset($temp_relation[$state_info->search->field]))
- {
- if(is_array($temp_relation[$state_info->search->field]))
- foreach($temp_relation[$state_info->search->field] as $search_field)
- $this->or_like($search_field , $state_info->search->text);
- else
- $this->like($temp_relation[$state_info->search->field] , $state_info->search->text);
- }
- elseif(isset($this->relation_n_n[$state_info->search->field]))
- {
- $escaped_text = $this->basic_model->escape_str($state_info->search->text);
- $this->having($state_info->search->field." LIKE '%".$escaped_text."%'");
- }
- else
- {
- $this->like($state_info->search->field , $state_info->search->text);
- }
- }
- else
- {
- $columns = $this->get_columns();
-
- $search_text = $state_info->search->text;
- if(!empty($this->where))
- foreach($this->where as $where)
- $this->basic_model->having($where[0],$where[1],$where[2]);
-
- foreach($columns as $column)
- {
- if(isset($temp_relation[$column->field_name]))
- {
- if(is_array($temp_relation[$column->field_name]))
- {
- foreach($temp_relation[$column->field_name] as $search_field)
- {
- $this->or_like($search_field, $search_text);
- }
- }
- else
- {
- $this->or_like($temp_relation[$column->field_name], $search_text);
- }
- }
- elseif(isset($this->relation_n_n[$column->field_name]))
- {
- //@todo have a where for the relation_n_n statement
- }
- else
- {
- $this->or_like($column->field_name, $search_text);
- }
- }
- }
- }
- }
-
- protected function table_exists($table_name = null)
- {
- if($this->basic_model->db_table_exists($table_name))
- return true;
- return false;
- }
-
- protected function get_relation_array($relation_info, $primary_key_value = null, $limit = null)
- {
- list($field_name , $related_table , $related_field_title, $where_clause, $order_by) = $relation_info;
- if($primary_key_value !== null)
- {
- $primary_key = $this->basic_model->get_primary_key($related_table);
-
- //A where clause with the primary key is enough to take the selected key row
- $where_clause = array($primary_key => $primary_key_value);
- }
-
- $relation_array = $this->basic_model->get_relation_array($field_name , $related_table , $related_field_title, $where_clause, $order_by, $limit);
-
- return $relation_array;
- }
-
- protected function get_relation_total_rows($relation_info)
- {
- list($field_name , $related_table , $related_field_title, $where_clause) = $relation_info;
-
- $relation_array = $this->basic_model->get_relation_total_rows($field_name , $related_table , $related_field_title, $where_clause);
-
- return $relation_array;
- }
-
- protected function db_insert_validation()
- {
- $validation_result = (object)array('success'=>false);
-
- $field_types = $this->get_field_types();
- $required_fields = $this->required_fields;
- $add_fields = $this->get_add_fields();
-
- if(!empty($required_fields))
- {
- foreach($add_fields as $add_field)
- {
- $field_name = $add_field->field_name;
- if(!isset($this->validation_rules[$field_name]) && in_array( $field_name, $required_fields) )
- {
- $this->set_rules( $field_name, $field_types[$field_name]->display_as, 'required');
- }
- }
- }
-
- if(!empty($this->validation_rules))
- {
- $form_validation = $this->form_validation();
-
- $add_fields = $this->get_add_fields();
-
- foreach($add_fields as $add_field)
- {
- $field_name = $add_field->field_name;
- if(isset($this->validation_rules[$field_name]))
- {
- $rule = $this->validation_rules[$field_name];
- $form_validation->set_rules($rule['field'],$rule['label'],$rule['rules']);
- }
- }
-
- if($form_validation->run())
- {
- $validation_result->success = true;
- }
- else
- {
- $validation_result->error_message = $form_validation->error_string();
- $validation_result->error_fields = $form_validation->_error_array;
- }
- }
- else
- {
- $validation_result->success = true;
- }
-
- return $validation_result;
- }
- protected function form_validation()
- {
- if($this->form_validation === null)
- {
- $this->form_validation = new grocery_CRUD_Form_validation();
- $ci = &get_instance();
- $ci->load->library('form_validation');
- $ci->form_validation = $this->form_validation;
- }
- return $this->form_validation;
- }
-
- protected function db_update_validation()
- {
- $validation_result = (object)array('success'=>false);
-
- $field_types = $this->get_field_types();
- $required_fields = $this->required_fields;
- $edit_fields = $this->get_edit_fields();
-
- if(!empty($required_fields))
- {
- foreach($edit_fields as $edit_field)
- {
- $field_name = $edit_field->field_name;
- if(!isset($this->validation_rules[$field_name]) && in_array( $field_name, $required_fields) )
- {
- $this->set_rules( $field_name, $field_types[$field_name]->display_as, 'required');
- }
- }
- }
-
- if(!empty($this->validation_rules))
- {
- $form_validation = $this->form_validation();
-
- $edit_fields = $this->get_edit_fields();
-
- foreach($edit_fields as $edit_field)
- {
- $field_name = $edit_field->field_name;
- if(isset($this->validation_rules[$field_name]))
- {
- $rule = $this->validation_rules[$field_name];
- $form_validation->set_rules($rule['field'],$rule['label'],$rule['rules']);
- }
- }
-
- if($form_validation->run())
- {
- $validation_result->success = true;
- }
- else
- {
- $validation_result->error_message = $form_validation->error_string();
- $validation_result->error_fields = $form_validation->_error_array;
- }
- }
- else
- {
- $validation_result->success = true;
- }
-
- return $validation_result;
- }
- protected function db_insert($state_info)
- {
- $validation_result = $this->db_insert_validation();
-
- if($validation_result->success)
- {
- $post_data = $state_info->unwrapped_data;
-
- $add_fields = $this->get_add_fields();
- if($this->callback_insert === null)
- {
- if($this->callback_before_insert !== null)
- {
- $callback_return = call_user_func($this->callback_before_insert, $post_data);
-
- if(!empty($callback_return) && is_array($callback_return))
- $post_data = $callback_return;
- elseif($callback_return === false)
- return false;
- }
-
- $insert_data = array();
- $types = $this->get_field_types();
- foreach($add_fields as $num_row => $field)
- {
- /* If the multiselect or the set is empty then the browser doesn't send an empty array. Instead it sends nothing */
- if(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect') && !isset($post_data[$field->field_name]))
- {
- $post_data[$field->field_name] = array();
- }
-
- if(isset($post_data[$field->field_name]) && !isset($this->relation_n_n[$field->field_name]))
- {
- if(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && is_array($post_data[$field->field_name]) && empty($post_data[$field->field_name]))
- {
- $insert_data[$field->field_name] = null;
- }
- elseif(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && $post_data[$field->field_name] === '')
- {
- $insert_data[$field->field_name] = null;
- }
- elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'date')
- {
- $insert_data[$field->field_name] = $this->_convert_date_to_sql_date($post_data[$field->field_name]);
- }
- elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'readonly')
- {
- //This empty if statement is to make sure that a readonly field will never inserted/updated
- }
- elseif(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect'))
- {
- $insert_data[$field->field_name] = !empty($post_data[$field->field_name]) ? implode(',',$post_data[$field->field_name]) : '';
- }
- elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'datetime'){
- $insert_data[$field->field_name] = $this->_convert_date_to_sql_date(substr($post_data[$field->field_name],0,10)).
- substr($post_data[$field->field_name],10);
- }
- else
- {
- $insert_data[$field->field_name] = $post_data[$field->field_name];
- }
- }
- }
-
- $insert_result = $this->basic_model->db_insert($insert_data);
-
- if($insert_result !== false)
- {
- $insert_primary_key = $insert_result;
- }
- else
- {
- return false;
- }
-
- if(!empty($this->relation_n_n))
- {
- foreach($this->relation_n_n as $field_name => $field_info)
- {
- $relation_data = isset( $post_data[$field_name] ) ? $post_data[$field_name] : array() ;
- $this->db_relation_n_n_update($field_info, $relation_data ,$insert_primary_key);
- }
- }
-
- if($this->callback_after_insert !== null)
- {
- $callback_return = call_user_func($this->callback_after_insert, $post_data, $insert_primary_key);
-
- if($callback_return === false)
- {
- return false;
- }
-
- }
- }else
- {
- $callback_return = call_user_func($this->callback_insert, $post_data);
-
- if($callback_return === false)
- {
- return false;
- }
- }
-
- if(isset($insert_primary_key))
- return $insert_primary_key;
- else
- return true;
- }
-
- return false;
-
- }
-
- protected function db_update($state_info)
- {
- $validation_result = $this->db_update_validation();
-
- $edit_fields = $this->get_edit_fields();
-
- if($validation_result->success)
- {
- $post_data = $state_info->unwrapped_data;
- $primary_key = $state_info->primary_key;
-
- if($this->callback_update === null)
- {
- if($this->callback_before_update !== null)
- {
- $callback_return = call_user_func($this->callback_before_update, $post_data, $primary_key);
-
- if(!empty($callback_return) && is_array($callback_return))
- {
- $post_data = $callback_return;
- }
- elseif($callback_return === false)
- {
- return false;
- }
-
- }
-
- $update_data = array();
- $types = $this->get_field_types();
- foreach($edit_fields as $num_row => $field)
- {
- /* If the multiselect or the set is empty then the browser doesn't send an empty array. Instead it sends nothing */
- if(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect') && !isset($post_data[$field->field_name]))
- {
- $post_data[$field->field_name] = array();
- }
-
- if(isset($post_data[$field->field_name]) && !isset($this->relation_n_n[$field->field_name]))
- {
- if(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && is_array($post_data[$field->field_name]) && empty($post_data[$field->field_name]))
- {
- $update_data[$field->field_name] = null;
- }
- elseif(isset($types[$field->field_name]->db_null) && $types[$field->field_name]->db_null && $post_data[$field->field_name] === '')
- {
- $update_data[$field->field_name] = null;
- }
- elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'date')
- {
- $update_data[$field->field_name] = $this->_convert_date_to_sql_date($post_data[$field->field_name]);
- }
- elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'readonly')
- {
- //This empty if statement is to make sure that a readonly field will never inserted/updated
- }
- elseif(isset($types[$field->field_name]->crud_type) && ($types[$field->field_name]->crud_type == 'set' || $types[$field->field_name]->crud_type == 'multiselect'))
- {
- $update_data[$field->field_name] = !empty($post_data[$field->field_name]) ? implode(',',$post_data[$field->field_name]) : '';
- }
- elseif(isset($types[$field->field_name]->crud_type) && $types[$field->field_name]->crud_type == 'datetime'){
- $update_data[$field->field_name] = $this->_convert_date_to_sql_date(substr($post_data[$field->field_name],0,10)).
- substr($post_data[$field->field_name],10);
- }
- else
- {
- $update_data[$field->field_name] = $post_data[$field->field_name];
- }
- }
- }
-
- if($this->basic_model->db_update($update_data, $primary_key) === false)
- {
- return false;
- }
-
- if(!empty($this->relation_n_n))
- {
- foreach($this->relation_n_n as $field_name => $field_info)
- {
- if ( $this->unset_edit_fields !== null
- && is_array($this->unset_edit_fields)
- && in_array($field_name,$this->unset_edit_fields)
- ) {
- continue;
- }
-
- $relation_data = isset( $post_data[$field_name] ) ? $post_data[$field_name] : array() ;
- $this->db_relation_n_n_update($field_info, $relation_data ,$primary_key);
- }
- }
-
- if($this->callback_after_update !== null)
- {
- $callback_return = call_user_func($this->callback_after_update, $post_data, $primary_key);
-
- if($callback_return === false)
- {
- return false;
- }
-
- }
- }
- else
- {
- $callback_return = call_user_func($this->callback_update, $post_data, $primary_key);
-
- if($callback_return === false)
- {
- return false;
- }
- }
-
- return true;
- }
- else
- {
- return false;
- }
- }
-
- protected function _convert_date_to_sql_date($date)
- {
- $date = substr($date,0,10);
- if(preg_match('/\d{4}-\d{2}-\d{2}/',$date))
- {
- //If it's already a sql-date don't convert it!
- return $date;
- }elseif(empty($date))
- {
- return '';
- }
-
- $date_array = preg_split( '/[-\.\/ ]/', $date);
- if($this->php_date_format == 'd/m/Y')
- {
- $sql_date = date('Y-m-d',mktime(0,0,0,$date_array[1],$date_array[0],$date_array[2]));
- }
- elseif($this->php_date_format == 'm/d/Y')
- {
- $sql_date = date('Y-m-d',mktime(0,0,0,$date_array[0],$date_array[1],$date_array[2]));
- }
- else
- {
- $sql_date = $date;
- }
-
- return $sql_date;
- }
-
- protected function _get_field_names_to_search(array $relation_values)
- {
- if(!strstr($relation_values[2],'{'))
- return $this->_unique_join_name($relation_values[0]).'.'.$relation_values[2];
- else
- {
- $relation_values[2] = ' '.$relation_values[2].' ';
- $temp1 = explode('{',$relation_values[2]);
- unset($temp1[0]);
-
- $field_names_array = array();
- foreach($temp1 as $field)
- list($field_names_array[]) = explode('}',$field);
-
- return $field_names_array;
- }
- }
-
- protected function _unique_join_name($field_name)
- {
- return 'j'.substr(md5($field_name),0,8); //This j is because is better for a string to begin with a letter and not a number
- }
- protected function _unique_field_name($field_name)
- {
- return 's'.substr(md5($field_name),0,8); //This s is because is better for a string to begin with a letter and not a number
- }
-
- protected function db_delete($state_info)
- {
- $primary_key = $state_info->primary_key;
-
- if($this->callback_delete === null)
- {
- if($this->callback_before_delete !== null)
- {
- $callback_return = call_user_func($this->callback_before_delete, $primary_key);
-
- if($callback_return === false)
- {
- return false;
- }
-
- }
-
- if(!empty($this->relation_n_n))
- {
- foreach($this->relation_n_n as $field_name => $field_info)
- {
- $this->db_relation_n_n_delete( $field_info, $primary_key );
- }
- }
-
- $delete_result = $this->basic_model->db_delete($primary_key);
-
- if($delete_result === false)
- {
- return false;
- }
-
- if($this->callback_after_delete !== null)
- {
- $callback_return = call_user_func($this->callback_after_delete, $primary_key);
-
- if($callback_return === false)
- {
- return false;
- }
-
- }
- }
- else
- {
- $callback_return = call_user_func($this->callback_delete, $primary_key);
-
- if($callback_return === false)
- {
- return false;
- }
- }
-
- return true;
- }
-
- protected function db_relation_n_n_update($field_info, $post_data , $primary_key_value)
- {
- $this->basic_model->db_relation_n_n_update($field_info, $post_data , $primary_key_value);
- }
- protected function db_relation_n_n_delete($field_info, $primary_key_value)
- {
- $this->basic_model->db_relation_n_n_delete($field_info, $primary_key_value);
- }
-
- protected function get_list()
- {
- if(!empty($this->order_by))
- $this->basic_model->order_by($this->order_by[0],$this->order_by[1]);
-
- if(!empty($this->where))
- foreach($this->where as $where)
- $this->basic_model->where($where[0],$where[1],$where[2]);
- if(!empty($this->or_where))
- foreach($this->or_where as $or_where)
- $this->basic_model->or_where($or_where[0],$or_where[1],$or_where[2]);
- if(!empty($this->like))
- foreach($this->like as $like)
- $this->basic_model->like($like[0],$like[1],$like[2]);
-
- if(!empty($this->or_like))
- foreach($this->or_like as $or_like)
- $this->basic_model->or_like($or_like[0],$or_like[1],$or_like[2]);
-
- if(!empty($this->having))
- foreach($this->having as $having)
- $this->basic_model->having($having[0],$having[1],$having[2]);
-
- if(!empty($this->or_having))
- foreach($this->or_having as $or_having)
- $this->basic_model->or_having($or_having[0],$or_having[1],$or_having[2]);
-
- if(!empty($this->relation))
- foreach($this->relation as $relation)
- $this->basic_model->join_relation($relation[0],$relation[1],$relation[2]);
-
- if(!empty($this->relation_n_n))
- {
- $columns = $this->get_columns();
- foreach($columns as $column)
- {
- //Use the relation_n_n ONLY if the column is called . The set_relation_n_n are slow and it will make the table slower without any reason as we don't need those queries.
- if(isset($this->relation_n_n[$column->field_name]))
- {
- $this->basic_model->set_relation_n_n_field($this->relation_n_n[$column->field_name]);
- }
- }
-
- }
-
- if($this->theme_config['crud_paging'] === true)
- {
- if($this->limit === null)
- {
- $default_per_page = $this->config->default_per_page;
- if(is_numeric($default_per_page) && $default_per_page >1)
- {
- $this->basic_model->limit($default_per_page);
- }
- else
- {
- $this->basic_model->limit(10);
- }
- }
- else
- {
- $this->basic_model->limit($this->limit[0],$this->limit[1]);
- }
- }
-
- $results = $this->basic_model->get_list();
-
- return $results;
- }
-
- protected function get_edit_values($primary_key_value)
- {
- $values = $this->basic_model->get_edit_values($primary_key_value);
-
- if(!empty($this->relation_n_n))
- {
- foreach($this->relation_n_n as $field_name => $field_info)
- {
- $values->$field_name = $this->get_relation_n_n_selection_array($primary_key_value, $field_info);
- }
- }
-
- return $values;
- }
-
- protected function get_relation_n_n_selection_array($primary_key_value, $field_info)
- {
- return $this->basic_model->get_relation_n_n_selection_array($primary_key_value, $field_info);
- }
-
- protected function get_relation_n_n_unselected_array($field_info, $selected_values)
- {
- return $this->basic_model->get_relation_n_n_unselected_array($field_info, $selected_values);
- }
-
- protected function set_basic_db_table($table_name = null)
- {
- $this->basic_model->set_basic_table($table_name);
- }
-
- protected function upload_file($state_info)
- {
- if(isset($this->upload_fields[$state_info->field_name]) )
- {
- if($this->callback_upload === null)
- {
- if($this->callback_before_upload !== null)
- {
- $callback_before_upload_response = call_user_func($this->callback_before_upload, $_FILES, $this->upload_fields[$state_info->field_name]);
-
- if($callback_before_upload_response === false)
- return false;
- elseif(is_string($callback_before_upload_response))
- return $callback_before_upload_response;
- }
-
- $upload_info = $this->upload_fields[$state_info->field_name];
-
- header('Pragma: no-cache');
- header('Cache-Control: private, no-cache');
- header('Content-Disposition: inline; filename="files.json"');
- header('X-Content-Type-Options: nosniff');
- header('Access-Control-Allow-Origin: *');
- header('Access-Control-Allow-Methods: OPTIONS, HEAD, GET, POST, PUT, DELETE');
- header('Access-Control-Allow-Headers: X-File-Name, X-File-Type, X-File-Size');
-
- $allowed_files = $this->config->file_upload_allow_file_types;
- $reg_exp = '/(\\.|\\/)('.$allowed_files.')$/i';
- $max_file_size_ui = $this->config->file_upload_max_file_size;
- $max_file_size_bytes = $this->_convert_bytes_ui_to_bytes($max_file_size_ui);
-
- $options = array(
- 'upload_dir' => $upload_info->upload_path.'/',
- 'param_name' => $this->_unique_field_name($state_info->field_name),
- 'upload_url' => base_url().$upload_info->upload_path.'/',
- 'accept_file_types' => $reg_exp,
- 'max_file_size' => $max_file_size_bytes
- );
- $upload_handler = new UploadHandler($options);
- $upload_handler->default_config_path = $this->default_config_path;
- $uploader_response = $upload_handler->post();
-
- if(is_array($uploader_response))
- {
- foreach($uploader_response as &$response)
- {
- unset($response->delete_url);
- unset($response->delete_type);
- }
- }
-
- if($this->callback_after_upload !== null)
- {
- $callback_after_upload_response = call_user_func($this->callback_after_upload, $uploader_response , $this->upload_fields[$state_info->field_name] , $_FILES );
-
- if($callback_after_upload_response === false)
- return false;
- elseif(is_string($callback_after_upload_response))
- return $callback_after_upload_response;
- elseif(is_array($callback_after_upload_response))
- $uploader_response = $callback_after_upload_response;
- }
-
- return $uploader_response;
- }
- else
- {
- $upload_response = call_user_func($this->callback_upload, $_FILES, $this->upload_fields[$state_info->field_name] );
- if($upload_response === false)
- {
- return false;
- }
- else
- {
- return $upload_response;
- }
- }
- }
- else
- {
- return false;
- }
- }
-
- protected function delete_file($state_info)
- {
-
- if(isset($state_info->field_name) && isset($this->upload_fields[$state_info->field_name]))
- {
- $upload_info = $this->upload_fields[$state_info->field_name];
-
- if(file_exists("{$upload_info->upload_path}/{$state_info->file_name}"))
- {
- if( unlink("{$upload_info->upload_path}/{$state_info->file_name}") )
- {
- $this->basic_model->db_file_delete($state_info->field_name, $state_info->file_name);
-
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- $this->basic_model->db_file_delete($state_info->field_name, $state_info->file_name);
- return true;
- }
- }
- else
- {
- return false;
- }
- }
- protected function ajax_relation($state_info)
- {
- if(!isset($this->relation[$state_info->field_name]))
- return false;
-
- list($field_name, $related_table, $related_field_title, $where_clause, $order_by) = $this->relation[$state_info->field_name];
-
- return $this->basic_model->get_ajax_relation_array($state_info->search, $field_name, $related_table, $related_field_title, $where_clause, $order_by);
- }
- }
- /**
- * PHP grocery CRUD
- *
- * LICENSE
- *
- * Grocery CRUD is released with dual licensing, using the GPL v3 (license-gpl3.txt) and the MIT license (license-mit.txt).
- * You don't have to do anything special to choose one license or the other and you don't have to notify anyone which license you are using.
- * Please see the corresponding license file for details of these licenses.
- * You are free to use, modify and distribute this software, but all copyright information must remain.
- *
- * @package grocery CRUD
- * @copyright Copyright (c) 2010 through 2012, John Skoumbourdis
- * @license https://github.com/scoumbourdis/grocery-crud/blob/master/license-grocery-crud.txt
- * @author John Skoumbourdis <scoumbourdisj@gmail.com>
- */
- // ------------------------------------------------------------------------
- /**
- * PHP grocery Layout
- *
- * Here you manage all the HTML Layout
- *
- * @package grocery CRUD
- * @author John Skoumbourdis <scoumbourdisj@gmail.com>
- * @version 1.3
- */
- class grocery_CRUD_Layout extends grocery_CRUD_Model_Driver
- {
- private $theme_path = null;
- private $views_as_string = '';
- private $echo_and_die = false;
- protected $theme = null;
- protected $default_true_false_text = array('inactive' , 'active');
-
- protected $css_files = array();
- protected $js_files = array();
-
- protected function set_basic_Layout()
- {
- if(!file_exists($this->theme_path.$this->theme.'/views/list_template.php'))
- {
- throw new Exception('The template does not exist. Please check your files and try again.', 12);
- die();
- }
- }
-
- protected function showList($ajax = false, $state_info = null)
- {
- $data = $this->get_common_data();
-
- $data->order_by = $this->order_by;
-
- $data->types = $this->get_field_types();
-
- $data->list = $this->get_list();
- $data->list = $this->change_list($data->list , $data->types);
- $data->list = $this->change_list_add_actions($data->list);
-
- $data->total_results = $this->get_total_results();
-
- $data->columns = $this->get_columns();
-
- $data->success_message = $this->get_success_message_at_list($state_info);
-
- $data->primary_key = $this->get_primary_key();
- $data->add_url = $this->getAddUrl();
- $data->edit_url = $this->getEditUrl();
- $data->delete_url = $this->getDeleteUrl();
- $data->ajax_list_url = $this->getAjaxListUrl();
- $data->ajax_list_info_url = $this->getAjaxListInfoUrl();
- $data->export_url = $this->getExportToExcelUrl();
- $data->print_url = $this->getPrintUrl();
- $data->actions = $this->actions;
- $data->unique_hash = $this->get_method_hash();
- $data->order_by = $this->order_by;
-
- $data->unset_add = $this->unset_add;
- $data->unset_edit = $this->unset_edit;
- $data->unset_delete = $this->unset_delete;
- $data->unset_export = $this->unset_export;
- $data->unset_print = $this->unset_print;
-
- $default_per_page = $this->config->default_per_page;
- $data->paging_options = array('10','25','50','100');
- $data->default_per_page = is_numeric($default_per_page) && $default_per_page >1 && in_array($default_per_page,$data->paging_options)? $default_per_page : 25;
-
- if($data->list === false)
- {
- throw new Exception('It is impossible to get data. Please check your model and try again.', 13);
- $data->list = array();
- }
-
- foreach($data->list as $num_row => $row)
- {
- $data->list[$num_row]->edit_url = $data->edit_url.'/'.$row->{$data->primary_key};
- $data->list[$num_row]->delete_url = $data->delete_url.'/'.$row->{$data->primary_key};
- }
-
- if(!$ajax)
- {
- $data->list_view = $this->_theme_view('list.php',$data,true);
- $this->_theme_view('list_template.php',$data);
- }
- else
- {
- $this->set_echo_and_die();
- $this->_theme_view('list.php',$data);
- }
- }
-
- protected function exportToExcel($state_info = null)
- {
- $data = $this->get_common_data();
-
- $data->order_by = $this->order_by;
- $data->types = $this->get_field_types();
-
- $data->list = $this->get_list();
- $data->list = $this->change_list($data->list , $data->types);
- $data->list = $this->change_list_add_actions($data->list);
-
- $data->total_results = $this->get_total_results();
-
- $data->columns = $this->get_columns();
- $data->primary_key = $this->get_primary_key();
-
- @ob_end_clean();
- $this->_export_to_excel($data);
- }
-
- protected function _export_to_excel($data)
- {
- /**
- * No need to use an external library here. The only bad thing without using external library is that Microsoft Excel is complaining
- * that the file is in a different format than specified by the file extension. If you press "Yes" everything will be just fine.
- * */
-
- $string_to_export = "";
- foreach($data->columns as $column){
- $string_to_export .= $column->display_as."\t";
- }
- $string_to_export .= "\n";
-
- foreach($data->list as $num_row => $row){
- foreach($data->columns as $column){
- $string_to_export .= $this->_trim_export_string($row->{$column->field_name})."\t";
- }
- $string_to_export .= "\n";
- }
-
- // Convert to UTF-16LE and Prepend BOM
- $string_to_export = "\xFF\xFE" .mb_convert_encoding($string_to_export, 'UTF-16LE', 'UTF-8');
-
- $filename = "export-".date("Y-m-d_H:i:s").".xls";
-
- header('Content-type: application/vnd.ms-excel;charset=UTF-16LE');
- header('Content-Disposition: attachment; filename='.$filename);
- header("Cache-Control: no-cache");
- echo $string_to_export;
- die();
- }
-
- protected function print_webpage($state_info = null)
- {
- $data = $this->get_common_data();
-
- $data->order_by = $this->order_by;
- $data->types = $this->get_field_types();
-
- $data->list = $this->get_list();
- $data->list = $this->change_list($data->list , $data->types);
- $data->list = $this->change_list_add_actions($data->list);
-
- $data->total_results = $this->get_total_results();
-
- $data->columns = $this->get_columns();
- $data->primary_key = $this->get_primary_key();
-
- @ob_end_clean();
- $this->_print_webpage($data);
- }
-
- protected function _print_webpage($data)
- {
- $string_to_print = "<meta charset=\"utf-8\" /><style type=\"text/css\" >
- #print-table{ color: #000; background: #fff; font-family: Verdana,Tahoma,Helvetica,sans-serif; font-size: 13px;}
- #print-table table tr td, #print-table table tr th{ border: 1px solid black; border-bottom: none; border-right: none; padding: 4px 8px 4px 4px}
- #print-table table{ border-bottom: 1px solid black; border-right: 1px solid black}
- #print-table table tr th{text-align: left;background: #ddd}
- #print-table table tr:nth-child(odd){background: #eee}
- </style>";
- $string_to_print .= "<div id='print-table'>";
-
- $string_to_print .= '<table width="100%" cellpadding="0" cellspacing="0" ><tr>';
- foreach($data->columns as $column){
- $string_to_print .= "<th>".$column->display_as."</th>";
- }
- $string_to_print .= "</tr>";
-
- foreach($data->list as $num_row => $row){
- $string_to_print .= "<tr>";
- foreach($data->columns as $column){
- $string_to_print .= "<td>".$this->_trim_print_string($row->{$column->field_name})."</td>";
- }
- $string_to_print .= "</tr>";
- }
-
- $string_to_print .= "</table></div>";
-
- echo $string_to_print;
- die();
- }
-
- protected function _trim_export_string($value)
- {
- $value = str_replace(array(" ","&",">","<"),array(" ","&",">","<"),$value);
- return strip_tags(str_replace(array("\t","\n","\r"),"",$value));
- }
-
- protected function _trim_print_string($value)
- {
- $value = str_replace(array(" ","&",">","<"),array(" ","&",">","<"),$value);
-
- //If the value has only spaces and nothing more then add the whitespace html character
- if(str_replace(" ","",$value) == "")
- $value = " ";
-
- return strip_tags($value);
- }
-
- protected function set_echo_and_die()
- {
- $this->echo_and_die = true;
- }
- protected function unset_echo_and_die()
- {
- $this->echo_and_die = false;
- }
-
- protected function showListInfo()
- {
- $this->set_echo_and_die();
-
- $total_results = (int)$this->get_total_results();
- @ob_end_clean();
- echo json_encode(array('total_results' => $total_results));
- die();
- }
-
- protected function change_list_add_actions($list)
- {
- if(empty($this->actions))
- return $list;
-
- $primary_key = $this->get_primary_key();
-
- foreach($list as $num_row => $row)
- {
- $actions_urls = array();
- foreach($this->actions as $unique_id => $action)
- {
- if(!empty($action->url_callback))
- {
- $actions_urls[$unique_id] = call_user_func($action->url_callback, $row->$primary_key, $row);
- }
- else
- {
- $actions_urls[$unique_id] =
- $action->url_has_http ?
- $action->link_url.$row->$primary_key :
- site_url($action->link_url.'/'.$row->$primary_key);
- }
- }
- $row->action_urls = $actions_urls;
- }
-
- return $list;
- }
-
- protected function change_list($list,$types)
- {
- $primary_key = $this->get_primary_key();
- $has_callbacks = !empty($this->callback_column) ? true : false;
- $output_columns = $this->get_columns();
- foreach($list as $num_row => $row)
- {
- foreach($output_columns as $column)
- {
- $field_name = $column->field_name;
- $field_value = isset( $row->{$column->field_name} ) ? $row->{$column->field_name} : null;
- if( $has_callbacks && isset($this->callback_column[$field_name]) )
- $list[$num_row]->$field_name = call_user_func($this->callback_column[$field_name], $field_value, $row);
- elseif(isset($types[$field_name]))
- $list[$num_row]->$field_name = $this->change_list_value($types[$field_name] , $field_value);
- else
- $list[$num_row]->$field_name = $field_value;
- }
- }
-
- return $list;
- }
-
- protected function showAddForm()
- {
- $this->set_js($this->default_javascript_path.'/'.grocery_CRUD::JQUERY);
-
- $data = $this->get_common_data();
- $data->types = $this->get_field_types();
-
- $data->list_url = $this->getListUrl();
- $data->insert_url = $this->getInsertUrl();
- $data->validation_url = $this->getValidationInsertUrl();
- $data->input_fields = $this->get_add_input_fields();
-
- $data->fields = $this->get_add_fields();
- $data->hidden_fields = $this->get_add_hidden_fields();
- $data->unset_back_to_list = $this->unset_back_to_list;
-
- $this->_theme_view('add.php',$data);
- $this->_inline_js("var js_date_format = '".$this->js_date_format."';");
- }
-
- protected function showEditForm($state_info)
- {
- $this->set_js($this->default_javascript_path.'/'.grocery_CRUD::JQUERY);
-
- $data = $this->get_common_data();
- $data->types = $this->get_field_types();
-
- $data->field_values = $this->get_edit_values($state_info->primary_key);
-
- $data->add_url = $this->getAddUrl();
-
- $data->list_url = $this->getListUrl();
- $data->update_url = $this->getUpdateUrl($state_info);
- $data->delete_url = $this->getDeleteUrl($state_info);
- $data->input_fields = $this->get_edit_input_fields($data->field_values);
- $data->fields = $this->get_edit_fields();
- $data->hidden_fields = $this->get_edit_hidden_fields();
- $data->unset_back_to_list = $this->unset_back_to_list;
-
- $data->validation_url = $this->getValidationUpdateUrl($state_info->primary_key);
-
- $this->_theme_view('edit.php',$data);
- $this->_inline_js("var js_date_format = '".$this->js_date_format."';");
- }
-
- protected function delete_layout($delete_result = true)
- {
- @ob_end_clean();
- if($delete_result === false)
- {
- $error_message = '<p>'.$this->l('delete_error_message').…
Large files files are truncated, but you can click here to view the full file