my-simon 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/.document +5 -0
  2. data/.gitignore.orig +55 -0
  3. data/DOC/Launch Check List.docx +0 -0
  4. data/DOC/Launch Check List.pdf +0 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +44 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +21 -0
  9. data/README.rdoc +19 -0
  10. data/Rakefile +46 -0
  11. data/VERSION +1 -0
  12. data/build/rakefile.rb +12 -0
  13. data/config.rb +24 -0
  14. data/lib/simon.rb +0 -5
  15. data/my-simon.gemspec +141 -0
  16. data/scaffolding/simon/controller.tpl +9 -0
  17. data/scaffolding/simon/model.tpl +10 -0
  18. data/scaffolding/simon/view.tpl +5 -0
  19. data/scaffolding/standards/html_template.html +44 -0
  20. data/scaffolding/standards/html_template.php +44 -0
  21. data/scaffolding/standards/jquery_plugin_template.js +45 -0
  22. data/scaffolding/standards/js_template.js +43 -0
  23. data/simon +282 -0
  24. data/test/helper.rb +18 -0
  25. data/test/test_simon.rb +7 -0
  26. data/www/.htaccess +488 -0
  27. data/www/404.html +32 -0
  28. data/www/crossdomain.xml +25 -0
  29. data/www/favicon.ico +0 -0
  30. data/www/index.php +17 -0
  31. data/www/lib/js/homePage.js +43 -0
  32. data/www/lib/js/jquery/JQbook.js +809 -0
  33. data/www/lib/js/jquery/jquery-1.8.0.min.js +27 -0
  34. data/www/lib/js/jquery/jquery.alphanumeric.js +82 -0
  35. data/www/lib/js/jquery/jquery.cookie.js +96 -0
  36. data/www/lib/js/jquery/jquery.easing.1.3.js +207 -0
  37. data/www/lib/js/main.js +117 -0
  38. data/www/lib/js/master.js +6 -0
  39. data/www/lib/js/plugins/handlebars-1.0.rc.1.js +1920 -0
  40. data/www/lib/js/plugins/modernizr-1.7.min.js +2 -0
  41. data/www/lib/js/plugins/swfobject.js +777 -0
  42. data/www/lib/js/plugins_mod/README.txt +3 -0
  43. data/www/lib/php/app.php +53 -0
  44. data/www/lib/php/controller/index.php +10 -0
  45. data/www/lib/php/controller/regex.php +23 -0
  46. data/www/lib/php/model/Book.php +8 -0
  47. data/www/lib/php/model/Model.php +8 -0
  48. data/www/lib/php/plugins/php-activerecord/ActiveRecord.php +44 -0
  49. data/www/lib/php/plugins/php-activerecord/lib/CallBack.php +226 -0
  50. data/www/lib/php/plugins/php-activerecord/lib/Column.php +155 -0
  51. data/www/lib/php/plugins/php-activerecord/lib/Config.php +288 -0
  52. data/www/lib/php/plugins/php-activerecord/lib/Connection.php +456 -0
  53. data/www/lib/php/plugins/php-activerecord/lib/ConnectionManager.php +38 -0
  54. data/www/lib/php/plugins/php-activerecord/lib/DateTime.php +45 -0
  55. data/www/lib/php/plugins/php-activerecord/lib/Exceptions.php +137 -0
  56. data/www/lib/php/plugins/php-activerecord/lib/Expressions.php +183 -0
  57. data/www/lib/php/plugins/php-activerecord/lib/Inflector.php +115 -0
  58. data/www/lib/php/plugins/php-activerecord/lib/Model.php +1673 -0
  59. data/www/lib/php/plugins/php-activerecord/lib/Reflections.php +86 -0
  60. data/www/lib/php/plugins/php-activerecord/lib/Relationship.php +637 -0
  61. data/www/lib/php/plugins/php-activerecord/lib/SQLBuilder.php +396 -0
  62. data/www/lib/php/plugins/php-activerecord/lib/Serialization.php +302 -0
  63. data/www/lib/php/plugins/php-activerecord/lib/Singleton.php +57 -0
  64. data/www/lib/php/plugins/php-activerecord/lib/Table.php +547 -0
  65. data/www/lib/php/plugins/php-activerecord/lib/Utils.php +351 -0
  66. data/www/lib/php/plugins/php-activerecord/lib/Validations.php +833 -0
  67. data/www/lib/php/plugins/php-activerecord/lib/adapters/MysqlAdapter.php +73 -0
  68. data/www/lib/php/plugins/php-activerecord/lib/adapters/OciAdapter.php +121 -0
  69. data/www/lib/php/plugins/php-activerecord/lib/adapters/PgsqlAdapter.php +104 -0
  70. data/www/lib/php/plugins/php-activerecord/lib/adapters/SqliteAdapter.php +81 -0
  71. data/www/lib/php/system/Config.php +174 -0
  72. data/www/lib/php/system/config.routes.php +29 -0
  73. data/www/lib/php/system/router.php +220 -0
  74. data/www/lib/php/template/footer.php +59 -0
  75. data/www/lib/php/template/header.php +74 -0
  76. data/www/lib/php/view/index.php +5 -0
  77. data/www/media/images/facebook_share.jpg +0 -0
  78. data/www/robots.txt +5 -0
  79. data/www/sandbox/readme.txt +3 -0
  80. data/www/sass/javascript.scss +1 -0
  81. data/www/sass/layout.scss +128 -0
  82. data/www/sass/master.scss +4 -0
  83. data/www/sass/reset.scss +47 -0
  84. data/www/sass/typography.scss +24 -0
  85. data/www/styles/javascript.css +1 -0
  86. data/www/styles/layout.css +186 -0
  87. data/www/styles/master.css +4 -0
  88. data/www/styles/reset.css +60 -0
  89. data/www/styles/typography.css +24 -0
  90. metadata +179 -7
@@ -0,0 +1,86 @@
1
+ <?php
2
+ /**
3
+ * @package ActiveRecord
4
+ */
5
+ namespace ActiveRecord;
6
+ use ReflectionClass;
7
+
8
+ /**
9
+ * Simple class that caches reflections of classes.
10
+ *
11
+ * @package ActiveRecord
12
+ */
13
+ class Reflections extends Singleton
14
+ {
15
+ /**
16
+ * Current reflections.
17
+ *
18
+ * @var array
19
+ */
20
+ private $reflections = array();
21
+
22
+ /**
23
+ * Instantiates a new ReflectionClass for the given class.
24
+ *
25
+ * @param string $class Name of a class
26
+ * @return Reflections $this so you can chain calls like Reflections::instance()->add('class')->get()
27
+ */
28
+ public function add($class=null)
29
+ {
30
+ $class = $this->get_class($class);
31
+
32
+ if (!isset($this->reflections[$class]))
33
+ $this->reflections[$class] = new ReflectionClass($class);
34
+
35
+ return $this;
36
+ }
37
+
38
+ /**
39
+ * Destroys the cached ReflectionClass.
40
+ *
41
+ * Put this here mainly for testing purposes.
42
+ *
43
+ * @param string $class Name of a class.
44
+ * @return void
45
+ */
46
+ public function destroy($class)
47
+ {
48
+ if (isset($this->reflections[$class]))
49
+ $this->reflections[$class] = null;
50
+ }
51
+
52
+ /**
53
+ * Get a cached ReflectionClass.
54
+ *
55
+ * @param string $class Optional name of a class
56
+ * @return mixed null or a ReflectionClass instance
57
+ * @throws ActiveRecordException if class was not found
58
+ */
59
+ public function get($class=null)
60
+ {
61
+ $class = $this->get_class($class);
62
+
63
+ if (isset($this->reflections[$class]))
64
+ return $this->reflections[$class];
65
+
66
+ throw new ActiveRecordException("Class not found: $class");
67
+ }
68
+
69
+ /**
70
+ * Retrieve a class name to be reflected.
71
+ *
72
+ * @param mixed $mixed An object or name of a class
73
+ * @return string
74
+ */
75
+ private function get_class($mixed=null)
76
+ {
77
+ if (is_object($mixed))
78
+ return get_class($mixed);
79
+
80
+ if (!is_null($mixed))
81
+ return $mixed;
82
+
83
+ return $this->get_called_class();
84
+ }
85
+ }
86
+ ?>
@@ -0,0 +1,637 @@
1
+ <?php
2
+ /**
3
+ * @package ActiveRecord
4
+ */
5
+ namespace ActiveRecord;
6
+
7
+ /**
8
+ * Interface for a table relationship.
9
+ *
10
+ * @package ActiveRecord
11
+ */
12
+ interface InterfaceRelationship
13
+ {
14
+ public function __construct($options=array());
15
+ public function build_association(Model $model, $attributes=array());
16
+ public function create_association(Model $model, $attributes=array());
17
+ }
18
+
19
+ /**
20
+ * Abstract class that all relationships must extend from.
21
+ *
22
+ * @package ActiveRecord
23
+ * @see http://www.phpactiverecord.org/guides/associations
24
+ */
25
+ abstract class AbstractRelationship implements InterfaceRelationship
26
+ {
27
+ /**
28
+ * Name to be used that will trigger call to the relationship.
29
+ *
30
+ * @var string
31
+ */
32
+ public $attribute_name;
33
+
34
+ /**
35
+ * Class name of the associated model.
36
+ *
37
+ * @var string
38
+ */
39
+ public $class_name;
40
+
41
+ /**
42
+ * Name of the foreign key.
43
+ *
44
+ * @var string
45
+ */
46
+ public $foreign_key = array();
47
+
48
+ /**
49
+ * Options of the relationship.
50
+ *
51
+ * @var array
52
+ */
53
+ protected $options = array();
54
+
55
+ /**
56
+ * Is the relationship single or multi.
57
+ *
58
+ * @var boolean
59
+ */
60
+ protected $poly_relationship = false;
61
+
62
+ /**
63
+ * List of valid options for relationships.
64
+ *
65
+ * @var array
66
+ */
67
+ static protected $valid_association_options = array('class_name', 'class', 'foreign_key', 'conditions', 'select', 'readonly');
68
+
69
+ /**
70
+ * Constructs a relationship.
71
+ *
72
+ * @param array $options Options for the relationship (see {@link valid_association_options})
73
+ * @return mixed
74
+ */
75
+ public function __construct($options=array())
76
+ {
77
+ $this->attribute_name = $options[0];
78
+ $this->options = $this->merge_association_options($options);
79
+
80
+ $relationship = strtolower(denamespace(get_called_class()));
81
+
82
+ if ($relationship === 'hasmany' || $relationship === 'hasandbelongstomany')
83
+ $this->poly_relationship = true;
84
+
85
+ if (isset($this->options['conditions']) && !is_array($this->options['conditions']))
86
+ $this->options['conditions'] = array($this->options['conditions']);
87
+
88
+ if (isset($this->options['class']))
89
+ $this->set_class_name($this->options['class']);
90
+ elseif (isset($this->options['class_name']))
91
+ $this->set_class_name($this->options['class_name']);
92
+
93
+ $this->attribute_name = strtolower(Inflector::instance()->variablize($this->attribute_name));
94
+
95
+ if (!$this->foreign_key && isset($this->options['foreign_key']))
96
+ $this->foreign_key = is_array($this->options['foreign_key']) ? $this->options['foreign_key'] : array($this->options['foreign_key']);
97
+ }
98
+
99
+ protected function get_table()
100
+ {
101
+ return Table::load($this->class_name);
102
+ }
103
+
104
+ /**
105
+ * What is this relationship's cardinality?
106
+ *
107
+ * @return bool
108
+ */
109
+ public function is_poly()
110
+ {
111
+ return $this->poly_relationship;
112
+ }
113
+
114
+ /**
115
+ * Eagerly loads relationships for $models.
116
+ *
117
+ * This method takes an array of models, collects PK or FK (whichever is needed for relationship), then queries
118
+ * the related table by PK/FK and attaches the array of returned relationships to the appropriately named relationship on
119
+ * $models.
120
+ *
121
+ * @param Table $table
122
+ * @param $models array of model objects
123
+ * @param $attributes array of attributes from $models
124
+ * @param $includes array of eager load directives
125
+ * @param $query_keys -> key(s) to be queried for on included/related table
126
+ * @param $model_values_keys -> key(s)/value(s) to be used in query from model which is including
127
+ * @return void
128
+ */
129
+ protected function query_and_attach_related_models_eagerly(Table $table, $models, $attributes, $includes=array(), $query_keys=array(), $model_values_keys=array())
130
+ {
131
+ $values = array();
132
+ $options = array();
133
+ $inflector = Inflector::instance();
134
+ $query_key = $query_keys[0];
135
+ $model_values_key = $model_values_keys[0];
136
+
137
+ foreach ($attributes as $column => $value)
138
+ $values[] = $value[$inflector->variablize($model_values_key)];
139
+
140
+ $values = array($values);
141
+ $options['conditions'] = SQLBuilder::create_conditions_from_underscored_string($table->conn,$query_key,$values);
142
+
143
+ if (!empty($includes))
144
+ $options['include'] = $includes;
145
+
146
+ $class = $this->class_name;
147
+
148
+ $related_models = $class::find('all', $options);
149
+ $used_models = array();
150
+ $model_values_key = $inflector->variablize($model_values_key);
151
+ $query_key = $inflector->variablize($query_key);
152
+
153
+ foreach ($models as $model)
154
+ {
155
+ $matches = 0;
156
+ $key_to_match = $model->$model_values_key;
157
+
158
+ foreach ($related_models as $related)
159
+ {
160
+ if ($related->$query_key == $key_to_match)
161
+ {
162
+ $hash = spl_object_hash($related);
163
+
164
+ if (in_array($hash, $used_models))
165
+ $model->set_relationship_from_eager_load(clone($related), $this->attribute_name);
166
+ else
167
+ $model->set_relationship_from_eager_load($related, $this->attribute_name);
168
+
169
+ $used_models[] = $hash;
170
+ $matches++;
171
+ }
172
+ }
173
+
174
+ if (0 === $matches)
175
+ $model->set_relationship_from_eager_load(null, $this->attribute_name);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Creates a new instance of specified {@link Model} with the attributes pre-loaded.
181
+ *
182
+ * @param Model $model The model which holds this association
183
+ * @param array $attributes Hash containing attributes to initialize the model with
184
+ * @return Model
185
+ */
186
+ public function build_association(Model $model, $attributes=array())
187
+ {
188
+ $class_name = $this->class_name;
189
+ return new $class_name($attributes);
190
+ }
191
+
192
+ /**
193
+ * Creates a new instance of {@link Model} and invokes save.
194
+ *
195
+ * @param Model $model The model which holds this association
196
+ * @param array $attributes Hash containing attributes to initialize the model with
197
+ * @return Model
198
+ */
199
+ public function create_association(Model $model, $attributes=array())
200
+ {
201
+ $class_name = $this->class_name;
202
+ $new_record = $class_name::create($attributes);
203
+ return $this->append_record_to_associate($model, $new_record);
204
+ }
205
+
206
+ protected function append_record_to_associate(Model $associate, Model $record)
207
+ {
208
+ $association =& $associate->{$this->attribute_name};
209
+
210
+ if ($this->poly_relationship)
211
+ $association[] = $record;
212
+ else
213
+ $association = $record;
214
+
215
+ return $record;
216
+ }
217
+
218
+ protected function merge_association_options($options)
219
+ {
220
+ $available_options = array_merge(self::$valid_association_options,static::$valid_association_options);
221
+ $valid_options = array_intersect_key(array_flip($available_options),$options);
222
+
223
+ foreach ($valid_options as $option => $v)
224
+ $valid_options[$option] = $options[$option];
225
+
226
+ return $valid_options;
227
+ }
228
+
229
+ protected function unset_non_finder_options($options)
230
+ {
231
+ foreach (array_keys($options) as $option)
232
+ {
233
+ if (!in_array($option, Model::$VALID_OPTIONS))
234
+ unset($options[$option]);
235
+ }
236
+ return $options;
237
+ }
238
+
239
+ protected function keyify($class_name)
240
+ {
241
+ return strtolower(classify(denamespace($class_name))). '_id';
242
+ }
243
+
244
+ /**
245
+ * Infers the $this->class_name based on $this->attribute_name.
246
+ *
247
+ * Will try to guess the appropriate class by singularizing and uppercasing $this->attribute_name.
248
+ *
249
+ * @return void
250
+ * @see attribute_name
251
+ */
252
+ protected function set_inferred_class_name()
253
+ {
254
+ $this->set_class_name(classify($this->attribute_name, true));
255
+ }
256
+
257
+ protected function set_class_name($class_name)
258
+ {
259
+ $reflection = Reflections::instance()->add($class_name)->get($class_name);
260
+
261
+ if (!$reflection->isSubClassOf('ActiveRecord\\Model'))
262
+ throw new RelationshipException("'$class_name' must extend from ActiveRecord\\Model");
263
+
264
+ $this->class_name = $class_name;
265
+ }
266
+
267
+ protected function create_conditions_from_keys(Model $model, $condition_keys=array(), $value_keys=array())
268
+ {
269
+ $condition_string = implode('_and_', $condition_keys);
270
+ $condition_values = array_values($model->get_values_for($value_keys));
271
+
272
+ // return null if all the foreign key values are null so that we don't try to do a query like "id is null"
273
+ if (all(null,$condition_values))
274
+ return null;
275
+
276
+ $conditions = SQLBuilder::create_conditions_from_underscored_string(Table::load(get_class($model))->conn,$condition_string,$condition_values);
277
+
278
+ # DO NOT CHANGE THE NEXT TWO LINES. add_condition operates on a reference and will screw options array up
279
+ if (isset($this->options['conditions']))
280
+ $options_conditions = $this->options['conditions'];
281
+ else
282
+ $options_conditions = array();
283
+
284
+ return Utils::add_condition($options_conditions, $conditions);
285
+ }
286
+
287
+ /**
288
+ * Creates INNER JOIN SQL for associations.
289
+ *
290
+ * @param Table $from_table the table used for the FROM SQL statement
291
+ * @param bool $using_through is this a THROUGH relationship?
292
+ * @param string $alias a table alias for when a table is being joined twice
293
+ * @return string SQL INNER JOIN fragment
294
+ */
295
+ public function construct_inner_join_sql(Table $from_table, $using_through=false, $alias=null)
296
+ {
297
+ if ($using_through)
298
+ {
299
+ $join_table = $from_table;
300
+ $join_table_name = $from_table->get_fully_qualified_table_name();
301
+ $from_table_name = Table::load($this->class_name)->get_fully_qualified_table_name();
302
+ }
303
+ else
304
+ {
305
+ $join_table = Table::load($this->class_name);
306
+ $join_table_name = $join_table->get_fully_qualified_table_name();
307
+ $from_table_name = $from_table->get_fully_qualified_table_name();
308
+ }
309
+
310
+ // need to flip the logic when the key is on the other table
311
+ if ($this instanceof HasMany || $this instanceof HasOne)
312
+ {
313
+ $this->set_keys($from_table->class->getName());
314
+
315
+ if ($using_through)
316
+ {
317
+ $foreign_key = $this->primary_key[0];
318
+ $join_primary_key = $this->foreign_key[0];
319
+ }
320
+ else
321
+ {
322
+ $join_primary_key = $this->foreign_key[0];
323
+ $foreign_key = $this->primary_key[0];
324
+ }
325
+ }
326
+ else
327
+ {
328
+ $foreign_key = $this->foreign_key[0];
329
+ $join_primary_key = $this->primary_key[0];
330
+ }
331
+
332
+ if (!is_null($alias))
333
+ {
334
+ $aliased_join_table_name = $alias = $this->get_table()->conn->quote_name($alias);
335
+ $alias .= ' ';
336
+ }
337
+ else
338
+ $aliased_join_table_name = $join_table_name;
339
+
340
+ return "INNER JOIN $join_table_name {$alias}ON($from_table_name.$foreign_key = $aliased_join_table_name.$join_primary_key)";
341
+ }
342
+
343
+ /**
344
+ * This will load the related model data.
345
+ *
346
+ * @param Model $model The model this relationship belongs to
347
+ */
348
+ abstract function load(Model $model);
349
+ };
350
+
351
+ /**
352
+ * One-to-many relationship.
353
+ *
354
+ * <code>
355
+ * # Table: people
356
+ * # Primary key: id
357
+ * # Foreign key: school_id
358
+ * class Person extends ActiveRecord\Model {}
359
+ *
360
+ * # Table: schools
361
+ * # Primary key: id
362
+ * class School extends ActiveRecord\Model {
363
+ * static $has_many = array(
364
+ * array('people')
365
+ * );
366
+ * });
367
+ * </code>
368
+ *
369
+ * Example using options:
370
+ *
371
+ * <code>
372
+ * class Payment extends ActiveRecord\Model {
373
+ * static $belongs_to = array(
374
+ * array('person'),
375
+ * array('order')
376
+ * );
377
+ * }
378
+ *
379
+ * class Order extends ActiveRecord\Model {
380
+ * static $has_many = array(
381
+ * array('people',
382
+ * 'through' => 'payments',
383
+ * 'select' => 'people.*, payments.amount',
384
+ * 'conditions' => 'payments.amount < 200')
385
+ * );
386
+ * }
387
+ * </code>
388
+ *
389
+ * @package ActiveRecord
390
+ * @see http://www.phpactiverecord.org/guides/associations
391
+ * @see valid_association_options
392
+ */
393
+ class HasMany extends AbstractRelationship
394
+ {
395
+ /**
396
+ * Valid options to use for a {@link HasMany} relationship.
397
+ *
398
+ * <ul>
399
+ * <li><b>limit/offset:</b> limit the number of records</li>
400
+ * <li><b>primary_key:</b> name of the primary_key of the association (defaults to "id")</li>
401
+ * <li><b>group:</b> GROUP BY clause</li>
402
+ * <li><b>order:</b> ORDER BY clause</li>
403
+ * <li><b>through:</b> name of a model</li>
404
+ * </ul>
405
+ *
406
+ * @var array
407
+ */
408
+ static protected $valid_association_options = array('primary_key', 'order', 'group', 'having', 'limit', 'offset', 'through', 'source');
409
+
410
+ protected $primary_key;
411
+
412
+ private $has_one = false;
413
+ private $through;
414
+
415
+ /**
416
+ * Constructs a {@link HasMany} relationship.
417
+ *
418
+ * @param array $options Options for the association
419
+ * @return HasMany
420
+ */
421
+ public function __construct($options=array())
422
+ {
423
+ parent::__construct($options);
424
+
425
+ if (isset($this->options['through']))
426
+ {
427
+ $this->through = $this->options['through'];
428
+
429
+ if (isset($this->options['source']))
430
+ $this->set_class_name($this->options['source']);
431
+ }
432
+
433
+ if (!$this->primary_key && isset($this->options['primary_key']))
434
+ $this->primary_key = is_array($this->options['primary_key']) ? $this->options['primary_key'] : array($this->options['primary_key']);
435
+
436
+ if (!$this->class_name)
437
+ $this->set_inferred_class_name();
438
+ }
439
+
440
+ protected function set_keys($model_class_name, $override=false)
441
+ {
442
+ //infer from class_name
443
+ if (!$this->foreign_key || $override)
444
+ $this->foreign_key = array($this->keyify($model_class_name));
445
+
446
+ if (!$this->primary_key || $override)
447
+ $this->primary_key = Table::load($model_class_name)->pk;
448
+ }
449
+
450
+ public function load(Model $model)
451
+ {
452
+ $class_name = $this->class_name;
453
+ $this->set_keys(get_class($model));
454
+
455
+ // since through relationships depend on other relationships we can't do
456
+ // this initiailization in the constructor since the other relationship
457
+ // may not have been created yet and we only want this to run once
458
+ if (!isset($this->initialized))
459
+ {
460
+ if ($this->through)
461
+ {
462
+ // verify through is a belongs_to or has_many for access of keys
463
+ if (!($through_relationship = $this->get_table()->get_relationship($this->through)))
464
+ throw new HasManyThroughAssociationException("Could not find the association $this->through in model " . get_class($model));
465
+
466
+ if (!($through_relationship instanceof HasMany) && !($through_relationship instanceof BelongsTo))
467
+ throw new HasManyThroughAssociationException('has_many through can only use a belongs_to or has_many association');
468
+
469
+ // save old keys as we will be reseting them below for inner join convenience
470
+ $pk = $this->primary_key;
471
+ $fk = $this->foreign_key;
472
+
473
+ $this->set_keys($this->get_table()->class->getName(), true);
474
+
475
+ $through_table = Table::load(classify($this->through, true));
476
+ $this->options['joins'] = $this->construct_inner_join_sql($through_table, true);
477
+
478
+ // reset keys
479
+ $this->primary_key = $pk;
480
+ $this->foreign_key = $fk;
481
+ }
482
+
483
+ $this->initialized = true;
484
+ }
485
+
486
+ if (!($conditions = $this->create_conditions_from_keys($model, $this->foreign_key, $this->primary_key)))
487
+ return null;
488
+
489
+ $options = $this->unset_non_finder_options($this->options);
490
+ $options['conditions'] = $conditions;
491
+ return $class_name::find($this->poly_relationship ? 'all' : 'first',$options);
492
+ }
493
+
494
+ private function inject_foreign_key_for_new_association(Model $model, &$attributes)
495
+ {
496
+ $this->set_keys($model);
497
+ $primary_key = Inflector::instance()->variablize($this->foreign_key[0]);
498
+
499
+ if (!isset($attributes[$primary_key]))
500
+ $attributes[$primary_key] = $model->id;
501
+
502
+ return $attributes;
503
+ }
504
+
505
+ public function build_association(Model $model, $attributes=array())
506
+ {
507
+ $attributes = $this->inject_foreign_key_for_new_association($model, $attributes);
508
+ return parent::build_association($model, $attributes);
509
+ }
510
+
511
+ public function create_association(Model $model, $attributes=array())
512
+ {
513
+ $attributes = $this->inject_foreign_key_for_new_association($model, $attributes);
514
+ return parent::create_association($model, $attributes);
515
+ }
516
+
517
+ public function load_eagerly($models=array(), $attributes=array(), $includes, Table $table)
518
+ {
519
+ $this->set_keys($table->class->name);
520
+ $this->query_and_attach_related_models_eagerly($table,$models,$attributes,$includes,$this->foreign_key, $table->pk);
521
+ }
522
+ };
523
+
524
+ /**
525
+ * One-to-one relationship.
526
+ *
527
+ * <code>
528
+ * # Table name: states
529
+ * # Primary key: id
530
+ * class State extends ActiveRecord\Model {}
531
+ *
532
+ * # Table name: people
533
+ * # Foreign key: state_id
534
+ * class Person extends ActiveRecord\Model {
535
+ * static $has_one = array(array('state'));
536
+ * }
537
+ * </code>
538
+ *
539
+ * @package ActiveRecord
540
+ * @see http://www.phpactiverecord.org/guides/associations
541
+ */
542
+ class HasOne extends HasMany
543
+ {
544
+ };
545
+
546
+ /**
547
+ * @todo implement me
548
+ * @package ActiveRecord
549
+ * @see http://www.phpactiverecord.org/guides/associations
550
+ */
551
+ class HasAndBelongsToMany extends AbstractRelationship
552
+ {
553
+ public function __construct($options=array())
554
+ {
555
+ /* options =>
556
+ * join_table - name of the join table if not in lexical order
557
+ * foreign_key -
558
+ * association_foreign_key - default is {assoc_class}_id
559
+ * uniq - if true duplicate assoc objects will be ignored
560
+ * validate
561
+ */
562
+ }
563
+
564
+ public function load(Model $model)
565
+ {
566
+
567
+ }
568
+ };
569
+
570
+ /**
571
+ * Belongs to relationship.
572
+ *
573
+ * <code>
574
+ * class School extends ActiveRecord\Model {}
575
+ *
576
+ * class Person extends ActiveRecord\Model {
577
+ * static $belongs_to = array(
578
+ * array('school')
579
+ * );
580
+ * }
581
+ * </code>
582
+ *
583
+ * Example using options:
584
+ *
585
+ * <code>
586
+ * class School extends ActiveRecord\Model {}
587
+ *
588
+ * class Person extends ActiveRecord\Model {
589
+ * static $belongs_to = array(
590
+ * array('school', 'primary_key' => 'school_id')
591
+ * );
592
+ * }
593
+ * </code>
594
+ *
595
+ * @package ActiveRecord
596
+ * @see valid_association_options
597
+ * @see http://www.phpactiverecord.org/guides/associations
598
+ */
599
+ class BelongsTo extends AbstractRelationship
600
+ {
601
+ public function __construct($options=array())
602
+ {
603
+ parent::__construct($options);
604
+
605
+ if (!$this->class_name)
606
+ $this->set_inferred_class_name();
607
+
608
+ //infer from class_name
609
+ if (!$this->foreign_key)
610
+ $this->foreign_key = array($this->keyify($this->class_name));
611
+
612
+ $this->primary_key = array(Table::load($this->class_name)->pk[0]);
613
+ }
614
+
615
+ public function load(Model $model)
616
+ {
617
+ $keys = array();
618
+ $inflector = Inflector::instance();
619
+
620
+ foreach ($this->foreign_key as $key)
621
+ $keys[] = $inflector->variablize($key);
622
+
623
+ if (!($conditions = $this->create_conditions_from_keys($model, $this->primary_key, $keys)))
624
+ return null;
625
+
626
+ $options = $this->unset_non_finder_options($this->options);
627
+ $options['conditions'] = $conditions;
628
+ $class = $this->class_name;
629
+ return $class::first($options);
630
+ }
631
+
632
+ public function load_eagerly($models=array(), $attributes, $includes, Table $table)
633
+ {
634
+ $this->query_and_attach_related_models_eagerly($table,$models,$attributes,$includes, $this->primary_key,$this->foreign_key);
635
+ }
636
+ };
637
+ ?>