0
@@ -10,7 +10,22 @@ include SCAR_LIB . 'constants.php';
0
include SCAR_LIB . 'sql.php';
0
include SCAR_LIB . 'datastore.php';
0
include SCAR_LIB . 'repository.php';
0
+include SCAR_LIB . 'scargeneric.php';
0
+ * SCAR Factory and Bridge Class
0
+ * The SCAR Object is a static object that:
0
+ * - creates new SCAR_Generic Objects
0
+ * - runs queries for SCAR_Generic Objects
0
+ * - can retrieve tables and columns for databases
0
+ * - can escape strings
0
+ * - serves as a bridge for multiple DB types
0
+ * It should be used as the start of any SCAR retrieval chain, using the format
0
+ * SCAR::get('tables') and from that point forward, you will be working with
0
+ * SCAR_Generic objects. To trigger an insert, use the format SCAR::make('object')
0
+ * to get a SCAR_Generic object geared towards inserting data.
0
* contains an array of timings for events as they happen
0
@@ -19,6 +34,26 @@ class SCAR {
0
public static $timings = array();
0
+ * Specify a config path for the application or retrieve the config path
0
+ * @param $cfg string a string to set the config path to
0
+ public static function config($cfg = null) {
0
+ if (!isset($config)) {
0
* Record a timestamp for benchmarking
0
* if $finish is provided, then it will be the time lapsed since
0
* mark was called last for $method without $finish.
0
@@ -60,6 +95,7 @@ class SCAR {
0
* @param $name string a name of a table to create an object for
0
* @param $columns string [optional] a list of columns to limit to
0
+ * @throws SCAR_Object_Not_Found_Exception
0
public static function get($name, $columns = null) {
0
@@ -70,14 +106,15 @@ class SCAR {
0
if (class_exists($klass)) {
0
- $k->
payload($datastore);
0
+ $k->
datastore($datastore);
0
// class does not exist, check the repository
0
if (!isset($repository)) {
0
self::mark('repository');
0
- $repository = new SCAR_Repository();
0
+ $repository = new SCAR_Repository(SCAR::config());
0
self::mark('repository', true);
0
@@ -87,7 +124,7 @@ class SCAR {
0
throw new SCAR_Object_Not_Found_Exception(Inflector::camelize($name));
0
- $k->
payload($datastore);
0
+ $k->
datastore($datastore);
0
@@ -97,6 +134,7 @@ class SCAR {
0
* can then call. This serves as a factory method, attempting to load
0
* schemes out of the db/ directory
0
* @param $scheme string The scheme type to load, ie 'mysql'
0
+ * @throws SCAR_Scheme_Not_Found_Exception
0
public static function load($scheme) {
0
$klass = 'SCAR_'.$scheme;
0
@@ -133,6 +171,7 @@ class SCAR {
0
* Opens a connection to a database via a subscheme
0
* @param $dsn string a scheme://user:pass@host/db formatted string
0
* @return a connection object reference for that db combination
0
+ * @throws SCAR_Connection_Exception
0
public static function connect($dsn) {
0
@@ -162,6 +201,12 @@ class SCAR {
0
return $connectors[$hash];
0
+ * Calls a scheme specific escape function
0
+ * @param $dsn string a formatted scheme://user:pass@host/db string
0
+ * @param $string string what we want to escape for SQL
0
public static function escape($dsn, $string) {
0
$uri = parse_url($dsn);
0
@@ -170,6 +215,14 @@ class SCAR {
0
return call_user_func_array(array('SCAR_'.$uri['scheme'], 'escape'), array($string));
0
+ * Runs a scheme specific query and normalizes the results for SCAR objects
0
+ * @param $dsn string a scheme://user:pass@host/db formatted string
0
+ * @param $sql string the SQL to run
0
+ * @param $pk_list array the primary key list for the object
0
+ * @throws SCAR_Query_Exception
0
public static function query($dsn, $sql, $pk_list) {
0
@@ -216,6 +269,11 @@ class SCAR {
0
+ * Calls a scheme specific show tables command
0
+ * @param $dsn string a scheme://user:pass@host/db formatted string
0
public static function showTables($dsn) {
0
$db = SCAR::connect($dsn);
0
$uri = parse_url($dsn);
0
@@ -241,6 +299,12 @@ class SCAR {
0
+ * Calls a scheme specific version of showing the columns in a database
0
+ * @param $dsn string a scheme://user:pass@host/db formatted string
0
+ * @param $table string a table name to get the columns for
0
public static function showColumns($dsn, $table) {
0
$db = SCAR::connect($dsn);
0
$uri = parse_url($dsn);
0
@@ -271,613 +335,3 @@ class SCAR {
0
-class SCAR_Generic implements Iterator {
0
- protected $_keys = array();
0
- protected $_whoami = false;
0
- protected $_datastore = null;
0
- protected $_cksum = null;
0
- protected $_lastrs = null;
0
- protected $_filter = null;
0
- protected $_data = array(
0
- 'primary_key' => array(),
0
- 'relations' => array(),
0
- public function SCAR($scar) { $this->_data['scar'] = $scar; return $this; }
0
- public function getSCAR() { return $this->_data['scar']; }
0
- public function dsn($dsn) { $this->_data['dsn'] = $dsn; return $this; }
0
- public function getDsn() { return $this->_data['dsn']; }
0
- public function name($name) { $this->_data['name'] = $name; return $this; }
0
- public function getName() { return ($this->_data['name']) ? $this->_data['name'] : get_class($this); }
0
- public function fields($fields) { $this->_data['fields'] = $fields; return $this; }
0
- public function getFields() { return $this->_data['fields']; }
0
- public function primaryKey() {
0
- $keys = func_get_args();
0
- $this->_data['primary_key'] = (is_array($keys[0])) ? $keys[0] : $keys;
0
- public function getPrimaryKey() { return $this->_data['primary_key']; }
0
- public function table($table) { $this->_data['table'] = $table; return $this; }
0
- public function getTable() { return ($this->_data['table']) ? $this->_data['table'] : Inflector::tableize($this->getName()); }
0
- public function getWhere() { return $this->_data['where']; }
0
- public function getSet() { return $this->_data['set']; }
0
- public function payload(SCAR_Datastore_Interface $pl) { $this->_datastore = $pl; }
0
- public function getPayload() { return $this->_datastore; }
0
- public function iAm($key) { $this->_whoami = $key; return $this; }
0
- public function whoAmI() { return $this->_whoami; }
0
- public function columns($col) {
0
- $this->_data['columns'] = null;
0
- $this->_data['columns'] = (is_array($col)) ? $col : array($col);
0
- public function getColumns() { return $this->_data['columns']; }
0
- public function hasOne($what, $key_relation = null) { return $this->_has(RELATION_HASONE, $what, $key_relation); }
0
- public function hasMany($what, $key_relation = null) { return $this->_has(RELATION_HASMANY, $what, $key_relation); }
0
- // what is $klass relation to this class
0
- public function getRelation($klass) {
0
- $klass = strtolower($klass);
0
- return (isset($this->_data['relations'][$klass])) ? $this->_data['relations'][$klass] : false;
0
- public function save() {
0
- public function __call($method, $args) {
0
- if (substr($method, 0, 2) == 'by') {
0
- array_unshift($args, Inflector::columnize(substr($method, 2)));
0
- return $this->_by($args);
0
- return $this->_join($method);
0
- // ----------------------------------------------------------------------
0
- // ----------------------------------------------------------------------
0
- // byColumnName($col, $val);
0
- // byColumnName($col, $val_array);
0
- // byColumnName($compare, $col, $val);
0
- protected function _by($args) {
0
- // is $args[1] an object?
0
- if (is_object($args[1]) && $args[1] instanceof SCAR_Generic) {
0
- list($column, $scar) = $args;
0
- $relation = $this->getRelation($scar->getName());
0
- // if it has a relation, use a join
0
- return ($this->_join($scar->getTable()));
0
- // attempt to find the relation via intermediate table
0
- $relation_name = $this->getName().$scar->getName();
0
- $relation = $this->getRelation($relation_name);
0
- $relation_name = $scar->getName().$this->getName();
0
- $relation = $this->getRelation($relation_name);
0
- throw new SCAR_Relation_Exception($this->getName(), $scar->getName());
0
- // relation_name is the object we need
0
- // relation describes that relation
0
- $m = Inflector::tableize($relation_name);
0
- $results = $scar->$m();
0
- foreach ($results as $result) {
0
- $remote = $relation['keys'][$column];
0
- $value[] = $result->$remote;
0
- // not a relational object, that makes life easier
0
- if (isset($args[2])) {
0
- list($column, $operator, $value) = $args;
0
- list($column, $value) = $args;
0
- $operator = (is_array($value) && count($value) > 1) ? 'IN' : '=';
0
- // optimize for a single value array
0
- if (is_array($value) && count($value) == 1) {
0
- $this->_data['where'][] = array('col' => $column, 'oper' => $operator, 'value' => $value);
0
- // setColumnName($value)
0
- protected function _set($args) {
0
- list($column, $value) = $args;
0
- $fields = $this->getFields();
0
- $type = $fields[$column];
0
- if ($type === TYPE_INT_AUTOINCREMENT) {
0
- $value = (string)$value;
0
- $value = (ctype_digit($value)) ? $value : 0;
0
- $this->_data['set'][] = array('col' => $column, 'value' => $value);
0
- protected function _join($table) {
0
- $klass = call_user_func_array(array($this->getSCAR(), 'get'), array($table));
0
- $klassname = $klass->getName();
0
- $relation = $this->getRelation($klassname);
0
- // attempt to find relational table for Many Many
0
- $relation_name = $this->getName().$klass->getName();
0
- $relation = $this->getRelation($relation_name);
0
- $relation_name = $klass->getName().$this->getName();
0
- $relation = $this->getRelation($relation_name);
0
- throw new SCAR_Relation_Exception($this->getName(), $klassname);
0
- // relates via many/many
0
- $link_table = Inflector::tableize($relation_name);
0
- return $this->$link_table()->$table();
0
- // join by SQL many records
0
- if (!$this->whoAmI()) {
0
- $rs = $this->_doSQL();
0
- foreach($relation['keys'] as $local_key => $foreign_key) {
0
- // find local key in key index
0
- foreach ($rs['keys'] as $keyspace => $match) {
0
- $keys = array_flip(explode(',', $keyspace));
0
- foreach ($match as $key_list) {
0
- $list = explode(',', $key_list);
0
- $ids[] = $list[$keys[$local_key]];
0
- // if ($local_key == 'tag_id') { var_dump($relation); var_dump($rs); }
0
- // $ids = $rs['keys'][$local_key];
0
- $klass_method = Inflector::byMethodize($foreign_key);
0
- $klass->$klass_method($ids);
0
- // join by one to many records, need ID
0
- $id = $this->whoAmI();
0
- $row = $this->getPayload()->get($this->getName(), $id);
0
- foreach($relation['keys'] as $local_key => $foreign_key) {
0
- $f_keys[] = $row[$local_key];
0
- $klass_method = Inflector::byMethodize($foreign_key);
0
- $klass->$klass_method($row[$local_key]);
0
- // does this thing already exist in our datastore? if so
0
- // we can iAm() it and it will live on its own
0
- $f_keys = implode(',', $f_keys);
0
- if ($this->getPayload()->get($klass->getName(), $f_keys)) {
0
- // share the data storage love
0
- $klass->payload($this->getPayload());
0
- // now calls are on the new object
0
- // ----------------------------------------------------------------------
0
- // ----------------------------------------------------------------------
0
- protected function _doSQL() {
0
- // things who know who they are don't need SQL
0
- if ($this->whoAmI()) {
0
- $table = $this->getTable();
0
- $table = '`'.$table.'`';
0
- if (count($this->getSet()) > 0 && $this->whoAmI()) {
0
- $sql = new SCAR_SQL('update', $this->getDSN(), $this->getSCAR());
0
- $sql->table = $this->getTable();
0
- $values = explode(',', $this->whoAmI());
0
- $keys = $this->getPrimaryKey();
0
- foreach ($keys as $idx => $key) {
0
- $where[] = array('col' => $key, 'oper' => '=', 'value' => $values[$idx]);
0
- $sql->set = $this->getSet();
0
- $stmt = $sql->render();
0
- $rs = call_user_func_array(array($this->getSCAR(), 'query'), array($this->getDSN(), $stmt, $this->getPrimaryKey()));
0
- // okay, update payload
0
- if ($rs['affected'] === 1) {
0
- $row = $this->getPayload()->get($this->getName(), $this->whoAmI());
0
- foreach ($this->getSet() as $set_piece) {
0
- $row[$set_piece['col']] = $set_piece['value'];
0
- $this->getPayload()->set($this->getName(), $this->whoAmI(), $row);
0
- elseif (count($this->getSet()) > 0) {
0
- $sql = new SCAR_SQL('insert', $this->getDSN(), $this->getSCAR());
0
- $sql->table = $this->getTable();
0
- $sql->set = $this->getSet();
0
- $stmt = $sql->render();
0
- $rs = call_user_func_array(array($this->getSCAR(), 'query'), array($this->getDSN(), $stmt, $this->getPrimaryKey()));
0
- if ($rs['affected'] === 1) {
0
- // get a new one and select it
0
- $klass = call_user_func_array(array($this->getSCAR(), 'get'), array($this->getName()));
0
- // change set to key/value pairs
0
- foreach ($this->getSet() as $set_piece) {
0
- $set[$set_piece['col']] = $set_piece['value'];