Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added datamapper

Signed-off-by: Purwandi <free6300@gmail.com>
  • Loading branch information...
commit 06e5800a9b487102e057b14ef5db6b7225f01dd4 1 parent b224b84
Purwandi purwandi authored

Showing 29 changed files with 10,634 additions and 50 deletions. Show diff stats Hide diff stats

  1. +83 0 _assets/css/body.css
  2. +2 2 application/config/autoload.php
  3. +3 3 application/config/database.php
  4. +36 0 application/config/datamapper.php
  5. +28 0 application/controllers/login.php
  6. +0 1  application/core/MY_Controller.php
  7. +53 0 application/core/MY_Model.php
  8. +221 0 application/extensions/array.php
  9. +225 0 application/extensions/csv.php
  10. +798 0 application/extensions/htmlform.php
  11. +227 0 application/extensions/json.php
  12. +1,397 0 application/extensions/nestedsets.php
  13. +211 0 application/extensions/rowindex.php
  14. +70 0 application/extensions/simplecache.php
  15. +76 0 application/extensions/translate.php
  16. +6,677 0 application/libraries/datamapper.php
  17. +5 26 application/models/auth_m.php
  18. +11 0 application/models/user_gas.php
  19. +90 0 application/third_party/datamapper/bootstrap.php
  20. +162 0 application/third_party/datamapper/system/DB.php
  21. +71 0 application/third_party/datamapper/system/DB_driver.php
  22. +41 0 application/third_party/datamapper/system/Lang.php
  23. +65 0 application/third_party/datamapper/system/Loader.php
  24. +5 11 application/views/layouts/default.php
  25. +5 6 application/views/layouts/footer.php
  26. +27 0 application/views/layouts/navbar.php
  27. +19 0 application/views/login/index.php
  28. +19 0 application/views/welcome/index.php
  29. +7 1 index.php
83 _assets/css/body.css
... ... @@ -0,0 +1,83 @@
  1 +/* Body and structure
  2 +-------------------------------------------------- */
  3 +body {
  4 + position: relative;
  5 + padding-top: 60px;
  6 + background-color: #fff;
  7 +}
  8 +
  9 +/* Faded out hr */
  10 +hr.soften {
  11 + height: 1px;
  12 + margin: 54px 0;
  13 + background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
  14 + background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
  15 + background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
  16 + background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
  17 + border: 0;
  18 +}
  19 +
  20 +/* Tweak navbar brand link to be super sleek
  21 +-------------------------------------------------- */
  22 +.navbar-fixed-top .brand {
  23 + padding-right: 0;
  24 + padding-left: 0;
  25 + margin: 0 auto;
  26 + font-weight: bold;
  27 + color: #000;
  28 + text-shadow: 0 1px 0 rgba(255,255,255,.1), 0 0 30px rgba(255,255,255,.125);
  29 + -webkit-transition: all .2s linear;
  30 + -moz-transition: all .2s linear;
  31 + transition: all .2s linear;
  32 +}
  33 +.navbar-fixed-top .brand:hover {
  34 + text-decoration: none;
  35 +}
  36 +
  37 +
  38 +/* Welcome
  39 +-------------------------------------------------- */
  40 +/* Masthead (docs home) */
  41 +.masthead {
  42 + padding-top: 36px;
  43 + margin-bottom: 72px;
  44 +}
  45 +.masthead h1 {
  46 + margin-bottom: 9px;
  47 + font-size: 81px;
  48 + font-weight: bold;
  49 + letter-spacing: -1px;
  50 + line-height: 1;
  51 +}
  52 +.masthead h1,
  53 +.masthead p {
  54 + text-align: center;
  55 +}
  56 +.masthead h1 {
  57 + margin-bottom: 18px;
  58 +}
  59 +.masthead p {
  60 + margin-left: 5%;
  61 + margin-right: 5%;
  62 + font-size: 30px;
  63 + line-height: 36px;
  64 +}
  65 +
  66 +/* marketing
  67 +-------------------------------------------------- */
  68 +.marketing p {
  69 + text-align: center;
  70 +}
  71 +
  72 +/* Footer
  73 +-------------------------------------------------- */
  74 +.footer {
  75 + margin-top: 45px;
  76 + padding: 10px 0 36px;
  77 + border-top: 1px solid #e5e5e5;
  78 +}
  79 +.footer p {
  80 + font-size: 12px;
  81 + margin-bottom: 0;
  82 + color: #555;
  83 +}
4 application/config/autoload.php
@@ -78,7 +78,7 @@
78 78 | $autoload['libraries'] = array('database', 'session', 'xmlrpc');
79 79 */
80 80
81   -$autoload['libraries'] = array();
  81 +$autoload['libraries'] = array('session','database');
82 82
83 83
84 84 /*
@@ -135,7 +135,7 @@
135 135 |
136 136 */
137 137
138   -$autoload['model'] = array();
  138 +$autoload['model'] = array('auth_m');
139 139
140 140
141 141 /* End of file autoload.php */
6 application/config/database.php
@@ -77,9 +77,9 @@
77 77
78 78 $db['default']['dsn'] = '';
79 79 $db['default']['hostname'] = 'localhost';
80   -$db['default']['username'] = '';
81   -$db['default']['password'] = '';
82   -$db['default']['database'] = '';
  80 +$db['default']['username'] = 'root';
  81 +$db['default']['password'] = 'neki';
  82 +$db['default']['database'] = 'wiki_codeigniter';
83 83 $db['default']['dbdriver'] = 'mysql';
84 84 $db['default']['dbprefix'] = '';
85 85 $db['default']['pconnect'] = FALSE;
36 application/config/datamapper.php
... ... @@ -0,0 +1,36 @@
  1 +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2 +
  3 +/**
  4 + * Data Mapper Configuration
  5 + *
  6 + * Global configuration settings that apply to all DataMapped models.
  7 + */
  8 +
  9 +$config['prefix'] = '';
  10 +$config['join_prefix'] = '';
  11 +$config['error_prefix'] = '<p>';
  12 +$config['error_suffix'] = '</p>';
  13 +$config['created_field'] = 'created';
  14 +$config['updated_field'] = 'updated';
  15 +$config['local_time'] = FALSE;
  16 +$config['unix_timestamp'] = FALSE;
  17 +$config['timestamp_format'] = '';
  18 +$config['lang_file_format'] = 'model_${model}';
  19 +$config['field_label_lang_format'] = '${model}_${field}';
  20 +$config['auto_transaction'] = FALSE;
  21 +$config['auto_populate_has_many'] = FALSE;
  22 +$config['auto_populate_has_one'] = FALSE;
  23 +$config['all_array_uses_ids'] = FALSE;
  24 +
  25 +// set to FALSE to use the same DB instance across the board (breaks subqueries)
  26 +// Set to any acceptable parameters to $CI->database() to override the default.
  27 +$config['db_params'] = '';
  28 +
  29 +// Uncomment to enable the production cache
  30 +// $config['production_cache'] = APPPATH.'cache';
  31 +
  32 +$config['extensions_path'] = '../extensions';
  33 +$config['extensions'] = array();
  34 +
  35 +/* End of file datamapper.php */
  36 +/* Location: ./sparks/Datamapper-ORM/config/datamapper.php */
28 application/controllers/login.php
... ... @@ -0,0 +1,28 @@
  1 +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2 +
  3 +class Login extends MY_Controller{
  4 +
  5 + protected $module = 'login';
  6 +
  7 + public function index ()
  8 + {
  9 + if ($_POST)
  10 + {
  11 + $this->form_validation->set_rules('username','Username','trim|required');
  12 + $this->form_validation->set_rules('password','Password','trim|required');
  13 +
  14 + if ($this->form_validation->run())
  15 + {
  16 + if ($this->auth_m->login())
  17 + {
  18 + setSucces('User finded');
  19 + }
  20 + else
  21 + {
  22 + setError('User not found');
  23 + }
  24 + }
  25 + }
  26 + parent :: index ();
  27 + }
  28 +}
1  application/core/MY_Controller.php
@@ -33,7 +33,6 @@ public function __construct ()
33 33
34 34 // load spark
35 35 $this->load->spark('template/1.9.0');
36   -
37 36
38 37 $this->method = ucwords(preg_replace('/[_]+/', ' ', strtolower(trim($this->router->fetch_method()))));
39 38
53 application/core/MY_Model.php
... ... @@ -0,0 +1,53 @@
  1 +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2 +
  3 +class MY_Model extends CI_Model {
  4 +
  5 + public $table = '';
  6 + public $primary_key = '';
  7 + public $fields = array();
  8 +
  9 + public function valid ($ignoreField = FALSE)
  10 + {
  11 + foreach ($this->fields as $key=>$values)
  12 + {
  13 + if (is_array($ignoreField) && in_array($key,$ignoreField)) continue;
  14 +
  15 + $rules = 'trim';
  16 +
  17 + if (count($values) > 1)
  18 + {
  19 + if ( $values[1] ) $rules .= '|required';
  20 + if ( isset($values[2]) ) $rules .= '|'.$values[2];
  21 + }
  22 + $this->form_validation->set_rules($key, $values[0], $rules);
  23 + }
  24 + return $this->form_validation->run();
  25 + }
  26 +
  27 + /**
  28 + * Save and Edit Record
  29 + *
  30 + * @access public
  31 + * @param string
  32 + * @return object
  33 + */
  34 + public function save ($id = FALSE)
  35 + {
  36 + foreach ($this->fields as $key=>$values)
  37 + {
  38 + $this->db->set($key,$this->input->post($key));
  39 + }
  40 +
  41 + if ( ! empty($id))
  42 + {
  43 + $this->db->where($this->idx,$id);
  44 + $this->db->update($this->tableName);
  45 + }
  46 +
  47 + else
  48 + {
  49 + $this->db->insert($this->tableName);
  50 + }
  51 + return ($this->db->affected_rows() == 1);
  52 + }
  53 +}
221 application/extensions/array.php
... ... @@ -0,0 +1,221 @@
  1 +<?php
  2 +
  3 +/**
  4 + * Array Extension for DataMapper classes.
  5 + *
  6 + * Quickly convert DataMapper models to-and-from PHP arrays.
  7 + *
  8 + * @license MIT License
  9 + * @package DMZ-Included-Extensions
  10 + * @category DMZ
  11 + * @author Phil DeJarnett
  12 + * @link http://www.overzealous.com/dmz/pages/extensions/array.html
  13 + * @version 1.0
  14 + */
  15 +
  16 +// --------------------------------------------------------------------------
  17 +
  18 +/**
  19 + * DMZ_Array Class
  20 + *
  21 + * @package DMZ-Included-Extensions
  22 + */
  23 +class DMZ_Array {
  24 +
  25 + /**
  26 + * Convert a DataMapper model into an associative array.
  27 + * If the specified fields includes a related object, the ids from the
  28 + * objects are collected into an array and stored on that key.
  29 + * This method does not recursively add objects.
  30 + *
  31 + * @param DataMapper $object The DataMapper Object to convert
  32 + * @param array $fields Array of fields to include. If empty, includes all database columns.
  33 + * @return array An associative array of the requested fields and related object ids.
  34 + */
  35 + function to_array($object, $fields = '')
  36 + {
  37 + // assume all database columns if $fields is not provided.
  38 + if(empty($fields))
  39 + {
  40 + $fields = $object->fields;
  41 + }
  42 + else
  43 + {
  44 + $fields = (array) $fields;
  45 + }
  46 +
  47 + $result = array();
  48 +
  49 + foreach($fields as $f)
  50 + {
  51 + // handle related fields
  52 + if(array_key_exists($f, $object->has_one) || array_key_exists($f, $object->has_many))
  53 + {
  54 + // each related item is stored as an array of ids
  55 + // Note: this method will NOT get() the related object.
  56 + $rels = array();
  57 + foreach($object->{$f} as $item)
  58 + {
  59 + $rels[] = $item->id;
  60 + }
  61 + $result[$f] = $rels;
  62 + }
  63 + else
  64 + {
  65 + // just the field.
  66 + $result[$f] = $object->{$f};
  67 + }
  68 + }
  69 +
  70 + return $result;
  71 + }
  72 +
  73 + /**
  74 + * Convert the entire $object->all array result set into an array of
  75 + * associative arrays.
  76 + *
  77 + * @see to_array
  78 + * @param DataMapper $object The DataMapper Object to convert
  79 + * @param array $fields Array of fields to include. If empty, includes all database columns.
  80 + * @return array An array of associative arrays.
  81 + */
  82 + function all_to_array($object, $fields = '')
  83 + {
  84 + // loop through each object in the $all array, convert them to
  85 + // an array, and add them to a new array.
  86 + $result = array();
  87 + foreach($object as $o)
  88 + {
  89 + $result[] = $o->to_array($fields);
  90 + }
  91 + return $result;
  92 + }
  93 +
  94 + /**
  95 + * Convert a single field from the entire $object->all array result set into an a single array
  96 + * with the objects' id field as key
  97 + *
  98 + * @param DataMapper $object The DataMapper Object to convert
  99 + * @param string $field to include
  100 + * @return array An array of associative arrays.
  101 + */
  102 + function all_to_single_array($object, $field = '')
  103 + {
  104 + // loop through each object in the $all array, convert them to
  105 + // an array, and add them to a new array.
  106 + $result = array();
  107 + if ( ! empty($field) )
  108 + {
  109 + foreach($object as $o)
  110 + {
  111 + isset($o->{$field}) and $result[$o->id] = $o->{$field};
  112 + }
  113 + }
  114 + return $result;
  115 + }
  116 +
  117 + /**
  118 + * Convert an associative array back into a DataMapper model.
  119 + *
  120 + * If $fields is provided, missing fields are assumed to be empty checkboxes.
  121 + *
  122 + * @param DataMapper $object The DataMapper Object to save to.
  123 + * @param array $data A an associative array of fields to convert.
  124 + * @param array $fields Array of 'safe' fields. If empty, only includes the database columns.
  125 + * @param bool $save If TRUE, then attempt to save the object automatically.
  126 + * @return array|bool A list of newly related objects, or the result of the save if $save is TRUE
  127 + */
  128 + function from_array($object, $data, $fields = '', $save = FALSE)
  129 + {
  130 + // keep track of newly related objects
  131 + $new_related_objects = array();
  132 +
  133 + // Assume all database columns.
  134 + // In this case, simply store $fields that are in the $data array.
  135 + if(empty($fields))
  136 + {
  137 + $fields = $object->fields;
  138 + foreach($data as $k => $v) {
  139 + if(in_array($k, $fields))
  140 + {
  141 + $object->{$k} = $v;
  142 + }
  143 + }
  144 + }
  145 + else
  146 + {
  147 + // If $fields is provided, assume all $fields should exist.
  148 + foreach($fields as $f)
  149 + {
  150 + if(array_key_exists($f, $object->has_one))
  151 + {
  152 + // Store $has_one relationships
  153 + $c = get_class($object->{$f});
  154 + $rel = new $c();
  155 + $id = isset($data[$f]) ? $data[$f] : 0;
  156 + $rel->get_by_id($id);
  157 + if($rel->exists())
  158 + {
  159 + // The new relationship exists, save it.
  160 + $new_related_objects[$f] = $rel;
  161 + }
  162 + else
  163 + {
  164 + // The new relationship does not exist, delete the old one.
  165 + $object->delete($object->{$f}->get());
  166 + }
  167 + }
  168 + else if(array_key_exists($f, $object->has_many))
  169 + {
  170 + // Store $has_many relationships
  171 + $c = get_class($object->{$f});
  172 + $rels = new $c();
  173 + $ids = isset($data[$f]) ? $data[$f] : FALSE;
  174 + if(empty($ids))
  175 + {
  176 + // if no IDs were provided, delete all old relationships.
  177 + $object->delete($object->{$f}->select('id')->get()->all);
  178 + }
  179 + else
  180 + {
  181 + // Otherwise, get the new ones...
  182 + $rels->where_in('id', $ids)->select('id')->get();
  183 + // Store them...
  184 + $new_related_objects[$f] = $rels->all;
  185 + // And delete any old ones that do not exist.
  186 + $old_rels = $object->{$f}->where_not_in('id', $ids)->select('id')->get();
  187 + $object->delete($old_rels->all);
  188 + }
  189 + }
  190 + else
  191 + {
  192 + // Otherwise, if the $data was set, store it...
  193 + if(isset($data[$f]))
  194 + {
  195 + $v = $data[$f];
  196 + }
  197 + else
  198 + {
  199 + // Or assume it was an unchecked checkbox, and clear it.
  200 + $v = FALSE;
  201 + }
  202 + $object->{$f} = $v;
  203 + }
  204 + }
  205 + }
  206 + if($save)
  207 + {
  208 + // Auto save
  209 + return $object->save($new_related_objects);
  210 + }
  211 + else
  212 + {
  213 + // return new objects
  214 + return $new_related_objects;
  215 + }
  216 + }
  217 +
  218 +}
  219 +
  220 +/* End of file array.php */
  221 +/* Location: ./application/datamapper/array.php */
225 application/extensions/csv.php
... ... @@ -0,0 +1,225 @@
  1 +<?php
  2 +
  3 +/**
  4 + * CSV Extension for DataMapper classes.
  5 + *
  6 + * Quickly import and export a set of DataMapper models to-and-from CSV files.
  7 + *
  8 + * @license MIT License
  9 + * @package DMZ-Included-Extensions
  10 + * @category DMZ
  11 + * @author Phil DeJarnett
  12 + * @link http://www.overzealous.com/dmz/pages/extensions/csv.html
  13 + * @version 1.0
  14 + */
  15 +
  16 +// --------------------------------------------------------------------------
  17 +
  18 +/**
  19 + * DMZ_CSV Class
  20 + *
  21 + * @package DMZ-Included-Extensions
  22 + */
  23 +class DMZ_CSV {
  24 +
  25 + /**
  26 + * Convert a DataMapper model into an associative array.
  27 + *
  28 + * @param DataMapper $object The DataMapper Object to export
  29 + * @param mixed filename The filename to export to, or a file pointer. If this is a file pointer, it will not be closed.
  30 + * @param array $fields Array of fields to include. If empty, includes all database columns.
  31 + * @param bool $include_header If FALSE the header is not exported with the CSV. Not recommended if planning to import this data.
  32 + * @return bool TRUE on success, or FALSE on failure.
  33 + */
  34 + function csv_export($object, $filename, $fields = '', $include_header = TRUE)
  35 + {
  36 + // determine the correct field set.
  37 + if(empty($fields))
  38 + {
  39 + $fields = $object->fields;
  40 + }
  41 +
  42 + $success = TRUE;
  43 +
  44 + // determine if we need to open the file or not.
  45 + if(is_string($filename))
  46 + {
  47 + // open the file, if possible.
  48 + $fp = fopen($filename, 'w');
  49 + if($fp === FALSE)
  50 + {
  51 + log_message('error', 'CSV Extension: Unable to open file ' . $filename);
  52 + return FALSE;
  53 + }
  54 + }
  55 + else
  56 + {
  57 + // assume file pointer.
  58 + $fp = $filename;
  59 + }
  60 +
  61 + if($include_header)
  62 + {
  63 + // Print out header line
  64 + $success = fputcsv($fp, $fields);
  65 + }
  66 +
  67 + if($success)
  68 + {
  69 + foreach($object as $o)
  70 + {
  71 + // convert each object into an array
  72 + $result = array();
  73 + foreach($fields as $f)
  74 + {
  75 + $result[] = $o->{$f};
  76 + }
  77 + // output CSV-formatted line
  78 + $success = fputcsv($fp, $result);
  79 + if(!$success)
  80 + {
  81 + // stop on first failure.
  82 + break;
  83 + }
  84 + }
  85 + }
  86 +
  87 + if(is_string($filename))
  88 + {
  89 + fclose($fp);
  90 + }
  91 +
  92 + return $success;
  93 + }
  94 +
  95 + /**
  96 + * Import objects from a CSV file.
  97 + *
  98 + * Completely empty rows are automatically skipped, as are rows that
  99 + * start with a # sign (assumed to be comments).
  100 + *
  101 + * @param DataMapper $object The type of DataMapper Object to import
  102 + * @param mixed $filename Name of CSV file, or a file pointer.
  103 + * @param array $fields If empty, the database fields are used. Otherwise used to limit what fields are saved.
  104 + * @param boolean $header_row If true, the first line is assumed to be a header row. Defaults to true.
  105 + * @param mixed $callback A callback method for each row. Can return FALSE on failure to save, or 'stop' to stop the import.
  106 + * @return array Array of imported objects, or FALSE if unable to import.
  107 + */
  108 + function csv_import($object, $filename, $fields = '', $header_row = TRUE, $callback = NULL)
  109 + {
  110 + $class = get_class($object);
  111 +
  112 + if(empty($fields))
  113 + {
  114 + $fields = $object->fields;
  115 + }
  116 +
  117 + // determine if we need to open the file or not.
  118 + if(is_string($filename))
  119 + {
  120 + // open the file, if possible.
  121 + $fp = fopen($filename, 'r');
  122 + if($fp === FALSE)
  123 + {
  124 + log_message('error', 'CSV Extension: Unable to open file ' . $filename);
  125 + return FALSE;
  126 + }
  127 + }
  128 + else
  129 + {
  130 + // assume file pointer.
  131 + $fp = $filename;
  132 + }
  133 +
  134 + if(empty($callback))
  135 + {
  136 + $result = array();
  137 + }
  138 + else
  139 + {
  140 + $result = 0;
  141 + }
  142 + $columns = NULL;
  143 +
  144 + while(($data = fgetcsv($fp)) !== FALSE)
  145 + {
  146 + // get column names
  147 + if(is_null($columns))
  148 + {
  149 + if($header_row)
  150 + {
  151 + // store header row for column names
  152 + $columns = $data;
  153 + // only include columns in $fields
  154 + foreach($columns as $index => $name)
  155 + {
  156 + if( ! in_array($name, $fields))
  157 + {
  158 + // mark column as false to skip
  159 + $columns[$index] = FALSE;
  160 + }
  161 + }
  162 + continue;
  163 + }
  164 + else
  165 + {
  166 + $columns = $fields;
  167 + }
  168 + }
  169 +
  170 + // skip on comments and empty rows
  171 + if(empty($data) || $data[0][0] == '#' || implode('', $data) == '')
  172 + {
  173 + continue;
  174 + }
  175 +
  176 + // create the object to save
  177 + $o = new $class();
  178 + foreach($columns as $index => $key)
  179 + {
  180 + if(count($data) <= $index)
  181 + {
  182 + // more header columns than data columns
  183 + break;
  184 + }
  185 +
  186 + // skip columns that were determined to not be needed above.
  187 + if($key === FALSE)
  188 + {
  189 + continue;
  190 + }
  191 +
  192 + // finally, it's OK to save the data column.
  193 + $o->{$key} = $data[$index];
  194 + }
  195 +
  196 + if( empty($callback))
  197 + {
  198 + $result[] = $o;
  199 + }
  200 + else
  201 + {
  202 + $test = call_user_func($callback, $o);
  203 + if($test === 'stop')
  204 + {
  205 + break;
  206 + }
  207 + if($test !== FALSE)
  208 + {
  209 + $result++;
  210 + }
  211 + }
  212 + }
  213 +
  214 + if(is_string($filename))
  215 + {
  216 + fclose($fp);
  217 + }
  218 +
  219 + return $result;
  220 + }
  221 +
  222 +}
  223 +
  224 +/* End of file csv.php */
  225 +/* Location: ./application/datamapper/csv.php */
798 application/extensions/htmlform.php
... ... @@ -0,0 +1,798 @@
  1 +<?php
  2 +
  3 +
  4 +/**
  5 + * HTMLForm Extension for DataMapper classes.
  6 + *
  7 + * A powerful extension that allows one to quickly
  8 + * generate standardized forms off a DMZ object.
  9 + *
  10 + * @license MIT License
  11 + * @package DMZ-Included-Extensions
  12 + * @category DMZ
  13 + * @author Phil DeJarnett
  14 + * @link http://www.overzealous.com/dmz/pages/extensions/htmlform.html
  15 + * @version 1.0
  16 + */
  17 +
  18 +// --------------------------------------------------------------------------
  19 +
  20 +/**
  21 + * DMZ_HTMLForm Class
  22 + *
  23 + * @package DMZ-Included-Extensions
  24 + */
  25 +class DMZ_HTMLForm {
  26 +
  27 + // this is the default template (view) to use for the overall form
  28 + var $form_template = 'dmz_htmlform/form';
  29 + // this is the default template (view) to use for the individual rows
  30 + var $row_template = 'dmz_htmlform/row';
  31 + // this is the default template (view) to use for the individual rows
  32 + var $section_template = 'dmz_htmlform/section';
  33 +
  34 + var $auto_rule_classes = array(
  35 + 'integer' => 'integer',
  36 + 'numeric' => 'numeric',
  37 + 'is_natural' => 'natural',
  38 + 'is_natural_no_zero' => 'positive_int',
  39 + 'valid_email' => 'email',
  40 + 'valid_ip' => 'ip',
  41 + 'valid_base64' => 'base64',
  42 + 'valid_date' => 'date',
  43 + 'alpha_dash_dot' => 'alpha_dash_dot',
  44 + 'alpha_slash_dot' => 'alpha_slash_dot',
  45 + 'alpha' => 'alpha',
  46 + 'alpha_numeric' => 'alpha_numeric',
  47 + 'alpha_dash' => 'alpha_dash',
  48 + 'required' => 'required'
  49 + );
  50 +
  51 + function __construct($options = array(), $object = NULL) {
  52 +
  53 + if (is_array($options) )
  54 + {
  55 + foreach($options as $k => $v)
  56 + {
  57 + $this->{$k} = $v;
  58 + }
  59 + }
  60 +
  61 + $this->CI =& get_instance();
  62 + $this->load = $this->CI->load;
  63 + }
  64 +
  65 + // --------------------------------------------------------------------------
  66 +
  67 + /**
  68 + * Render a single field. Can be used to chain together multiple fields in a column.
  69 + *
  70 + * @param object $object The DataMapper Object to use.
  71 + * @param string $field The field to render.
  72 + * @param string $type The type of field to render.
  73 + * @param array $options Various options to modify the output.
  74 + * @return Rendered String.
  75 + */
  76 + function render_field($object, $field, $type = NULL, $options = NULL)
  77 + {
  78 + $value = '';
  79 +
  80 + if(array_key_exists($field, $object->has_one) || array_key_exists($field, $object->has_many))
  81 + {
  82 + // Create a relationship field
  83 + $one = array_key_exists($field, $object->has_one);
  84 +
  85 + // attempt to look up the current value(s)
  86 + if( ! isset($options['value']))
  87 + {
  88 + if($this->CI->input->post($field))
  89 + {
  90 + $value = $this->CI->input->post($field);
  91 + }
  92 + else
  93 + {
  94 + // load the related object(s)
  95 + $sel = $object->{$field}->select('id')->get();
  96 + if($one)
  97 + {
  98 + // only a single value is allowed
  99 + $value = $sel->id;
  100 + }
  101 + else
  102 + {
  103 + // save what might be multiple values
  104 + $value = array();
  105 + foreach($sel as $s)
  106 + {
  107 + $value[] = $s->id;
  108 + }
  109 + }
  110 + }
  111 +
  112 + }
  113 + else
  114 + {
  115 + // value was already set in the options
  116 + $value = $options['value'];
  117 + unset($options['value']);
  118 + }
  119 +
  120 + // Attempt to get a list of possible values
  121 + if( ! isset($options['list']) || is_object($options['list']))
  122 + {
  123 + if( ! isset($options['list']))
  124 + {
  125 + // look up all of the related values
  126 + $c = get_class($object->{$field});
  127 + $total_items = new $c;
  128 + // See if the custom method is defined
  129 + if(method_exists($total_items, 'get_htmlform_list'))
  130 + {
  131 + // Get customized list
  132 + $total_items->get_htmlform_list($object, $field);
  133 + }
  134 + else
  135 + {
  136 + // Get all items
  137 + $total_items->get_iterated();
  138 + }
  139 + }
  140 + else
  141 + {
  142 + // process a passed-in DataMapper object
  143 + $total_items = $options['list'];
  144 + }
  145 + $list = array();
  146 + foreach($total_items as $item)
  147 + {
  148 + // use the __toString value of the item for the label
  149 + $list[$item->id] = (string)$item;
  150 + }
  151 + $options['list'] = $list;
  152 + }
  153 +
  154 + // By if there can be multiple items, use a dropdown for large lists,
  155 + // and a set of checkboxes for a small one.
  156 + if($one || count($options['list']) > 6)
  157 + {
  158 + $default_type = 'dropdown';
  159 + if( ! $one && ! isset($options['size']))
  160 + {
  161 + // limit to no more than 8 items high.
  162 + $options['size'] = min(count($options['list']), 8);
  163 + }
  164 + }
  165 + else
  166 + {
  167 + $default_type = 'checkbox';
  168 + }
  169 + }
  170 + else
  171 + {
  172 + // attempt to look up the current value(s)
  173 + if( ! isset($options['value']))
  174 + {
  175 + if($this->CI->input->post($field))
  176 + {
  177 + $value = $this->CI->input->post($field);
  178 + // clear default if set
  179 + unset($options['default_value']);
  180 + }
  181 + else
  182 + {
  183 + if(isset($options['default_value']))
  184 + {
  185 + $value = $options['default_value'];
  186 + unset($options['default_value']);
  187 + }
  188 + else
  189 + {
  190 + // the field IS the value.
  191 + $value = $object->{$field};
  192 + }
  193 + }
  194 +
  195 + }
  196 + else
  197 + {
  198 + // value was already set in the options
  199 + $value = $options['value'];
  200 + unset($options['value']);
  201 + }
  202 + // default to text
  203 + $default_type = ($field == 'id') ? 'hidden' : 'text';
  204 +
  205 + // determine default attributes
  206 + $a = array();
  207 + // such as the size of the field.
  208 + $max = $this->_get_validation_rule($object, $field, 'max_length');
  209 + if($max === FALSE)
  210 + {
  211 + $max = $this->_get_validation_rule($object, $field, 'exact_length');
  212 + }
  213 + if($max !== FALSE)
  214 + {
  215 + $a['maxlength'] = $max;
  216 + $a['size'] = min($max, 30);
  217 + }
  218 + $list = $this->_get_validation_info($object, $field, 'values', FALSE);
  219 + if($list !== FALSE)
  220 + {
  221 + $a['list'] = $list;
  222 + }
  223 + $options = $options + $a;
  224 + $extra_class = array();
  225 +
  226 + // Add any of the known rules as classes (for JS processing)
  227 + foreach($this->auto_rule_classes as $rule => $c)
  228 + {
  229 + if($this->_get_validation_rule($object, $field, $rule) !== FALSE)
  230 + {
  231 + $extra_class[] = $c;
  232 + }
  233 + }
  234 +
  235 + // add or set the class on the field.
  236 + if( ! empty($extra_class))
  237 + {
  238 + $extra_class = implode(' ', $extra_class);
  239 + if(isset($options['class']))
  240 + {
  241 + $options['class'] .= ' ' . $extra_class;
  242 + }
  243 + else
  244 + {
  245 + $options['class'] = $extra_class;
  246 + }
  247 + }
  248 + }
  249 +
  250 + // determine the renderer type
  251 + $type = $this->_get_type($object, $field, $type);
  252 + if(empty($type))
  253 + {
  254 + $type = $default_type;
  255 + }
  256 +
  257 + // attempt to find the renderer function
  258 + if(method_exists($this, '_input_' . $type))
  259 + {
  260 + return $this->{'_input_' . $type}($object, $field, $value, $options);
  261 + }
  262 + else if(function_exists('input_' . $type))
  263 + {
  264 + return call_user_func('input_' . $type, $object, $field, $value, $options);
  265 + }
  266 + else
  267 + {
  268 + log_message('error', 'FormMaker: Unable to find a renderer for '.$type);
  269 + return '<span style="color: Maroon; background-color: White; font-weight: bold">FormMaker: UNABLE TO FIND A RENDERER FOR '.$type.'</span>';
  270 + }
  271 +
  272 + }
  273 +
  274 + // --------------------------------------------------------------------------
  275 +
  276 + /**
  277 + * Render a row with a single field. If $field does not exist on
  278 + * $object->validation, then $field is output as-is.
  279 + *
  280 + * @param object $object The DataMapper Object to use.
  281 + * @param string $field The field to render (or content)
  282 + * @param string $type The type of field to render.
  283 + * @param array $options Various options to modify the output.
  284 + * @param string $row_template The template to use, or NULL to use the default.
  285 + * @return Rendered String.
  286 + */
  287 + function render_row($object, $field, $type = NULL, $options = array(), $row_template = NULL)
  288 + {
  289 + // try to determine type automatically
  290 + $type = $this->_get_type($object, $field, $type);
  291 +
  292 + if( ! isset($object->validation[$field]) && (empty($type) || $type == 'section' || $type == 'none'))
  293 + {
  294 + // this could be a multiple-field row, or just some text.
  295 + // if $type is 'section, it will be rendered using the section template.
  296 + $error = '';
  297 + $label = '';
  298 + $content = $field;
  299 + $id = NULL;
  300 + }
  301 + else
  302 + {
  303 + // use validation information to render the field.
  304 + $content = $this->render_field($object, $field, $type, $options);
  305 + if(empty($row_template))
  306 + {
  307 + if($type == 'hidden' || $field == 'id')
  308 + {
  309 + $row_template = 'none';
  310 + }
  311 + else
  312 + {
  313 + $row_template = $this->row_template;
  314 + }
  315 + }
  316 + // determine if there is an existing error
  317 + $error = isset($object->error->{$field}) ? $object->error->{$field} : '';
  318 + // determine if there is a pre-defined label
  319 + $label = $this->_get_validation_info($object, $field, 'label', $field);
  320 + // the field IS the id
  321 + $id = $field;
  322 + }
  323 +
  324 + $required = $this->_get_validation_rule($object, $field, 'required');
  325 +
  326 + // Append these items. Values in $options have priority
  327 + $view_data = $options + array(
  328 + 'object' => $object,
  329 + 'content' => $content,
  330 + 'field' => $field,
  331 + 'label' => $label,
  332 + 'error' => $error,
  333 + 'id' => $id,
  334 + 'required' => $required
  335 + );
  336 +
  337 + if(is_null($row_template))
  338 + {
  339 + if(empty($type))
  340 + {
  341 + $row_template = 'none';
  342 + }
  343 + else if($type == 'section')
  344 + {
  345 + $row_template = $this->section_template;
  346 + }
  347 + else
  348 + {
  349 + $row_template = $this->row_template;
  350 + }
  351 + }
  352 +
  353 + if($row_template == 'none')
  354 + {
  355 + return $content;
  356 + }
  357 + else
  358 + {
  359 + return $this->load->view($row_template, $view_data, TRUE);
  360 + }
  361 + }
  362 +
  363 + // --------------------------------------------------------------------------
  364 +
  365 + /**
  366 + * Renders an entire form.
  367 + *
  368 + * @param object $object The DataMapper Object to use.
  369 + * @param string $fields An associative array that defines the form.
  370 + * @param string $template The template to use.
  371 + * @param string $row_template The template to use for rows.
  372 + * @param array $template_options The template to use for rows.
  373 + * @return Rendered String.
  374 + */
  375 + function render_form($object, $fields, $url = '', $options = array(), $template = NULL, $row_template = NULL)
  376 + {
  377 + if(empty($url))
  378 + {
  379 + // set url to current url
  380 + $url =$this->CI->uri->uri_string();
  381 + }
  382 +
  383 + if(is_null($template))
  384 + {
  385 + $template = $this->form_template;
  386 + }
  387 +
  388 + $rows = '';
  389 + foreach($fields as $field => $field_options)
  390 + {
  391 + $rows .= $this->_render_row_from_form($object, $field, $field_options, $row_template);
  392 + }
  393 +
  394 + $view_data = $options + array(
  395 + 'object' => $object,
  396 + 'fields' => $fields,
  397 + 'url' => $url,
  398 + 'rows' => $rows
  399 + );
  400 +
  401 + return $this->load->view($template, $view_data, TRUE);
  402 + }
  403 +
  404 + // --------------------------------------------------------------------------
  405 + // Private Methods
  406 + // --------------------------------------------------------------------------
  407 +
  408 + // Converts information from render_form into a row of objects.
  409 + function _render_row_from_form($object, $field, $options, $row_template, $row = TRUE)
  410 + {
  411 + if(is_int($field))
  412 + {
  413 + // simple form, or HTML-content
  414 + $field = $options;
  415 + $options = NULL;
  416 + }
  417 + if(is_null($options))
  418 + {
  419 + // always have an array for options
  420 + $options = array();
  421 + }
  422 +
  423 + $type = '';
  424 + if( ! is_array($options))
  425 + {
  426 + // if options is a single string, assume it is the type.
  427 + $type = $options;
  428 + $options = array();
  429 + }
  430 +
  431 + if(isset($options['type']))
  432 + {
  433 + // type was set in options
  434 + $type = $options['type'];
  435 + unset($options['type']);
  436 + }
  437 +
  438 + // see if a different row_template was in the options
  439 + $rt = $row_template;
  440 + if(isset($options['template']))
  441 + {
  442 + $rt = $options['template'];
  443 + unset($options['template']);
  444 + }
  445 +
  446 + // Multiple fields, render them all as one.
  447 + if(is_array($field))
  448 + {
  449 + if(isset($field['row_options']))
  450 + {
  451 + $options = $field['row_options'];
  452 + unset($field['row_options']);</