├── application ├── models │ ├── grocery_crud_model_mysql.php │ ├── grocery_crud_model_mysqli.php │ ├── grocery_crud_model_oci8.php │ ├── grocery_crud_model_odbc.php │ ├── grocery_crud_model_cubrid.php │ ├── grocery_crud_model_ibase.php │ ├── grocery_crud_model_mssql.php │ ├── grocery_crud_model_postgre.php │ ├── grocery_crud_model_sqlite.php │ ├── grocery_crud_model_sqlite3.php │ ├── grocery_crud_model_sqlsrv.php │ ├── grocery_crud_model_pdo.php │ └── grocery_crud_generic_model.php └── controllers │ └── examples.php ├── example_database └── sqlite_example_database.sqlite └── README.md /application/models/grocery_crud_model_mysql.php: -------------------------------------------------------------------------------- 1 | 'mysql:host=localhost;port=3306;dbname=test_database', 14 | 'hostname' => 'localhost', 15 | 'username' => 'root', 16 | 'password' => 'my_password', 17 | 'database' => 'test_database', 18 | 'dbdriver' => 'pdo', 19 | 'dbprefix' => '', 20 | 'pconnect' => TRUE, 21 | 'db_debug' => TRUE, 22 | 'cache_on' => FALSE, 23 | 'cachedir' => '', 24 | 'char_set' => 'utf8', 25 | 'dbcollat' => 'utf8_general_ci', 26 | 'swap_pre' => '', 27 | 'autoinit' => TRUE, 28 | 'encrypt' => FALSE, 29 | 'compress' => FALSE, 30 | 'stricton' => FALSE, 31 | 'failover' => array() 32 | ); 33 | ``` 34 | If you want to use sqlite, change your dsn into this `'sqlite:'.FCPATH.'example_database/sqlite_example_database.sqlite'` 35 | -------------------------------------------------------------------------------- /application/models/grocery_crud_model_pdo.php: -------------------------------------------------------------------------------- 1 | subdriver = $this->db->subdriver; 9 | // these drivers doesn't have CONCAT command 10 | if(in_array($this->subdriver, array('sqlite', 'pgsql'))){ 11 | $this->CAPABLE_CONCAT = FALSE; 12 | } 13 | } 14 | 15 | function get_primary_key($table_name = null) 16 | { 17 | // let's see what the parent can do 18 | $primary_key = parent::get_primary_key($table_name); 19 | if($primary_key !== FALSE){ 20 | return $primary_key; 21 | } 22 | 23 | // set default value for table_name if not set. 24 | if(!isset($table_name)){ 25 | $table_name = $this->table_name; 26 | } 27 | // postgre need this 28 | if($this->subdriver=='pgsql'){ 29 | $SQL = "SELECT 30 | pg_attribute.attname 31 | FROM pg_index, pg_class, pg_attribute 32 | WHERE 33 | pg_class.oid = '".$table_name."'::regclass AND 34 | indrelid = pg_class.oid AND 35 | pg_attribute.attrelid = pg_class.oid AND 36 | pg_attribute.attnum = any(pg_index.indkey);"; 37 | $query = $this->db->query($SQL); 38 | $row = $query->row(); 39 | $primary_key = $row->attname; 40 | } 41 | 42 | return $primary_key; 43 | } 44 | 45 | function get_field_types_basic_table() 46 | { 47 | $results = parent::get_field_types_basic_table(); 48 | if($this->subdriver == 'pgsql'){ 49 | $results = array_reverse($results); 50 | } 51 | return $results; 52 | } 53 | 54 | function build_db_join_relation($related_table, $unique_name, $related_primary_key, $field_name){ 55 | if($this->subdriver=='pgsql'){ 56 | $this->db->join( $this->protect_identifiers($related_table).' as '.$this->protect_identifiers($unique_name) , 57 | 'cast('.$this->protect_identifiers($unique_name.'.'.$related_primary_key).' as character varying) = cast('. $this->protect_identifiers($this->table_name.'.'.$field_name).' as character varying)', 'left', FALSE); 58 | 59 | }else{ 60 | parent::build_db_join_relation($related_table, $unique_name, $related_primary_key, $field_name); 61 | } 62 | } 63 | 64 | function build_relation_n_n_subquery($field, $selection_table, $relation_table, $primary_key_alias_to_selection_table, $primary_key_selection_table, $primary_key_alias_to_this_table, $field_name){ 65 | if($this->subdriver=='pgsql'){ 66 | return "(SELECT string_agg(".$this->protect_identifiers($field).", ',') FROM ".$this->protect_identifiers($selection_table) 67 | ." LEFT JOIN ".$this->protect_identifiers($relation_table)." ON ".$this->protect_identifiers($relation_table.".".$primary_key_alias_to_selection_table)." = ".$this->protect_identifiers($selection_table.".".$primary_key_selection_table) 68 | ." WHERE cast(".$this->protect_identifiers($relation_table.".".$primary_key_alias_to_this_table)." as character varying ) = cast(".$this->protect_identifiers($this->table_name.".".$this->get_primary_key())." as character varying ) GROUP BY ".$this->protect_identifiers($relation_table.".".$primary_key_alias_to_this_table).") AS ".$this->protect_identifiers($field_name); 69 | }else{ 70 | return parent::build_relation_n_n_subquery($field, $selection_table, $relation_table, $primary_key_alias_to_selection_table, $primary_key_selection_table, $primary_key_alias_to_this_table, $field_name); 71 | } 72 | } 73 | 74 | 75 | } -------------------------------------------------------------------------------- /application/controllers/examples.php: -------------------------------------------------------------------------------- 1 | load->database(); 10 | $this->load->helper('url'); 11 | } 12 | 13 | public function new_crud(){ 14 | $db_driver = $this->db->platform(); 15 | $model_name = 'grocery_crud_model_'.$db_driver; 16 | $model_alias = 'm'.substr(md5(rand()), 0, rand(4,15) ); 17 | 18 | unset($this->{$model_name}); 19 | $this->load->library('grocery_CRUD'); 20 | $crud = new Grocery_CRUD(); 21 | if (file_exists(APPPATH.'/models/'.$model_name.'.php')){ 22 | $this->load->model('grocery_crud_model'); 23 | $this->load->model('grocery_crud_generic_model'); 24 | $this->load->model($model_name,$model_alias); 25 | $crud->basic_model = $this->{$model_alias}; 26 | } 27 | return $crud; 28 | } 29 | 30 | public function _example_output($output = null) 31 | { 32 | $this->load->view('example.php',$output); 33 | } 34 | 35 | public function offices() 36 | { 37 | $crud = $this->new_crud(); 38 | $output = $crud->render(); 39 | 40 | $this->_example_output($output); 41 | } 42 | 43 | public function index() 44 | { 45 | $this->_example_output((object)array('output' => '' , 'js_files' => array() , 'css_files' => array())); 46 | } 47 | 48 | public function offices_management() 49 | { 50 | try{ 51 | $crud = $this->new_crud(); 52 | 53 | $crud->set_theme('datatables'); 54 | $crud->set_table('offices'); 55 | $crud->set_subject('Office'); 56 | $crud->required_fields('city'); 57 | $crud->columns('city','country','phone','addressLine1','postalCode'); 58 | 59 | $output = $crud->render(); 60 | 61 | $this->_example_output($output); 62 | 63 | }catch(Exception $e){ 64 | show_error($e->getMessage().' --- '.$e->getTraceAsString()); 65 | } 66 | } 67 | 68 | public function employees_management() 69 | { 70 | $crud = $this->new_crud(); 71 | 72 | $crud->set_theme('datatables'); 73 | $crud->set_table('employees'); 74 | $crud->set_relation('officeCode','offices','city'); 75 | $crud->display_as('officeCode','Office City'); 76 | $crud->set_subject('Employee'); 77 | 78 | $crud->required_fields('lastName'); 79 | 80 | $crud->set_field_upload('file_url','assets/uploads/files'); 81 | 82 | $output = $crud->render(); 83 | 84 | $this->_example_output($output); 85 | } 86 | 87 | public function customers_management() 88 | { 89 | $crud = $this->new_crud(); 90 | 91 | $crud->set_table('customers'); 92 | $crud->columns('customerName','contactLastName','phone','city','country','salesRepEmployeeNumber','creditLimit'); 93 | $crud->display_as('salesRepEmployeeNumber','from Employeer') 94 | ->display_as('customerName','Name') 95 | ->display_as('contactLastName','Last Name'); 96 | $crud->set_subject('Customer'); 97 | $crud->set_relation('salesRepEmployeeNumber','employees','lastName'); 98 | 99 | $output = $crud->render(); 100 | 101 | $this->_example_output($output); 102 | } 103 | 104 | public function orders_management() 105 | { 106 | $crud = $this->new_crud(); 107 | 108 | $crud->set_relation('customerNumber','customers','{contactLastName} {contactFirstName}'); 109 | $crud->display_as('customerNumber','Customer'); 110 | $crud->set_table('orders'); 111 | $crud->set_subject('Order'); 112 | $crud->unset_add(); 113 | $crud->unset_delete(); 114 | 115 | $output = $crud->render(); 116 | 117 | $this->_example_output($output); 118 | } 119 | 120 | public function products_management() 121 | { 122 | $crud = $this->new_crud(); 123 | 124 | $crud->set_table('products'); 125 | $crud->set_subject('Product'); 126 | $crud->unset_columns('productDescription'); 127 | $crud->callback_column('buyPrice',array($this,'valueToEuro')); 128 | 129 | $output = $crud->render(); 130 | 131 | $this->_example_output($output); 132 | } 133 | 134 | public function valueToEuro($value, $row) 135 | { 136 | return $value.' €'; 137 | } 138 | 139 | public function film_management() 140 | { 141 | $crud = $this->new_crud(); 142 | 143 | $crud->set_table('film'); 144 | $crud->set_relation_n_n('actors', 'film_actor', 'actor', 'film_id', 'actor_id', 'fullname','priority'); 145 | $crud->set_relation_n_n('category', 'film_category', 'category', 'film_id', 'category_id', 'name'); 146 | $crud->unset_columns('special_features','description','actors'); 147 | 148 | $crud->fields('title', 'description', 'actors' , 'category' ,'release_year', 'rental_duration', 'rental_rate', 'length', 'replacement_cost', 'rating', 'special_features'); 149 | 150 | $output = $crud->render(); 151 | 152 | $this->_example_output($output); 153 | } 154 | 155 | public function film_management_twitter_bootstrap() 156 | { 157 | try{ 158 | $crud = $this->new_crud(); 159 | 160 | $crud->set_theme('twitter-bootstrap'); 161 | $crud->set_table('film'); 162 | $crud->set_relation_n_n('actors', 'film_actor', 'actor', 'film_id', 'actor_id', 'fullname','priority'); 163 | $crud->set_relation_n_n('category', 'film_category', 'category', 'film_id', 'category_id', 'name'); 164 | $crud->unset_columns('special_features','description','actors'); 165 | 166 | $crud->fields('title', 'description', 'actors' , 'category' ,'release_year', 'rental_duration', 'rental_rate', 'length', 'replacement_cost', 'rating', 'special_features'); 167 | 168 | $output = $crud->render(); 169 | $this->_example_output($output); 170 | 171 | }catch(Exception $e){ 172 | show_error($e->getMessage().' --- '.$e->getTraceAsString()); 173 | } 174 | } 175 | 176 | function multigrids() 177 | { 178 | $this->config->load('grocery_crud'); 179 | $this->config->set_item('grocery_crud_dialog_forms',true); 180 | $this->config->set_item('grocery_crud_default_per_page',10); 181 | 182 | $output1 = $this->offices_management2(); 183 | 184 | $output2 = $this->employees_management2(); 185 | 186 | $output3 = $this->customers_management2(); 187 | 188 | $js_files = $output1->js_files + $output2->js_files + $output3->js_files; 189 | $css_files = $output1->css_files + $output2->css_files + $output3->css_files; 190 | $output = "

List 1

".$output1->output."

List 2

".$output2->output."

List 3

".$output3->output; 191 | 192 | $this->_example_output((object)array( 193 | 'js_files' => $js_files, 194 | 'css_files' => $css_files, 195 | 'output' => $output 196 | )); 197 | } 198 | 199 | public function offices_management2() 200 | { 201 | $crud = $this->new_crud(); 202 | $crud->set_table('offices'); 203 | $crud->set_subject('Office'); 204 | $crud->required_fields('city'); 205 | $crud->columns('city','country','phone','addressLine1','postalCode'); 206 | 207 | $crud->set_crud_url_path(site_url(strtolower(__CLASS__."/".__FUNCTION__)),site_url(strtolower(__CLASS__."/multigrids"))); 208 | 209 | $output = $crud->render(); 210 | 211 | if($crud->getState() != 'list') { 212 | $this->_example_output($output); 213 | } else { 214 | return $output; 215 | } 216 | } 217 | 218 | public function employees_management2() 219 | { 220 | $crud = $this->new_crud(); 221 | 222 | $crud->set_theme('datatables'); 223 | $crud->set_table('employees'); 224 | $crud->set_relation('officeCode','offices','city'); 225 | $crud->display_as('officeCode','Office City'); 226 | $crud->set_subject('Employee'); 227 | 228 | $crud->required_fields('lastName'); 229 | 230 | $crud->set_field_upload('file_url','assets/uploads/files'); 231 | 232 | $crud->set_crud_url_path(site_url(strtolower(__CLASS__."/".__FUNCTION__)),site_url(strtolower(__CLASS__."/multigrids"))); 233 | 234 | $output = $crud->render(); 235 | 236 | if($crud->getState() != 'list') { 237 | $this->_example_output($output); 238 | } else { 239 | return $output; 240 | } 241 | } 242 | 243 | public function customers_management2() 244 | { 245 | 246 | $crud = $this->new_crud(); 247 | 248 | $crud->set_table('customers'); 249 | $crud->columns('customerName','contactLastName','phone','city','country','salesRepEmployeeNumber','creditLimit'); 250 | $crud->display_as('salesRepEmployeeNumber','from Employeer') 251 | ->display_as('customerName','Name') 252 | ->display_as('contactLastName','Last Name'); 253 | $crud->set_subject('Customer'); 254 | $crud->set_relation('salesRepEmployeeNumber','employees','lastName'); 255 | 256 | $crud->set_crud_url_path(site_url(strtolower(__CLASS__."/".__FUNCTION__)),site_url(strtolower(__CLASS__."/multigrids"))); 257 | 258 | $output = $crud->render(); 259 | 260 | if($crud->getState() != 'list') { 261 | $this->_example_output($output); 262 | } else { 263 | return $output; 264 | } 265 | } 266 | 267 | } -------------------------------------------------------------------------------- /application/models/grocery_crud_generic_model.php: -------------------------------------------------------------------------------- 1 | protect_identifiers('t'); 11 | $first_char = substr($test,0,1); 12 | if($first_char !== 't'){ 13 | $this->ESCAPE_CHAR = $first_char; 14 | } 15 | } 16 | 17 | public function protect_identifiers($value) 18 | { 19 | return $this->db->protect_identifiers($value); 20 | } 21 | 22 | // rather than mess around with this everytime, it is better to build a function for this. 23 | public function build_concat_from_template($template, $prefix_replacement='', $suffix_replacement='', $as=NULL){ 24 | if($this->CAPABLE_CONCAT){ 25 | // if CONCAT is possible in the current driver 26 | $concat_str = 27 | "CONCAT('". 28 | str_replace( 29 | array( 30 | "{", 31 | "}" 32 | ), 33 | array( 34 | "',COALESCE(".$prefix_replacement, 35 | $suffix_replacement.", ''),'" 36 | ), 37 | str_replace("'","\\'",$template) 38 | ). 39 | "')"; 40 | 41 | }else{ 42 | // if CONCAT is impossible in the current driver, use || instead 43 | $concat_str = 44 | "('". 45 | str_replace( 46 | array( 47 | "{", 48 | "}" 49 | ), 50 | array( 51 | "' || COALESCE(".$replacement, 52 | ", '') || '" 53 | ), 54 | str_replace("'","\\'",$template) 55 | ). 56 | "')"; 57 | } 58 | if(isset($as)){ 59 | $concat_str .= " as ".$as; 60 | } 61 | 62 | } 63 | 64 | function get_list() 65 | { 66 | if($this->table_name === null) 67 | return false; 68 | 69 | $select = $this->protect_identifiers("{$this->table_name}").".*"; 70 | 71 | // this variable is used to save table.column info since postgresql doesn't support "AS 'table.column'" syntax 72 | $additional_fields = array(); 73 | //set_relation special queries 74 | if(!empty($this->relation)) 75 | { 76 | foreach($this->relation as $relation) 77 | { 78 | list($field_name , $related_table , $related_field_title) = $relation; 79 | $unique_join_name = $this->_unique_join_name($field_name); 80 | $unique_field_name = $this->_unique_field_name($field_name); 81 | 82 | if(strstr($related_field_title,'{')) 83 | { 84 | $related_field_title = str_replace(" "," ",$related_field_title); 85 | $select .= ", ".$this->build_concat_from_template( 86 | $related_field_title, 87 | $this->protect_identifiers($unique_join_name).".".$this->ESCAPE_CHAR, 88 | $this->ESCAPE_CHAR, 89 | $this->protect_identifiers($unique_field_name) 90 | ); 91 | //$select .= ", CONCAT('".str_replace(array('{','}'),array("',COALESCE(".$this->protect_identifiers($unique_join_name).".".$this->ESCAPE_CHAR, $this->ESCAPE_CHAR.", ''),'"),str_replace("'","\\'",$related_field_title))."') as ".$this->protect_identifiers($unique_field_name); 92 | } 93 | else 94 | { 95 | $select .= ', ' . $this->protect_identifiers($unique_join_name. '.'. $related_field_title).' AS '. $this->protect_identifiers($unique_field_name); 96 | } 97 | 98 | if($this->field_exists($related_field_title)){ 99 | $additional_fields[$this->table_name. '.'. $related_field_title] = $related_field_title; 100 | // this syntax doesn't work on postgresql 101 | //$select .= ', '.$this->protect_identifiers($this->table_name. '.'. $related_field_title).' AS \''.$this->table_name. '.'. $related_field_title.'\''; 102 | } 103 | 104 | } 105 | } 106 | 107 | //set_relation_n_n special queries. We prefer sub queries from a simple join for the relation_n_n as it is faster and more stable on big tables. 108 | if(!empty($this->relation_n_n)) 109 | { 110 | $select = $this->relation_n_n_queries($select); 111 | } 112 | 113 | $this->db->select($select, false); 114 | 115 | $results = $this->db->get($this->table_name)->result(); 116 | 117 | // add information from additional_fields 118 | for($i=0; $i$real_field){ 120 | $results[$i]->{$alias} = $results[$i]->{$real_field}; 121 | } 122 | } 123 | 124 | return $results; 125 | } 126 | 127 | protected function relation_n_n_queries($select) 128 | { 129 | $this_table_primary_key = $this->get_primary_key(); 130 | foreach($this->relation_n_n as $relation_n_n) 131 | { 132 | list($field_name, $relation_table, $selection_table, $primary_key_alias_to_this_table, 133 | $primary_key_alias_to_selection_table, $title_field_selection_table, $priority_field_relation_table) = array_values((array)$relation_n_n); 134 | 135 | $primary_key_selection_table = $this->get_primary_key($selection_table); 136 | 137 | $field = ""; 138 | $use_template = strpos($title_field_selection_table,'{') !== false; 139 | $field_name_hash = $this->_unique_field_name($title_field_selection_table); 140 | if($use_template) 141 | { 142 | $title_field_selection_table = str_replace(" ", " ", $title_field_selection_table); 143 | $field .= $this->build_concat_from_template($this->protect_identifiers($title_field_selection_table)); 144 | //$field .= "CONCAT('".str_replace(array('{','}'),array("',COALESCE(",", ''),'"),str_replace("'","\\'",$this->protect_identifiers($title_field_selection_table)))."')"; 145 | } 146 | else 147 | { 148 | $field .= $this->protect_identifiers($selection_table.'.'.$title_field_selection_table); 149 | } 150 | 151 | //Sorry Codeigniter but you cannot help me with the subquery! 152 | $select .= ", ". 153 | $this->build_relation_n_n_subquery($field, $selection_table, $relation_table, $primary_key_alias_to_selection_table, $primary_key_selection_table, $primary_key_alias_to_this_table, $field_name); 154 | } 155 | 156 | return $select; 157 | } 158 | 159 | function get_total_results() 160 | { 161 | //set_relation_n_n special queries. We prefer sub queries from a simple join for the relation_n_n as it is faster and more stable on big tables. 162 | if(!empty($this->relation_n_n)) 163 | { 164 | $select = $this->protect_identifiers($this->table_name).'.'.'*'; 165 | $select = $this->relation_n_n_queries($select); 166 | 167 | $this->db->select($select,false); 168 | 169 | return $this->db->get($this->table_name)->num_rows(); 170 | } 171 | 172 | return $this->db->count_all_results($this->table_name); 173 | } 174 | 175 | function join_relation($field_name , $related_table , $related_field_title) 176 | { 177 | $related_primary_key = $this->get_primary_key($related_table); 178 | 179 | if($related_primary_key !== false) 180 | { 181 | $unique_name = $this->_unique_join_name($field_name); 182 | $this->build_db_join_relation($related_table, $unique_name, $related_primary_key, $field_name); 183 | 184 | $this->relation[$field_name] = array($field_name , $related_table , $related_field_title); 185 | 186 | return true; 187 | } 188 | 189 | return false; 190 | } 191 | 192 | function get_relation_array($field_name , $related_table , $related_field_title, $where_clause, $order_by, $limit = null, $search_like = null) 193 | { 194 | $relation_array = array(); 195 | $field_name_hash = $this->_unique_field_name($field_name); 196 | 197 | $related_primary_key = $this->get_primary_key($related_table); 198 | 199 | $select = $this->protect_identifiers($related_table).'.'.$this->protect_identifiers($related_primary_key).', '; 200 | 201 | if(strstr($related_field_title,'{')) 202 | { 203 | $related_field_title = str_replace(" ", " ", $related_field_title); 204 | $select .= $this->build_concat_from_template( 205 | $related_field_title, 206 | $this->ESCAPE_CHAR, 207 | $this->ESCAPE_CHAR, 208 | $this->protect_identifiers($field_name_hash) 209 | ); 210 | //$select .= "CONCAT('".str_replace(array('{','}'),array("',COALESCE(".$this->ESCAPE_CHAR , $this->ESCAPE_CHAR.", ''),'"),str_replace("'","\\'", $related_field_title))."') as ".$this->protect_identifiers($field_name_hash); 211 | } 212 | else 213 | { 214 | $select .= $this->protect_identifiers($related_table.'.'.$related_field_title).' as '.$this->protect_identifiers($field_name_hash); 215 | } 216 | 217 | $this->db->select($select,false); 218 | if($where_clause !== null) 219 | $this->db->where($where_clause); 220 | 221 | if($where_clause !== null) 222 | $this->db->where($where_clause); 223 | 224 | if($limit !== null) 225 | $this->db->limit($limit); 226 | 227 | if($search_like !== null) 228 | $this->db->having($this->protect_identifiers($field_name_hash)." LIKE '%".$this->db->escape_like_str($search_like)."%'"); 229 | 230 | $order_by !== null 231 | ? $this->db->order_by($order_by) 232 | : $this->db->order_by($field_name_hash); 233 | 234 | $results = $this->db->get($related_table)->result(); 235 | 236 | foreach($results as $row) 237 | { 238 | $relation_array[$row->$related_primary_key] = $row->$field_name_hash; 239 | } 240 | 241 | return $relation_array; 242 | } 243 | 244 | function get_relation_n_n_selection_array($primary_key_value, $field_info) 245 | { 246 | $select = ""; 247 | $related_field_title = $field_info->title_field_selection_table; 248 | $use_template = strpos($related_field_title,'{') !== false;; 249 | $field_name_hash = $this->_unique_field_name($related_field_title); 250 | if($use_template) 251 | { 252 | $related_field_title = str_replace(" ", " ", $related_field_title); 253 | $select .= $this->build_concat_from_template( 254 | $related_field_title, 255 | $this->ESCAPE_CHAR, 256 | $this->ESCAPE_CHAR, 257 | $this->protect_identifiers($field_name_hash) 258 | ); 259 | //$select .= "CONCAT('".str_replace(array('{','}'),array("',COALESCE(",", ''),'"),str_replace("'","\\'",$related_field_title))."') as $field_name_hash"; 260 | } 261 | else 262 | { 263 | $select .= "$related_field_title as $field_name_hash"; 264 | } 265 | $this->db->select('*, '.$select,false); 266 | 267 | $selection_primary_key = $this->get_primary_key($field_info->selection_table); 268 | 269 | if(empty($field_info->priority_field_relation_table)) 270 | { 271 | if(!$use_template){ 272 | $this->db->order_by("{$field_info->selection_table}.{$field_info->title_field_selection_table}"); 273 | } 274 | } 275 | else 276 | { 277 | $this->db->order_by("{$field_info->relation_table}.{$field_info->priority_field_relation_table}"); 278 | } 279 | $this->db->where($field_info->primary_key_alias_to_this_table, $primary_key_value); 280 | $this->db->join( 281 | $field_info->selection_table, 282 | "{$field_info->relation_table}.{$field_info->primary_key_alias_to_selection_table} = {$field_info->selection_table}.{$selection_primary_key}" 283 | ); 284 | $results = $this->db->get($field_info->relation_table)->result(); 285 | 286 | $results_array = array(); 287 | foreach($results as $row) 288 | { 289 | $results_array[$row->{$field_info->primary_key_alias_to_selection_table}] = $row->{$field_name_hash}; 290 | } 291 | 292 | return $results_array; 293 | } 294 | 295 | function get_relation_n_n_unselected_array($field_info, $selected_values) 296 | { 297 | $use_where_clause = !empty($field_info->where_clause); 298 | 299 | $select = ""; 300 | $related_field_title = $field_info->title_field_selection_table; 301 | $use_template = strpos($related_field_title,'{') !== false; 302 | $field_name_hash = $this->_unique_field_name($related_field_title); 303 | 304 | if($use_template) 305 | { 306 | $related_field_title = str_replace(" ", " ", $related_field_title); 307 | $select .= $this->build_concat_from_template( 308 | $related_field_title, 309 | $this->ESCAPE_CHAR, 310 | $this->ESCAPE_CHAR, 311 | $this->protect_identifiers($field_name_hash) 312 | ); 313 | //$select .= "CONCAT('".str_replace(array('{','}'),array("',COALESCE(",", ''),'"),str_replace("'","\\'",$related_field_title))."') as $field_name_hash"; 314 | } 315 | else 316 | { 317 | $select .= "$related_field_title as $field_name_hash"; 318 | } 319 | $this->db->select('*, '.$select,false); 320 | 321 | if($use_where_clause){ 322 | $this->db->where($field_info->where_clause); 323 | } 324 | 325 | $selection_primary_key = $this->get_primary_key($field_info->selection_table); 326 | if(!$use_template) 327 | $this->db->order_by("{$field_info->selection_table}.{$field_info->title_field_selection_table}"); 328 | $results = $this->db->get($field_info->selection_table)->result(); 329 | 330 | $results_array = array(); 331 | foreach($results as $row) 332 | { 333 | if(!isset($selected_values[$row->$selection_primary_key])) 334 | $results_array[$row->$selection_primary_key] = $row->{$field_name_hash}; 335 | } 336 | 337 | return $results_array; 338 | } 339 | 340 | function get_field_types_basic_table() 341 | { 342 | $db_field_types = array(); 343 | foreach($this->get_field_types($this->table_name) as $db_field_type) 344 | { 345 | $db_type = $db_field_type->type; 346 | $length = $db_field_type->max_length; 347 | $db_field_types[$db_field_type->name]['db_max_length'] = $length; 348 | $db_field_types[$db_field_type->name]['db_type'] = $db_type; 349 | $db_field_types[$db_field_type->name]['db_null'] = true; 350 | $db_field_types[$db_field_type->name]['db_extra'] = ''; 351 | } 352 | 353 | $results = $this->get_field_types($this->table_name); 354 | foreach($results as $num => $row) 355 | { 356 | $row = (array)$row; 357 | $results[$num] = (object)( array_merge($row, $db_field_types[$row['name']]) ); 358 | } 359 | return $results; 360 | } 361 | 362 | function get_field_types($table_name) 363 | { 364 | $results = $this->db->field_data($table_name); 365 | // some driver doesn't provide primary_key information 366 | foreach($results as $num => $row) 367 | { 368 | $row = (array)$row; 369 | if(!array_key_exists('primary_key', $row)){ 370 | $results[$num]->primary_key = 0; 371 | } 372 | } 373 | return $results; 374 | } 375 | 376 | function db_insert($post_array) 377 | { 378 | $insert = $this->db->insert($this->table_name,$post_array); 379 | if($insert) 380 | { 381 | $primary_key = $this->get_primary_key(); 382 | // if user already define a value for the primary key, then just return it 383 | // postgresql use LASTVAL() to retrieve insert_id which would cause an error if the sequence is not used. 384 | if(array_key_exists($primary_key, $post_array)){ 385 | return $post_array[$primary_key]; 386 | } 387 | return $this->db->insert_id(); 388 | } 389 | return false; 390 | } 391 | 392 | function build_db_join_relation($related_table, $unique_name, $related_primary_key, $field_name){ 393 | $this->db->join($this->protect_identifiers($related_table).' as '.$this->protect_identifiers($unique_name) , $this->protect_identifiers($unique_name.'.'.$related_primary_key).' = '. $this->protect_identifiers($this->table_name.'.'.$field_name),'left'); 394 | } 395 | 396 | function build_relation_n_n_subquery($field, $selection_table, $relation_table, $primary_key_alias_to_selection_table, $primary_key_selection_table, $primary_key_alias_to_this_table, $field_name){ 397 | return "(SELECT GROUP_CONCAT(DISTINCT ".$this->protect_identifiers($field).") FROM ".$this->protect_identifiers($selection_table) 398 | ." LEFT JOIN ".$this->protect_identifiers($relation_table)." ON ".$this->protect_identifiers($relation_table.".".$primary_key_alias_to_selection_table)." = ".$this->protect_identifiers($selection_table.".".$primary_key_selection_table) 399 | ." WHERE ".$this->protect_identifiers($relation_table.".".$primary_key_alias_to_this_table)." = ".$this->protect_identifiers($this->table_name.".".$this->get_primary_key($this->table_name))." GROUP BY ".$this->protect_identifiers($relation_table.".".$primary_key_alias_to_this_table).") AS ".$this->protect_identifiers($field_name); 400 | } 401 | 402 | function db_delete($primary_key_value) 403 | { 404 | $primary_key_field = $this->get_primary_key(); 405 | 406 | if($primary_key_field === false) 407 | return false; 408 | 409 | $this->db->delete($this->table_name,array( $primary_key_field => $primary_key_value)); 410 | if( $this->db->affected_rows() != 1) 411 | return false; 412 | else 413 | return true; 414 | } 415 | 416 | function field_exists($field,$table_name = null) 417 | { 418 | if(empty($table_name)) 419 | { 420 | $table_name = $this->table_name; 421 | } 422 | 423 | // sqlite doesn't support this $this->db->field_exists($field,$table_name) 424 | $field_data_list = $this->db->field_data($table_name); 425 | foreach($field_data_list as $field_data){ 426 | if($field_data->name == $field) return TRUE; 427 | } 428 | return FALSE; 429 | } 430 | 431 | function get_edit_values($primary_key_value) 432 | { 433 | $result = parent::get_edit_values($primary_key_value); 434 | // some driver like postgresql doesn't return string 435 | foreach($result as $key => $value) { 436 | $result->$key = (string)$value; 437 | } 438 | return $result; 439 | } 440 | 441 | } 442 | --------------------------------------------------------------------------------