Beispiel #1
0
 public function set($values, $value = NULL)
 {
     // Accept set($_POST, array('author', 'body'));
     // Only $_POST['author'] and $_POST['body'] will be passed
     if (is_array($values) and is_array($value)) {
         $keys = array_flip($value);
         $values = array_intersect_key($values, $keys);
         $value = NULL;
     }
     parent::set($values, $value);
     if (!empty($this->_unmapped)) {
         $related = array();
         foreach ($this->_meta->fields() as $k => $v) {
             if ($v instanceof Jelly_Field_Relationship) {
                 $related[$k] = Jelly::meta($v->foreign['model']);
             }
         }
         if (!empty($related)) {
             foreach ($this->_unmapped as $k => $v) {
                 foreach ($related as $key => $r) {
                     if ($r->fields($k) !== NULL and $r instanceof Model) {
                         $this->{$key}->set($k, $v);
                         continue;
                     }
                 }
             }
         }
     }
     return $this;
 }
Beispiel #2
0
 /**
  * Tracks a database result
  *
  * @param  mixed  $model
  * @param  mixed  $result
  */
 public function __construct($result, $model = NULL)
 {
     $this->_result = $result;
     // Load our default model
     if ($model and Jelly::meta($model)) {
         $this->_model = $model instanceof Jelly_Model ? $model : new $model();
         $this->_meta = $this->_model->meta();
     }
 }
Beispiel #3
0
 /**
  * Returns a query builder that can be used for querying.
  *
  * If $key is passed, the key will be passed to unique_key(), the result
  * will be limited to 1, and the record will be returned directly.
  *
  * In essence, passing a $key is analogous to:
  *
  *     Jelly::query($model)->where(':unique_key', '=' $key)->limit(1);
  *
  * @param   string  $model
  * @param   mixed   $key
  * @return  Jelly_Builder
  */
 public static function query($model, $key = NULL)
 {
     $builder = 'Jelly_Builder';
     if ($meta = Jelly::meta($model)) {
         if ($meta->builder()) {
             $builder = $meta->builder();
         }
     }
     return new $builder($model, $key);
 }
Beispiel #4
0
 /**
  * Tests Jelly::meta() and that meta objects are correctly returned.
  * 
  * @dataProvider provider_register
  */
 public function test_meta($model, $expected)
 {
     $result = Jelly::meta($model);
     // Should return a Jelly_Meta instance
     if ($expected === TRUE) {
         $this->assertTrue($result instanceof Jelly_Meta);
         $this->assertTrue($result->initialized());
     } else {
         $this->assertFalse($result);
     }
 }
Beispiel #5
0
 protected function init()
 {
     foreach ($this->model['fields'] as $key => &$field) {
         if (array_key_exists('data_source', $field)) {
             $val_field = $field['data_source']['val_field'];
             $text_field = $field['data_source']['text_field'];
             $params = array_key_exists('params', $field['data_source']) ? $field['data_source']['params'] : null;
             $list = call_user_func_array($field['data_source']['callback'], $params);
             if (!array_key_exists('items', $field)) {
                 $field['items'] = array();
             }
             if (!array_key_exists('result', $field['data_source']) || $field['data_source']['result'] == 'array') {
                 foreach ($list as $item) {
                     $field['items'][] = array('value' => $item[$val_field], 'text' => $item[$text_field]);
                 }
             } else {
                 if ($field['data_source']['result'] == 'object') {
                     foreach ($list as $item) {
                         $field['items'][] = array('value' => $item->{$val_field}, 'text' => $item->{$text_field});
                     }
                 } else {
                     throw new Exception('unknown result type: ' . $field['data_source']['result']);
                 }
             }
         }
         //pull info if from a Jelly Model
         if (array_key_exists('model', $field)) {
             //get model
             if (!isset($this->models[$field['model']])) {
                 $this->metas[$field['model']] = $meta = Jelly::meta($field['model']);
             } else {
                 $meta = $this->metas[$field['model']];
             }
             $fld = $meta->fields($field['field']);
             //get Jelly class of field
             $class = get_class($fld);
             $field['type'] = self::$field_map[$class];
             //now grab info needed from the field
             $field['name'] = $fld->name;
             if ($this->model['populate_defaults'] === true) {
                 $field['value'] = $fld->default;
             }
         }
         if (isset($field['attributes'])) {
             $field['attributes'] = array();
         }
         $field['attributes']['type'] = $field['type'];
         if (in_array($field['type'], array('password'))) {
             $field['type'] = 'text';
         }
         //Jx_Debug::dump($field, "field $key in init()");
     }
 }
Beispiel #6
0
 /**
  * Tests returning a model directly from a SELECT.
  *
  * @dataProvider  provider_single_select
  * @param         Jelly                   $model
  * @param         bool                    $exists
  * @return        void
  */
 public function test_single_select($model, $exists)
 {
     $this->assertTrue($model instanceof Jelly_Model);
     if ($exists) {
         $this->assertTrue($model->loaded());
         $this->assertTrue($model->saved());
         $this->assertTrue($model->id > 0);
     } else {
         $this->assertFalse($model->loaded());
         $this->assertFalse($model->saved());
         $this->assertTrue($model->id === $model->meta()->field('id')->default);
     }
 }
Beispiel #7
0
 /**
  * Constructor.
  *
  * A key can be passed to automatically load a model by its
  * unique key.
  *
  * @param  mixed|null  $key
  */
 public function __construct($key = NULL)
 {
     // Load the object's meta data for quick access
     $this->_meta = Jelly::meta($this);
     // Copy over the defaults into the original data.
     $this->_original = $this->_meta->defaults();
     // Have an id? Attempt to load it
     if ($key !== NULL) {
         $result = Jelly::query($this, $key)->as_object(FALSE)->select();
         // Only load if a record is found
         if ($result) {
             $this->load_values($result);
         }
     }
 }
Beispiel #8
0
 /**
  * Implementation for Jelly_Field_Behavior_Saveable.
  *
  * @param   Jelly  $model
  * @param   mixed  $value
  * @return  void
  */
 public function save($model, $value, $loaded)
 {
     // Find all current records so that we can calculate what's changed
     $in = $loaded ? $this->_in($model, true) : array();
     // Find old relationships that must be deleted
     if ($old = array_diff($in, (array) $value)) {
         Jelly::delete($this->through['model'])->where($this->through['columns'][0], '=', $model->id())->where($this->through['columns'][1], 'IN', $old)->execute(Jelly::meta($model)->db());
     }
     // Find new relationships that must be inserted
     if (!empty($value) && ($new = array_diff((array) $value, $in))) {
         foreach ($new as $new_id) {
             if (!is_null($new_id)) {
                 Jelly::insert($this->through['model'])->columns($this->through['columns'])->values(array($model->id(), $new_id))->execute(Jelly::meta($model)->db());
             }
         }
     }
 }
Beispiel #9
0
 /**
  * Constructor.
  *
  * If $values is passed and it is an array, it will be
  * applied to the model as if it were a database result.
  * The model is then considered to be loaded.
  *
  * It is important to note that, although Jelly Models are
  * not instantiated from Database_Results (by using
  * as_object()), they can be instantiated this way.
  *
  * @param  array  $values
  **/
 public function __construct($values = array())
 {
     // Load the object's meta data for quick access
     $this->_meta = Jelly::meta($this);
     // Copy over the defaults into the original data. This also has
     // the added benefit of registering the model's metadata, if it does not exist yet
     $this->_original = $this->_meta->defaults();
     // Add the values stored by mysql_set_object
     if (!empty($this->_preload_data) and is_array($this->_preload_data)) {
         $this->load_values($this->_preload_data);
         $this->_preload_data = array();
     }
     // Have an id? Attempt to load it
     if ($values) {
         // Arrays are loaded as values, but not load()ed
         if (is_array($values)) {
             $this->set($values);
         }
     }
 }
Beispiel #10
0
 public function testInitialization()
 {
     $this->assertEquals(TRUE, Jelly::meta('alias')->initialized());
     $this->assertEquals(TRUE, Jelly::meta(new Model_Alias())->initialized());
     $this->assertEquals(FALSE, Jelly::meta('non-existent-model'));
 }
Beispiel #11
0
 protected function generate_field(Jelly_Model $model, &$fields, $field_id, $field, array $validation_errors = array(), $attrs = array(), $field_prefix = 'field-')
 {
     $field_id_attr = $field_prefix . $field->name;
     if (!$this->include_field($field, $model->id() == 0)) {
         return;
     }
     $id_attribs = array('attributes' => array('id' => $field_id_attr) + $attrs, 'name' => $field_id_attr);
     if ($field->prevent_edit) {
         $label = Form::label($field_id_attr, $field->label);
         $field_str = $field->display($model, $model->get($field_id));
         $fields[$label] = '<div class="non-editable">' . ($field_str == '' || $field_str == ' ' ? '&nbsp;' : $field_str) . '</div>';
     } else {
         $field_output = $model->input($field->name, $id_attribs);
         if ($field instanceof Field_HasManyUniquely) {
             $label = View::factory('jelly/field/hasmanyuniquely/header', array('label' => $field->label, 'is_sortable' => isset($field->sort_on) && $field->sort_on)) . '';
         } else {
             if ($field instanceof Field_BelongsTo && $field->edit_inline) {
                 $label = '<!-- ' . $field_id . ' -->';
                 $sub_model = $model->{$field_id};
                 $sub_meta = Jelly::meta($sub_model);
                 $field_output = View::factory('kadmium/fieldset_subedit', array('field_id' => $field_id, 'label' => $field->label, 'fields' => $this->generate_fields($sub_model, $sub_meta, 'field-' . $field_id . '-', $validation_errors)));
             } else {
                 $label = Form::label($field_id_attr, $field->label);
             }
         }
         $fields[$label] = $field_output;
         if (isset($validation_errors[$field_id])) {
             array_push($field->css_class, 'error');
             $fields[$label]->errors = $validation_errors[$field_id];
         }
     }
 }
Beispiel #12
0
 /**
  * This method aliases models to tables.
  *
  * @param   string  $table
  * @return  string
  */
 protected function _table($model)
 {
     if ($meta = Jelly::meta($model)) {
         $model = $meta->table();
     }
     return $model;
 }
Beispiel #13
0
 protected function _tables()
 {
     // Prepare an array to hold tables
     $tables = array();
     // Create a new database table with name and database
     $table = new Database_Table($this->_model->table(), $this->_db);
     // Get the model's primary keys as an array
     $model_pks = is_array($this->_model->primary_key()) ? $this->_model->primary_key() : array($this->_model->primary_key());
     // Loop through each field within the model
     foreach ($this->_model->fields() as $field) {
         // Check if the field implaments the migratable field interface
         if ($field instanceof Jelly_Field_Migratable) {
             // Loop through each column in the field
             foreach ($field->columns() as $column) {
                 // Add the column to the table
                 $table->add_column($column);
             }
         } elseif ($field->in_db) {
             // If the field is unique
             if ($field->unique) {
                 // Add a unique constraint to the table
                 $table->add_constraint(new Database_Constraint_Unique($field->column));
             }
             // Loop through every column in the model
             foreach ($this->_columns($field, $table) as $column) {
                 // Add the column to the table
                 $table->add_column($column);
             }
         } elseif ($field instanceof Jelly_Field_ManyToMany) {
             // ManyToMany fields also contain a pivot table
             $pivot = new Database_Table($field->through['model'], $this->_db);
             // Get fields
             $columns = $field->through['columns'];
             foreach ($columns as $field) {
                 // Chekt if the field names are defaults
                 if (strstr($field, ':')) {
                     list($model, $field) = explode(':', $field);
                     // Append the : back onto $field, it's key for recognizing the alias below
                     $field = ':' . $field;
                     // We should be able to find a valid meta object here
                     if (FALSE == ($meta = Jelly::meta($model))) {
                         throw new Kohana_Exception('Meta data for :model was not found while trying to resolve :field', array(':model' => $model, ':field' => $field));
                     }
                     $field = $meta->foreign_key();
                 }
                 $column = Database_Column::factory('int');
                 $column->auto_increment = FALSE;
                 $column->name = $field;
                 $cols[] = $column;
             }
             // Add to pivot
             foreach ($cols as $column) {
                 // Add it to the pivot table
                 $pivot->add_column($column);
             }
             // Add a primary key constraint on all fields within the pivot table
             $pivot->add_constraint(new Database_Constraint_Primary(array_keys($pivot->columns()), $pivot->name));
             /**
             * @todo It would be more than appropriate to add a contstraint in a following 
             * form into a database:
             							ALTER TABLE `roles_users`
             						  ADD CONSTRAINT `roles_users_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
             * 
             */
             // Add the pivot table to the list of tables
             $tables[] = $pivot;
         }
     }
     // Add the primary key constraints to the table
     $table->add_constraint(new Database_Constraint_Primary($model_pks, $table->name));
     // Add the table to the list
     $tables[] = $table;
     // And return all tables.
     return $tables;
 }
Beispiel #14
0
 /**
  * Easy-to-override method that expands aliases.
  *
  * @param   string  $model
  * @param   string  $alias
  * @param   array   $state
  * @return  array
  */
 protected function _expand_alias($model, $alias, $state)
 {
     switch ($alias) {
         case ':primary_key':
             $state['field'] = Jelly::meta($model)->primary_key();
             break;
         case ':name_key':
             $state['field'] = Jelly::meta($model)->name_key();
             break;
         case ':foreign_key':
             $state['field'] = Jelly::meta($model)->foreign_key();
             break;
         case ':unique_key':
             $state['field'] = Jelly::query(Jelly::meta($model)->model())->unique_key($state['value']);
             break;
         default:
             throw new Kohana_Exception('Unknown meta alias :alias', array(':alias' => $alias));
     }
     return $state;
 }
Beispiel #15
0
 public function display($model, $value)
 {
     return $value->execute()->{Jelly::meta($this->foreign['model'])->name_key()};
 }
Beispiel #16
0
 /**
  * Generates a builder where clause based on the provided values
  *
  * @param   Jelly_Builder   $builder
  * @param   string  $model  Model name used in the where clause
  * @param   mixed   $values argument list used to construct the clause
  * @return  Jelly_Builder
  */
 protected function _where($builder, $model, array $values)
 {
     // Check for an outer and/or indexed array
     $where = 'where';
     if (isset($values['or'])) {
         $where = 'or_where';
         $values = is_array($values['or']) ? $values['or'] : array($values['or']);
     } elseif (isset($values['and'])) {
         $where = 'and_where';
         $values = is_array($values['and']) ? $values['and'] : array($values['and']);
     }
     $count = count($values);
     /* One Argument is passed, can be:
      *  interger - for the primary key lookup
      *  string   - for the name key lookup
      *  object   - a loaded model of the same class
      */
     if ($count == 1) {
         if (is_integer($values[0])) {
             return $builder->{$where}($model . '.:primary_key', '=', $values[0]);
         } elseif (is_string($values[0])) {
             return $builder->{$where}($model . '.:name_key', '=', $values[0]);
         } elseif (is_object($values[0])) {
             $class = Jelly::class_name($model);
             if ($values[0] instanceof $class) {
                 return $builder->where($model . '.:primary_key', '=', $values[0]->id());
             }
         }
     } elseif ($count == 2) {
         if (!Jelly::meta($model)->fields($values[0])) {
             throw new Kohana_Exception('":field" is not a valid :model field', array(':field' => $values[0], ':model' => $model));
         }
         return $builder->{$where}($model . '.' . $values[0], '=', $values[1]);
     } elseif ($count == 3) {
         if (!Jelly::meta($model)->fields($values[0])) {
             throw new Kohana_Exception('":field" is not a valid :model field', array(':field' => $values[0], ':model' => $model));
         }
         return $builder->{$where}($model . '.' . $values[0], $values[1], $values[2]);
     }
     // Not Supported
     throw new Kohana_Exception('invalid or unsupported argument');
 }
Beispiel #17
0
 /**
  * Returns either an array or unexecuted query to find
  * which columns the model is "in" in the join table
  *
  * @param   Jelly    $model
  * @param   boolean  $as_array
  * @return  mixed
  */
 protected function _in($model, $as_array = FALSE)
 {
     $result = Jelly::select($this->through['model'])->select($this->through['columns'][1])->where($this->through['columns'][0], '=', $model->id());
     if ($as_array) {
         $result = $result->execute(Jelly::meta($model)->db())->as_array(NULL, $this->through['columns'][1]);
     }
     return $result;
 }
Beispiel #18
0
 /**
  * Returns the builder class to use for the specified model
  *
  * @param   string  $model
  * @param   int     $type
  * @return  string
  */
 protected static function builder($model, $type = NULL)
 {
     $builder = 'Jelly_Builder';
     if ($meta = Jelly::meta($model)) {
         if ($meta->builder()) {
             $builder = $meta->builder();
         }
     }
     return new $builder($model, $type);
 }