function hydrate_model($file) { if (is_file($file) && strpos($file, '.php')) { preg_match_all('/class\\s(\\S+)\\s/', read($file), $match); require $file; foreach ($match[1] as $klass) { $re = new \ReflectionClass($klass); switch ($re->getParentClass()->getName()) { case 'Servant\\Mapper\\Database': status('hydrate', $file); $dsn = option('database.' . $klass::CONNECTION); $db = \Grocery\Base::connect($dsn); $columns = $klass::columns(); $indexes = $klass::indexes(); if (!isset($db[$klass::table()])) { $db[$klass::table()] = $columns; } \Grocery\Helpers::hydrate($db[$klass::table()], $columns, $indexes); break; case 'Servant\\Mapper\\MongoDB': status('hydrate', $file); $dsn_string = \Servant\Config::get($klass::CONNECTION); $database = substr($dsn_string, strrpos($dsn_string, '/') + 1); $mongo = $dsn_string ? new \Mongo($dsn_string) : new \Mongo(); $db = $mongo->{$database ?: 'default'}; \Servant\Helpers::reindex($db->{$klass::table()}, $klass::indexes()); break; default: break; } } } }
public function __set($key, $value) { $exists = isset($this->{$key}); if ($value === NULL) { unset($this[$key]); } elseif (is_string($value)) { if (!$exists) { throw new \Exception("Table '{$key}' does not exists"); } elseif (strlen(trim($value)) === 0) { throw new \Exception("Cannot rename the table '{$key}' to '{$value}'"); } elseif (isset($this->{$value})) { throw new \Exception("Cannot rename the table '{$key}' to '{$value}' (already exists)"); } $this->rename($key, $value); } elseif (is_array($value)) { if ($exists) { throw new \Exception("Table '{$key}' already exists"); } elseif (sizeof($value) === 0) { throw new \Exception("Empty fields for '{$key}'"); } elseif (!\Grocery\Helpers::is_assoc($value)) { throw new \Exception("Invalid fields for '{$key}'"); } $this->create($key, $value); } else { throw new \Exception("Nothing to do with '{$value}' on '{$key}'"); } }
public static function hydrate($table, array $columns, array $indexes = array()) { $old = $table->columns(); foreach ($columns as $key => $val) { is_array($val) or $val = array($val); if (!\Grocery\Helpers::is_assoc($val)) { @(list($type, $length, $default, $not_null) = $val); $val = compact('type', 'length', 'default', 'not_null'); } if (isset($old[$key])) { $type = isset($val['type']) ? $val['type'] : $old[$key]['type']; $length = isset($val['length']) ? $val['length'] : $old[$key]['length']; $default = isset($val['default']) ? $val['default'] : $old[$key]['default']; $not_null = isset($val['not_null']) ? $val['not_null'] : $old[$key]['not_null']; $tmp = $old[$key]['type']; $left = isset(static::$mask[$tmp]) ? static::$mask[$tmp] : array_search($tmp, static::$mask); $right = isset(static::$mask[$type]) ? static::$mask[$type] : array_search($type, static::$mask); if ($left === $right) { continue; } $tmp = compact('type', 'length', 'default', 'not_null'); if ($tmp != $old[$key]) { $table[$key] = $tmp; } } else { $table[$key] = $val; } } if (sizeof($old) != sizeof($columns)) { foreach (array_keys(array_diff_key($old, $columns)) as $one) { unset($table[$one]); } } $tmp = $out = array(); $idx = $table->indexes(); foreach ($idx as $name => $set) { foreach ($set['column'] as $one) { $tmp[$one] = $set['unique']; } } foreach ($indexes as $key => $val) { $on = is_numeric($key) ? FALSE : (bool) $val; $key = is_numeric($key) ? $val : $key; if (isset($tmp[$key])) { if ($on !== $tmp[$key]) { $table[$key]->unindex('_'); $table[$key]->index('_', $on); } } else { $table[$key]->index('_', $on); } $out[] = $key; } foreach (array_diff(array_keys($tmp), $out) as $old) { $table[$old]->unindex('_'); } }
public function prepare($sql, array $vars = array()) { if (\Grocery\Helpers::is_assoc($vars)) { $sql = strtr($sql, $this->fixate_value($vars, TRUE)); } else { $args = $this->fixate_value($vars, TRUE); $sql = preg_replace_callback('/((?<!\\\\)\\?)/', function () use($args) { return array_shift($args); }, $sql); } return $sql; }
public function import($from, $raw = FALSE) { ob_start(); $old = (include $from); $test = ob_get_clean(); if (!is_array($old)) { if ($raw) { return array_map(array($this, 'execute'), \Grocery\Helpers::sql_split($test)); } return FALSE; } foreach ((array) $old as $key => $val) { if (!empty($val['scheme'])) { $this->build_table($key, (array) $val['scheme']); } if (!empty($val['data'])) { foreach ((array) $val['data'] as $one) { $this->insert($key, $one); } } } }
}); it('should add columns on extra fields', function ($a) { \Grocery\Helpers::hydrate($a, array('x' => 'integer', 'y' => 'integer')); }); it('should remove columns on missing fields', function ($a) { \Grocery\Helpers::hydrate($a, array('x' => 'integer')); }); }); describe('indexes', function () { it('should add indexes when they are provided', function ($a) { \Grocery\Helpers::hydrate($a, array('x' => 'integer', 'y' => 'integer'), array('x')); $test = $a->indexes(); expect($test['a_x___idx']['unique'])->toBeFalsy(); }); it('should set indexes as unique when passing true', function ($a) { \Grocery\Helpers::hydrate($a, array('x' => 'integer', 'y' => 'integer'), array('x', 'y' => true)); $test = $a->indexes(); expect($test['a_y___idx']['unique'])->toBeTruthy(); }); it('should remove indexes when they are missing', function ($a) { \Grocery\Helpers::hydrate($a, array('x' => 'integer', 'y' => 'integer'), array('y' => false)); $test = $a->indexes(); expect($test)->toHaveLength(1); }); }); }); }); }); }; array_map($suitcase, $datasources); });
public function scheme() { return \Grocery\Helpers::map($this, function ($obj) { return array('columns' => $obj->columns(), 'indexes' => $obj->indexes()); }); }
protected function build_where($test, $operator = 'AND', $supertable = FALSE) { $sql = array(); $operator = strtoupper($operator); $sub_prefix = $supertable ? $this->protect_names($supertable) . '.' : ''; foreach ($test as $key => $val) { if (is_numeric($key)) { if (!\Grocery\Helpers::is_assoc($val)) { $raw = array_shift($val); if ($val && strpos($raw, '?')) { $sql[] = $this->prepare($raw, $val); } else { array_unshift($val, $raw) && ($sql[] = join("\n", $val)); } } else { $sql[] = is_array($val) ? $this->build_where($val, $operator, $supertable) : $val; } } elseif (\Grocery\Helpers::is_keyword($key)) { $sql[] = '(' . trim($this->build_where($val, strtoupper($key), $supertable)) . ')'; } elseif (preg_match('/_(?:and|or)_/i', $key, $match)) { $sub = array(); foreach (explode($match[0], $key) as $one) { $sub[$one] = $val; } $sql[] = '(' . trim($this->build_where($sub, strtoupper(trim($match[0], '_')), $supertable)) . ')'; } elseif (preg_match('/^(.+?)(?:\\s+(!=?|[<>]=?|<>|NOT|R?LIKE)\\s*)?$/', $key, $match)) { $sub = ''; $key = $this->protect_names($match[1]); if ($val === NULL) { $sub = 'IS NULL'; } else { $val = $this->fixate_value($val, TRUE); $sub = !empty($match[2]) ? $match[2] == '!' ? '!=' : $match[2] : '='; } if (is_array($val) && sizeof($val) > 1) { $key .= in_array($sub, array('!=', '<>')) ? ' NOT' : ''; $sql[] = " {$sub_prefix}{$key} IN(" . join(', ', $val) . ")"; } else { $val = is_array($val) ? array_shift($val) : $val; $sql[] = " {$sub_prefix}{$key} {$sub} {$val}"; } } } return join("\n{$operator}\n", $sql); }