/** * Serve fields anotation and description * * @param string Field general rule * @param array Field custom rule * @param string Field anotation * @return void */ public static final function field($type = '', $args = array(), $schema = '') { $rules = array(); $args = is_array($args) ? $args : (array) $args; $annotations = array(); // Diagnose the type pattern if (preg_match('/^([^)]+)\\[(.*?)\\]$/', $type, $m) and count($m) == 3) { // Parsing [n,n] $type = $m[1]; $constraint = explode(',', $m[2]); if (count($constraint) == 2) { $rules[] = 'min_length[' . trim($constraint[0]) . ']'; $rules[] = 'max_length[' . trim($constraint[1]) . ']'; $annotations[] = trim($constraint[1]); } else { $rules[] = 'max_length[' . $constraint[0] . ']'; $annotations[] = $constraint[0]; } } // Determine each type into its validation rule respectively switch ($type) { case 'auto': $rules[] = 'callback_auto_check'; // Add exception for database spec if (self::driver('mysql')) { $annotations[] = 'INT'; $annotations[] = 'unsigned'; $annotations[] = 'auto_increment'; } elseif (self::driver('postgre')) { $annotations[] = 'SERIAL'; } else { $annotations[] = 'INTEGER'; } break; case 'datetime': $rules[] = 'callback_date_check'; $annotations[] = 'DATETIME'; break; case 'string': $rules[] = 'callback_char_check'; if (self::driver('postgre')) { $annotations[] = 'VARCHAR'; } else { $annotations[] = 'TEXT'; } break; case 'spatial': $rules[] = 'callback_char_check'; $annotations[] = 'GEOMETRY'; break; case 'char': $rules[] = 'callback_char_check'; $annotations[] = 'VARCHAR'; break; case 'numeric': $rules[] = 'numeric'; // Add exception for mysql if (self::driver('mysql')) { $annotations[] = 'TINYINT'; } else { $annotations[] = 'INTEGER'; } break; case 'int': $rules[] = 'integer'; // Add exception for mysql if (self::driver('mysql')) { $annotations[] = 'INT'; } else { $annotations[] = 'INTEGER'; } break; case 'email': $rules[] = 'valid_email'; $annotations[] = 'VARCHAR'; break; } // Are there other annotations? $other_annotations = explode(',', $schema); // If yes, then merge it with above if (!empty($other_annotations)) { $other_annotations = Janitor::arr_trim($other_annotations); $annotations = array_merge($annotations, $other_annotations); } // Merge the rules and separate between internal callback // And CI validation rules $callbacks = array(); $rules = array_merge($rules, $args); foreach ($rules as $index => $rule) { if (strpos($rule, 'callback') === 0) { $callbacks[] = str_replace('callback', '', $rule); unset($rules[$index]); } } // We now have define all rules, callbacks and annotations return array('rules' => implode('|', $rules), 'callbacks' => $callbacks, 'annotations' => $annotations); }
/** * Overloading static method triggered when invoking special method. * * @param string * @param array * @return mixed */ public static function __callStatic($name, $args) { // Defined DBAL component $dbal = array('forge', 'util'); if (in_array($name, $dbal)) { // Return corresponding component (DB Forge or DB Util) $dbal_component = 'db' . $name; return static::${$dbal_component}; } elseif ($name == 'insert_id' && isset(static::$db->pdodriver) && static::$db->pdodriver == 'pgsql') { return static::$db->conn_id->lastInsertId(); } elseif ($name == 'last_created') { // Get last created entry if (($last_id = static::$db->insert_id()) && empty($last_id)) { // Nothing return NULL; } // Return the corresponding model instance with last id $gas = array_shift($args); return self::find($gas, array($last_id)); } elseif (preg_match('/^find_by_([^)]+)$/', $name, $m) && count($m) == 2) { // Get the instance, passed field and value for WHERE condition $gas = array_shift($args); $field = $m[1]; $value = array_shift($args); // Build the task onto the Gas instance $gas->recorder->set('where', array($field, $value)); $multirow = is_array($args) && !empty($args) ? current($args) : TRUE; return self::all($gas, $multirow); } elseif (preg_match('/^(min|max|avg|sum)$/', $name, $m) && count($m) == 2) { // Get the instance, passed arguments for SELECT condition $gas = array_shift($args); $type = $m[1]; $value = array_shift($args); $value = empty($value) ? $gas->primary_key : $value; // Build the task onto the Gas instance $gas->recorder->set('select_' . $type, array($value)); return self::all($gas, FALSE); } elseif (preg_match('/^(first|last)$/', $name, $m) && count($m) == 2) { // Get the instance, passed arguments for ORDER BY condition $gas = array_shift($args); $order = $m[1] == 'first' ? 'asc' : 'desc'; $collumn = array_shift($args); $collumn = is_null($collumn) ? $gas->primary_key : $collumn; // Build the task onto the Gas instance $gas->recorder->set('order_by', array($collumn, $order)); $gas->recorder->set('limit', array('1')); return self::all($gas, FALSE); } elseif (($method_type = self::diagnostic($name)) && !empty($method_type)) { // Give appropriate return, based by each task node needs if ($method_type == 'condition' or $method_type == 'selector') { // Always, sanitize arguments $args = Janitor::get_input($name, $args, TRUE); // Ensure once, in case there are some deprecated method if (!is_callable(array(static::$db, $name))) { throw new \BadMethodCallException('[' . $name . ']Unknown method.'); } // Build the task onto the Gas instance $gas = array_shift($args); $gas->recorder->set($name, $args); return $gas; } elseif ($method_type == 'executor') { $executor = static::$dictionary['executor']; $write = array_slice($executor, 0, 6); $operation = array_slice($executor, 6, 4); $utility = array_slice($executor, 10, 6); if (in_array($name, $utility)) { // This not affected any row or any record return static::$db->{$name}(); } else { // Always, sanitize arguments $args = Janitor::get_input($name, $args, TRUE); // Ensure once, in case there are some deprecated method if (!is_callable(array(static::$db, $name))) { throw new \BadMethodCallException('[' . $name . ']Unknown method.'); } // Build the task onto the Gas instance $gas = array_shift($args); // Merge the table alongside with sent arguments $table = $gas->validate_table()->table; $argument = array_unshift($args, $table); $gas->recorder->set($name, $args); return self::_execute($gas); } } } else { // Last try check relationships $gas = array_shift($args); if (FALSE != ($relationship = $gas->meta->get('entities.' . $name))) { // Gotcha! // Check for any pre-process options if (!empty($args)) { $relationship['options'] = array_merge($args, $relationship['options']); } return self::generate_entity($gas, $relationship); } // Good bye throw new \BadMethodCallException('[' . $name . ']Unknown method.'); } }