my-simon 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/README.md +3 -20
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/my-simon.gemspec +3 -78
  5. metadata +2 -77
  6. data/DOC/Launch Check List.docx +0 -0
  7. data/DOC/Launch Check List.pdf +0 -0
  8. data/build/rakefile.rb +0 -12
  9. data/config.rb +0 -24
  10. data/scaffolding/simon/controller.tpl +0 -9
  11. data/scaffolding/simon/model.tpl +0 -10
  12. data/scaffolding/simon/view.tpl +0 -5
  13. data/scaffolding/standards/html_template.html +0 -44
  14. data/scaffolding/standards/html_template.php +0 -44
  15. data/scaffolding/standards/jquery_plugin_template.js +0 -45
  16. data/scaffolding/standards/js_template.js +0 -43
  17. data/www/.htaccess +0 -488
  18. data/www/404.html +0 -32
  19. data/www/crossdomain.xml +0 -25
  20. data/www/favicon.ico +0 -0
  21. data/www/index.php +0 -17
  22. data/www/lib/js/homePage.js +0 -43
  23. data/www/lib/js/jquery/JQbook.js +0 -809
  24. data/www/lib/js/jquery/jquery-1.8.0.min.js +0 -27
  25. data/www/lib/js/jquery/jquery.alphanumeric.js +0 -82
  26. data/www/lib/js/jquery/jquery.cookie.js +0 -96
  27. data/www/lib/js/jquery/jquery.easing.1.3.js +0 -207
  28. data/www/lib/js/main.js +0 -117
  29. data/www/lib/js/master.js +0 -6
  30. data/www/lib/js/plugins/handlebars-1.0.rc.1.js +0 -1920
  31. data/www/lib/js/plugins/modernizr-1.7.min.js +0 -2
  32. data/www/lib/js/plugins/swfobject.js +0 -777
  33. data/www/lib/js/plugins_mod/README.txt +0 -3
  34. data/www/lib/php/app.php +0 -53
  35. data/www/lib/php/controller/index.php +0 -10
  36. data/www/lib/php/controller/regex.php +0 -23
  37. data/www/lib/php/model/Book.php +0 -8
  38. data/www/lib/php/model/Model.php +0 -8
  39. data/www/lib/php/plugins/php-activerecord/ActiveRecord.php +0 -44
  40. data/www/lib/php/plugins/php-activerecord/lib/CallBack.php +0 -226
  41. data/www/lib/php/plugins/php-activerecord/lib/Column.php +0 -155
  42. data/www/lib/php/plugins/php-activerecord/lib/Config.php +0 -288
  43. data/www/lib/php/plugins/php-activerecord/lib/Connection.php +0 -456
  44. data/www/lib/php/plugins/php-activerecord/lib/ConnectionManager.php +0 -38
  45. data/www/lib/php/plugins/php-activerecord/lib/DateTime.php +0 -45
  46. data/www/lib/php/plugins/php-activerecord/lib/Exceptions.php +0 -137
  47. data/www/lib/php/plugins/php-activerecord/lib/Expressions.php +0 -183
  48. data/www/lib/php/plugins/php-activerecord/lib/Inflector.php +0 -115
  49. data/www/lib/php/plugins/php-activerecord/lib/Model.php +0 -1673
  50. data/www/lib/php/plugins/php-activerecord/lib/Reflections.php +0 -86
  51. data/www/lib/php/plugins/php-activerecord/lib/Relationship.php +0 -637
  52. data/www/lib/php/plugins/php-activerecord/lib/SQLBuilder.php +0 -396
  53. data/www/lib/php/plugins/php-activerecord/lib/Serialization.php +0 -302
  54. data/www/lib/php/plugins/php-activerecord/lib/Singleton.php +0 -57
  55. data/www/lib/php/plugins/php-activerecord/lib/Table.php +0 -547
  56. data/www/lib/php/plugins/php-activerecord/lib/Utils.php +0 -351
  57. data/www/lib/php/plugins/php-activerecord/lib/Validations.php +0 -833
  58. data/www/lib/php/plugins/php-activerecord/lib/adapters/MysqlAdapter.php +0 -73
  59. data/www/lib/php/plugins/php-activerecord/lib/adapters/OciAdapter.php +0 -121
  60. data/www/lib/php/plugins/php-activerecord/lib/adapters/PgsqlAdapter.php +0 -104
  61. data/www/lib/php/plugins/php-activerecord/lib/adapters/SqliteAdapter.php +0 -81
  62. data/www/lib/php/system/Config.php +0 -174
  63. data/www/lib/php/system/config.routes.php +0 -29
  64. data/www/lib/php/system/router.php +0 -220
  65. data/www/lib/php/template/footer.php +0 -59
  66. data/www/lib/php/template/header.php +0 -74
  67. data/www/lib/php/view/index.php +0 -5
  68. data/www/media/images/facebook_share.jpg +0 -0
  69. data/www/robots.txt +0 -5
  70. data/www/sandbox/readme.txt +0 -3
  71. data/www/sass/javascript.scss +0 -1
  72. data/www/sass/layout.scss +0 -128
  73. data/www/sass/master.scss +0 -4
  74. data/www/sass/reset.scss +0 -47
  75. data/www/sass/typography.scss +0 -24
  76. data/www/styles/javascript.css +0 -1
  77. data/www/styles/layout.css +0 -186
  78. data/www/styles/master.css +0 -4
  79. data/www/styles/reset.css +0 -60
  80. data/www/styles/typography.css +0 -24
@@ -1,351 +0,0 @@
1
- <?php
2
- /**
3
- *
4
- * @package ActiveRecord
5
- */
6
-
7
- /*
8
- * Thanks to http://www.eval.ca/articles/php-pluralize (MIT license)
9
- * http://dev.rubyonrails.org/browser/trunk/activesupport/lib/active_support/inflections.rb (MIT license)
10
- * http://www.fortunecity.com/bally/durrus/153/gramch13.html
11
- * http://www2.gsu.edu/~wwwesl/egw/crump.htm
12
- *
13
- * Changes (12/17/07)
14
- * Major changes
15
- * --
16
- * Fixed irregular noun algorithm to use regular expressions just like the original Ruby source.
17
- * (this allows for things like fireman -> firemen
18
- * Fixed the order of the singular array, which was backwards.
19
- *
20
- * Minor changes
21
- * --
22
- * Removed incorrect pluralization rule for /([^aeiouy]|qu)ies$/ => $1y
23
- * Expanded on the list of exceptions for *o -> *oes, and removed rule for buffalo -> buffaloes
24
- * Removed dangerous singularization rule for /([^f])ves$/ => $1fe
25
- * Added more specific rules for singularizing lives, wives, knives, sheaves, loaves, and leaves and thieves
26
- * Added exception to /(us)es$/ => $1 rule for houses => house and blouses => blouse
27
- * Added excpetions for feet, geese and teeth
28
- * Added rule for deer -> deer
29
- *
30
- * Changes:
31
- * Removed rule for virus -> viri
32
- * Added rule for potato -> potatoes
33
- * Added rule for *us -> *uses
34
- */
35
- namespace ActiveRecord;
36
-
37
- use \Closure;
38
-
39
- function classify($class_name, $singularize=false)
40
- {
41
- if ($singularize)
42
- {
43
- $parts = explode('_', Inflector::instance()->uncamelize($class_name));
44
- $class_name = '';
45
- foreach ($parts as $name)
46
- $class_name .= '_' . Utils::singularize($name);
47
-
48
- $class_name = ltrim($class_name, '_');
49
- }
50
-
51
- $class_name = Inflector::instance()->camelize($class_name);
52
-
53
- return ucfirst($class_name);
54
- }
55
-
56
- // http://snippets.dzone.com/posts/show/4660
57
- function array_flatten(array $array)
58
- {
59
- $i = 0;
60
- $n = count($array);
61
-
62
- while ($i < $n)
63
- {
64
- if (is_array($array[$i]))
65
- array_splice($array,$i,1,$array[$i]);
66
- else
67
- ++$i;
68
-
69
- $n = count($array);
70
- }
71
- return $array;
72
- }
73
-
74
- /**
75
- * Somewhat naive way to determine if an array is a hash.
76
- */
77
- function is_hash(&$array)
78
- {
79
- if (!is_array($array))
80
- return false;
81
-
82
- $keys = array_keys($array);
83
- return @is_string($keys[0]) ? true : false;
84
- }
85
-
86
- /**
87
- * Strips a class name of any namespaces and namespace operator.
88
- *
89
- * @param string $class
90
- * @return string stripped class name
91
- * @access public
92
- */
93
- function denamespace($class_name)
94
- {
95
- if (is_object($class_name))
96
- $class_name = get_class($class_name);
97
-
98
- if (has_namespace($class_name))
99
- {
100
- $parts = explode('\\', $class_name);
101
- return end($parts);
102
- }
103
- return $class_name;
104
- }
105
-
106
- function get_namespaces($class_name)
107
- {
108
- if (has_namespace($class_name))
109
- return explode('\\', $class_name);
110
- return null;
111
- }
112
-
113
- function has_namespace($class_name)
114
- {
115
- if (strpos($class_name, '\\') !== false)
116
- return true;
117
- return false;
118
- }
119
-
120
- /**
121
- * Returns true if all values in $haystack === $needle
122
- * @param $needle
123
- * @param $haystack
124
- * @return unknown_type
125
- */
126
- function all($needle, array $haystack)
127
- {
128
- foreach ($haystack as $value)
129
- {
130
- if ($value !== $needle)
131
- return false;
132
- }
133
- return true;
134
- }
135
-
136
- function collect(&$enumerable, $name_or_closure)
137
- {
138
- $ret = array();
139
-
140
- foreach ($enumerable as $value)
141
- {
142
- if (is_string($name_or_closure))
143
- $ret[] = is_array($value) ? $value[$name_or_closure] : $value->$name_or_closure;
144
- elseif ($name_or_closure instanceof Closure)
145
- $ret[] = $name_or_closure($value);
146
- }
147
- return $ret;
148
- }
149
-
150
- /**
151
- * Some internal utility functions.
152
- *
153
- * @package ActiveRecord
154
- */
155
- class Utils
156
- {
157
- public static function extract_options($options)
158
- {
159
- return is_array(end($options)) ? end($options) : array();
160
- }
161
-
162
- public static function add_condition(&$conditions=array(), $condition, $conjuction='AND')
163
- {
164
- if (is_array($condition))
165
- {
166
- if (empty($conditions))
167
- $conditions = array_flatten($condition);
168
- else
169
- {
170
- $conditions[0] .= " $conjuction " . array_shift($condition);
171
- $conditions[] = array_flatten($condition);
172
- }
173
- }
174
- elseif (is_string($condition))
175
- $conditions[0] .= " $conjuction $condition";
176
-
177
- return $conditions;
178
- }
179
-
180
- public static function human_attribute($attr)
181
- {
182
- $inflector = Inflector::instance();
183
- $inflected = $inflector->variablize($attr);
184
- $normal = $inflector->uncamelize($inflected);
185
-
186
- return ucfirst(str_replace('_', ' ', $normal));
187
- }
188
-
189
- public static function is_odd($number)
190
- {
191
- return $number & 1;
192
- }
193
-
194
- public static function is_a($type, $var)
195
- {
196
- switch($type)
197
- {
198
- case 'range':
199
- if (is_array($var) && (int)$var[0] < (int)$var[1])
200
- return true;
201
-
202
- }
203
-
204
- return false;
205
- }
206
-
207
- public static function is_blank($var)
208
- {
209
- return 0 === strlen($var);
210
- }
211
-
212
- private static $plural = array(
213
- '/(quiz)$/i' => "$1zes",
214
- '/^(ox)$/i' => "$1en",
215
- '/([m|l])ouse$/i' => "$1ice",
216
- '/(matr|vert|ind)ix|ex$/i' => "$1ices",
217
- '/(x|ch|ss|sh)$/i' => "$1es",
218
- '/([^aeiouy]|qu)y$/i' => "$1ies",
219
- '/(hive)$/i' => "$1s",
220
- '/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
221
- '/(shea|lea|loa|thie)f$/i' => "$1ves",
222
- '/sis$/i' => "ses",
223
- '/([ti])um$/i' => "$1a",
224
- '/(tomat|potat|ech|her|vet)o$/i'=> "$1oes",
225
- '/(bu)s$/i' => "$1ses",
226
- '/(alias)$/i' => "$1es",
227
- '/(octop)us$/i' => "$1i",
228
- '/(ax|test)is$/i' => "$1es",
229
- '/(us)$/i' => "$1es",
230
- '/s$/i' => "s",
231
- '/$/' => "s"
232
- );
233
-
234
- private static $singular = array(
235
- '/(quiz)zes$/i' => "$1",
236
- '/(matr)ices$/i' => "$1ix",
237
- '/(vert|ind)ices$/i' => "$1ex",
238
- '/^(ox)en$/i' => "$1",
239
- '/(alias)es$/i' => "$1",
240
- '/(octop|vir)i$/i' => "$1us",
241
- '/(cris|ax|test)es$/i' => "$1is",
242
- '/(shoe)s$/i' => "$1",
243
- '/(o)es$/i' => "$1",
244
- '/(bus)es$/i' => "$1",
245
- '/([m|l])ice$/i' => "$1ouse",
246
- '/(x|ch|ss|sh)es$/i' => "$1",
247
- '/(m)ovies$/i' => "$1ovie",
248
- '/(s)eries$/i' => "$1eries",
249
- '/([^aeiouy]|qu)ies$/i' => "$1y",
250
- '/([lr])ves$/i' => "$1f",
251
- '/(tive)s$/i' => "$1",
252
- '/(hive)s$/i' => "$1",
253
- '/(li|wi|kni)ves$/i' => "$1fe",
254
- '/(shea|loa|lea|thie)ves$/i'=> "$1f",
255
- '/(^analy)ses$/i' => "$1sis",
256
- '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
257
- '/([ti])a$/i' => "$1um",
258
- '/(n)ews$/i' => "$1ews",
259
- '/(h|bl)ouses$/i' => "$1ouse",
260
- '/(corpse)s$/i' => "$1",
261
- '/(us)es$/i' => "$1",
262
- '/s$/i' => ""
263
- );
264
-
265
- private static $irregular = array(
266
- 'move' => 'moves',
267
- 'foot' => 'feet',
268
- 'goose' => 'geese',
269
- 'sex' => 'sexes',
270
- 'child' => 'children',
271
- 'man' => 'men',
272
- 'tooth' => 'teeth',
273
- 'person' => 'people'
274
- );
275
-
276
- private static $uncountable = array(
277
- 'sheep',
278
- 'fish',
279
- 'deer',
280
- 'series',
281
- 'species',
282
- 'money',
283
- 'rice',
284
- 'information',
285
- 'equipment'
286
- );
287
-
288
- public static function pluralize( $string )
289
- {
290
- // save some time in the case that singular and plural are the same
291
- if ( in_array( strtolower( $string ), self::$uncountable ) )
292
- return $string;
293
-
294
- // check for irregular singular forms
295
- foreach ( self::$irregular as $pattern => $result )
296
- {
297
- $pattern = '/' . $pattern . '$/i';
298
-
299
- if ( preg_match( $pattern, $string ) )
300
- return preg_replace( $pattern, $result, $string);
301
- }
302
-
303
- // check for matches using regular expressions
304
- foreach ( self::$plural as $pattern => $result )
305
- {
306
- if ( preg_match( $pattern, $string ) )
307
- return preg_replace( $pattern, $result, $string );
308
- }
309
-
310
- return $string;
311
- }
312
-
313
- public static function singularize( $string )
314
- {
315
- // save some time in the case that singular and plural are the same
316
- if ( in_array( strtolower( $string ), self::$uncountable ) )
317
- return $string;
318
-
319
- // check for irregular plural forms
320
- foreach ( self::$irregular as $result => $pattern )
321
- {
322
- $pattern = '/' . $pattern . '$/i';
323
-
324
- if ( preg_match( $pattern, $string ) )
325
- return preg_replace( $pattern, $result, $string);
326
- }
327
-
328
- // check for matches using regular expressions
329
- foreach ( self::$singular as $pattern => $result )
330
- {
331
- if ( preg_match( $pattern, $string ) )
332
- return preg_replace( $pattern, $result, $string );
333
- }
334
-
335
- return $string;
336
- }
337
-
338
- public static function pluralize_if($count, $string)
339
- {
340
- if ($count == 1)
341
- return $string;
342
- else
343
- return self::pluralize($string);
344
- }
345
-
346
- public static function squeeze($char, $string)
347
- {
348
- return preg_replace("/$char+/",$char,$string);
349
- }
350
- };
351
- ?>
@@ -1,833 +0,0 @@
1
- <?php
2
- /**
3
- * These two classes have been <i>heavily borrowed</i> from Ruby on Rails' ActiveRecord so much that
4
- * this piece can be considered a straight port. The reason for this is that the vaildation process is
5
- * tricky due to order of operations/events. The former combined with PHP's odd typecasting means
6
- * that it was easier to formulate this piece base on the rails code.
7
- *
8
- * @package ActiveRecord
9
- */
10
-
11
- namespace ActiveRecord;
12
- use ActiveRecord\Model;
13
- use IteratorAggregate;
14
- use ArrayIterator;
15
-
16
- /**
17
- * Manages validations for a {@link Model}.
18
- *
19
- * This class isn't meant to be directly used. Instead you define
20
- * validators thru static variables in your {@link Model}. Example:
21
- *
22
- * <code>
23
- * class Person extends ActiveRecord\Model {
24
- * static $validates_length_of = array(
25
- * array('name', 'within' => array(30,100),
26
- * array('state', 'is' => 2)
27
- * );
28
- * }
29
- *
30
- * $person = new Person();
31
- * $person->name = 'Tito';
32
- * $person->state = 'this is not two characters';
33
- *
34
- * if (!$person->is_valid())
35
- * print_r($person->errors);
36
- * </code>
37
- *
38
- * @package ActiveRecord
39
- * @see Errors
40
- * @link http://www.phpactiverecord.org/guides/validations
41
- */
42
- class Validations
43
- {
44
- private $model;
45
- private $options = array();
46
- private $validators = array();
47
- private $record;
48
-
49
- private static $VALIDATION_FUNCTIONS = array(
50
- 'validates_presence_of',
51
- 'validates_size_of',
52
- 'validates_length_of',
53
- 'validates_inclusion_of',
54
- 'validates_exclusion_of',
55
- 'validates_format_of',
56
- 'validates_numericality_of',
57
- 'validates_uniqueness_of'
58
- );
59
-
60
- private static $DEFAULT_VALIDATION_OPTIONS = array(
61
- 'on' => 'save',
62
- 'allow_null' => false,
63
- 'allow_blank' => false,
64
- 'message' => null,
65
- );
66
-
67
- private static $ALL_RANGE_OPTIONS = array(
68
- 'is' => null,
69
- 'within' => null,
70
- 'in' => null,
71
- 'minimum' => null,
72
- 'maximum' => null,
73
- );
74
-
75
- private static $ALL_NUMERICALITY_CHECKS = array(
76
- 'greater_than' => null,
77
- 'greater_than_or_equal_to' => null,
78
- 'equal_to' => null,
79
- 'less_than' => null,
80
- 'less_than_or_equal_to' => null,
81
- 'odd' => null,
82
- 'even' => null
83
- );
84
-
85
- /**
86
- * Constructs a {@link Validations} object.
87
- *
88
- * @param Model $model The model to validate
89
- * @return Validations
90
- */
91
- public function __construct(Model $model)
92
- {
93
- $this->model = $model;
94
- $this->record = new Errors($this->model);
95
- $this->validators = array_intersect(array_keys(Reflections::instance()->get(get_class($this->model))->getStaticProperties()), self::$VALIDATION_FUNCTIONS);
96
- }
97
-
98
- /**
99
- * Returns validator data.
100
- *
101
- * @return array
102
- */
103
- public function rules()
104
- {
105
- $data = array();
106
- $reflection = Reflections::instance()->get(get_class($this->model));
107
-
108
- foreach ($this->validators as $validate)
109
- {
110
- $attrs = $reflection->getStaticPropertyValue($validate);
111
-
112
- foreach ($attrs as $attr)
113
- {
114
- $field = $attr[0];
115
-
116
- if (!isset($data[$field]) || !is_array($data[$field]))
117
- $data[$field] = array();
118
-
119
- $attr['validator'] = $validate;
120
- unset($attr[0]);
121
- array_push($data[$field],$attr);
122
- }
123
- }
124
- return $data;
125
- }
126
-
127
- /**
128
- * Runs the validators.
129
- *
130
- * @return Errors the validation errors if any
131
- */
132
- public function validate()
133
- {
134
- $reflection = Reflections::instance()->get(get_class($this->model));
135
-
136
- foreach ($this->validators as $validate)
137
- $this->$validate($reflection->getStaticPropertyValue($validate));
138
-
139
- $this->record->clear_model();
140
- return $this->record;
141
- }
142
-
143
- /**
144
- * Validates a field is not null and not blank.
145
- *
146
- * <code>
147
- * class Person extends ActiveRecord\Model {
148
- * static $validates_presence_of = array(
149
- * array('first_name'),
150
- * array('last_name')
151
- * );
152
- * }
153
- * </code>
154
- *
155
- * Available options:
156
- *
157
- * <ul>
158
- * <li><b>message:</b> custom error message</li>
159
- * </ul>
160
- *
161
- * @param array $attrs Validation definition
162
- */
163
- public function validates_presence_of($attrs)
164
- {
165
- $configuration = array_merge(self::$DEFAULT_VALIDATION_OPTIONS, array('message' => Errors::$DEFAULT_ERROR_MESSAGES['blank'], 'on' => 'save'));
166
-
167
- foreach ($attrs as $attr)
168
- {
169
- $options = array_merge($configuration, $attr);
170
- $this->record->add_on_blank($options[0], $options['message']);
171
- }
172
- }
173
-
174
- /**
175
- * Validates that a value is included the specified array.
176
- *
177
- * <code>
178
- * class Car extends ActiveRecord\Model {
179
- * static $validates_inclusion_of = array(
180
- * array('fuel_type', 'in' => array('hyrdogen', 'petroleum', 'electric')),
181
- * );
182
- * }
183
- * </code>
184
- *
185
- * Available options:
186
- *
187
- * <ul>
188
- * <li><b>in/within:</b> attribute should/shouldn't be a value within an array</li>
189
- * <li><b>message:</b> custome error message</li>
190
- * </ul>
191
- *
192
- * @param array $attrs Validation definition
193
- */
194
- public function validates_inclusion_of($attrs)
195
- {
196
- $this->validates_inclusion_or_exclusion_of('inclusion', $attrs);
197
- }
198
-
199
- /**
200
- * This is the opposite of {@link validates_include_of}.
201
- *
202
- * @param array $attrs Validation definition
203
- * @see validates_inclusion_of
204
- */
205
- public function validates_exclusion_of($attrs)
206
- {
207
- $this->validates_inclusion_or_exclusion_of('exclusion', $attrs);
208
- }
209
-
210
- /**
211
- * Validates that a value is in or out of a specified list of values.
212
- *
213
- * @see validates_inclusion_of
214
- * @see validates_exclusion_of
215
- * @param string $type Either inclusion or exclusion
216
- * @param $attrs Validation definition
217
- */
218
- public function validates_inclusion_or_exclusion_of($type, $attrs)
219
- {
220
- $configuration = array_merge(self::$DEFAULT_VALIDATION_OPTIONS, array('message' => Errors::$DEFAULT_ERROR_MESSAGES[$type], 'on' => 'save'));
221
-
222
- foreach ($attrs as $attr)
223
- {
224
- $options = array_merge($configuration, $attr);
225
- $attribute = $options[0];
226
- $var = $this->model->$attribute;
227
-
228
- if (isset($options['in']))
229
- $enum = $options['in'];
230
- elseif (isset($options['within']))
231
- $enum = $options['within'];
232
-
233
- if (!is_array($enum))
234
- array($enum);
235
-
236
- $message = str_replace('%s', $var, $options['message']);
237
-
238
- if ($this->is_null_with_option($var, $options) || $this->is_blank_with_option($var, $options))
239
- continue;
240
-
241
- if (('inclusion' == $type && !in_array($var, $enum)) || ('exclusion' == $type && in_array($var, $enum)))
242
- $this->record->add($attribute, $message);
243
- }
244
- }
245
-
246
- /**
247
- * Validates that a value is numeric.
248
- *
249
- * <code>
250
- * class Person extends ActiveRecord\Model {
251
- * static $validates_numericality_of = array(
252
- * array('salary', 'greater_than' => 19.99, 'less_than' => 99.99)
253
- * );
254
- * }
255
- * </code>
256
- *
257
- * Available options:
258
- *
259
- * <ul>
260
- * <li><b>only_integer:</b> value must be an integer (e.g. not a float)</li>
261
- * <li><b>even:</b> must be even</li>
262
- * <li><b>odd:</b> must be odd"</li>
263
- * <li><b>greater_than:</b> must be greater than specified number</li>
264
- * <li><b>greater_than_or_equal_to:</b> must be greater than or equal to specified number</li>
265
- * <li><b>equal_to:</b> ...</li>
266
- * <li><b>less_than:</b> ...</li>
267
- * <li><b>less_than_or_equal_to:</b> ...</li>
268
- * </ul>
269
- *
270
- * @param array $attrs Validation definition
271
- */
272
- public function validates_numericality_of($attrs)
273
- {
274
- $configuration = array_merge(self::$DEFAULT_VALIDATION_OPTIONS, array('only_integer' => false));
275
-
276
- // Notice that for fixnum and float columns empty strings are converted to nil.
277
- // Validates whether the value of the specified attribute is numeric by trying to convert it to a float with Kernel.Float
278
- // (if only_integer is false) or applying it to the regular expression /\A[+\-]?\d+\Z/ (if only_integer is set to true).
279
- foreach ($attrs as $attr)
280
- {
281
- $options = array_merge($configuration, $attr);
282
- $attribute = $options[0];
283
- $var = $this->model->$attribute;
284
-
285
- $numericalityOptions = array_intersect_key(self::$ALL_NUMERICALITY_CHECKS, $options);
286
-
287
- if ($this->is_null_with_option($var, $options))
288
- continue;
289
-
290
- if (true === $options['only_integer'] && !is_integer($var))
291
- {
292
- if (!preg_match('/\A[+-]?\d+\Z/', (string)($var)))
293
- {
294
- if (isset($options['message']))
295
- $message = $options['message'];
296
- else
297
- $message = Errors::$DEFAULT_ERROR_MESSAGES['not_a_number'];
298
-
299
- $this->record->add($attribute, $message);
300
- continue;
301
- }
302
- }
303
- else
304
- {
305
- if (!is_numeric($var))
306
- {
307
- $this->record->add($attribute, Errors::$DEFAULT_ERROR_MESSAGES['not_a_number']);
308
- continue;
309
- }
310
-
311
- $var = (float)$var;
312
- }
313
-
314
- foreach ($numericalityOptions as $option => $check)
315
- {
316
- $option_value = $options[$option];
317
-
318
- if ('odd' != $option && 'even' != $option)
319
- {
320
- $option_value = (float)$options[$option];
321
-
322
- if (!is_numeric($option_value))
323
- throw new ValidationsArgumentError("$option must be a number");
324
-
325
- if (isset($options['message']))
326
- $message = $options['message'];
327
- else
328
- $message = Errors::$DEFAULT_ERROR_MESSAGES[$option];
329
-
330
- $message = str_replace('%d', $option_value, $message);
331
-
332
- if ('greater_than' == $option && !($var > $option_value))
333
- $this->record->add($attribute, $message);
334
-
335
- elseif ('greater_than_or_equal_to' == $option && !($var >= $option_value))
336
- $this->record->add($attribute, $message);
337
-
338
- elseif ('equal_to' == $option && !($var == $option_value))
339
- $this->record->add($attribute, $message);
340
-
341
- elseif ('less_than' == $option && !($var < $option_value))
342
- $this->record->add($attribute, $message);
343
-
344
- elseif ('less_than_or_equal_to' == $option && !($var <= $option_value))
345
- $this->record->add($attribute, $message);
346
- }
347
- else
348
- {
349
- if (isset($options['message']))
350
- $message = $options['message'];
351
- else
352
- $message = Errors::$DEFAULT_ERROR_MESSAGES[$option];
353
-
354
- if ( ('odd' == $option && !( Utils::is_odd($var))) || ('even' == $option && ( Utils::is_odd($var))))
355
- $this->record->add($attribute, $message);
356
- }
357
- }
358
- }
359
- }
360
-
361
- /**
362
- * Alias of {@link validates_length_of}
363
- *
364
- * @param array $attrs Validation definition
365
- */
366
- public function validates_size_of($attrs)
367
- {
368
- $this->validates_length_of($attrs);
369
- }
370
-
371
- /**
372
- * Validates that a value is matches a regex.
373
- *
374
- * <code>
375
- * class Person extends ActiveRecord\Model {
376
- * static $validates_format_of = array(
377
- * array('email', 'with' => '/^.*?@.*$/')
378
- * );
379
- * }
380
- * </code>
381
- *
382
- * Available options:
383
- *
384
- * <ul>
385
- * <li><b>with:</b> a regular expression</li>
386
- * <li><b>message:</b> custom error message</li>
387
- * </ul>
388
- *
389
- * @param array $attrs Validation definition
390
- */
391
- public function validates_format_of($attrs)
392
- {
393
- $configuration = array_merge(self::$DEFAULT_VALIDATION_OPTIONS, array('message' => Errors::$DEFAULT_ERROR_MESSAGES['invalid'], 'on' => 'save', 'with' => null));
394
-
395
- foreach ($attrs as $attr)
396
- {
397
- $options = array_merge($configuration, $attr);
398
- $attribute = $options[0];
399
- $var = $this->model->$attribute;
400
-
401
- if (is_null($options['with']) || !is_string($options['with']) || !is_string($options['with']))
402
- throw new ValidationsArgumentError('A regular expression must be supplied as the [with] option of the configuration array.');
403
- else
404
- $expression = $options['with'];
405
-
406
- if ($this->is_null_with_option($var, $options) || $this->is_blank_with_option($var, $options))
407
- continue;
408
-
409
- if (!@preg_match($expression, $var))
410
- $this->record->add($attribute, $options['message']);
411
- }
412
- }
413
-
414
- /**
415
- * Validates the length of a value.
416
- *
417
- * <code>
418
- * class Person extends ActiveRecord\Model {
419
- * static $validates_length_of = array(
420
- * array('name', 'within' => array(1,50))
421
- * );
422
- * }
423
- * </code>
424
- *
425
- * Available options:
426
- *
427
- * <ul>
428
- * <li><b>is:</b> attribute should be exactly n characters long</li>
429
- * <li><b>in/within:</b> attribute should be within an range array(min,max)</li>
430
- * <li><b>maximum/minimum:</b> attribute should not be above/below respectively</li>
431
- * </ul>
432
- *
433
- * @param array $attrs Validation definition
434
- */
435
- public function validates_length_of($attrs)
436
- {
437
- $configuration = array_merge(self::$DEFAULT_VALIDATION_OPTIONS, array(
438
- 'too_long' => Errors::$DEFAULT_ERROR_MESSAGES['too_long'],
439
- 'too_short' => Errors::$DEFAULT_ERROR_MESSAGES['too_short'],
440
- 'wrong_length' => Errors::$DEFAULT_ERROR_MESSAGES['wrong_length']
441
- ));
442
-
443
- foreach ($attrs as $attr)
444
- {
445
- $options = array_merge($configuration, $attr);
446
- $range_options = array_intersect(array_keys(self::$ALL_RANGE_OPTIONS), array_keys($attr));
447
- sort($range_options);
448
-
449
- switch (sizeof($range_options))
450
- {
451
- case 0:
452
- throw new ValidationsArgumentError('Range unspecified. Specify the [within], [maximum], or [is] option.');
453
-
454
- case 1:
455
- break;
456
-
457
- default:
458
- throw new ValidationsArgumentError('Too many range options specified. Choose only one.');
459
- }
460
-
461
- $attribute = $options[0];
462
- $var = $this->model->$attribute;
463
- $range_option = $range_options[0];
464
-
465
- if ($this->is_null_with_option($var, $options) || $this->is_blank_with_option($var, $options))
466
- continue;
467
-
468
- if ('within' == $range_option || 'in' == $range_option)
469
- {
470
- $range = $options[$range_options[0]];
471
-
472
- if (!(Utils::is_a('range', $range)))
473
- throw new ValidationsArgumentError("$range_option must be an array composing a range of numbers with key [0] being less than key [1]");
474
-
475
- if (is_float($range[0]) || is_float($range[1]))
476
- throw new ValidationsArgumentError("Range values cannot use floats for length.");
477
-
478
- if ((int)$range[0] <= 0 || (int)$range[1] <= 0)
479
- throw new ValidationsArgumentError("Range values cannot use signed integers.");
480
-
481
- $too_short = isset($options['message']) ? $options['message'] : $options['too_short'];
482
- $too_long = isset($options['message']) ? $options['message'] : $options['too_long'];
483
-
484
- $too_short = str_replace('%d', $range[0], $too_short);
485
- $too_long = str_replace('%d', $range[1], $too_long);
486
-
487
- if (strlen($this->model->$attribute) < (int)$range[0])
488
- $this->record->add($attribute, $too_short);
489
- elseif (strlen($this->model->$attribute) > (int)$range[1])
490
- $this->record->add($attribute, $too_long);
491
- }
492
-
493
- elseif ('is' == $range_option || 'minimum' == $range_option || 'maximum' == $range_option)
494
- {
495
- $option = $options[$range_option];
496
-
497
- if ((int)$option <= 0)
498
- throw new ValidationsArgumentError("$range_option value cannot use a signed integer.");
499
-
500
- if (is_float($option))
501
- throw new ValidationsArgumentError("$range_option value cannot use a float for length.");
502
-
503
- if (!is_null($this->model->$attribute))
504
- {
505
- $messageOptions = array('is' => 'wrong_length', 'minimum' => 'too_short', 'maximum' => 'too_long');
506
-
507
- if (isset($options[$messageOptions[$range_option]]))
508
- $message = $options[$messageOptions[$range_option]];
509
- else
510
- $message = $options['message'];
511
-
512
- $message = str_replace('%d', $option, $message);
513
- $attribute_value = $this->model->$attribute;
514
- $len = strlen($attribute_value);
515
- $value = (int)$attr[$range_option];
516
-
517
- if ('maximum' == $range_option && $len > $value)
518
- $this->record->add($attribute, $message);
519
-
520
- if ('minimum' == $range_option && $len < $value)
521
- $this->record->add($attribute, $message);
522
-
523
- if ('is' == $range_option && $len !== $value)
524
- $this->record->add($attribute, $message);
525
- }
526
- }
527
- }
528
- }
529
-
530
- /**
531
- * Validates the uniqueness of a value.
532
- *
533
- * <code>
534
- * class Person extends ActiveRecord\Model {
535
- * static $validates_uniqueness_of = array(
536
- * array('name'),
537
- * array(array('blah','bleh'), 'message' => 'blech')
538
- * );
539
- * }
540
- * </code>
541
- *
542
- * @param array $attrs Validation definition
543
- */
544
- public function validates_uniqueness_of($attrs)
545
- {
546
- $configuration = array_merge(self::$DEFAULT_VALIDATION_OPTIONS, array(
547
- 'message' => Errors::$DEFAULT_ERROR_MESSAGES['unique']
548
- ));
549
-
550
- foreach ($attrs as $attr)
551
- {
552
- $options = array_merge($configuration, $attr);
553
- $pk = $this->model->get_primary_key();
554
- $pk_value = $this->model->$pk[0];
555
-
556
- if (is_array($options[0]))
557
- {
558
- $add_record = join("_and_", $options[0]);
559
- $fields = $options[0];
560
- }
561
- else
562
- {
563
- $add_record = $options[0];
564
- $fields = array($options[0]);
565
- }
566
-
567
- $sql = "";
568
- $conditions = array("");
569
-
570
- if ($pk_value === null)
571
- $sql = "{$pk[0]} is not null";
572
- else
573
- {
574
- $sql = "{$pk[0]}!=?";
575
- array_push($conditions,$pk_value);
576
- }
577
-
578
- foreach ($fields as $field)
579
- {
580
- $field = $this->model->get_real_attribute_name($field);
581
- $sql .= " and {$field}=?";
582
- array_push($conditions,$this->model->$field);
583
- }
584
-
585
- $conditions[0] = $sql;
586
-
587
- if ($this->model->exists(array('conditions' => $conditions)))
588
- $this->record->add($add_record, $options['message']);
589
- }
590
- }
591
-
592
- private function is_null_with_option($var, &$options)
593
- {
594
- return (is_null($var) && (isset($options['allow_null']) && $options['allow_null']));
595
- }
596
-
597
- private function is_blank_with_option($var, &$options)
598
- {
599
- return (Utils::is_blank($var) && (isset($options['allow_blank']) && $options['allow_blank']));
600
- }
601
- }
602
-
603
- /**
604
- * Class that holds {@link Validations} errors.
605
- *
606
- * @package ActiveRecord
607
- */
608
- class Errors implements IteratorAggregate
609
- {
610
- private $model;
611
- private $errors;
612
-
613
- public static $DEFAULT_ERROR_MESSAGES = array(
614
- 'inclusion' => "is not included in the list",
615
- 'exclusion' => "is reserved",
616
- 'invalid' => "is invalid",
617
- 'confirmation' => "doesn't match confirmation",
618
- 'accepted' => "must be accepted",
619
- 'empty' => "can't be empty",
620
- 'blank' => "can't be blank",
621
- 'too_long' => "is too long (maximum is %d characters)",
622
- 'too_short' => "is too short (minimum is %d characters)",
623
- 'wrong_length' => "is the wrong length (should be %d characters)",
624
- 'taken' => "has already been taken",
625
- 'not_a_number' => "is not a number",
626
- 'greater_than' => "must be greater than %d",
627
- 'equal_to' => "must be equal to %d",
628
- 'less_than' => "must be less than %d",
629
- 'odd' => "must be odd",
630
- 'even' => "must be even",
631
- 'unique' => "must be unique",
632
- 'less_than_or_equal_to' => "must be less than or equal to %d",
633
- 'greater_than_or_equal_to' => "must be greater than or equal to %d"
634
- );
635
-
636
- /**
637
- * Constructs an {@link Errors} object.
638
- *
639
- * @param Model $model The model the error is for
640
- * @return Errors
641
- */
642
- public function __construct(Model $model)
643
- {
644
- $this->model = $model;
645
- }
646
-
647
- /**
648
- * Nulls $model so we don't get pesky circular references. $model is only needed during the
649
- * validation process and so can be safely cleared once that is done.
650
- */
651
- public function clear_model()
652
- {
653
- $this->model = null;
654
- }
655
-
656
- /**
657
- * Add an error message.
658
- *
659
- * @param string $attribute Name of an attribute on the model
660
- * @param string $msg The error message
661
- */
662
- public function add($attribute, $msg)
663
- {
664
- if (is_null($msg))
665
- $msg = self :: $DEFAULT_ERROR_MESSAGES['invalid'];
666
-
667
- if (!isset($this->errors[$attribute]))
668
- $this->errors[$attribute] = array($msg);
669
- else
670
- $this->errors[$attribute][] = $msg;
671
- }
672
-
673
- /**
674
- * Adds an error message only if the attribute value is {@link http://www.php.net/empty empty}.
675
- *
676
- * @param string $attribute Name of an attribute on the model
677
- * @param string $msg The error message
678
- */
679
- public function add_on_empty($attribute, $msg)
680
- {
681
- if (empty($msg))
682
- $msg = self::$DEFAULT_ERROR_MESSAGES['empty'];
683
-
684
- if (empty($this->model->$attribute))
685
- $this->add($attribute, $msg);
686
- }
687
-
688
- /**
689
- * Retrieve error message for an attribute.
690
- *
691
- * @param string $attribute Name of an attribute on the model
692
- * @return string
693
- */
694
- public function __get($attribute)
695
- {
696
- if (!isset($this->errors[$attribute]))
697
- return null;
698
-
699
- return $this->errors[$attribute];
700
- }
701
-
702
- /**
703
- * Adds the error message only if the attribute value was null or an empty string.
704
- *
705
- * @param string $attribute Name of an attribute on the model
706
- * @param string $msg The error message
707
- */
708
- public function add_on_blank($attribute, $msg)
709
- {
710
- if (!$msg)
711
- $msg = self::$DEFAULT_ERROR_MESSAGES['blank'];
712
-
713
- if (($value = $this->model->$attribute) === '' || $value === null)
714
- $this->add($attribute, $msg);
715
- }
716
-
717
- /**
718
- * Returns true if the specified attribute had any error messages.
719
- *
720
- * @param string $attribute Name of an attribute on the model
721
- * @return boolean
722
- */
723
- public function is_invalid($attribute)
724
- {
725
- return isset($this->errors[$attribute]);
726
- }
727
-
728
- /**
729
- * Returns the error message for the specified attribute or null if none.
730
- *
731
- * @param string $attribute Name of an attribute on the model
732
- * @return string
733
- */
734
- public function on($attribute)
735
- {
736
- if (!isset($this->errors[$attribute]))
737
- return null;
738
-
739
- $errors = $this->errors[$attribute];
740
-
741
- if (null === $errors)
742
- return null;
743
- else
744
- return count($errors) == 1 ? $errors[0] : $errors;
745
- }
746
-
747
- /**
748
- * Returns all the error messages as an array.
749
- *
750
- * <code>
751
- * $model->errors->full_messages();
752
- *
753
- * # array(
754
- * # "Name can't be blank",
755
- * # "State is the wrong length (should be 2 chars)"
756
- * # )
757
- * </code>
758
- *
759
- * @param array $options Options for messages
760
- * @return array
761
- */
762
- public function full_messages()
763
- {
764
- $full_messages = array();
765
-
766
- if ($this->errors)
767
- {
768
- foreach ($this->errors as $attribute => $messages)
769
- {
770
- foreach ($messages as $msg)
771
- {
772
- if (is_null($msg))
773
- continue;
774
-
775
- $full_messages[] = Utils::human_attribute($attribute) . ' ' . $msg;
776
- }
777
- }
778
- }
779
- return $full_messages;
780
- }
781
-
782
- /**
783
- * Returns true if there are no error messages.
784
- * @return boolean
785
- */
786
- public function is_empty()
787
- {
788
- return empty($this->errors);
789
- }
790
-
791
- /**
792
- * Clears out all error messages.
793
- */
794
- public function clear()
795
- {
796
- $this->errors = array();
797
- }
798
-
799
- /**
800
- * Returns the number of error messages there are.
801
- * @return int
802
- */
803
- public function size()
804
- {
805
- if ($this->is_empty())
806
- return 0;
807
-
808
- $count = 0;
809
-
810
- foreach ($this->errors as $attribute => $error)
811
- $count += count($error);
812
-
813
- return $count;
814
- }
815
-
816
- /**
817
- * Returns an iterator to the error messages.
818
- *
819
- * This will allow you to iterate over the {@link Errors} object using foreach.
820
- *
821
- * <code>
822
- * foreach ($model->errors as $msg)
823
- * echo "$msg\n";
824
- * </code>
825
- *
826
- * @return ArrayIterator
827
- */
828
- public function getIterator()
829
- {
830
- return new ArrayIterator($this->full_messages());
831
- }
832
- };
833
- ?>